---
id: CAP-ACC-REC-015
title: Investigate and resolve reconciliation concerns
feature: FEAT-ACC-REC-05
product_area: accounting
module: reconciliation
revision: 2
status: draft
product_intent: confirmed
implementation_evidence: observed
supersedes:
  - 'react-console acceptance inventory CAP-ACC-REC-010 (raise, work and resolve)'
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D6 (architecture §3.4 U10)'
  - >-
    services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D9 (attention items for the holders of the
    reconciliation responsibility)
  - >-
    services-accounting:docs/milestones/ACCT-M8-payout-reconciliation.md#Built (WP-B4: as_of on exception
    resolve)
purpose: Finance staff need a continuing record of a problem and the work used to explain it.
outcomes:
  - Repeated detection does not duplicate an active concern.
  - Missing settlement cannot receive an unsupported resolution.
  - Responsibility holders receive required blocker attention.
concepts:
  - CON-ACC-REC-004
actors:
  - ACT-ACC-017
  - ACT-ACC-018
  - ACT-ACC-007
  - ACT-ACC-011
surfaces:
  - console
  - api
preconditions: []
postconditions: []
permissions:
  - key: accounting.reconciliation-exceptions.read
    where_checked: api
    scope: tenant
  - key: accounting.reconciliation-exceptions.update
    where_checked: api
    scope: tenant
  - key: accounting.reconciliation-exceptions.update
    where_checked: console
    scope: tenant
