---
id: DOM-CRM-ACT-003
title: Task
realises: CON-CRM-ACT-003
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-tasks
readable_by:
  - SVC-CRM-ACT-activities
lifecycle: STATE-CRM-ACT-002
custom_fields: none
identity: >-
  A workspace identifies each task independently of its title. The service accepts a
  chosen record identifier or generates one; console recovery uses a preselected
  time-ordered identifier. A workflow creation reference is unique while its task exists,
  and external references are also locally unique. Type and queue identifiers are
  immutable configuration names.
attributes:
  - name: title
    kind: text
    required: true
    computed: false
    notes: 'The work heading is trimmed, nonblank and limited to 500 characters.'
  - name: description
    kind: text
    required: false
    computed: false
    notes: 'Optional work context may contain at most 20,000 characters.'
  - name: task type
    kind: reference
    required: true
    computed: false
    notes: >-
      Every task names a local category. The service also accepts an inactive category for
      new tasks.
  - name: status
    kind: enum
    required: true
    computed: false
    notes: >-
      Open, Waiting for someone else and Deferred remain unfinished work. Completed and
      Cancelled require the corresponding closing action and attribution.
  - name: priority
    kind: enum
    required: true
    computed: false
    notes: 'Low, Normal, High or Urgent expresses urgency; Normal is the creation default.'
  - name: task date
    kind: date
    required: true
    computed: false
    notes: >-
      The required work day defaults to today in the workspace calendar and remains
      unchanged when omitted from an edit.
  - name: due date
    kind: date
    required: false
    computed: false
    notes: An optional due day expresses a calendar deadline without a time of day.
  - name: related contact and organization
    kind: reference
    required: false
    computed: false
    notes: Optional contact and organization references identify local CRM context.
  - name: subject in another application
    kind: reference
    required: false
    computed: false
    notes: >-
      The optional cross-application subject supplies both an object and its record
      reference together.
  - name: holder and assignment record
    kind: reference
    required: false
    computed: false
    notes: >-
      A holder has assignment actor and time stamps. Assignment changes refresh them,
      while retaining the same holder preserves them.
  - name: queue and arrival time
    kind: reference
    required: false
    computed: false
    notes: >-
      Queue routing has an arrival instant. Entering or moving queues refreshes it;
      releasing work to its retained queue preserves it.
  - name: offered role
    kind: reference
    required: false
    computed: false
    notes: >-
      A candidate role identifies eligible claimants. The service checks its reference
      syntax without proving existence; claiming retains it, while assigning a different
      holder clears it.
  - name: closing record
    kind: computed
    required: false
    computed: true
    notes: >-
      Completion or cancellation records actor and instant only for its corresponding
      closed status; reopening removes both pairs.
  - name: workflow origin
    kind: text
    required: false
    computed: false
    notes: >-
      The creating workflow action reference is assigned on insertion and preserved by
      later task edits.
  - name: overdue standing
    kind: computed
    required: true
    computed: true
    notes: >-
      Open work is overdue when its due day is before today in the workspace calendar.
      This condition drives timeline marking and attention synchronization.
  - name: 'record lock, version and stamps'
    kind: computed
    required: true
    computed: true
    notes: >-
      An optional lock restricts changes or deletion. Edits compare the read version where
      required and record modifier and time; original creation attribution is retained.
  - name: type and queue · configuration
    kind: collection
    required: true
    computed: false
    notes: >-
      Types and queues store a trimmed locally unique name of at most 100 characters,
      description, availability and position. Queue membership, distribution and
      escalation settings are absent from service persistence.
relationships:
  - to: DOM-CRM-ENT-001
    cardinality: many tasks to zero or one contact
    ownership: >-
      Task owns its contact reference; deletion clears it, and merge transfer changes the
      destination.
    cross_service: false
  - to: DOM-CRM-ENT-002
    cardinality: many tasks to zero or one organization
    ownership: Task owns its organization reference with the same deletion and merge treatment.
    cross_service: false
  - to: DOM-CRM-ACT-001
    cardinality: zero or one follow-up created by an activity request
    ownership: >-
      The activity save creates the work transactionally without keeping a persistent
      relationship afterwards.
    cross_service: false
  - to: DOM-CRM-ACT-005
    cardinality: one task appearance on each related record timeline
    ownership: The timeline reads task context only when the caller can read task records.
    cross_service: false
