---
id: ATS-CRM-ACT-003
scope: CAP-CRM-ACT-003
product_area: crm
module: activities-tasks
revision: 3
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
  rhythm-v2-docs: 18a49edf30ee6bda18b159b65a2b91e093ea713d
scenarios:
- id: ATS-CRM-ACT-003-01
  title: Reject stale edits and missing versions
  level: api
  proves:
  - BR-CAP-CRM-ACT-003-01
  preconditions: An activity has advanced to its second version.
  steps: Replace and patch using the first version, then omit the patch version.
  expected: Stale requests conflict, the missing version fails validation, and the saved record remains.
  negative: true
  data_needs: Each run creates and isolates the records it needs.
  bound_to:
  - 'services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses a replace of a version it
    has moved on from: 409'
  - 'services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses a patch at a version the
    activity has moved on from: 409'
  - 'services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses a patch that names no version:
    400 naming sys_version'
  - services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
    a version the activity has moved on from
  - TST-CRM-ACT-002
  - TST-CRM-ACT-007
  provenance: test
  source: 'services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses a replace of a version
    it has moved on from: 409'
  category: concurrency
  binding_scope: Each registered suite contributes the assertions named by the retained file bindings;
    a compound scenario can require several suites. Conformance remains unverified.
- id: ATS-CRM-ACT-003-02
  title: Preserve unnamed fields in a partial edit
  level: api
  proves:
  - BR-CAP-CRM-ACT-003-02
  preconditions: A meeting contains all optional details.
  steps: Change only its subject, then explicitly clear its end.
  expected: The first patch changes only subject and the next clears only end.
  negative: false
  data_needs: Each run creates and isolates the records it needs.
  bound_to:
  - 'services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#leaves every property the patch
    omits as it was: duration, end, body, external id, owner and links'
  - services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#clears a property the patch sets
    to null, and only that one
  - TST-CRM-ACT-002
  provenance: test
  source: 'services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#leaves every property the
    patch omits as it was: duration, end, body, external id, owner and links'
  category: rule
  binding_scope: Each registered suite contributes the assertions named by the retained file bindings;
    a compound scenario can require several suites. Conformance remains unverified.
- id: ATS-CRM-ACT-003-03
  title: Reject incomplete replacement before writing
  level: api
  proves:
  - BR-CAP-CRM-ACT-003-03
  preconditions: The saved meeting includes duration.
  steps: Replace without duration, then with complete replacement content.
  expected: The incomplete request identifies duration without changing the record; the complete request
    succeeds.
  negative: true
  data_needs: Each run creates and isolates the records it needs.
  bound_to:
  - 'services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses a replacement missing a
    property: 400 naming it'
  - services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#changes nothing when it refuses the
    incomplete replacement
  - 'services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#accepts a complete replacement,
    where null clears: 200, the end is gone'
  - react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0692.spec.ts#CRM-ACC-0692
  - TST-CRM-ACT-002
  - TST-CRM-ACT-036
  provenance: test
  source: 'services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses a replacement missing
    a property: 400 naming it'
  category: validation
  binding_scope: Each registered suite contributes the assertions named by the retained file bindings;
    a compound scenario can require several suites. Conformance remains unverified.
- id: ATS-CRM-ACT-003-04
  title: Match replacement links to retained records
  level: api
  proves:
  - BR-CAP-CRM-ACT-003-04
  preconditions: An activity links two contacts.
  steps: Retain one contact and replace the other with an organization.
  expected: The retained link survives, the removed link disappears and the new link is created.
  negative: false
  data_needs: Each run creates and isolates the records it needs.
  bound_to:
  - services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#replaces
    the links as a set on update, keeping the row of a record still linked
  - TST-CRM-ACT-007
  provenance: test
  source: services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#replaces
    the links as a set on update, keeping the row of a record still linked
  category: interaction
  binding_scope: Each registered suite contributes the assertions named by the retained file bindings;
    a compound scenario can require several suites. Conformance remains unverified.
- id: ATS-CRM-ACT-003-05
  title: Keep deactivated selections while correcting history
  level: api
  proves:
  - BR-CAP-CRM-ACT-003-05
  preconditions: A saved activity’s type and outcome are deactivated.
  steps: Correct its subject and attempt to move another activity to the inactive type.
  expected: Correction retains the earlier selections; the new selection fails.
  negative: false
  data_needs: Each run creates and isolates the records it needs.
  bound_to:
  - services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#keeps
    an inactive type on an activity that already has it
  - services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#keeps
    a deactivated outcome on an activity that already has it
  - react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0700.spec.ts#CRM-ACC-0700
  - TST-CRM-ACT-007
  - TST-CRM-ACT-044
  provenance: test
  source: services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#keeps
    an inactive type on an activity that already has it
  category: edge
  binding_scope: Each registered suite contributes the assertions named by the retained file bindings;
    a compound scenario can require several suites. Conformance remains unverified.
