---
id: STATE-ACC-REC-001
title: Payout reconciliation standing
object: DOM-ACC-REC-001
product_area: accounting
module: reconciliation
revision: 3
status: draft
design_intent: confirmed
origin: >-
  ACCT-M8 plan D1 (reverse and redo) and D10, approved by Andrew 2026-10-22;
  services-accounting docs/reconciliation/architecture.md §14.1 (three separate
  facts on a payout)
implementation_evidence: observed
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
states:
  - name: unreconciled
    meaning: A live payout has no active explanation.
  - name: in-reconciliation
    meaning: An open explanation currently holds the payout.
  - name: reconciled
    meaning: >-
      An approved explanation holds the payout and protects its money and
      evidence.
  - name: voided
    meaning: Cancellation retains the entry and releases its live processor reference.
transitions:
  - from: unreconciled
    to: in-reconciliation
    trigger: Create an explanation over this payout.
    guard: >-
      The payout is live, unheld and financially compatible with the other
      payouts; the creation key is valid.
    side_effects:
      - Add the holding and payout total; retain creator and creation activity.
    who: Authorized preparer
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/persistence/reconciliation-workspaces.ts:createReconciliationBatch
  - from: in-reconciliation
    to: reconciled
    trigger: Approve the holding explanation.
    guard: The explanation meets its finalization guards.
    side_effects:
      - >-
        Protect payout money, dates and evidence; clear qualifying
        unbalanced-payout concerns.
    who: Eligible finalizer
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/batch-lifecycle/finalize-batch.ts:finalizeReconciliationBatch
  - from: in-reconciliation
    to: unreconciled
    trigger: Abandon the holding draft.
    guard: >-
      The draft is open at the expected version and the request includes a
      reason.
    side_effects:
      - Retain a release reason on the holding.
    who: Authorized draft canceller
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/batch-lifecycle/void-batch.ts:voidReconciliationBatch
  - from: reconciled
    to: unreconciled
    trigger: Complete reversal of the approved holder.
    guard: >-
      Open-period reversal succeeds, or a closed-period request receives
      independent approval.
    side_effects:
      - Release the holding and retain mirrored requests.
    who: Authorized reversal actors
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/batch-lifecycle/reverse-batch.ts:reverseReconciliationBatch
  - from: unreconciled
    to: voided
    trigger: Cancel an unheld entry.
    guard: 'No holder exists; reason, key and current version are provided.'
    side_effects:
      - >-
        Retain cancellation actor and time; free the processor reference and
        write activity.
    who: Authorized payout canceller
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/persistence/payouts.ts:voidPayout
invalid:
  - from: in-reconciliation
    to: voided
    why: Cancel preparation before voiding a held payout.
  - from: reconciled
    to: voided
    why: Reverse the approved explanation before cancelling its payout.
  - from: reconciled
    to: in-reconciliation
    why: A second holder is refused while the approved holding remains active.
  - from: voided
    to: in-reconciliation
    why: >-
      Cancellation excludes linking, correction, verification and evidence
      changes.
  - from: voided
    to: unreconciled
    why: There is no payout-reactivation command; record a replacement entry.
concurrency: >-
  Lifecycle locks cover the explanation and relevant holdings; payout commands
  lock the existing holder before the payout. Expected-version checks apply only
  to commands that accept one, and the active-link index prevents competing
  holders.
invariants:
  - INV-DOM-ACC-REC-001-04
  - INV-DOM-ACC-REC-001-05
  - INV-DOM-ACC-REC-001-07
evidence:
  - >-
    services-accounting at f47cb263:
    modules/reconciliation/services/persistence/payouts.ts,
    reconciliation-workspaces.ts, reconciliation-batch-lifecycles.ts;
    services/rules/payout-rules.ts; db/payouts.table.ts,
    reconciliation-batch-links.table.ts; docs/reconciliation/architecture.md
    §14.1.
---
# Payout reconciliation standing

## The Lifecycle

```mermaid
stateDiagram-v2
  [*] --> unreconciled : recorded
  unreconciled --> in_reconciliation : reconciliation opened
  in_reconciliation --> unreconciled : draft abandoned
  in_reconciliation --> reconciled : finalized
  reconciled --> unreconciled : reversal completed
  unreconciled --> voided : voided with a reason
  voided --> [*]
```

## Transitions Explained

Payout standing follows its active explanation. Creation takes the holding, approval seals financial facts, and abandonment or reversal releases the holding while preserving history.

## What Cannot Happen

Held payouts cannot be voided, and approved holdings prevent financial edits. Bank outcome remains a separate lifecycle.

## Concurrency and Timing

Lifecycle locks cover the explanation and relevant holdings; payout commands lock the existing holder before the payout. Expected-version checks apply only to commands that accept one, and the active-link index prevents competing holders.
