---
id: STATE-ACC-REC-003
title: Reconciliation lifecycle
object: DOM-ACC-REC-003
product_area: accounting
module: reconciliation
revision: 4
status: draft
design_intent: confirmed
origin: >-
  ACCT-M8 plan D1 (reverse and redo, second approver in a closed month), D3
  (second person by default) and D7 (ledger entries at finalize), approved
  by Andrew 2026-10-22; services-accounting
  docs/reconciliation/architecture.md §14.2 and §14.3
implementation_evidence: observed
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
states:
  - name: draft
    meaning: 'Open, with no active claim, including a zero-value unclaimed draft.'
  - name: in-progress
    meaning: 'Open, with claims and a nonzero difference.'
  - name: balanced
    meaning: 'Open, with claims and an exactly zero difference.'
  - name: finalized
    meaning: 'Approved and sealed, with accounting requests retained.'
  - name: reversal-requested
    meaning: >-
      Approved, with a closed-period reversal request waiting for another
      actor.
  - name: reversed
    meaning: >-
      Correction is complete; mirror requests and released holdings are
      retained.
  - name: voided
    meaning: >-
      Preparation was abandoned and holdings released without approval
      requests.
transitions:
  - from: draft
    to: in-progress
    trigger: Select effects or add a manual effect.
    guard: >-
      The explanation is open and current; effects are compatible, unheld
      and within bounds. The resulting difference is nonzero.
    side_effects:
      - >-
        Maintain counters and activity; the resulting difference determines
        in-progress or balanced display.
    who: Authorized preparer
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/persistence/reconciliation-allocations.ts:claimSettlementItems
  - from: draft
    to: balanced
    trigger: Select settlement effects that fully explain the payout total.
    guard: >-
      Open preparation passes claim compatibility, holding and version
      checks; at least one claim remains and difference is zero.
    side_effects:
      - >-
        Maintain counters and derive balanced display without a separate
        state-write command.
    who: Authorized preparer
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/persistence/reconciliation-allocations.ts:claimSettlementItems;
      services-accounting:modules/reconciliation/services/rules/batch-status.ts:displayStatusOf
  - from: in-progress
    to: balanced
    trigger: Change holdings or payout money until the difference is zero.
    guard: The financial command satisfies its own state and version guards.
    side_effects:
      - Derive balanced display with no separate approval.
    who: Authorized contributor
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/rules/batch-status.ts:DISPLAY_STATUSES
  - from: balanced
    to: in-progress
    trigger: Change financial preparation away from zero.
    guard: The contributing command passes its own guards.
    side_effects:
      - Derive in-progress display.
    who: Authorized contributor
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/rules/batch-status.ts:DISPLAY_STATUSES
  - from: in-progress
    to: draft
    trigger: Release all claims and withdraw all manual effects.
    guard: Release and removal pass their open-state and version checks.
    side_effects:
      - Preserve released history and derive draft display.
    who: Authorized preparer
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/persistence/reconciliation-allocations.ts:releaseSettlementItems
  - from: balanced
    to: draft
    trigger: Remove all remaining preparation holdings and manual effects.
    guard: >-
      Release and removal pass their command guards and leave no active
      claims.
    side_effects:
      - >-
        Preserve released history and derive draft display even if payout
        total is zero.
    who: Authorized preparer
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/persistence/reconciliation-allocations.ts:releaseSettlementItems;
      services-accounting:modules/reconciliation/services/rules/batch-status.ts:displayStatusOf
  - from: balanced
    to: finalized
    trigger: Approve the balanced explanation.
    guard: >-
      Valid key and version, permitted finalizer, valid documented holdings,
      zero recomputed difference and required accounting setup.
    side_effects:
      - >-
        Create accounting requests; seal holdings and retain approval,
        waiver, cleared payout concerns and keyed answer.
    who: Authorized independent approver
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/batch-lifecycle/finalize-batch.ts:finalizeReconciliationBatch
  - from: draft
    to: finalized
    trigger: Approve a claim-free explanation whose payouts sum to zero.
    guard: >-
      Finalization guards pass and recomputed difference is zero, even
      though display remains draft.
    side_effects:
      - Omit an all-zero transfer; retain ordinary approval evidence.
    who: Eligible finalizer
    provenance: inferred
    source: >-
      services-accounting:modules/reconciliation/services/rules/batch-status.ts:displayStatusOf;
      services-accounting:modules/reconciliation/services/batch-lifecycle/finalize-batch.ts:finalizeReconciliationBatch
  - from: draft
    to: voided
    trigger: Abandon untouched preparation.
    guard: 'Open state, current version and cancellation reason.'
    side_effects:
      - >-
        Release holdings and withdraw draft-created manual effects without
        ledger requests.
    who: Authorized draft canceller
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/batch-lifecycle/void-batch.ts:voidReconciliationBatch
  - from: in-progress
    to: voided
    trigger: Abandon unfinished preparation.
    guard: 'Open state, current version and cancellation reason.'
    side_effects:
      - Release active holdings and withdraw manual effects.
    who: Authorized draft canceller
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/batch-lifecycle/void-batch.ts:voidReconciliationBatch
  - from: balanced
    to: voided
    trigger: Abandon balanced preparation before approval.
    guard: 'Open state, current version and cancellation reason.'
    side_effects:
      - Release active holdings and withdraw manual effects.
    who: Authorized draft canceller
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/batch-lifecycle/void-batch.ts:voidReconciliationBatch
  - from: finalized
    to: reversed
    trigger: Reverse approval in an open document period.
    guard: >-
      A valid key, current version and reason with no pending reversal;
      mirror plans have an accepting batch.
    side_effects:
      - >-
        Append mirror requests, retain reversal and release holdings after
        changing state.
    who: Authorized reversal requester
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/batch-lifecycle/reverse-batch.ts:reverseReconciliationBatch
  - from: finalized
    to: reversal-requested
    trigger: Request reversal in a closed document period.
    guard: 'A valid key, current version and reason with no pending reversal.'
    side_effects:
      - >-
        Retain the pending request without mirrors; readiness reports its
        approval gap.
    who: Authorized reversal requester
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/batch-lifecycle/reverse-batch.ts:reverseReconciliationBatch
  - from: reversal-requested
    to: reversed
    trigger: Approve the pending closed-period reversal.
    guard: >-
      A different actor uses the current version and an accepting
      operational batch.
    side_effects:
      - >-
        Append mirrors on the selected batch date with original document
        dates, then release holdings.
    who: Independent authorized reversal approver
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/batch-lifecycle/reverse-batch.ts:approveReconciliationBatchReversal
invalid:
  - from: finalized
    to: draft
    why: >-
      Approved explanations require reversal and replacement rather than
      reopening.
  - from: finalized
    to: voided
    why: Abandonment is restricted to open preparation.
  - from: in-progress
    to: finalized
    why: A nonzero recomputed difference prevents approval.
  - from: reversed
    to: finalized
    why: Reversed explanations are terminal; correction uses a new record.
  - from: voided
    to: draft
    why: Voided preparation remains terminal.
  - from: reversal-requested
    to: finalized
    why: No command withdraws a pending reversal request.
