---
id: ATS-PFM-OPS-010
scope: CAP-PFM-OPS-010
product_area: platform
module: operations
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  macroservice-libraries: 54536a441935c6e09fdb7f96f0bec71c52ba4e03
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-PFM-OPS-010-01
    title: Enforce the event vocabulary
    level: api
    proves:
      - BR-CAP-PFM-OPS-010-01
    preconditions: An inserted row uses an undeclared event type.
    steps: Write it through the application database role.
    expected: The event-type constraint refuses the row.
    negative: true
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to:
      - TST-PFM-OPS-057
    provenance: test
    source: >-
      services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
      an event type the store does not hold, by audit_events_event_type_check
    evidence_candidates:
      - >-
        services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
        an event type the store does not hold, by audit_events_event_type_check
    category: validation
    binding_evidence:
      - >-
        services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
        an event type the store does not hold, by audit_events_event_type_check
  - id: ATS-PFM-OPS-010-02
    title: Keep metadata specific and bounded
    level: api
    proves:
      - BR-CAP-PFM-OPS-010-02
    preconditions: A merge uses a view key and an intervention embeds its explanation.
    steps: Insert both rows.
    expected: The event-specific metadata checks reject them.
    negative: true
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to:
      - TST-PFM-OPS-057
    provenance: test
    source: >-
      services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
      an intervention that carries its reason inline: the reason lives in Commerce’s intervention_log row
    evidence_candidates:
      - >-
        services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
        an intervention that carries its reason inline: the reason lives in Commerce’s intervention_log
        row
    category: boundary
    binding_evidence:
      - >-
        services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
        an intervention that carries its reason inline: the reason lives in Commerce’s intervention_log
        row
  - id: ATS-PFM-OPS-010-03
    title: Prevent application rewriting of history
    level: api
    proves:
      - BR-CAP-PFM-OPS-010-03
      - INV-DOM-PFM-OPS-002-01
    preconditions: An activity entry already exists.
    steps: Attempt update and delete with application authority.
    expected: Both operations fail and the stored entry remains intact.
    negative: true
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to:
      - TST-PFM-OPS-057
    provenance: test
    source: >-
      services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
      an UPDATE of the event by the application role, so a trail cannot be rewritten
    evidence_candidates:
      - >-
        services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
        an UPDATE of the event by the application role, so a trail cannot be rewritten
    category: invariant
    binding_evidence:
      - >-
        services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
        an UPDATE of the event by the application role, so a trail cannot be rewritten
  - id: ATS-PFM-OPS-010-04
    title: Enforce workspace boundaries
    level: api
    proves:
      - BR-CAP-PFM-OPS-010-04
      - INV-DOM-PFM-OPS-002-02
    preconditions: Events exist in separate workspaces.
    steps: Read across the boundary and attempt a foreign-workspace insert.
    expected: Foreign rows remain invisible and the insert is refused.
    negative: true
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to:
      - TST-PFM-OPS-057
    provenance: test
    source: >-
      services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
      a row written for another tenant from this tenant’s session, by the policy’s WITH CHECK
    evidence_candidates:
      - >-
        services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
        a row written for another tenant from this tenant’s session, by the policy’s WITH CHECK
    category: boundary
    binding_evidence:
      - >-
        services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
        a row written for another tenant from this tenant’s session, by the policy’s WITH CHECK
  - id: ATS-PFM-OPS-010-05
    title: Keep deterministic ordering and timestamp precision
    level: api
    proves:
      - BR-CAP-PFM-OPS-010-05
    preconditions: Time-based generated identities and timestamp checks are enabled.
    steps: Inspect ordering behavior and insert a submillisecond timestamp.
    expected: Timestamp and identity provide a total order and excessive precision is refused.
    negative: true
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to:
      - TST-PFM-OPS-057
    provenance: test
    source: >-
      services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
      an instant finer than a millisecond, by audit_events_occurred_at_precision_check
    evidence_candidates:
      - >-
        services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
        an instant finer than a millisecond, by audit_events_occurred_at_precision_check
    category: boundary
    binding_evidence:
      - >-
        services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
        an instant finer than a millisecond, by audit_events_occurred_at_precision_check
  - id: ATS-PFM-OPS-010-06
    title: Join event writing to the business transaction
    level: api
    proves:
      - BR-CAP-PFM-OPS-010-06
    preconditions: An owning mutation and eligibility event share a transaction.
    steps: Commit a valid mutation and roll back a failing one.
    expected: Only the committed mutation retains its attributed event.
    negative: false
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to: []
    provenance: proposed
    source: 'services-platform:modules/audit/services/persistence/audit-events.ts:recordEligibilityChange'
    evidence_candidates:
      - >-
        services-platform:modules/audit/tests/integration/services/persistence/audit-events.integration.spec.js#answers
        the event whole, the actor the execution’s caller and the occurrence key minted for it
    category: rule
  - id: ATS-PFM-OPS-010-07
    title: Record merge participants without repeat entries
    level: api
    proves:
      - BR-CAP-PFM-OPS-010-07
    preconditions: A survivor absorbs two contact records.
    steps: Apply the merge twice.
    expected: Each participant has one event and repetition adds none.
    negative: false
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to:
      - TST-PFM-OPS-120
    provenance: test
    source: >-
      services-platform:tests/integration/db/merge-participant.integration.spec.ts#writes one row for the
      survivor and one for each record merged away
    evidence_candidates:
      - >-
        services-platform:tests/integration/db/merge-participant.integration.spec.ts#writes one row for
        the survivor and one for each record merged away
    category: rule
    binding_evidence:
      - >-
        services-platform:tests/integration/db/merge-participant.integration.spec.ts#writes one row for
        the survivor and one for each record merged away
  - id: ATS-PFM-OPS-010-08
    title: Restrict event removal to retirement
    level: api
    proves:
      - BR-CAP-PFM-OPS-010-08
    preconditions: One workspace is deleting and another is not.
    steps: Invoke the batched event purge for each.
    expected: The deleting workspace empties by batches and the other is refused.
    negative: true
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to:
      - TST-PFM-OPS-058
    provenance: test
    source: >-
      services-platform:modules/audit/tests/integration/services/persistence/audit-events.integration.spec.js#is
      refused by the database, so the purger is never a delete-by-tenant tool
    evidence_candidates:
      - >-
        services-platform:modules/audit/tests/integration/services/persistence/audit-events.integration.spec.js#is
        refused by the database, so the purger is never a delete-by-tenant tool
    category: transition
    binding_evidence:
      - >-
        services-platform:modules/audit/tests/integration/services/persistence/audit-events.integration.spec.js#is
        refused by the database, so the purger is never a delete-by-tenant tool
  - id: ATS-PFM-OPS-010-09
    title: Limit the query role to reading
    level: api
    proves:
      - BR-CAP-PFM-OPS-010-09
      - INV-DOM-PFM-OPS-002-09
    preconditions: The configured query-reader role is active in a workspace.
    steps: Read activity and attempt insertion.
    expected: Local reads succeed and writes are refused.
    negative: true
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to:
      - TST-PFM-OPS-057
    provenance: test
    source: >-
      services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
      an INSERT by that role, because the grant is SELECT and nothing else
    evidence_candidates:
      - >-
        services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
        an INSERT by that role, because the grant is SELECT and nothing else
    category: permission
    binding_evidence:
      - >-
        services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
        an INSERT by that role, because the grant is SELECT and nothing else
  - id: ATS-PFM-OPS-010-10
    title: Write a visit into the protected activity trail
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-OPS-008-04
      - BR-CAP-PFM-OPS-010-03
    exercises:
      - CAP-PFM-OPS-010
      - CAP-PFM-OPS-008
    preconditions: A person opens a readable record using verified execution context.
    steps: >-
      Report the visit, attempt to rewrite its stored activity with ordinary application privileges, and
      read the retained event.
    expected: The retained event identifies the original visit and caller despite the refused rewrite.
    negative: false
    data_needs: Isolated workspace records and caller contexts for both sides of the interaction.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/audit/tests/unit/aws/api/audit-api-mapper.spec.ts#refuses a body naming
      the actor, which is how a trail would be written in somebody else’s name;
      services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
      an UPDATE of the event by the application role, so a trail cannot be rewritten; CAP-PFM-OPS-008;
      WF-PFM-OPS-008; WF-PFM-OPS-009
  - id: ATS-PFM-OPS-010-11
    title: Retain history after its target disappears
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-OPS-009-02
      - BR-CAP-PFM-OPS-010-03
    exercises:
      - CAP-PFM-OPS-010
      - CAP-PFM-OPS-009
    preconditions: A person has a stored visit and the target record is subsequently removed.
    steps: Read that person’s raw history and compare it with currently resolvable recent records.
    expected: The visit remains in raw history even when the target cannot appear in a current record list.
    negative: false
    data_needs: Isolated workspace records and caller contexts for both sides of the interaction.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/audit/tests/integration/services/record-views/view-history.integration.spec.js#still
      holds the view after the contact is gone, because a trail is not a list of records;
      services-platform:modules/audit/tests/integration/db/audit-events.table.integration.spec.js#refuses
      an UPDATE of the event by the application role, so a trail cannot be rewritten; CAP-PFM-OPS-009;
      WF-PFM-OPS-008; WF-PFM-OPS-009
  - id: ATS-PFM-OPS-010-12
    title: Relate a change to its security history
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-OPS-010-06
    exercises:
      - CAP-PFM-OPS-010
      - CAP-PFM-SEC-011
    preconditions: Staff make a reasoned change and later security-history insertion can fail.
    steps: Complete one change and repeat with failure injected after the decision commits.
    expected: >-
      The successful flow has attributable history; the later failure leaves the committed decision
      visible for investigation.
    negative: false
    data_needs: Isolated workspace records and caller contexts for both sides of the interaction.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/audit/services/persistence/audit-events.ts:recordEligibilityChange;
      CAP-PFM-SEC-011; WF-PFM-OPS-008; WF-PFM-OPS-009
  - id: ATS-PFM-OPS-010-13
    title: Expose partial purge without claiming activity removal
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-OPS-010-08
    exercises:
      - CAP-PFM-OPS-001
      - CAP-PFM-OPS-010
      - CAP-PFM-OPS-012
      - CAP-PFM-OPS-015
    workflows:
      - WF-PFM-OPS-009
    preconditions: An operational purge reaches the protected activity stage with a workspace that is not deleting.
    steps: 'Attempt that stage, record its refusal and inspect participant inventories independently.'
    expected: >-
      Activity remains intact after the refusal; progress in another participant does not imply
      successful activity removal.
    negative: true
    data_needs: >-
      Isolated workspace and run-owned lifecycle records, with a second linked workspace where shared
      company evidence is checked.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/jobs/services/persistence/tenant-purges.ts:JOB_PURGE_RESOURCES;
      services-platform:modules/audit/tests/integration/services/persistence/audit-events.integration.spec.js#is
      refused by the database, so the purger is never a delete-by-tenant tool;
      services-platform:modules/licensing/services/maintenance/tenant-participant.ts:licensingParticipant