- id: ATS-CRM-ACT-003-06
  title: Enforce an activity full lock
  level: api
  proves:
  - BR-CAP-CRM-ACT-003-06
  preconditions: The activity is locked against updates and deletes.
  steps: Try replacement and deletion.
  expected: Both operations conflict without changing the activity.
  negative: true
  data_needs: Each run creates and isolates the records it needs.
  bound_to:
  - services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
    a locked activity
  - TST-CRM-ACT-007
  provenance: test
  source: services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
    a locked activity
  category: failure
  binding_scope: Each registered suite contributes the assertions named by the retained file bindings;
    a compound scenario can require several suites. Conformance remains unverified.
- id: ATS-CRM-ACT-003-07
  title: Delete an activity and its local relationships
  level: api
  proves:
  - BR-CAP-CRM-ACT-003-07
  preconditions: An activity links two records.
  steps: Delete it, read it and delete it again.
  expected: The activity and links are absent; later read and deletion return Not Found.
  negative: true
  data_needs: Each run creates and isolates the records it needs.
  bound_to:
  - services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#removes
    the activity and its links
  - 'services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#deletes it: 200, and a read afterwards
    is 404, as is a second delete'
  - services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#writes
    a deletion revision
  - TST-CRM-ACT-007
  - TST-CRM-ACT-002
  provenance: test
  source: services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#removes
    the activity and its links
  category: transition
  binding_scope: Each registered suite contributes the assertions named by the retained file bindings;
    a compound scenario can require several suites. Conformance remains unverified.
- id: ATS-CRM-ACT-003-08
  title: Allow activity deletion at user tier
  level: browser
  proves:
  - BR-CAP-CRM-ACT-003-08
  preconditions: A Standard User can access a colleague’s activity.
  steps: Delete the activity and attempt contact deletion.
  expected: Activity deletion succeeds and contact deletion lacks authority.
  negative: false
  data_needs: Each run creates and isolates the records it needs.
  bound_to:
  - react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0717.spec.ts#CRM-ACC-0717
  - TST-CRM-ACT-061
  provenance: test
  source: react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0717.spec.ts#CRM-ACC-0717
  category: permission
  binding_scope: Each registered suite contributes the assertions named by the retained file bindings;
    a compound scenario can require several suites. Conformance remains unverified.
- id: ATS-CRM-ACT-003-09
  title: Correction settles files and history under the access guard
  category: interaction
  level: api
  proves:
  - BR-CAP-CRM-ACT-003-01
  - BR-CAP-CRM-ACT-004-03
  - BR-CAP-CRM-ACT-006-02
  - BR-CAP-CRM-ACT-019-04
  preconditions: An unlocked interaction has two prepared files and a current revision.
  steps: As an updater, correct the subject and remove one file; read the revision and remaining attachments.
    Repeat a correction with a read-only caller.
  expected: The successful correction has one revision and the retained file; the forbidden correction
    changes neither content, files nor history.
  negative: false
  data_needs: Run-owned records in an isolated workspace; fixed clock for calendar checks.
  bound_to: []
  provenance: proposed
  source: 'services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses a replace of a version
    it has moved on from: 409; services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#keeps
    an attachment sent back unchanged, and removes one left out; services-crm:modules/activities/services/persistence/activities.ts:recordedStampsOf;
    services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses a create to a caller who
    may only read activities: 403'
  exercises:
  - CAP-CRM-ACT-003
  - CAP-CRM-ACT-004
  - CAP-CRM-ACT-006
  - CAP-CRM-ACT-019
  related:
  - CAP-CRM-ACT-004
  - CAP-CRM-ACT-006
  - CAP-CRM-ACT-019
