---
id: DOM-CRM-ACT-005
title: Record Timeline
realises: CON-CRM-ACT-005
product_area: crm
module: activities-tasks
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
owned_by: SVC-CRM-ACT-activities
readable_by: []
custom_fields: none
identity: >-
  A timeline is addressed through its contact or organization rather than a separate
  persisted identity. Section, filters and a two-source cursor determine a page, with
  independent continuation positions for activities and tasks.
attributes:
  - name: record
    kind: reference
    required: true
    computed: false
    notes: >-
      The related local contact or organization supplies context. Missing records return
      not found; an absorbed record’s route identifies the merge survivor.
  - name: section
    kind: enum
    required: true
    computed: false
    notes: >-
      Upcoming combines Scheduled interactions and unfinished tasks in ascending time
      order. History combines other interactions and closed tasks in descending time
      order.
  - name: items
    kind: collection
    required: true
    computed: true
    notes: >-
      Each linked interaction contributes one item. Task readers also receive related
      tasks. Pages default to 25 items and stop at 100; continuation positions apply to
      the current source data.
  - name: item position
    kind: computed
    required: true
    computed: true
    notes: >-
      Interactions use their instant. Open tasks use the due day or task day when undated
      for due purposes; closed tasks use the task day. Date-only positions use workspace
      midnight.
  - name: filters and search
    kind: collection
    required: false
    computed: false
    notes: >-
      Filtering covers kind, owner or holder, outcome, status and date range. Outcome
      filtering excludes tasks, and unfinished tasks map to Scheduled. Text matching
      ignores case and accents; invalid parameters or cursors are rejected.
  - name: overdue flag
    kind: computed
    required: true
    computed: true
    notes: >-
      A Scheduled interaction is overdue after its instant; unfinished work is overdue
      after its due day ends.
  - name: editable flag
    kind: computed
    required: true
    computed: true
    notes: >-
      The update permission for each item kind determines the editing flag. Record locks
      do not contribute to that flag.
  - name: summary
    kind: computed
    required: true
    computed: true
    notes: >-
      Independent aggregation counts the whole timeline by type and status, lists up to
      200 owners or holders, and totals upcoming work. Task aggregates require task-read
      authority.
relationships:
  - to: DOM-CRM-ACT-001
    cardinality: one timeline to many linked interactions
    ownership: Activity owns the associations from which the timeline reads.
    cross_service: false
  - to: DOM-CRM-ACT-003
    cardinality: one timeline to many related tasks
    ownership: Task owns the local references used to select the work.
    cross_service: false
  - to: DOM-CRM-ENT-001
    cardinality: one computed timeline for each contact
    ownership: The contact screen hosts the view; the timeline stores no contact data.
    cross_service: false
  - to: DOM-CRM-ENT-002
    cardinality: one computed timeline for each organization
    ownership: The organization screen hosts the same read model without storing it.
    cross_service: false
invariants:
  - id: INV-DOM-CRM-ACT-005-01
    statement: >-
      Timeline routes require both activity-read authority and read authority for their
      contact or organization.
    enforced_at:
      - api
    provenance: test
    source: >-
      services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses a timeline
      to a caller who may not read the contact: 403
  - id: INV-DOM-CRM-ACT-005-02
    statement: >-
      Task-read authority controls both task items and task aggregate counts; without it
      neither is returned.
    enforced_at:
      - api
      - service
    provenance: test
    source: >-
      services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#leaves the tasks
      out for a caller who may not read tasks
  - id: INV-DOM-CRM-ACT-005-03
    statement: A linked interaction contributes once to each related record’s stream and summary.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.queries.integration.spec.js#shows
      the activity linked to three contacts and an organization once on each of the four
      timelines
  - id: INV-DOM-CRM-ACT-005-04
    statement: >-
      With unchanged source data and filters, independent source positions preserve the
      defined interleaving without duplicates; pages do not share a retained snapshot.
    enforced_at:
      - service
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.queries.integration.spec.js#answers
      every item exactly once, in order, across pages of 25 that interleave the two
      sources
  - id: INV-DOM-CRM-ACT-005-05
    statement: >-
      Routes for an absorbed record return Gone with the surviving context rather than
      ordinary absence.
    enforced_at:
      - api
    provenance: observed
    source: 'services-crm:modules/activities/aws/api/activities.routes.ts:timelineRoutes'
physical:
  - activity_links
  - activities
  - tasks
evidence:
  - >-
    services-crm at a8d1364f: modules/activities/services/persistence/timelines.ts
    (header, listTimeline, getTimelineSummary, requireTimelineRecord);
    aws/api/activities.routes.ts (timelineRoute, timelineSummaryRoute, timelineRoutes);
    modules/activities/README.md (The timeline summary at volume);
    docs/migrations/activities/README.md (§5, D1, D2).
  - >-
    react-console at baf6dae3: components/activities/record-activity-timeline.tsx,
    activity-timeline.tsx.
---

# Record Timeline

## What It Models

Staff read a timeline to understand one relationship’s interactions and work. Upcoming and History present a computed stream assembled from activity associations and task references. The view has no independent persistence or ownership of those records.

## Identity and Attributes

The record address establishes context. A request specifies its section and filters, while the cursor retains each source’s position. Item attributes carry time, overdue standing and permission-based editability. A separate summary describes the full record context rather than the loaded page.

## Relationships

The view combines Activity and Task within CRM and is hosted by the contact and organization screens. Selecting work opens the task drawer. Removing an association changes the view without removing its underlying interaction or work.

## Invariants

The structured rows define read authorization, task visibility and continuation behavior. Continuation assumes unchanged inputs; it provides no snapshot spanning page requests. Permission-based editability can still lead to a lock refusal on save.

## How It Is Stored and Shared

The activities service implements the timeline and summary reads. Activity links supply indexed time, status and type copies, while task rows supply work context. Console record screens consume these reads and keep no alternative timeline store.

## Open Design Questions

Editing signals still need alignment with locks. Large-record owner aggregation may need further evidence before introducing another stored value. Retained interactions without associations have no timeline context.
