---
id: CAP-CRM-ACT-019
title: Apply workspace access and maintenance permissions
feature: FEAT-CRM-ACT-05
product_area: crm
module: activities-tasks
revision: 2
status: draft
product_intent: proposed
implementation_evidence: inconsistent
supersedes:
  - react-console acceptance inventory CAP-CRM-ACT-017
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-crm:docs/milestones/CRM-M8-activities-and-tasks.md#D-08'
  - 'services-crm:docs/migrations/activities/README.md#D9'
purpose: 'Customers control who reads, records and maintains interactions and work.'
outcomes:
  - Workspace boundaries on local records
  - Actions aligned with declared permissions
  - Permission-aware console controls
concepts:
  - CON-CRM-ACT-001
  - CON-CRM-ACT-003
actors:
  - ACT-CRM-001
  - ACT-CRM-002
  - ACT-CRM-003
  - ACT-CRM-006
surfaces:
  - console
  - api
preconditions: []
postconditions: []
permissions:
  - key: crm.activities.read
    where_checked: api
    scope: tenant
  - key: crm.activities.create
    where_checked: api
    scope: tenant
  - key: crm.activities.update
    where_checked: api
    scope: tenant
  - key: crm.activities.delete
    where_checked: api
    scope: tenant
  - key: crm.activities.bulk
    where_checked: api
    scope: tenant
  - key: crm.activities.query
    where_checked: api
    scope: tenant
  - key: crm.activities.history
    where_checked: api
    scope: tenant
  - 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.bulk
    where_checked: api
    scope: tenant
  - key: crm.tasks.query
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-CRM-ACT-019-01
    proved_by: [ATS-CRM-ACT-019-01, TST-CRM-ACT-002, TST-CRM-ACT-003, TST-CRM-ACT-025, TST-CRM-ACT-062]
    statement: >-
      Local records and foreign keys are workspace-scoped, while external user
      and role references need separate validation rather than local foreign
      keys.
    kind: invariant
    enforced_at:
      - database
    must_prove: true
    provenance: observed
    source: >-
      services-crm:modules/tasks/db/tasks.table.ts;
      services-crm:modules/activities/db/activity-links.table.ts
    origin: none
  - id: BR-CAP-CRM-ACT-019-02
    proved_by: [ATS-CRM-ACT-017-09, ATS-CRM-ACT-019-01, TST-CRM-ACT-002, TST-CRM-ACT-003, TST-CRM-ACT-025, TST-CRM-ACT-062]
    statement: >-
      Another workspace’s activity or task appears absent, and attempted writes
      to it are refused without changes.
    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#is
      left exactly as the other tenant had it, every refusal above having
      written nothing
    origin: none
  - id: BR-CAP-CRM-ACT-019-03
    proved_by: [ATS-CRM-ACT-019-02, TST-CRM-ACT-002, TST-CRM-ACT-015]
    statement: >-
      A signed workspace context cannot be used against another workspace’s
      address.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses a
      context for tenant B on tenant A’s path: 403
    origin: none
  - id: BR-CAP-CRM-ACT-019-04
    proved_by: [ATS-CRM-ACT-003-09, ATS-CRM-ACT-019-03, ATS-CRM-ACT-019-07, TST-CRM-ACT-002, TST-CRM-ACT-059]
    statement: >-
      Activity read, query and history are reader-tier permissions, creation,
      editing and deletion are user-tier permissions, and bulk operations are
      administrator-tier permissions.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses a
      create to a caller who may only read activities: 403
    origin: none
    note: >-
      This source is an implementation decision record, so it does not confirm
      Product authority for the rule.
  - id: BR-CAP-CRM-ACT-019-05
    proved_by: [ATS-CRM-ACT-019-04, ATS-CRM-ACT-019-07, TST-CRM-ACT-015, TST-CRM-ACT-060]
    statement: >-
      Task read and query are reader-tier permissions, task work and lifecycle
      actions are user-tier permissions, and deletion and bulk are
      administrator-tier permissions.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/tasks/tests/e2e/tasks.e2e.spec.js#answers 403 to a
      caller who may only read tasks claiming one
    origin: none
  - id: BR-CAP-CRM-ACT-019-06
    proved_by: [ATS-CRM-ACT-019-05, ATS-CRM-ACT-019-07, TST-CRM-ACT-002, TST-CRM-ACT-015]
    statement: >-
      Activity types, task types and queues are readable by readers and
      maintained by administrators.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses a
      type’s create to a caller who may only read types: 403
    origin: none
  - id: BR-CAP-CRM-ACT-019-07
    proved_by: [ATS-CRM-ACT-019-08, TST-CRM-ACT-002]
    statement: A request with no signed execution context is rejected as unauthenticated.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#answers
      401 without a context
    origin: none
  - id: BR-CAP-CRM-ACT-019-08
    proved_by: [ATS-CRM-ACT-019-06, TST-CRM-ACT-043]
    statement: >-
      Ordinary saves can set deletion or full locks on module records, but no
      supported action can clear a full lock afterward.
    kind: policy
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0699.spec.ts#CRM-ACC-0699
    origin: 'services-crm:docs/milestones/CRM-M8-activities-and-tasks.md#D-08'
    note: >-
      The recorded audited lock contract remains different from ordinary save
      behavior.
  - id: BR-CAP-CRM-ACT-019-09
    proved_by: []
    statement: >-
      Task, task-type and task-queue bulk permissions are declared without
      operations that consume them.
    kind: permission
    enforced_at:
      - api
    must_prove: false
    provenance: observed
    source: 'services-crm:aws/crm.service.ts:TasksPermissions'
    origin: none
  - id: BR-CAP-CRM-ACT-019-10
    proved_by: []
    statement: >-
      Console activity and task controls are hidden or disabled according to the
      user’s relevant permissions.
    kind: permission
    enforced_at:
      - console
    must_prove: true
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0715.spec.ts#CRM-ACC-0715
    origin: none