- id: ATS-CRM-ACT-003-10
  title: Persist interaction from Scheduled to Completed
  category: transition
  level: api
  proves:
  - INV-DOM-CRM-ACT-001-04
  - INV-DOM-CRM-ACT-001-07
  - INV-DOM-CRM-ACT-001-10
  - INV-DOM-CRM-ACT-001-11
  preconditions: Run-owned interaction has Scheduled standing. The read version matches, updates are unlocked,
    and the proposed values satisfy the type’s field requirements.
  steps: An ordinary edit chooses completed as the interaction status. Read the resulting record and affected
    projections after commit.
  expected: The resulting interaction has Completed standing. The database refreshes status on the interaction’s
    links and captures the committed revision. The interaction appears in history and must satisfy any
    required completion duration and result.
  negative: false
  data_needs: Run-owned records in an isolated workspace; fixed clock for calendar checks.
  bound_to: []
  provenance: proposed
  source: services-crm:modules/activities/services/activities/field-modes.ts:fieldModeProblems
  state_model: STATE-CRM-ACT-001
  transition:
    from: scheduled
    to: completed
    trigger: An ordinary edit chooses completed as the interaction status.
- id: ATS-CRM-ACT-003-11
  title: Persist interaction from Scheduled to Cancelled
  category: transition
  level: api
  proves:
  - INV-DOM-CRM-ACT-001-04
  - INV-DOM-CRM-ACT-001-07
  - INV-DOM-CRM-ACT-001-10
  - INV-DOM-CRM-ACT-001-11
  preconditions: Run-owned interaction has Scheduled standing. The read version matches, updates are unlocked,
    and the proposed values satisfy the type’s field requirements.
  steps: An ordinary edit chooses cancelled as the interaction status. Read the resulting record and affected
    projections after commit.
  expected: The resulting interaction has Cancelled standing. The database refreshes status on the interaction’s
    links and captures the committed revision. The interaction appears in history without completion-only
    requirements.
  negative: false
  data_needs: Run-owned records in an isolated workspace; fixed clock for calendar checks.
  bound_to: []
  provenance: proposed
  source: services-crm:modules/activities/services/persistence/activities.ts:updateActivity
  state_model: STATE-CRM-ACT-001
  transition:
    from: scheduled
    to: cancelled
    trigger: An ordinary edit chooses cancelled as the interaction status.
- id: ATS-CRM-ACT-003-12
  title: Persist interaction from Completed to Scheduled
  category: transition
  level: api
  proves:
  - INV-DOM-CRM-ACT-001-04
  - INV-DOM-CRM-ACT-001-07
  - INV-DOM-CRM-ACT-001-10
  - INV-DOM-CRM-ACT-001-11
  preconditions: Run-owned interaction has Completed standing. The read version matches, updates are unlocked,
    and the proposed values satisfy the type’s field requirements.
  steps: An ordinary edit chooses scheduled as the interaction status. Read the resulting record and affected
    projections after commit.
  expected: The resulting interaction has Scheduled standing. The database refreshes status on the interaction’s
    links and captures the committed revision. The interaction appears in upcoming items; completion-only
    requirements no longer apply.
  negative: false
  data_needs: Run-owned records in an isolated workspace; fixed clock for calendar checks.
  bound_to: []
  provenance: proposed
  source: services-crm:modules/activities/services/persistence/activities.ts:updateActivity
  state_model: STATE-CRM-ACT-001
  transition:
    from: completed
    to: scheduled
    trigger: An ordinary edit chooses scheduled as the interaction status.
- id: ATS-CRM-ACT-003-13
  title: Persist interaction from Completed to Cancelled
  category: transition
  level: api
  proves:
  - INV-DOM-CRM-ACT-001-04
  - INV-DOM-CRM-ACT-001-07
  - INV-DOM-CRM-ACT-001-10
  - INV-DOM-CRM-ACT-001-11
  preconditions: Run-owned interaction has Completed standing. The read version matches, updates are unlocked,
    and the proposed values satisfy the type’s field requirements.
  steps: An ordinary edit chooses cancelled as the interaction status. Read the resulting record and affected
    projections after commit.
  expected: The resulting interaction has Cancelled standing. The database refreshes status on the interaction’s
    links and captures the committed revision. The interaction appears in history without completion-only
    requirements.
  negative: false
  data_needs: Run-owned records in an isolated workspace; fixed clock for calendar checks.
  bound_to: []
  provenance: proposed
  source: services-crm:modules/activities/services/persistence/activities.ts:updateActivity
  state_model: STATE-CRM-ACT-001
  transition:
    from: completed
    to: cancelled
    trigger: An ordinary edit chooses cancelled as the interaction status.
