---
id: CAP-PFM-OPS-010
title: Preserve a shared record-activity trail
feature: FEAT-PFM-OPS-02
product_area: platform
module: operations
revision: 1
status: draft
product_intent: confirmed
implementation_evidence: observed
supersedes: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
intent_sources:
  - 'services-platform:docs/audit-events.md#2026-10-12 — Final acceptance (the shared append-only store)'
  - 'services-platform:docs/audit-events.md#The merge event (decision D8, 2026-10-12)'
purpose: Keep bounded descriptions of record activity for shared history and downstream queries.
outcomes:
  - Shared writers can join the owning change transaction.
  - Application authority cannot rewrite retained activity.
  - Typed metadata excludes free-text explanations and record contents.
concepts:
  - CON-PFM-OPS-002
actors:
  - ACT-PFM-006
surfaces:
  - job
  - api
preconditions:
  - The event type and metadata vocabulary are declared in both the writer and database checks.
postconditions:
  - The stored entry remains until workspace purge under the current retention policy.
permissions: []
rules:
  - id: BR-CAP-PFM-OPS-010-01
    proved_by: [ATS-PFM-OPS-010-01, TST-PFM-OPS-057]
    statement: >-
      The database permits declared view, merge, intervention, eligibility, custom-record and attention events
      and rejects undeclared event types.
    kind: validation
    enforced_at:
      - service
      - database
    must_prove: true
    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
    origin: none
  - id: BR-CAP-PFM-OPS-010-02
    proved_by: [ATS-PFM-OPS-010-02, TST-PFM-OPS-057]
    statement: >-
      Each event type has its own metadata allow list and a one-kilobyte limit, preventing inline reasons,
      expressions and keys belonging to other types.
    kind: validation
    enforced_at:
      - service
      - database
    must_prove: true
    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
    origin: none
  - id: BR-CAP-PFM-OPS-010-03
    proved_by: [ATS-PFM-OPS-008-13, ATS-PFM-OPS-009-07, ATS-PFM-OPS-010-03, ATS-PFM-OPS-010-10, ATS-PFM-OPS-010-11, TST-PFM-OPS-057]
    statement: The application database role cannot update or delete stored activity events.
    kind: invariant
    enforced_at:
      - database
    must_prove: true
    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
    origin: 'services-platform:docs/audit-events.md#Append-only'
  - id: BR-CAP-PFM-OPS-010-04
    proved_by: [ATS-PFM-OPS-010-04, TST-PFM-OPS-057]
    statement: >-
      Workspace row policies prevent reading another workspace’s events or inserting an event for that other
      workspace.
    kind: invariant
    enforced_at:
      - database
    must_prove: true
    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
    origin: none
  - id: BR-CAP-PFM-OPS-010-05
    proved_by: [ATS-PFM-OPS-010-05, TST-PFM-OPS-057]
    statement: >-
      Database-generated time-based event identities break ties between millisecond timestamps to provide
      stable history ordering.
    kind: invariant
    enforced_at:
      - database
    must_prove: true
    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
    origin: none
  - id: BR-CAP-PFM-OPS-010-06
    proved_by: [ATS-PFM-OPS-010-06, ATS-PFM-OPS-010-12]
    statement: >-
      Mutation-event writers participate in an existing caller transaction, and business-change atomicity
      requires the owning caller to invoke them within that transaction.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: 'services-platform:modules/audit/services/persistence/audit-events.ts:recordEligibilityChange'
    origin: none
  - id: BR-CAP-PFM-OPS-010-07
    proved_by: [ATS-PFM-OPS-010-07, TST-PFM-OPS-120]
    statement: >-
      A merge records its survivor and each absorbed record within the merge transaction, avoids duplicate
      lines on repeat application and refuses unattributed execution.
    kind: policy
    enforced_at:
      - database
    must_prove: true
    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
    origin: 'services-platform:docs/audit-events.md#The merge event (decision D8, 2026-10-12)'
  - id: BR-CAP-PFM-OPS-010-08
    proved_by: [ATS-PFM-OPS-010-08, ATS-PFM-OPS-010-13, TST-PFM-OPS-058]
    statement: >-
      Activity events are removed only through workspace purge, which deletes bounded batches and refuses
      workspaces outside deletion.
    kind: lifecycle
    enforced_at:
      - database
    must_prove: true
    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
    origin: none
  - id: BR-CAP-PFM-OPS-010-09
    proved_by: [ATS-PFM-OPS-010-09, TST-PFM-OPS-057]
    statement: >-
      The query-reader role receives only read authority for activity events and remains subject to workspace
      isolation.
    kind: permission
    enforced_at:
      - database
    must_prove: true
    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
    origin: none
  - id: BR-CAP-PFM-OPS-010-10
    proved_by: []
    statement: >-
      The product should decide activity retention before high-volume use; the current decision leaves
      retention unresolved.
    kind: lifecycle
    enforced_at:
      - database
    must_prove: false
    provenance: unknown
    source: OQ-PFM-OPS-001
    origin: 'services-platform:docs/audit-events.md#2026-10-12 — Final acceptance (Andrew: decide later)'
