---
id: CAP-ACC-REC-017
title: Detect reconciliation concerns through scheduled checks
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-011
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
intent_sources:
  - 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D9'
  - >-
    services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (§2: the outstanding settlement ledger and
    its daily sweep raising attention items)
  - >-
    services-accounting:docs/milestones/ACCT-M8-payout-reconciliation.md#Built (WP-B: daily schedules per
    workspace; WP-B3, WP-B4: as_of and business unit on the on-demand run)
purpose: The system needs recurring detection and monitoring beyond the staff member’s current screen.
outcomes:
  - Recurring work detects concerns within its bounded scans.
  - Repeated detection preserves one active problem.
  - Authorized staff can invoke checks for investigation.
concepts:
  - CON-ACC-REC-004
  - CON-ACC-REC-002
actors:
  - ACT-ACC-011
  - ACT-ACC-018
surfaces:
  - job
  - api
preconditions: []
postconditions: []
permissions:
  - key: accounting.reconciliation-exceptions.accept
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-ACC-REC-017-01
    proved_by: [ATS-ACC-REC-017-01, TST-ACC-REC-077]
    statement: >-
      The hourly attention pass creates missing workspace-local daily schedules for purge at 03:00, drift at
      05:30 and overdue work at 06:00, preserving existing modified or disabled schedules.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-schedules.integration.spec.js#creates
      the three daily schedules on the first pass;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-schedules.integration.spec.js#keeps
      the tenant’s zone on each schedule;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-schedules.integration.spec.js#creates
      nothing on a second pass;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-schedules.integration.spec.js#leaves
      a schedule a person disabled disabled;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-schedules.integration.spec.js#gives
      another tenant its own three
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D9'
  - id: BR-CAP-ACC-REC-017-02
    proved_by: [ATS-ACC-REC-005-14, ATS-ACC-REC-006-10, ATS-ACC-REC-015-14, ATS-ACC-REC-017-02, ATS-ACC-REC-017-11, ATS-ACC-REC-017-12, TST-ACC-REC-076, TST-ACC-REC-080]
    statement: >-
      The overdue sweep opens a blocker for unclaimed money beyond grace, anchored to its expected month with
      amount, customer, method, kind, occurrence and investigation steps.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      the item past its grace as an open `overdue-settlement` blocker;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#titles
      the item’s exception with its amount, payment method, kind and the date it occurred, never its source
      key;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      nothing for an item in transit, resolved or already under investigation;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#leaves
      the gift in transit on 2026-10-12, raising nothing for it;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      nothing when it runs again at the same occurrence;
      services-accounting:modules/reconciliation/tests/unit/exceptions/exception-titles.spec.js#reads the
      amount, the payment method, the kind, the date and the customer
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D9'
  - id: BR-CAP-ACC-REC-017-03
    proved_by: [ATS-ACC-REC-005-14, ATS-ACC-REC-006-10, ATS-ACC-REC-015-14, ATS-ACC-REC-017-02, ATS-ACC-REC-017-11, ATS-ACC-REC-017-12, TST-ACC-REC-076, TST-ACC-REC-080]
    statement: >-
      Transit, resolved and already investigating items create no new overdue problem, and repeating a day
      does not duplicate a detected problem.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      nothing for an item in transit, resolved or already under investigation;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      the item past its grace as an open `overdue-settlement` blocker;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#titles
      the item’s exception with its amount, payment method, kind and the date it occurred, never its source
      key;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#leaves
      the gift in transit on 2026-10-12, raising nothing for it;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      nothing when it runs again at the same occurrence;
      services-accounting:modules/reconciliation/tests/unit/exceptions/exception-titles.spec.js#reads the
      amount, the payment method, the kind, the date and the customer
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D9'
  - id: BR-CAP-ACC-REC-017-04
    proved_by: [ATS-ACC-REC-017-03, TST-ACC-REC-076]
    statement: >-
      The sweep resolves open overdue exceptions after finalized claims or item resolution, recording how the
      money was explained.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#clears
      the exception of an item a finalized batch now claims, naming the batch;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#clears
      the exception of an item since resolved, naming the resolution
    origin: none
  - id: BR-CAP-ACC-REC-017-05
    proved_by: [ATS-ACC-REC-017-04, TST-ACC-REC-076, TST-ACC-REC-080]
    statement: >-
      The bounded payout scan detects live unreconciled deposits older than five business days, excluding
      exactly-five-day and voided deposits, and clears detected problems after finalize or void.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: 'services-accounting:modules/reconciliation/services/scheduled/overdue-sweep.ts:sweepOverdueSettlement'
    origin: none
  - id: BR-CAP-ACC-REC-017-06
    proved_by: [ATS-ACC-REC-017-05, TST-ACC-REC-076]
    statement: >-
      Drift inspection compares open and finalized reconciliations with their rows, raises one totals-drift
      blocker identifying discrepancies and leaves totals unrepaired on repeat runs.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#rewrites
      no total;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#checks
      every open and finalized batch, and raises the drifting one;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      `totals-drift` naming each total that differs from the rows;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      nothing new when it runs again
    origin: none
  - id: BR-CAP-ACC-REC-017-07
    proved_by: [ATS-ACC-REC-017-06, TST-ACC-REC-031, TST-ACC-REC-076]
    statement: Purge removes expired completions and abandoned claims across workspaces while retaining fresh keys.
    kind: policy
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#keeps
      the fresh completion;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#removes
      every tenant’s old completions and lost claims and answers how many (at least these four; the purge is
      every tenant’s);
      services-accounting:modules/reconciliation/tests/integration/db/idempotency-keys.table.integration.spec.js#let
      that transaction delete the purgeable keys and no other, rolled back here
    origin: none
  - id: BR-CAP-ACC-REC-017-08
    proved_by: [ATS-ACC-REC-017-07, TST-ACC-REC-024, TST-ACC-REC-076, TST-ACC-REC-098]
    statement: >-
      Accept-authorized staff can run any daily job manually and supply a sweep day, limiting only its
      new-overdue-item step to one unit.
    kind: permission
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      one exception: the beta unit’s overdue item, and leaves alpha’s item alone;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#runs the totals drift check
      for the tenant and answers its outcome;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#runs the overdue sweep as
      of today in the tenant’s zone;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#runs the idempotency purge;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a job that is not
      one of the three with 400;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a principal without
      accounting.reconciliation-exceptions.accept with 403;
      services-accounting:tests/unit/reconciliation/outstanding-api-mapper.spec.ts#keeps as_of when the body
      gives a local date; services-accounting:tests/unit/reconciliation/outstanding-api-mapper.spec.ts#keeps
      business_unit_id when the body names a unit;
      services-accounting:tests/unit/reconciliation/outstanding-api-mapper.spec.ts#refuses an as_of that is
      not a real date
    origin: 'services-accounting:docs/milestones/ACCT-M8-payout-reconciliation.md#Built (WP-B3, WP-B4)'
  - id: BR-CAP-ACC-REC-017-09
    proved_by: [ATS-ACC-REC-017-07, TST-ACC-REC-024, TST-ACC-REC-076, TST-ACC-REC-098]
    statement: Manual job requests reject names outside the three supported jobs.
    kind: validation
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a job that is not
      one of the three with 400;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#runs the totals drift check
      for the tenant and answers its outcome;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#runs the overdue sweep as
      of today in the tenant’s zone;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#runs the idempotency purge;
      services-accounting:modules/reconciliation/tests/e2e/outstanding.e2e.spec.js#refuses a principal without
      accounting.reconciliation-exceptions.accept with 403;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      one exception: the beta unit’s overdue item, and leaves alpha’s item alone;
      services-accounting:tests/unit/reconciliation/outstanding-api-mapper.spec.ts#keeps as_of when the body
      gives a local date; services-accounting:tests/unit/reconciliation/outstanding-api-mapper.spec.ts#keeps
      business_unit_id when the body names a unit;
      services-accounting:tests/unit/reconciliation/outstanding-api-mapper.spec.ts#refuses an as_of that is
      not a real date
    origin: none
  - id: BR-CAP-ACC-REC-017-10
    proved_by: [ATS-ACC-REC-005-14, ATS-ACC-REC-006-10, ATS-ACC-REC-015-14, ATS-ACC-REC-017-02, ATS-ACC-REC-017-11, ATS-ACC-REC-017-12, TST-ACC-REC-076, TST-ACC-REC-080]
    statement: Duplicate delivery of the same scheduled occurrence does not create duplicate problems.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      nothing when it runs again at the same occurrence;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      the item past its grace as an open `overdue-settlement` blocker;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#titles
      the item’s exception with its amount, payment method, kind and the date it occurred, never its source
      key;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      nothing for an item in transit, resolved or already under investigation;
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#leaves
      the gift in transit on 2026-10-12, raising nothing for it;
      services-accounting:modules/reconciliation/tests/unit/exceptions/exception-titles.spec.js#reads the
      amount, the payment method, the kind, the date and the customer
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D9'
  - id: BR-CAP-ACC-REC-017-11
    proved_by: []
    statement: >-
      Monitoring reports raised or reopened overdue work, drifting reconciliations and purged keys using each
      job’s metric.
    kind: policy
    enforced_at:
      - service
    must_prove: false
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/scheduled/reconciliation-jobs.ts:runReconciliationJob
    origin: none
  - id: BR-CAP-ACC-REC-017-12
    proved_by: [ATS-ACC-REC-017-09]
    statement: >-
      Each overdue step stops after five hundred rows, and payout detection scans only a 120-calendar-day
      lookback before its threshold without a continuation cursor.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/persistence/unreconciled-payouts.ts:listUnreconciledPayoutsBefore
    origin: none