- id: ATS-CRM-ACT-003-14
  title: Persist interaction from Cancelled to Scheduled
  category: transition
  level: api
  proves:
  - INV-DOM-CRM-ACT-001-04
  - INV-DOM-CRM-ACT-001-07
  - INV-DOM-CRM-ACT-001-10
  - INV-DOM-CRM-ACT-001-11
  preconditions: Run-owned interaction has Cancelled standing. The read version matches, updates are unlocked,
    and the proposed values satisfy the type’s field requirements.
  steps: An ordinary edit chooses scheduled as the interaction status. Read the resulting record and affected
    projections after commit.
  expected: The resulting interaction has Scheduled standing. The database refreshes status on the interaction’s
    links and captures the committed revision. The interaction appears in upcoming items; completion-only
    requirements no longer apply.
  negative: false
  data_needs: Run-owned records in an isolated workspace; fixed clock for calendar checks.
  bound_to: []
  provenance: proposed
  source: services-crm:modules/activities/services/persistence/activities.ts:updateActivity
  state_model: STATE-CRM-ACT-001
  transition:
    from: cancelled
    to: scheduled
    trigger: An ordinary edit chooses scheduled as the interaction status.
- id: ATS-CRM-ACT-003-15
  title: Persist interaction from Cancelled to Completed
  category: transition
  level: api
  proves:
  - INV-DOM-CRM-ACT-001-04
  - INV-DOM-CRM-ACT-001-07
  - INV-DOM-CRM-ACT-001-10
  - INV-DOM-CRM-ACT-001-11
  preconditions: Run-owned interaction has Cancelled standing. The read version matches, updates are unlocked,
    and the proposed values satisfy the type’s field requirements.
  steps: An ordinary edit chooses completed as the interaction status. Read the resulting record and affected
    projections after commit.
  expected: The resulting interaction has Completed standing. The database refreshes status on the interaction’s
    links and captures the committed revision. The interaction appears in history and must satisfy any
    required completion duration and result.
  negative: false
  data_needs: Run-owned records in an isolated workspace; fixed clock for calendar checks.
  bound_to: []
  provenance: proposed
  source: services-crm:modules/activities/services/activities/field-modes.ts:fieldModeProblems
  state_model: STATE-CRM-ACT-001
  transition:
    from: cancelled
    to: completed
    trigger: An ordinary edit chooses completed as the interaction status.
- id: ATS-CRM-ACT-003-16
  title: Persist interaction from Scheduled to Deleted
  category: transition
  level: api
  proves:
  - INV-DOM-CRM-ACT-001-04
  - INV-DOM-CRM-ACT-001-07
  - INV-DOM-CRM-ACT-001-10
  - INV-DOM-CRM-ACT-001-11
  preconditions: Run-owned interaction has Scheduled standing. Neither deletion nor update-and-deletion
    protection is set; deletion does not require a read version.
  steps: A caller requests removal. Read the resulting record and affected projections after commit.
  expected: The resulting interaction has Deleted standing. The interaction’s owned links and file entries
    are removed, and released files are submitted for cleanup. Import matching references are dropped
    and the committed deletion is captured in history.
  negative: false
  data_needs: Run-owned records in an isolated workspace; fixed clock for calendar checks.
  bound_to: []
  provenance: proposed
  source: services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#removes
    the activity and its links
  state_model: STATE-CRM-ACT-001
  transition:
    from: scheduled
    to: deleted
    trigger: A caller requests removal.
- id: ATS-CRM-ACT-003-17
  title: Persist interaction from Completed to Deleted
  category: transition
  level: api
  proves:
  - INV-DOM-CRM-ACT-001-04
  - INV-DOM-CRM-ACT-001-07
  - INV-DOM-CRM-ACT-001-10
  - INV-DOM-CRM-ACT-001-11
  preconditions: Run-owned interaction has Completed standing. Neither deletion nor update-and-deletion
    protection is set; deletion does not require a read version.
  steps: A caller requests removal. Read the resulting record and affected projections after commit.
  expected: The resulting interaction has Deleted standing. The interaction’s owned links and file entries
    are removed, and released files are submitted for cleanup. Import matching references are dropped
    and the committed deletion is captured in history.
  negative: false
  data_needs: Run-owned records in an isolated workspace; fixed clock for calendar checks.
  bound_to: []
  provenance: proposed
  source: services-crm:modules/activities/services/persistence/activities.ts:deleteActivity
  state_model: STATE-CRM-ACT-001
  transition:
    from: completed
    to: deleted
    trigger: A caller requests removal.