rules:
  - id: BR-CAP-ACC-REC-015-01
    proved_by: [ATS-ACC-REC-015-01, ATS-ACC-REC-015-13, TST-ACC-REC-024, TST-ACC-REC-042, TST-ACC-REC-066]
    statement: >-
      A manual problem records its unit, blocker or warning severity, title, description and one to fifty
      local subjects, optionally an amount, period anchor, owner and up to twenty steps, and receives a
      number.
    kind: validation
    enforced_at:
      - api
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a subject the
      business unit does not have with 400 subject_not_found;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#answers 200 with the
      exception open, numbered, of kind manual;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#answers every subject with
      the console route that opens it;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#answers its steps, none
      done; services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a body
      without a title with 400;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#raises
      a manual exception about its subjects, answering each subject’s navigation target;
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-exception-subjects.table.integration.spec.js#refuses
      the same subject twice for one exception
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D6 (architecture §3.4 U10)'
  - id: BR-CAP-ACC-REC-015-02
    proved_by: [ATS-ACC-REC-015-01, ATS-ACC-REC-015-13, TST-ACC-REC-024, TST-ACC-REC-042, TST-ACC-REC-066]
    statement: Every exception subject supplies a navigation target for opening its record in the console.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#answers every subject with
      the console route that opens it;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#answers 200 with the
      exception open, numbered, of kind manual;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#answers its steps, none
      done; services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a body
      without a title with 400;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a subject the
      business unit does not have with 400 subject_not_found;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#raises
      a manual exception about its subjects, answering each subject’s navigation target;
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-exception-subjects.table.integration.spec.js#refuses
      the same subject twice for one exception
    origin: none
  - id: BR-CAP-ACC-REC-015-03
    proved_by: [ATS-ACC-REC-015-02, ATS-ACC-REC-015-12, ATS-ACC-REC-017-10, TST-ACC-REC-043, TST-ACC-REC-066]
    statement: >-
      Detectors suppress an already open, investigating or accepted condition, reopen a resolved condition’s
      existing problem and clear open problems when their condition disappears.
    kind: policy
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#reopens
      the key’s resolved exception, recording `exception.reopened`;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#raises
      nothing while the key’s exception is open;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#raises
      nothing while the key’s exception is accepted;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#raises
      nothing when the dedupe index already holds the key open (two detectors racing);
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#raises
      a new exception, numbered after the tenant’s highest, with its steps and its event;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#clears
      the open exceptions of a kind about a subject, recording `exception.auto-resolved`;
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-exceptions.table.integration.spec.js#refuses
      a second open exception with the dedupe key of an open one
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D6 (architecture §3.4 U10: detectors with
      dedupe keys)
  - id: BR-CAP-ACC-REC-015-04
    proved_by: [ATS-ACC-REC-015-03, ATS-ACC-REC-015-11, TST-ACC-REC-066, TST-ACC-REC-095]
    statement: >-
      People can assign an owner and move between open and investigating at the current version, while
      resolved or accepted exceptions reject those edits and reopening belongs to detectors.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/unit/rules/transitions.spec.js#refuses open as
      exception-reopen-by-detector-only;
      services-accounting:modules/reconciliation/tests/unit/rules/transitions.spec.js#allows investigating;
      services-accounting:modules/reconciliation/tests/unit/rules/transitions.spec.js#refuses investigating as
      exception-closed; services-accounting:modules/reconciliation/tests/unit/rules/transitions.spec.js#allows
      open;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#sets
      the owner and moves the exception to investigating, recording `exception.updated`;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#refuses
      a change at a version that is not the exception’s (409, `stale_version`);
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#refuses
      an owner or status change of a closed exception (409, `exception_closed`)
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D6 (architecture §3.4 U10: not any status to
      any status)
  - id: BR-CAP-ACC-REC-015-05
    proved_by: [ATS-ACC-REC-015-04, TST-ACC-REC-024, TST-ACC-REC-040, TST-ACC-REC-066]
    statement: >-
      Notes record their author, cannot be edited or deleted, allow four thousand characters each and stop at
      two hundred per exception.
    kind: validation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#refuses
      the note after the 200th (409, `notes_limit`);
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a blank note with
      400;
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-exception-notes.table.integration.spec.js#refuses
      a body of 4001 characters;
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-exception-notes.table.integration.spec.js#refuses
      even the owner an UPDATE, by the append-only trigger (RHF32);
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-exception-notes.table.integration.spec.js#refuses
      the owner a DELETE outside a tenant purge, by the append-only trigger (RHF32)
    origin: none
  - id: BR-CAP-ACC-REC-015-06
    proved_by: [ATS-ACC-REC-015-05, TST-ACC-REC-024, TST-ACC-REC-041, TST-ACC-REC-066]
    statement: 'Checklist completion records the person and time and supports undo, with at most twenty steps.'
    kind: lifecycle
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#marks
      a step done by the caller now, and undone again;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a position outside
      1 to 20 with 400; services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a
      step the exception does not have with 404;
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-exception-steps.table.integration.spec.js#refuses
      a done step without who did it and when
    origin: none
  - id: BR-CAP-ACC-REC-015-07
    proved_by: [ATS-ACC-REC-003-07, ATS-ACC-REC-007-10, ATS-ACC-REC-015-06, TST-ACC-REC-024, TST-ACC-REC-066]
    statement: >-
      Resolution requires written explanation and an open problem; an overdue exception fails while the item
      remains overdue and unclaimed on the supplied date or today.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#refuses
      to resolve as of 2026-10-06, when the item is overdue then (409, `condition_still_holds`);
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#refuses
      to resolve an overdue-settlement exception while its item is still overdue and unclaimed (409,
      `condition_still_holds`);
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#resolves
      an overdue-settlement exception once its item is claimed, recording `exception.resolved`;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#resolves
      as of 2026-10-05, when the item is only late then, though it is overdue today;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#resolves
      an exception whose item was written off, as of a later date too (200);
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#refuses
      to resolve a closed exception (409, `exception_closed`);
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a body without a
      resolution with 400
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D6 (architecture §3.4 U10: resolution text
      required)
  - id: BR-CAP-ACC-REC-015-08
    proved_by: [ATS-ACC-REC-015-07, ATS-ACC-REC-015-14, ATS-ACC-REC-017-12, TST-ACC-REC-061, TST-ACC-REC-079]
    statement: >-
      Open blockers publish required attention for the unit’s reconciliation responsibility, resolution or
      acceptance closes attention, and the hourly repair sweep republishes missing items and clears stale
      ones.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-blocker-items.integration.spec.js#publishes
      one open item of the blocker with every element mapped;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-blocker-items.integration.spec.js#publishes
      nothing for a warning;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-blocker-items.integration.spec.js#resolves
      a person's resolution resolved;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-blocker-items.integration.spec.js#resolves
      a second user's approval of the acceptance accepted;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-blocker-items.integration.spec.js#keeps
      a blocker whose acceptance is only requested open;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-blocker-items.integration.spec.js#publishes
      the blocker whose item was lost;
      services-accounting:modules/reconciliation/tests/unit/attention/reconciliation-blockers.spec.js#resolves
      a blocker lowered to a warning severity_lowered
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D9 (raising attention items for the holders of
      the reconciliation responsibility)
  - id: BR-CAP-ACC-REC-015-09
    proved_by: [ATS-ACC-REC-015-08, TST-ACC-REC-024, TST-ACC-REC-066]
    statement: >-
      Exception pages sort by descending number and support status, severity, kind, unit, owner and subject
      filters.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#filters by severity and
      kind; services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#answers 200 with the
      exceptions about a subject, newest first;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#pages by the cursor it
      answers, the last page answering none;
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#filters
      by status, severity, kind and subject type, newest number first
    origin: none
  - id: BR-CAP-ACC-REC-015-10
    proved_by: [ATS-ACC-REC-015-09, TST-ACC-REC-043]
    statement: Closed exceptions require a resolution and retain their original kind and condition key.
    kind: invariant
    enforced_at:
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-exceptions.table.integration.spec.js#refuses
      a resolved exception without its resolution;
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-exceptions.table.integration.spec.js#refuses
      a change of kind (RHF01);
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-exceptions.table.integration.spec.js#refuses
      a change of dedupe_key (RHF01)
    origin: none
  - id: BR-CAP-ACC-REC-015-11
    proved_by: [ATS-ACC-REC-015-10, TST-ACC-REC-024]
    statement: >-
      Exception read governs inspection, update governs ordinary problem work and cross-workspace records are
      absent.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a principal without
      accounting.reconciliation-exceptions.update with 403;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#lets a principal with the
      read keys alone list exceptions;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a principal without
      accounting.reconciliation-exceptions.read with 403;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses tenant A’s
      exception in tenant B with 404
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (§2: permissions)'
  - id: BR-CAP-ACC-REC-015-12
    proved_by: []
    statement: >-
      The console lists active and resolved exceptions, changes investigation status, appends notes and
      submits a written resolution, but cannot create problems or update checklist steps.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: observed
    source: 'react-console:components/accounting/reconciliation/exceptions-screen.tsx:ExceptionsScreen'
    origin: none