invariants:
  - id: INV-DOM-CRM-ACT-003-01
    statement: >-
      Every task has a nonblank title of at most 500 characters and a local task type,
      with local contact, organization and queue references checked within the workspace.
    enforced_at:
      - api
      - service
      - database
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/integration/services/persistence/tasks.integration.spec.js#refuses
      a contact the tenant does not have
  - id: INV-DOM-CRM-ACT-003-02
    statement: >-
      Closing attribution matches the task’s closed status, open tasks carry no closing
      stamps, and the service uses dedicated actions for crossing that boundary.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/unit/services/tasks/lifecycle.spec.js#refuses an
      update that would complete the task, naming the operation that would have worked
  - id: INV-DOM-CRM-ACT-003-03
    statement: >-
      Holder references require both assignment stamps, and queue references require their
      arrival instant; removing either reference removes its paired stamps.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/integration/db/tasks.table.integration.spec.js#refuses
      a queue with no moment, so no task sits in a queue in no order
  - id: INV-DOM-CRM-ACT-003-04
    statement: >-
      Only a syntactically valid Rhythm user reference can hold work; this check does not
      establish actual workspace eligibility.
    enforced_at:
      - api
      - service
      - database
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/e2e/tasks.e2e.spec.js#answers 400 for an assignee
      that is not a Rhythm user id
  - id: INV-DOM-CRM-ACT-003-05
    statement: Creation rejects a task that names both a holder and a candidate role.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/integration/services/persistence/tasks.role-claim.integration.spec.js#refuses
      a create naming both an assignee and a role, naming the field, and writes nothing
  - id: INV-DOM-CRM-ACT-003-06
    statement: >-
      Conditional queue updates and locked role claims admit at most one committed holder
      from competing claims of the same available task.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/integration/services/persistence/tasks.concurrency.integration.spec.js#lets
      exactly one of them have it
  - id: INV-DOM-CRM-ACT-003-07
    statement: >-
      While its task exists, a workflow creation reference admits only one task per
      workspace across repeated or concurrent deliveries.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/integration/services/workflow-actions/task-service-operations.integration.spec.js#answers
      the repeat with the same task
  - id: INV-DOM-CRM-ACT-003-08
    statement: Later persistence changes retain the workflow origin recorded by creation.
    enforced_at:
      - service
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts:updateTask'
  - id: INV-DOM-CRM-ACT-003-09
    statement: >-
      Removing a related contact or organization clears its task reference and retains the
      task.
    enforced_at:
      - database
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/integration/db/tasks.table.integration.spec.js#keeps
      the task: the work outlives the record it was about
  - id: INV-DOM-CRM-ACT-003-10
    statement: >-
      When enabled, persistence writes publish or resolve overdue attention within their
      task transaction using holder, queue responsibility or administrator audiences;
      reconciliation and direct reference changes may leave older item details.
    enforced_at:
      - service
    provenance: observed
    source: >-
      services-crm:modules/tasks/services/persistence/task-attention-items.ts:syncTaskOverdueAttention;
      services-crm:modules/tasks/services/persistence/task-attention-items.ts:sweepOverdueTasks
  - id: INV-DOM-CRM-ACT-003-11
    statement: >-
      The database prevents removing a task type or queue while a surviving task
      references it.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/e2e/tasks.e2e.spec.js#refuses the delete of a task
      type a task is of (409)
  - id: INV-DOM-CRM-ACT-003-12
    statement: >-
      Console edits and closing actions send a read version; the assignment API permits
      omission and then applies the last serialized assignment.
    enforced_at:
      - api
      - service
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/e2e/tasks.e2e.spec.js#answers 409 to the reopen
      sent at the version the completion moved on from
  - id: INV-DOM-CRM-ACT-003-13
    statement: >-
      Task, task type and queue registrations omit custom-field support and their API
      schemas do not accept custom-field values.
    enforced_at:
      - api
    provenance: observed
    source: 'services-crm:modules/tasks/metadata/tasks.object.ts:tasksObject'
physical:
  - tasks
  - task_types
  - task_queues
evidence:
  - >-
    services-crm at a8d1364f: modules/tasks/db/tasks.table.ts, task-configurations.ts,
    task-types.table.ts, task-queues.table.ts; db/migrations/0040_tasks.sql
    (tasks_contact_fk ON DELETE SET NULL); services/persistence/tasks.ts;
    services/tasks/lifecycle.ts; services/persistence/task-attention-items.ts;
    services/persistence/task-configurations.ts; metadata/tasks.object.ts;
    docs/migrations/task-management/README.md (§3, §4, §10, §12);
    docs/workstreams/crm-tasks-role-claim.md.
  - 'react-console at baf6dae3: lib/api/tasks.ts; lib/configuration/task-queues.ts.'
---

# Task

## What It Models

Staff use a task to retain a piece of work until someone completes or cancels it. The record combines the work description with priority, dates, related context and routing. Types and queues belong to this broad object as classification and shared-work configuration.

## Identity and Attributes

The identifier persists as staff change the work. Workflow creation also carries the originating action reference, providing insertion deduplication rather than a log of later deliveries. The structured attributes describe the task facts, routing pairs, closing attribution and write safeguards. Overdue standing is calculated from the workspace calendar.

## Relationships

Task owns its local CRM references and its optional subject in another application. A follow-up is created during activity logging but continues independently. Record Timeline reads tasks for the related CRM records, and Platform supplies user and role authority rather than local foreign keys.

## Invariants

The structured invariants describe database consistency separately from service policy. Valid reference syntax establishes neither an eligible assignee nor an existing candidate role. Attention synchronization covers the persistence path; it does not make reconciliation immune to concurrent changes.

## How It Is Stored and Shared

The tasks service owns work records and both configuration catalogs. Activities delegates follow-up insertion and directly reads task rows for timelines. Workflow callers invoke the service function, while Platform queries consume registered datasets for lists and exports. Attention receives published overdue conditions, and security supplies the role-holder check. The offered list separately reads security assignments. Tasks have no registered change stream or revision store.

## Open Design Questions

Product still needs to choose task history, role-offer discovery and retirement behavior for inactive configuration. Assignment eligibility and external workflow proof remain unfinished. The attention failure policy needs a decision before task availability can be assessed with publishing enabled.