scenarios:
  - id: SC-CAP-PFM-OPS-010-01
    given: An owning operation supplies an eligibility-change event.
    when: The shared writer records the event under its execution context.
    then: 'The event identifies the actor, definition, action and supplied version metadata.'
    provenance: inferred
    source: >-
      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
    note: >-
      This illustrative example combines behavior established by the cited test and the capability’s
      implementation evidence; it is not an independently bound end-to-end proof.
  - id: SC-CAP-PFM-OPS-010-02
    given: The workspace remains outside deletion.
    when: A caller invokes the restricted event purge.
    then: The database rejects the purge and retains the events.
    provenance: inferred
    source: >-
      services-platform:modules/audit/tests/integration/services/persistence/audit-events.integration.spec.js#leaves
      the event standing
    note: >-
      This illustrative example combines behavior established by the cited test and the capability’s
      implementation evidence; it is not an independently bound end-to-end proof.
edge_cases: []
constraints:
  - 'Activity events remain separate from security history for access, role and licence decisions.'
depends_on: []
related:
  - CAP-PFM-OPS-008
  - CAP-PFM-OPS-009
  - CAP-PFM-SEC-011
journeys: []
open_questions:
  - OQ-PFM-OPS-001
evidence:
  - >-
    services-platform at ad3f6a6: modules/audit/db/audit-events.table.ts, services/persistence/audit-events.ts
    (recordEligibilityChange, recordCustomRecordChange, recordAttentionStateChange, recordAttentionEscalation,
    purgeTenantAuditEvents), services/lifecycle/tenant-participant.ts; audit-events table and persistence
    integration suites; docs/audit-events.md (all event-type sections, Append-only, Tenant deletion,
    Retention).
  - 'services-platform at ad3f6a6, tables named by this capability: audit-events.table.ts.'
  - >-
    Examination: proposed acceptance matrices retain candidate test references; incomplete proof is recorded
    by FND-PFM-OPS-028.
controls: [TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-003, TC-PI-005, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-VEN-001, TC-VEN-002, TC-VEN-003]
exercised_by: [FAS-PFM-OPS-02-01, FAS-PFM-OPS-02-02, FAS-PFM-OPS-02-03, FAS-PFM-OPS-02-04, FAS-PFM-OPS-02-05]
suites: [TST-PFM-OPS-057, TST-PFM-OPS-058, TST-PFM-OPS-120]
---

# Preserve a shared record-activity trail

## Purpose

Keep bounded descriptions of record activity for shared history and downstream queries.

## How It Works

Owning modules append short activity entries through shared writers. Event types determine the metadata vocabulary that each entry may carry. The database protects workspace isolation and prevents the application role from rewriting existing entries. Mutation writers can join the caller’s transaction so a change and its event commit together. That guarantee still depends on the owning module using the shared writer within its change transaction. Reads for view history select only visits, while other event types remain available as stored activity. Workspace retirement removes entries through a restricted batched purge. The product should settle retention before event volume makes indefinite storage a practical constraint.

## Relationships

Record owners establish the activity, and authorized queries use visits to support recent work without replacing raw history.