scenarios:
  - id: SC-CAP-ACC-REC-017-01
    given: The gift has passed grace by Friday’s review.
    when: Sweep that day twice.
    then: One blocker changes its position to investigation and the repeated pass adds no problem.
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/reconciliation-scenario.e2e.spec.js#step 9: raises
      one overdue-settlement exception for the gift, which then reads under investigation
  - id: SC-CAP-ACC-REC-017-02
    given: A live unexplained payout is older than five business days.
    when: Sweep the review day.
    then: 'Its unbalanced-deposit blocker identifies amount, accounting day and payout number.'
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#titles
      the old payout’s exception with its amount, accounting date and number
edge_cases:
  - id: SC-CAP-ACC-REC-017-03
    given: Two units each have overdue money.
    when: 'Scope the manual sweep to one, then run it across the workspace.'
    then: New detection first raises only the selected unit’s item and then raises the other.
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/scheduled/reconciliation-scheduled-work.integration.spec.js#raises
      alpha’s item on the tenant-wide run that follows, and does not raise beta’s again
constraints: []
depends_on:
  - CAP-ACC-REC-006
  - CAP-ACC-REC-015
related:
  - CAP-ACC-REC-018
journeys:
  - JNY-ACC-REC-004
open_questions: []
evidence:
  - >-
    Examined supporting service material: outstanding.routes.ts (runReconciliationScheduledWork),
    services/scheduled/overdue-sweep.ts, drift-check.ts, reconciliation-jobs.ts,
    reconciliation-scheduled-work.ts, reconciliation-schedules.ts, persistence/unreconciled-payouts.ts,
    idempotency-keys.ts, exceptions/detectors.ts; aws/lambda/RECONCILIATION_ATTENTION_SWEEP.ts; tests
    integration reconciliation-scheduled-work and reconciliation-schedules, e2e outstanding (running the daily
    jobs on demand) and scenario step 9.
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-005, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-LOG-001, 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-004, TC-PI-005, TC-PRV-001, TC-PRV-002]
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-031, TST-ACC-REC-076, TST-ACC-REC-077, TST-ACC-REC-080, TST-ACC-REC-098]
---

# Detect reconciliation concerns through scheduled checks

## Purpose

The system needs recurring detection and monitoring beyond the staff member’s current screen.

## How It Works

Workspace-local schedules run overdue detection, integrity inspection and key cleanup. Detectors preserve one active concern for the same condition rather than multiplying work on retry. Staff with the required grant can invoke these jobs for investigation. The overdue scan is bounded and currently does not establish complete traversal of large backlogs. Integrity checks report discrepancies without silently repairing the underlying totals.

## Relationships

Outstanding records supply timing, exceptions retain detection results, responsibility attention distributes work and Accounting scheduling invokes the jobs.