evidence:
  - >-
    Pinned capability rules, object invariants, state transitions and workflows are reviewed for testing
    obligations.
  - >-
    Executable bindings refer only to existing suites; no module executable suite runs during this
    documentation job.
coverage:
  rule: covered
  transition: covered
  validation: covered
  permission: covered
  edge: 'gap: FND-PFM-OPS-062'
  failure: 'gap: FND-PFM-OPS-062'
  boundary: covered
  concurrency: 'gap: FND-PFM-OPS-062'
  invariant: covered
  interaction: covered
coverage_notes:
  edge: 'Empty, missing and unusual inputs need dedicated proof.'
  failure: Injected dependency failures need dedicated proof.
  concurrency: >-
    No controlled overlapping execution proves the capability’s read or write behavior while related
    state changes.
related_capabilities:
  - CAP-PFM-OPS-008
  - CAP-PFM-OPS-009
  - CAP-PFM-SEC-011
workflow_interactions:
  - WF-PFM-OPS-008
  - WF-PFM-OPS-009
coverage_obligations:
  finding: FND-PFM-OPS-062
  uncovered_must_prove: []
  object_invariants_requiring_explicit_trace:
    - INV-DOM-PFM-OPS-002-03
    - INV-DOM-PFM-OPS-002-04
    - INV-DOM-PFM-OPS-002-05
    - INV-DOM-PFM-OPS-002-06
    - INV-DOM-PFM-OPS-002-07
    - INV-DOM-PFM-OPS-002-08
  related_scenarios:
    - capabilities:
        - CAP-PFM-OPS-010
        - CAP-PFM-OPS-008
      scenario: ATS-PFM-OPS-010-10
    - capabilities:
        - CAP-PFM-OPS-010
        - CAP-PFM-OPS-009
      scenario: ATS-PFM-OPS-010-11
    - capabilities:
        - CAP-PFM-OPS-010
        - CAP-PFM-SEC-011
      scenario: ATS-PFM-OPS-010-12
  unbound_scenarios:
    - ATS-PFM-OPS-010-06
    - ATS-PFM-OPS-010-10
    - ATS-PFM-OPS-010-11
    - ATS-PFM-OPS-010-12
    - ATS-PFM-OPS-010-13
  transition_review: []
  permission_review: []
  gap_detail: >-
    Unattributed mutation events, rollback with the owning business change and simultaneous duplicate
    writes need complete proof at the activity boundary.
