---
id: CAP-ACC-REC-003
title: Verify payouts using bank evidence
feature: FEAT-ACC-REC-01
product_area: accounting
module: reconciliation
revision: 2
status: draft
product_intent: confirmed
implementation_evidence: inconsistent
supersedes:
  - react-console acceptance inventory CAP-ACC-REC-002 (verify part)
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - >-
    services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D6 (architecture §3.4 U1: bank verification only
    by evidence)
  - >-
    services-accounting:docs/reconciliation/architecture.md#14.1 Three separate facts on a payout (approved
    through ACCT-M8-plan D10 §4)
purpose: Finance staff need an independent account of whether the bank agrees with a reported payout.
outcomes:
  - Bank agreement comes from verification evidence rather than entry origin.
  - Verified accounting follows the posted bank day.
  - Disagreement remains visible as a warning.
concepts:
  - CON-ACC-REC-001
  - CON-ACC-REC-004
actors:
  - ACT-ACC-017
  - ACT-ACC-018
surfaces:
  - console
  - api
preconditions: []
postconditions: []
permissions:
  - key: accounting.payouts.verify
    where_checked: api
    scope: tenant
  - key: accounting.payouts.verify
    where_checked: console
    scope: tenant
rules:
  - id: BR-CAP-ACC-REC-003-01
    proved_by: [ATS-ACC-REC-003-01, TST-ACC-REC-025, TST-ACC-REC-057]
    statement: >-
      Verification requires bank evidence, a posted day, verified or mismatch outcome, the read version and a
      request key; the bank’s amount is optional.
    kind: validation
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/payouts.e2e.spec.js#refuses a verification without
      its evidence with 400 naming the field;
      services-accounting:modules/reconciliation/tests/e2e/payouts.e2e.spec.js#refuses a principal without
      accounting.payouts.verify with 403;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#answers
      the stored payout for the same key and request
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D6 (architecture §3.4 U1)'
  - id: BR-CAP-ACC-REC-003-02
    proved_by: [ATS-ACC-REC-003-02, ATS-ACC-REC-003-08, TST-ACC-REC-033, TST-ACC-REC-057, TST-ACC-REC-090]
    statement: >-
      Creation and correction leave bank verification unset; a verification supplies the status, verifier and
      verification time.
    kind: invariant
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/db/payouts.table.integration.spec.js#refuses
      a verified payout without who verified it and when;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#records
      the verification, the bank’s posted date becoming the accounting date, and keeps the statement as
      evidence; services-accounting:modules/reconciliation/tests/unit/rules/payout-rules.spec.js#is the bank
      posted date once the bank verified the payout;
      services-accounting:modules/reconciliation/tests/unit/rules/payout-rules.spec.js#is the reported deposit
      date while the bank evidence is a mismatch;
      services-accounting:modules/reconciliation/tests/unit/rules/payout-rules.spec.js#is the processor
      funding date when nothing was reported;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#keeps
      one evidence file when the statement is named again
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D6 (architecture §3.4 U1)'
  - id: BR-CAP-ACC-REC-003-03
    proved_by: [ATS-ACC-REC-003-02, ATS-ACC-REC-003-06, ATS-ACC-REC-003-08, TST-ACC-REC-033, TST-ACC-REC-057, TST-ACC-REC-090]
    statement: >-
      A verified payout uses the bank’s posted day for accounting, otherwise its reported day takes precedence
      over processor funding day, which can shift the payout’s period.
    kind: calculation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/unit/rules/payout-rules.spec.js#is the bank posted date
      once the bank verified the payout;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#records
      the verification, the bank’s posted date becoming the accounting date, and keeps the statement as
      evidence;
      services-accounting:modules/reconciliation/tests/integration/db/payouts.table.integration.spec.js#refuses
      a verified payout without who verified it and when;
      services-accounting:modules/reconciliation/tests/unit/rules/payout-rules.spec.js#is the reported deposit
      date while the bank evidence is a mismatch;
      services-accounting:modules/reconciliation/tests/unit/rules/payout-rules.spec.js#is the processor
      funding date when nothing was reported;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#keeps
      one evidence file when the statement is named again
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (plan approved 2026-10-22 10:40 ET; §2
      scope); journey 0594
  - id: BR-CAP-ACC-REC-003-04
    proved_by: [ATS-ACC-REC-003-02, ATS-ACC-REC-003-08, TST-ACC-REC-033, TST-ACC-REC-057, TST-ACC-REC-090]
    statement: A successful verification retains its bank evidence without duplicating an already attached statement.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#keeps
      one evidence file when the statement is named again;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#records
      the verification, the bank’s posted date becoming the accounting date, and keeps the statement as
      evidence;
      services-accounting:modules/reconciliation/tests/integration/db/payouts.table.integration.spec.js#refuses
      a verified payout without who verified it and when;
      services-accounting:modules/reconciliation/tests/unit/rules/payout-rules.spec.js#is the bank posted date
      once the bank verified the payout;
      services-accounting:modules/reconciliation/tests/unit/rules/payout-rules.spec.js#is the reported deposit
      date while the bank evidence is a mismatch;
      services-accounting:modules/reconciliation/tests/unit/rules/payout-rules.spec.js#is the processor
      funding date when nothing was reported
    origin: none
  - id: BR-CAP-ACC-REC-003-05
    proved_by: [ATS-ACC-REC-003-03, ATS-ACC-REC-003-06, ATS-ACC-REC-003-07, TST-ACC-REC-057]
    statement: >-
      Mismatch retains the reported accounting day and opens a single bank-mismatch warning, including the
      bank amount and difference when supplied; another open mismatch creates no second warning.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#says
      what the bank showed and by how much it differs, in the exception’s title and description
      (DEF-ACT-0593);
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#keeps
      the reported date as the accounting date of a mismatch and raises a bank-mismatch exception;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#raises
      no second exception for a second mismatch while the first is open;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#refuses
      a bank amount that contradicts the outcome (DEF-ACT-0593);
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#resolves
      the open mismatch when the bank’s evidence later verifies the payout
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D6 (architecture §3.4 U10: exceptions come
      from detectors with dedupe keys)
  - id: BR-CAP-ACC-REC-003-06
    proved_by: [ATS-ACC-REC-003-03, ATS-ACC-REC-003-06, ATS-ACC-REC-003-07, TST-ACC-REC-057]
    statement: Subsequent agreement with the bank closes the open mismatch warning and records the resolution.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#resolves
      the open mismatch when the bank’s evidence later verifies the payout;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#keeps
      the reported date as the accounting date of a mismatch and raises a bank-mismatch exception;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#says
      what the bank showed and by how much it differs, in the exception’s title and description
      (DEF-ACT-0593);
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#raises
      no second exception for a second mismatch while the first is open;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#refuses
      a bank amount that contradicts the outcome (DEF-ACT-0593)
    origin: none
  - id: BR-CAP-ACC-REC-003-07
    proved_by: [ATS-ACC-REC-003-03, ATS-ACC-REC-003-07, TST-ACC-REC-057]
    statement: >-
      The stated bank amount must agree with the outcome: unequal amounts cannot be verified and equal amounts
      cannot be marked mismatch.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#refuses
      a bank amount that contradicts the outcome (DEF-ACT-0593);
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#keeps
      the reported date as the accounting date of a mismatch and raises a bank-mismatch exception;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#says
      what the bank showed and by how much it differs, in the exception’s title and description
      (DEF-ACT-0593);
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#raises
      no second exception for a second mismatch while the first is open;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#resolves
      the open mismatch when the bank’s evidence later verifies the payout
    origin: none
  - id: BR-CAP-ACC-REC-003-08
    proved_by: [ATS-ACC-REC-003-04, TST-ACC-REC-057]
    statement: Verification is unavailable once a finalized reconciliation holds the payout.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#refuses
      a payout in a finalized reconciliation with payout-reconciled
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (§4: the architecture §6 invariants hold;
      INV-09)
  - id: BR-CAP-ACC-REC-003-09
    proved_by: [ATS-ACC-REC-003-01, TST-ACC-REC-025, TST-ACC-REC-057]
    statement: >-
      Only the verify permission allows bank verification, and an identical keyed retry returns the recorded
      result.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/payouts.e2e.spec.js#refuses a principal without
      accounting.payouts.verify with 403;
      services-accounting:modules/reconciliation/tests/e2e/payouts.e2e.spec.js#refuses a verification without
      its evidence with 400 naming the field;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/payouts.integration.spec.js#answers
      the stored payout for the same key and request
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (§2: permissions)'
  - id: BR-CAP-ACC-REC-003-10
    proved_by: [ATS-ACC-REC-003-05]
    statement: >-
      The console verification command omits evidence, posted day and outcome, so the live service rejects it
      without verifying the payout.
    kind: validation
    enforced_at:
      - console
      - api
    must_prove: true
    provenance: observed
    source: 'react-console:lib/accounting/reconciliation/client.ts:verifyBank'
    origin: none
