---
id: WF-ACC-TRX-015
title: Capture and publish the month-end aging snapshot
trigger: >-
  Scheduled planning discovers closed months, while operators can request new
  historical capture versions through HQ.
product_area: accounting
module: transactions
revision: 1
status: draft
design_intent: confirmed
origin: >-
  The snapshot architecture approved by Andrew on 2026-10-15,
  services-accounting:docs/snapshots/ar-aging.md#The A/R Aging Snapshot
  (`accounting.ar_aging`)
implementation_evidence: observed
inference: []
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
  - CAP-ACC-TRX-018
moves:
  - STATE-ACC-TRX-013
crosses:
  - SVC-ACC-TRX-transactions
hops:
  - 'n': 1
    actor_or_service: Snapshot planner
    action: >-
      Schedule the first monthly capture after the two-hour grace period with
      exclusive month end as knowledge cutoff, then request dispatch.
    anchor: >-
      services-accounting:modules/transactions/aws/logic/snapshot-functions.lambda.ts:snapshotPlannerFunction
    seam: schedule
    on_failure: Log a missed nudge and rely on scheduled dispatch.
    left_inconsistent: 'The admitted work may wait until scheduled dispatch, subject to capacity.'
    observer: Planning diagnostics record scheduling failures.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/aws/logic/snapshot-functions.lambda.ts:snapshotPlannerFunction;
      services-accounting:modules/transactions/tests/integration/services/runs/ar-aging-pipeline.integration.spec.js#it
      plans nothing twice: a second pass creates no run, and the ledger holds
      one run per tenant
  - 'n': 2
    actor_or_service: Snapshot dispatcher
    action: >-
      Admit planned runs within overall and backfill capacity and start their
      named state-machine executions.
    anchor: >-
      services-accounting:modules/transactions/aws/logic/snapshot-functions.lambda.ts:snapshotDispatcherFunction
    seam: schedule
    on_failure: Retain planned status until dispatch can admit the run.
    left_inconsistent: Capacity limits delay admission.
    observer: The overdue-work alarm exposes delayed capture.
    provenance: documented
    source: 'services-accounting:docs/snapshots/ar-aging.md#Operating it'
  - 'n': 3
    actor_or_service: Snapshot run state machine
    action: >-
      Capture cutoff-aware open items and totals, validate them and publish the
      result using atomic capture or keyset chunks.
    anchor: >-
      services-accounting:modules/transactions/services/runs/snapshot-run-workflow.ts
    seam: state_machine
    on_failure: >-
      Single-transaction failure undoes capture and preserves current
      publication; retries use fifteen-minute, one-hour and four-hour delays,
      with chunk cleanup still unproved.
    left_inconsistent: >-
      The read surface exposes the latest capture state while publication is
      unavailable.
    observer: Run-failure and execution alarms expose unsuccessful capture.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/runs/snapshot-run-workflow.ts;
      services-accounting:modules/transactions/tests/integration/services/runs/ar-aging-pipeline.integration.spec.js#it
      leaves none of the failed run’s rows behind: its transaction rolled back
  - 'n': 4
    actor_or_service: Platform HQ snapshot APIs
    action: >-
      Process an operator rerun or backfill as a new version that supersedes the
      old publication only after success.
    anchor: 'services-accounting:docs/snapshots/ar-aging.md#Operating it'
    seam: sync
    on_failure: Reject overlapping active runs and allow a later request.
    left_inconsistent: No partial change remains at this hop.
    observer: Operators inspect the request through HQ.
    provenance: observed
    source: >-
      services-accounting:docs/snapshots/ar-aging.md#Operating it;
      services-accounting:modules/transactions/tests/integration/services/runs/ar-aging-pipeline.integration.spec.js#it
      keeps version 1’s rows as they were captured, readable by its run
idempotency: >-
  The ledger identifies a workspace, month and version; scheduled planning does
  not duplicate its initial version and retry stays within its existing run.
concurrency: >-
  One active capture is permitted per workspace and month, and paging remains
  tied to its published version.
branches:
  - >-
    Period-close reconstruction and final-capture requests are planned but not
    implemented.
waits:
  - >-
    Initial capture waits until two hours after month end in the workspace
    calendar.
evidence:
  - >-
    services-accounting at f47cb263: docs/snapshots/ar-aging.md;
    services/runs/snapshot-run-workflow.ts, nudge-dispatcher.ts;
    aws/snapshots.module.ts, snapshots.configuration.ts;
    logic/snapshot-functions.lambda.ts, snapshot-run.step-function.ts.
controls: [TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-DAT-001, TC-LOG-004, TC-LOG-005, TC-AVL-001, TC-AVL-004, TC-MON-001, TC-MON-002, TC-MON-004, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005]
---
# Capture and publish the month-end aging snapshot

## What It Does

Historical aging uses durable planning and publication around a fixed knowledge cutoff. Failed attempts preserve current publication; single-transaction rollback does not prove chunk cleanup.

## The Flow

```mermaid
flowchart TD
  h0["Snapshot planner"]
  h1["Snapshot dispatcher"]
  h0 --> h1
  h2["Snapshot run state machine"]
  h1 --> h2
  h3["Platform HQ snapshot APIs"]
  h2 --> h3
```

The numbered hops identify the participating services, synchronization boundary and evidence. Branch conditions in the frontmatter explain where preparation, completion and recovery diverge.

## When Something Fails

Each hop records its rollback, retry or compensation boundary and the result visible to callers or operators. External outcomes can remain unresolved after local preparation commits; the listed recovery behavior defines what remains pending.

## Open Design Questions

Establish chunk-failure cleanup and recovery of a lost execution before depending on automatic historical capture recovery.
