---
id: CAP-CRM-ACT-010
title: Record and maintain a piece of work
feature: FEAT-CRM-ACT-03
product_area: crm
module: activities-tasks
revision: 2
status: draft
product_intent: proposed
implementation_evidence: inconsistent
supersedes:
  - react-console acceptance inventory CAP-CRM-ACT-011
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - >-
    Andrew 2026-10-12 (task date), recorded at
    services-crm:modules/tasks/db/tasks.table.ts
purpose: >-
  Staff give work a durable task record that can be managed and related to CRM
  records.
outcomes:
  - Identifiable work with a type and dates
  - Related-record context that can be cleared without losing work
  - Edits checked against the version read
concepts:
  - CON-CRM-ACT-003
actors:
  - ACT-CRM-001
  - ACT-CRM-004
  - ACT-CRM-006
surfaces:
  - console
  - api
preconditions:
  - The workspace provides a task type for selection.
postconditions:
  - >-
    New work starts Open and uses Normal priority unless another priority is
    supplied.
permissions:
  - key: crm.tasks.read
    where_checked: api
    scope: tenant
  - key: crm.tasks.create
    where_checked: api
    scope: tenant
  - key: crm.tasks.update
    where_checked: api
    scope: tenant
  - key: crm.tasks.delete
    where_checked: api
    scope: tenant
  - key: crm.tasks.create
    where_checked: console
    scope: tenant
rules:
  - id: BR-CAP-CRM-ACT-010-01
    statement: >-
      Tasks require a nonblank title of at most 500 characters and allow
      descriptions up to 20,000 characters, with field-specific refusals.
    kind: validation
    enforced_at:
      - api
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/integration/services/persistence/tasks.integration.spec.js#refuses
      a create whose title is blank, naming the field
    origin: none
  - id: BR-CAP-CRM-ACT-010-02
    statement: A task must reference a task type belonging to its workspace.
    kind: validation
    enforced_at:
      - api
      - database
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/e2e/tasks.e2e.spec.js#answers 400 for a
      task with no type, since every task is of some kind
    origin: none
  - id: BR-CAP-CRM-ACT-010-03
    statement: >-
      Creation uses Open by default, permits explicitly selected open statuses
      and refuses either closed status.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: >-
      services-crm:modules/tasks/services/persistence/tasks.ts:createTaskWithOutcome
    origin: none
  - id: BR-CAP-CRM-ACT-010-04
    statement: >-
      Omitted priority becomes Normal and omitted task date becomes today in the
      workspace; replacement preserves an omitted task date.
    kind: calculation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/integration/services/persistence/tasks.integration.spec.js#dates
      a task today, in the tenant's calendar, when the create gives no task date
    origin: >-
      Andrew 2026-10-12 (task date), recorded at
      services-crm:modules/tasks/db/tasks.table.ts
  - id: BR-CAP-CRM-ACT-010-05
    statement: >-
      A due day must exist in the calendar, with invalid dates rejected against
      the due-date field.
    kind: validation
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/e2e/tasks.e2e.spec.js#answers 400 naming
      the field for a due date that is not a day of the calendar
    origin: none
  - id: BR-CAP-CRM-ACT-010-06
    statement: >-
      Supplying a time with the due date succeeds, but storage retains only the
      calendar day.
    kind: validation
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0712.spec.ts#CRM-ACC-0712
    origin: none
    note: >-
      The finding preserves the difference between observed behavior and the
      earlier acceptance or product expectation.
  - id: BR-CAP-CRM-ACT-010-07
    statement: >-
      A task can reference one workspace contact and one workspace organization,
      and missing or foreign-workspace contact, organization, type and queue
      references are refused.
    kind: validation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/integration/services/persistence/tasks.integration.spec.js#refuses
      a contact the tenant does not have
    origin: none
  - id: BR-CAP-CRM-ACT-010-08
    statement: >-
      Deleting a related contact or organization preserves the task and clears
      only the corresponding reference.
    kind: lifecycle
    enforced_at:
      - database
    must_prove: true
    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
    origin: none
  - id: BR-CAP-CRM-ACT-010-09
    statement: External task references are unique within the workspace.
    kind: invariant
    enforced_at:
      - database
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/integration/services/persistence/tasks.integration.spec.js#refuses
      a second task of the tenant with an external id another task holds
      (DEF-CRM-0719)
    origin: none
  - id: BR-CAP-CRM-ACT-010-10
    statement: >-
      Edits require the version read; partial edits preserve omissions, while
      replacement resets omitted optional values except retained task date, role
      offer and workflow origin.
    kind: policy
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: observed
    source: 'services-crm:modules/tasks/services/persistence/tasks.ts:updateTask'
    origin: 'services-crm:docs/milestones/CRM-M1-contacts-and-organizations.md#D-05'
  - id: BR-CAP-CRM-ACT-010-11
    statement: >-
      Full locks block task edits, and either supported lock blocks task
      deletion.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/e2e/tasks.e2e.spec.js#refuses deleting a
      task locked against deletes
    origin: none
  - id: BR-CAP-CRM-ACT-010-12
    statement: >-
      Deleting tasks requires administrator permission and has no console
      action.
    kind: permission
    enforced_at:
      - api
      - console
    must_prove: true
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0707.spec.ts#CRM-ACC-0707
    origin: none
  - id: BR-CAP-CRM-ACT-010-13
    statement: >-
      The task creation form searches workspace contacts and organizations
      through its related-record selectors.
    kind: policy
    enforced_at:
      - console
    must_prove: true
    provenance: observed
    source: >-
      react-console:app/(console)/console/[tenantId]/tasks/page.tsx:ContactSelector
    origin: none
scenarios:
  - id: SC-CAP-CRM-ACT-010-01
    given: A coordinator opens Tasks.
    when: Create work with all supported details supplied.
    then: The list includes the task and its drawer returns the saved details.
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0707.spec.ts#CRM-ACC-0707
edge_cases:
  - id: SC-CAP-CRM-ACT-010-02
    given: >-
      Task inputs include a blank title, a 500-character title, an earlier due
      day and replacement without task date.
    when: Submit these variants.
    then: >-
      The blank title fails, the other valid variants succeed, and the
      replacement retains task date.
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0712.spec.ts#CRM-ACC-0712
constraints: []
depends_on:
  - CAP-CRM-ACT-016
related:
  - CAP-CRM-ACT-011
  - CAP-CRM-ACT-012
  - CAP-CRM-ACT-005
journeys:
  - JNY-CRM-ACT-002
open_questions: []
evidence:
  - >-
    services-crm at a8d1364f1dd44b723bb5f9acba12f983e9ec8d69: Independently
    reviewed declarations, behavior and assertions identified in this
    capability’s row citations.
  - >-
    react-console at baf6dae382d6f41dce976c7f848667ccc37e076f: Independently
    reviewed declarations, behavior and assertions identified in this
    capability’s row citations.
controls: [TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-006, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-003, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003]
---

# Record and maintain a piece of work

## Purpose

Staff give work a durable task record that can be managed and related to CRM records.

## How It Works

A coordinator chooses Create Task and enters a title and type. They can add a description, priority, dates and related records. Without an explicit status, the task starts Open; the service also accepts the other open statuses. Related-record selectors search within the workspace. Rhythm refuses missing local references and invalid content. A later edit includes the version read so it cannot silently replace a newer save. A complete replacement can reset omitted optional information. Deleting a related person or organization leaves the task available. Task deletion requires an administrator’s API action because the console provides no delete control.

## Relationships

- Follow-up creation records an ordinary task through this capability.
- Task assignment routes the work to a person or queue.
- Task lifecycle actions close or reopen the record.