scenarios:
  - id: SC-CAP-ACC-REC-003-01
    given: The reported day is September’s last day and the statement posts it on October’s first day.
    when: Verify bank agreement using the statement.
    then: The payout becomes verified and accounting moves to October.
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/payouts.e2e.spec.js#answers the payout verified,
      its accounting date the bank’s posted date
  - id: SC-CAP-ACC-REC-003-02
    given: The statement shows unequal money.
    when: Record a mismatch and the bank amount.
    then: The warning describes the bank amount and its difference from the payout.
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/payouts.e2e.spec.js#answers a mismatch and raises a
      bank-mismatch exception about the payout
edge_cases: []
constraints: []
depends_on:
  - CAP-ACC-REC-001
related:
  - CAP-ACC-REC-015
  - CAP-ACC-REC-018
journeys:
  - JNY-ACC-REC-002
open_questions: []
evidence:
  - >-
    Examined supporting service material: payouts.routes.ts (verifyPayoutBank), payouts.schemas.ts
    (verifyPayoutBankRequestSchema), services/persistence/payouts.ts (verify region),
    bank-mismatch-exceptions.ts, services/rules/payout-rules.ts (accounting date); tests
    e2e/payouts.e2e.spec.js, integration payouts.integration.spec.js, unit/rules/payout-rules.spec.js,
    unit/exceptions/exception-titles.spec.js.
  - >-
    Examined supporting console material: lib/accounting/reconciliation/client.ts (payouts.verifyBank),
    store.tsx (verifyBank), client.test.ts, components/accounting/reconciliation/workspace/workspace.tsx (Mark
    Bank Verified); e2e/mock/accounting-reconciliation.mock.spec.ts; acceptance journey ACT-ACC-0594.
controls: [TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, 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-LOG-004, TC-PI-001, TC-PI-002, TC-PI-005]
exercised_by: [FAS-ACC-REC-01-01, FAS-ACC-REC-01-04, FAS-ACC-REC-01-05]
suites: [TST-ACC-REC-025, TST-ACC-REC-033, TST-ACC-REC-057, TST-ACC-REC-090]
---

# Verify payouts using bank evidence

## Purpose

Finance staff need an independent account of whether the bank agrees with a reported payout.

## How It Works

A preparer supplies the statement evidence and bank-posted day to the service. Rhythm records agreement or creates an investigation warning for disagreement. Agreement can change which accounting period contains the payout. Finalization protects that bank context from subsequent verification. The current console sends insufficient information, so its button cannot complete the live workflow.

## Relationships

Payout creation supplies the reported movement, exceptions retain disagreements and readiness uses the resulting bank standing.