scenarios:
  - id: SC-CAP-ACC-REC-015-01
    given: A controller suspects a deposit needs investigation.
    when: 'Record and assign its concern, work the checklist and notes, then resolve.'
    then: History preserves responsible work and closed status prevents further ordinary edits.
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#answers 200 with the
      exception open, numbered, of kind manual
  - id: SC-CAP-ACC-REC-015-02
    given: An overdue capture still has no settlement explanation.
    when: Attempt to resolve its exception.
    then: The missing-money condition prevents resolution.
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses an
      overdue-settlement exception whose item is still overdue with 409 condition_still_holds
edge_cases:
  - id: SC-CAP-ACC-REC-015-03
    given: The item was only late on an earlier review day.
    when: Resolve using that earlier day.
    then: The earlier-day condition permits resolution despite today’s overdue state.
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/persistence/reconciliation-exceptions.integration.spec.js#resolves
      as of 2026-10-05, when the item is only late then, though it is overdue today
constraints: []
depends_on: []
related:
  - CAP-ACC-REC-016
  - CAP-ACC-REC-017
  - CAP-ACC-REC-018
journeys:
  - JNY-ACC-REC-004
open_questions: []
evidence:
  - >-
    Examined supporting service material: outstanding.routes.ts (listReconciliationExceptions,
    createReconciliationException, getReconciliationException, updateReconciliationException,
    addReconciliationExceptionNote, setReconciliationExceptionStep, resolveReconciliationException),
    outstanding.schemas.ts, services/persistence/reconciliation-exceptions.ts,
    reconciliation-blocker-items.ts, exceptions/detectors.ts, exception-resolution.ts, exception-titles.ts,
    rules/transitions.ts, rules/blocker-attention.ts, attention/reconciliation-blockers.attention.ts,
    services/attention/reconciliation-blockers-sweep.ts, metadata/reconciliation-exceptions.object.ts;
    db/reconciliation-exceptions.table.ts (exceptions, subjects, steps, notes);
    aws/accounting.responsibilities.ts (accounting.reconciliation); tests e2e/outstanding.e2e.spec.js,
    integration reconciliation-exceptions, reconciliation-blocker-items, db exception tables, unit
    transitions, attention and exception-titles specs.
  - >-
    Examined supporting console material: components/accounting/reconciliation/exceptions-screen.tsx;
    lib/accounting/reconciliation/store.tsx (updateException, resolveException); acceptance journey
    ACT-ACC-0604.
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-DAT-001, TC-DAT-004, TC-LOG-002, TC-LOG-003, TC-LOG-004, 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]
exercised_by: [FAS-ACC-REC-05-01, FAS-ACC-REC-05-02, FAS-ACC-REC-05-03, FAS-ACC-REC-05-04, FAS-ACC-REC-05-05]
suites: [TST-ACC-REC-024, TST-ACC-REC-040, TST-ACC-REC-041, TST-ACC-REC-042, TST-ACC-REC-043, TST-ACC-REC-061, TST-ACC-REC-066, TST-ACC-REC-079, TST-ACC-REC-095]
---

# Investigate and resolve reconciliation concerns

## Purpose

Finance staff need a continuing record of a problem and the work used to explain it.

## How It Works

Rhythm or a staff member records a concern against its financial subjects. A preparer assigns investigation, updates active status and appends what they learn. Responsible people receive attention for an active blocker. Resolution closes a concern only when its applicable condition allows it. A missing settlement that is still overdue needs more investigation or policy acceptance rather than an unsupported resolution.

## Relationships

Bank review and daily checks detect concerns, policy acceptance concludes understood risks and readiness associates blockers with their financial records.