- id: ATS-CRM-ACT-003-18
  title: Persist interaction from Cancelled to Deleted
  category: transition
  level: api
  proves:
  - INV-DOM-CRM-ACT-001-04
  - INV-DOM-CRM-ACT-001-07
  - INV-DOM-CRM-ACT-001-10
  - INV-DOM-CRM-ACT-001-11
  preconditions: Run-owned interaction has Cancelled standing. Neither deletion nor update-and-deletion
    protection is set; deletion does not require a read version.
  steps: A caller requests removal. Read the resulting record and affected projections after commit.
  expected: The resulting interaction has Deleted standing. The interaction’s owned links and file entries
    are removed, and released files are submitted for cleanup. Import matching references are dropped
    and the committed deletion is captured in history.
  negative: false
  data_needs: Run-owned records in an isolated workspace; fixed clock for calendar checks.
  bound_to: []
  provenance: proposed
  source: services-crm:modules/activities/services/persistence/activities.ts:deleteActivity
  state_model: STATE-CRM-ACT-001
  transition:
    from: cancelled
    to: deleted
    trigger: A caller requests removal.
evidence:
- 'services-crm at a8d1364f1dd44b723bb5f9acba12f983e9ec8d69: scenario sources, executable assertions and
  local dependency boundaries are inspected.'
- 'react-console at baf6dae382d6f41dce976c7f848667ccc37e076f: scoped component tests and browser journey
  assertions are inspected.'
coverage:
  rule: covered
  transition: covered
  validation: covered
  permission: covered
  edge: covered
  failure: covered
  boundary: 'gap: FND-CRM-ACT-070'
  concurrency: covered
  invariant: 'gap: FND-CRM-ACT-070'
  interaction: covered
coverage_obligations:
  finding: FND-CRM-ACT-070
  unproved_rules:
  - BR-CAP-CRM-ACT-003-09
  - BR-CAP-CRM-ACT-003-11
  permission_matrix:
    keys:
    - crm.activities.read
    - crm.activities.update
    - crm.activities.delete
    remaining: Complete allow/refuse combinations, including each console guard and each API operation.
  execution_note: Covered means a scenario is specified; it does not mean that scenario has executed or
    every variant has an executable binding.
related_coverage:
- capability: CAP-CRM-ACT-004
  scenarios:
  - ATS-CRM-ACT-003-09
  finding: FND-CRM-ACT-070
- capability: CAP-CRM-ACT-006
  scenarios:
  - ATS-CRM-ACT-003-09
  finding: FND-CRM-ACT-070
- capability: CAP-CRM-ACT-019
  scenarios:
  - ATS-CRM-ACT-003-09
  finding: FND-CRM-ACT-070
permission_coverage:
- key: crm.activities.read
  finding: FND-CRM-ACT-070
  note: The finding covers unproved operation and surface combinations; a permission-category scenario
    is not a complete permission matrix.
- key: crm.activities.update
  finding: FND-CRM-ACT-070
  note: The finding covers unproved operation and surface combinations; a permission-category scenario
    is not a complete permission matrix.
- key: crm.activities.delete
  finding: FND-CRM-ACT-070
  note: The finding covers unproved operation and surface combinations; a permission-category scenario
    is not a complete permission matrix.
---

# Correct or delete an activity with protection against stale edits: Capability Test Specification

## Coverage

Category coverage counts specified proof. Unbound cases remain proposed; registered assertions do not establish a passing run.

| Rule | Proof Scenario Or Finding |
|---|---|
| `BR-CAP-CRM-ACT-003-01` | `ATS-CRM-ACT-003-01`, `ATS-CRM-ACT-003-09` |
| `BR-CAP-CRM-ACT-003-02` | `ATS-CRM-ACT-003-02` |
| `BR-CAP-CRM-ACT-003-03` | `ATS-CRM-ACT-003-03` |
| `BR-CAP-CRM-ACT-003-04` | `ATS-CRM-ACT-003-04` |
| `BR-CAP-CRM-ACT-003-05` | `ATS-CRM-ACT-003-05` |
| `BR-CAP-CRM-ACT-003-06` | `ATS-CRM-ACT-003-06` |
| `BR-CAP-CRM-ACT-003-07` | `ATS-CRM-ACT-003-07` |
| `BR-CAP-CRM-ACT-003-08` | `ATS-CRM-ACT-003-08` |
| `BR-CAP-CRM-ACT-003-09` | `FND-CRM-ACT-070` |
| `BR-CAP-CRM-ACT-003-11` | `FND-CRM-ACT-070` |

## Interactions With Related Capabilities

An unlocked interaction has two prepared files and a current revision. As an updater, correct the subject and remove one file; read the revision and remaining attachments. Repeat a correction with a read-only caller.

The interaction scenario names the capabilities and rules it exercises. The coverage finding retains incomplete permission combinations and failure variants.
