---
id: CAP-CRM-ACT-004
title: Retain supporting files with an activity
feature: FEAT-CRM-ACT-01
product_area: crm
module: activities-tasks
revision: 2
status: draft
product_intent: proposed
implementation_evidence: partially-observed
supersedes:
  - react-console acceptance inventory CAP-CRM-ACT-009
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources: []
purpose: Staff keep supporting documents attached to the interaction they explain.
outcomes:
  - Managed attachment references
  - Files released with their owning activity
concepts:
  - CON-CRM-ACT-001
actors:
  - ACT-CRM-001
  - ACT-CRM-004
surfaces:
  - console
  - api
preconditions:
  - The workspace has configured managed file storage.
postconditions: []
permissions:
  - key: crm.activities.create
    where_checked: api
    scope: tenant
  - key: crm.activities.update
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-CRM-ACT-004-01
    proved_by: [ATS-CRM-ACT-004-01, TST-CRM-ACT-007]
    statement: >-
      An activity accepts no more than 20 attachments, with file names limited
      to 255 characters.
    kind: validation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
      more than 20 attachments
    origin: none
  - id: BR-CAP-CRM-ACT-004-02
    proved_by: [ATS-CRM-ACT-004-02, TST-CRM-ACT-007]
    statement: >-
      New attachment references must come from the shared file pipeline, which
      prepares a permanent copy for the activity and rejects unprepared
      references.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
      a file reference that did not come through the pipeline
    origin: none
  - id: BR-CAP-CRM-ACT-004-03
    proved_by: [ATS-CRM-ACT-003-09, ATS-CRM-ACT-004-03, ATS-CRM-ACT-004-05, TST-CRM-ACT-007]
    statement: >-
      Submitting an attachment list retains unchanged files and removes entries
      absent from that list, while a partial edit that omits the list preserves
      it.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#keeps
      an attachment sent back unchanged, and removes one left out
    origin: none
  - id: BR-CAP-CRM-ACT-004-04
    proved_by: []
    statement: The attachment list determines the display order of its files.
    kind: policy
    enforced_at:
      - service
    must_prove: false
    provenance: observed
    source: >-
      services-crm:modules/activities/db/activity-attachments.table.ts:ACTIVITY_ATTACHMENT_COLLECTION
    origin: none
  - id: BR-CAP-CRM-ACT-004-05
    proved_by: [ATS-CRM-ACT-004-05]
    statement: >-
      Activity deletion requests cleanup of released file references; the shared
      file service owns physical deletion.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: >-
      services-crm:modules/activities/services/persistence/activities.ts:deleteActivity
    origin: none
  - id: BR-CAP-CRM-ACT-004-06
    proved_by: [ATS-CRM-ACT-004-04, TST-CRM-ACT-006]
    statement: An activity create replay does not copy its attachments again.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.create-retries.integration.spec.js#copies
      nothing for the retry
    origin: 'services-crm:docs/milestones/CRM-M8-activities-and-tasks.md#D-43'
  - id: BR-CAP-CRM-ACT-004-07
    proved_by: []
    statement: >-
      The activity editor displays existing attachments and permits removal, but
      provides no upload control.
    kind: policy
    enforced_at:
      - console
    must_prove: true
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0703.spec.ts#CRM-ACC-0703
    origin: none
scenarios:
  - id: SC-CAP-CRM-ACT-004-01
    given: An activity has an attachment prepared through the file pipeline.
    when: Submit an unprepared file reference as a new attachment.
    then: The activity save rejects the file reference.
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0703.spec.ts#CRM-ACC-0703
edge_cases: []
constraints: []
depends_on:
  - CAP-CRM-ACT-001
related:
  - CAP-CRM-ACT-003
journeys: []
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-004, TC-LOG-005, TC-MON-001, TC-MON-002, TC-PI-001, TC-PI-004, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003]
exercised_by: [FAS-CRM-ACT-01-06]
suites: [TST-CRM-ACT-006, TST-CRM-ACT-007]
---

# Retain supporting files with an activity

## Purpose

Staff keep supporting documents attached to the interaction they explain.

## How It Works

A client supplies files through Rhythm’s shared upload process. The activity save receives permanent references prepared for that record. Rhythm rejects a new file reference that bypasses preparation. The submitted attachment list controls which files remain and their order. A partial edit can leave the list untouched. Deleting the activity releases its references and requests shared cleanup. The console displays attached files and lets staff remove them. It currently has no control for adding uploads. The product should decide whether staff need that control before treating console attachment support as complete.

## Relationships

- Activity logging owns attachment saves.
- Activity correction changes or removes the attachment list.
- Platform file management owns storage and cleanup.