scenarios:
  - id: SC-CAP-CRM-ACT-019-01
    given: 'Callers have administrator, read-only, absent-role and non-CRM authority.'
    when: >-
      Attempt activity reading, creation, correction, deletion and
      configuration.
    then: Each request follows its declared permission boundary.
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0715.spec.ts#CRM-ACC-0715
  - id: SC-CAP-CRM-ACT-019-02
    given: An administrator belongs to another customer workspace.
    when: Target this workspace’s activity and task references.
    then: >-
      Requests are rejected at the context boundary or treated as absent
      records.
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0718.spec.ts#CRM-ACC-0718
edge_cases: []
constraints: []
depends_on: []
related:
  - CAP-CRM-ACT-003
  - CAP-CRM-ACT-010
  - CAP-CRM-ACT-008
  - CAP-CRM-ACT-016
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-005, 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-005, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003]
exercised_by: [FAS-CRM-ACT-05-01, FAS-CRM-ACT-05-02, FAS-CRM-ACT-05-04, FAS-CRM-ACT-05-06]
suites: [TST-CRM-ACT-002, TST-CRM-ACT-003, TST-CRM-ACT-015, TST-CRM-ACT-025, TST-CRM-ACT-043, TST-CRM-ACT-059, TST-CRM-ACT-060, TST-CRM-ACT-062]
---

# Apply workspace access and maintenance permissions

## Purpose

Customers control who reads, records and maintains interactions and work.

## How It Works

Each API operation declares the authority needed for its action. The signed context identifies the workspace being accessed. Local storage relationships preserve that workspace boundary. Console controls reflect the user’s available actions. Service invocation has a separate trusted access boundary. External user and role references require checks beyond local foreign keys. Locks can be set through ordinary saves, but a full lock cannot be released through the supported actions. The product should replace that gap with the recorded authorized and audited lock operations. Declared bulk keys do not imply corresponding task bulk operations exist.

## Relationships

- All activity and task capabilities rely on these access boundaries.
- Platform security owns role and permission evaluation.
- Platform data jobs own supported bulk activity operations.
