---
id: TST-ACC-CLS-021
title: 'Close execution, refusal and recovery'
kind: integration
product_area: accounting
module: close
revision: 1
status: draft
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
repository: services-accounting
files:
  - >-
    modules/fiscal-close/tests/integration/services/jobs/close-job.integration.spec.js
implements:
  - ATS-ACC-CLS-008-02
  - ATS-ACC-CLS-008-04
  - ATS-ACC-CLS-008-05
  - ATS-ACC-CLS-009-02
  - ATS-ACC-CLS-010-01
  - ATS-ACC-CLS-010-03
  - ATS-ACC-CLS-012-01
  - ATS-ACC-CLS-012-02
  - ATS-ACC-CLS-012-03
  - ATS-ACC-CLS-012-05
  - ATS-ACC-CLS-013-01
  - ATS-ACC-CLS-014-01
  - ATS-ACC-CLS-015-01
environment: local
implementation_state: implemented
latest_result: not-run
latest_run_at: null
latest_run_ref: null
conformance: not-verified
estimated_minutes: 3
isolation: >-
  The suite owns test-identifier workspaces and fixture records, removed by its
  teardown.
binding_policy: >-
  Each binding identifies the assertions this suite executes; combined scenarios
  may require other bound suites. Existence is not a recorded execution result.
evidence:
  - >-
    services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-job.integration.spec.js
  - provenance: test
    source: >-
      services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-job.integration.spec.js
    assertion_titles:
      - the close job (integration)
      - a clean period
      - 'answers the run queued, a period close'
      - ends the run succeeded and finished
      - 'closes the period, by the requester, naming the run'
      - >-
        settles every step: the revenue and COGS steps skipped, the others
        completed
      - records why revenue recognition and COGS were skipped
      - keeps the readiness the close evaluated on the run
      - records the close snapshot of the period
      - >-
        requests the A/R aging snapshot of September, reconstructed while gamma
        still has September open
      - rolls the fiscal years forward to three open years after September 2026
      - records the years it generated
      - a period blocked by an unposted batch
      - 'ends the run failed at revalidate, not retryable'
      - names the blocking check in the run’s failure
      - returns the period to open with no run holding it
      - records the refusal in the job’s events
      - fails the revalidate step and skips nothing after it
      - 'refuses a retry: the period is no longer held'
      - writes no close snapshot and requests no A/R snapshot
      - idempotency keys
      - 'answers the same run for the same key, created once'
      - creates one job for the run
      - >-
        refuses another key while the first run holds the period, as
        period-run-active
      - refuses the same key with another body as idempotency-key-reused (409)
      - 'a failure in finalize, then a new close'
      - >-
        fails the run on finalize, not retryable, saying the period was given
        back (DEF-ACT-0819)
      - 'gives the period back: open, no run holding it'
      - 'refuses a retry of the released run, naming a new close'
      - leaves the failed job failed on finalize
      - lets a new close succeed and close the period
      - a cancel before finalize
      - 'fails the run on finalize, the revenue step skipped (premise)'
      - answers the run cancelled
      - >-
        leaves the period open with no run holding it (finalize had already
        given it back)
      - refuses a cancel of the cancelled run as finished
      - refuses a cancel to a caller without the close permission
      - a cancel after revenue was recognised
      - 'refuses the cancel as run-not-cancellable, naming the way out'
      - >-
        reverses nothing: the port was asked to recognise once, by the close’s
        event key
      - 'leaves the run failed and the period closing, held by it'
      - the year’s last period
      - 'runs it as a year close, succeeded'
      - closes the fiscal year with its twelfth period
      - evaluates the year’s checks in the close
limitations:
  - >-
    Financial port stand-ins in selected cases prove orchestration and output
    retention, not actual ledger entries.
real_dependencies: >-
  The in-process runner uses real persistence, readiness and snapshot-request
  writes. Selected cases replace recognition or aging ports to inject faults;
  those cases do not prove the replaced financial effects.
product_intent: proposed
implementation_evidence: observed
---
# Close execution, refusal and recovery

## Verification Boundary

The suite checks its declared service or persistence boundary against local PostgreSQL. Bindings identify the assertions it contributes to a capability case; they do not establish every assertion in a combined case.

## What This Suite Proves

The job suite follows clean and year-end closes, readiness refusal, command replay, finalization failure and cancellation before or after recorded recognition. Fault cases replace the aging port and selected cases use a recording recognition stand-in.

## What It Does Not Prove

Financial port stand-ins in selected cases prove orchestration and output retention, not actual ledger entries.

## Real Dependencies and Test Doubles

The in-process runner uses real persistence, readiness and snapshot-request writes. Selected cases replace recognition or aging ports to inject faults; those cases do not prove the replaced financial effects.

## Must Not Be Doubled

Keep production queries, writes, mappings, application-role privileges and database constraints real wherever they are the subject of an assertion. Recording financial ports establish invocation behavior; actual recognition and reversal require the suite using the real posting service.