workflow_scenarios:
  WF-PFM-OPS-008:
    - ATS-PFM-OPS-008-13
  WF-PFM-OPS-009:
    - ATS-PFM-OPS-001-17
    - ATS-PFM-OPS-010-13
    - ATS-PFM-OPS-012-19
    - ATS-PFM-OPS-015-15
---

# Preserve a shared record-activity trail: Capability Test Specification

## Coverage

The category map distinguishes authored scenarios from unresolved proof obligations. A bound scenario names an existing executable suite; its recorded result remains unrun.

| Rule | Proof status |
|---|---|
| `BR-CAP-PFM-OPS-010-01` | `ATS-PFM-OPS-010-01` |
| `BR-CAP-PFM-OPS-010-02` | `ATS-PFM-OPS-010-02` |
| `BR-CAP-PFM-OPS-010-03` | `ATS-PFM-OPS-010-03`, `ATS-PFM-OPS-010-10`, `ATS-PFM-OPS-010-11` |
| `BR-CAP-PFM-OPS-010-04` | `ATS-PFM-OPS-010-04` |
| `BR-CAP-PFM-OPS-010-05` | `ATS-PFM-OPS-010-05` |
| `BR-CAP-PFM-OPS-010-06` | `ATS-PFM-OPS-010-06`, `ATS-PFM-OPS-010-12` |
| `BR-CAP-PFM-OPS-010-07` | `ATS-PFM-OPS-010-07` |
| `BR-CAP-PFM-OPS-010-08` | `ATS-PFM-OPS-010-08` |
| `BR-CAP-PFM-OPS-010-09` | `ATS-PFM-OPS-010-09` |

## Interactions With Related Capabilities

Write a visit into the protected activity trail. The retained event identifies the original visit and caller despite the refused rewrite.

Retain history after its target disappears. The visit remains in raw history even when the target cannot appear in a current record list.

Relate a change to its security history. The successful flow has attributable history; the later failure leaves the committed decision visible for investigation.

Expose partial purge without claiming activity removal. Activity remains intact after the refusal; progress in another participant does not imply successful activity removal.

## Evidence and Boundaries

Pinned assertion sources support the listed executable bindings. Proposed cases retain the proof required beyond those boundaries. Structured obligations name incomplete object, transition and permission trace; row-level concurrency proof does not establish complete workflow serialization.