concurrency: >-
  Lifecycle completion locks its explanation and holdings, then applicable
  fiscal periods and operational batch. Keyed repeats can replay retained
  answers; audited guards retain refusals, while later storage errors can
  roll back without an attempt.
invariants:
  - INV-DOM-ACC-REC-003-02
  - INV-DOM-ACC-REC-003-03
  - INV-DOM-ACC-REC-003-04
  - INV-DOM-ACC-REC-003-06
  - INV-DOM-ACC-REC-003-07
evidence:
  - >-
    services-accounting at f47cb263:
    modules/reconciliation/services/batch-lifecycle/finalize-batch.ts,
    reverse-batch.ts, void-batch.ts, batch-commands.ts;
    services/rules/transitions.ts, batch-status.ts, segregation.ts;
    services/persistence/reconciliation-allocations.ts,
    reconciliation-batch-lifecycles.ts; db/reconciliation-batches.table.ts;
    docs/reconciliation/architecture.md §9.3, §14.2, §14.3, §24a.
---
# Reconciliation lifecycle

## The Lifecycle

```mermaid
stateDiagram-v2
  [*] --> draft : opened over payouts
  state open {
    draft --> in_progress : claim with a remaining difference
    draft --> balanced : first claims reach zero
    in_progress --> balanced : difference becomes zero
    balanced --> in_progress : difference changes
    in_progress --> draft : everything released
    balanced --> draft : all claims released
  }
  balanced --> finalized : finalize by an eligible approver
  draft --> finalized : zero payout, nothing claimed
  draft --> voided : abandon
  in_progress --> voided : abandon
  balanced --> voided : abandon
  finalized --> reversed : reverse in an open period
  finalized --> reversal_requested : reverse in a closed period
  reversal_requested --> reversed : second person approves
  reversed --> [*]
  voided --> [*]
```

## Transitions Explained

Open preparation displays draft, in-progress or balanced according to its claims and difference. The first claim can produce balance immediately, and removing every claim returns even a balanced explanation to draft. Approval, abandonment and reversal are retained decisions; a waiting reversal request appears over approved state.

## What Cannot Happen

A finalized explanation cannot reopen or be abandoned. An all-zero unclaimed draft can pass service approval despite displaying draft, while closed-period reversal requires another actor.

## Concurrency and Timing

Lifecycle completion locks its explanation and holdings, then applicable fiscal periods and operational batch. Keyed repeats can replay retained answers; audited guards retain refusals, while later storage errors can roll back without an attempt.
