---
id: CAP-ACC-CLS-003
title: Protect periods from ordinary postings during close
feature: FEAT-ACC-CLS-01
product_area: accounting
module: close
revision: 1
status: draft
product_intent: confirmed
implementation_evidence: observed
supersedes:
  - CAP-ACC-REC-020 (react-console acceptance inventory)
  - RUL-ACC-REC-090
  - RUL-ACC-REC-091
  - RUL-ACC-REC-092
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - >-
    services-accounting:docs/milestones/plans/ACCT-M4-plan.md#4a row 74 (class
    A: a posting into a closed period is refused)
purpose: >-
  The closing boundary prevents ordinary postings from changing a month while
  its close is running or complete.
outcomes:
  - Period totals remain protected throughout closing and reopening.
  - >-
    Late reconciliation effects reach an open period with an explicit late
    marker.
concepts:
  - CON-ACC-CLS-001
actors:
  - ACT-ACC-012
  - ACT-ACC-013
  - ACT-ACC-016
surfaces:
  - api
  - job
preconditions: []
postconditions: []
permissions: []
rules:
  - id: BR-CAP-ACC-CLS-003-01
    proved_by: [ATS-ACC-CLS-003-03, ATS-ACC-CLS-003-06]
    statement: >-
      Ordinary posting and unposting of a batch in a closing, closed or
      reopening month are refused because the period is not open.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#refuses
      a batch dated in the closing period
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M4-plan.md#4a row 74 (class
      A; plan approved 2026-10-21)
  - id: BR-CAP-ACC-CLS-003-02
    proved_by: [ATS-ACC-CLS-003-02, ATS-ACC-CLS-003-06, TST-ACC-CLS-023]
    statement: >-
      Close-owned recognition and system posting may run in an open or closing
      month, while their reversal requires a closed or reopening month.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: >-
      services-accounting:modules/batches/services/posting-period-guard.ts:POSTING_PERIOD_RULES
    origin: batch posting amendment A2 agreed with the close (2026-10-16)
  - id: BR-CAP-ACC-CLS-003-03
    proved_by: [ATS-ACC-CLS-003-01, ATS-ACC-CLS-003-06, TST-ACC-CLS-020]
    statement: >-
      Reconciliation effects assigned to a closed or closing month move to the
      first day of the next available open month and carry a late-after-close
      marker.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#posts
      a reconciliation dated in it on the first open period, October 1, flagged
      late after close
    origin: fiscal-close design L11 and reconciliation architecture §15.4 (INV-16)
  - id: BR-CAP-ACC-CLS-003-04
    proved_by: [ATS-ACC-CLS-003-03]
    statement: >-
      A late reconciliation effect is refused if no following open period can
      receive it.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: >-
      services-accounting:modules/reconciliation/services/close-readiness/assess-period.ts:assertPeriodWritable
    origin: reconciliation architecture §15.4 (INV-16)
  - id: BR-CAP-ACC-CLS-003-05
    proved_by: [ATS-ACC-CLS-003-04, ATS-ACC-CLS-003-06, TST-ACC-CLS-020]
    statement: >-
      Period row locks serialize close work with posting work, making whichever
      arrives later wait for the existing holder.
    kind: invariant
    enforced_at:
      - database
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#waits
      on the period row while the FOR SHARE is held
    origin: fiscal-close design L8 (Rhythm 1.0 CLOSE-10 fixed)
  - id: BR-CAP-ACC-CLS-003-06
    proved_by: [ATS-ACC-CLS-003-05, TST-ACC-CLS-026, TST-ACC-CLS-047]
    statement: >-
      Period state follows the six allowed close and reopen transitions,
      including release or cancellation paths; direct jumps and unchanged-state
      moves are refused.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/fiscal-close/tests/integration/services/persistence/fiscal-periods.integration.spec.js#refuses
      every move the transition table does not allow, by name
    origin: >-
      fiscal-close foundation FC2-1 (the only writer of a month's status; Rhythm
      1.0 FY-14)
  - id: BR-CAP-ACC-CLS-003-07
    proved_by: [ATS-ACC-CLS-003-05, TST-ACC-CLS-026, TST-ACC-CLS-047]
    statement: >-
      A state update succeeds only if the period still has the state the writer
      expected.
    kind: invariant
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/fiscal-close/tests/integration/services/persistence/fiscal-periods.integration.spec.js#refuses
      the second of two writers that read the period open, once the first has
      moved it
    origin: none
scenarios:
  - id: SC-CAP-ACC-CLS-003-01
    given: A close holds September in closing state.
    when: Staff attempt a September-dated batch posting.
    then: Posting returns a period-not-open refusal.
    provenance: test
    source: >-
      services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#refuses
      a batch dated in the closing period
  - id: SC-CAP-ACC-CLS-003-02
    given: September is closed and October is open.
    when: Staff finalize a September reconciliation.
    then: >-
      The effect posts on October’s first day and remains late-review work in
      that month.
    provenance: test
    source: >-
      services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#posts
      a reconciliation dated in it on the first open period, October 1, flagged
      late after close
edge_cases: []
constraints:
  - >-
    Batch management and Reconciliation implement the shared closing boundary
    described by this capability.
depends_on: []
related:
  - CAP-ACC-CLS-008
  - CAP-ACC-CLS-009
  - CAP-ACC-CLS-006
journeys:
  - JNY-ACC-CLS-006
open_questions: []
evidence:
  - >-
    services-accounting examination inputs:
    modules/fiscal-close/services/persistence/fiscal-periods.ts
    (lockPeriodForUpdate, setPeriodStatus), services/rules/transitions.ts;
    modules/batches/services/posting-period-guard.ts and
    modules/reconciliation/services/close-readiness/assess-period.ts
    (assertPeriodWritable), read to name the dependencies; tests
    integration/services/jobs/close-concurrency.integration.spec.js,
    persistence/fiscal-periods.integration.spec.js,
    unit/rules/transitions.spec.js.
  - >-
    react-console examination inputs:
    acceptance/accounting/journeys/reconciliation-close/ACT-ACC-0621.json and
    its browser specification.
controls: [TC-IAM-001, TC-IAM-005, TC-IAM-006, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-DAT-001, TC-LOG-002, TC-LOG-003, TC-LOG-005, TC-PI-003, TC-PI-005]
exercised_by: [FAS-ACC-CLS-01-02, FAS-ACC-CLS-01-03, FAS-ACC-CLS-01-05]
suites: [TST-ACC-CLS-020, TST-ACC-CLS-023, TST-ACC-CLS-026, TST-ACC-CLS-047]
---

# Protect periods from ordinary postings during close

## Purpose

The closing boundary prevents ordinary postings from changing a month while its close is running or complete.

## How It Works

A close takes the period before it assesses the books. Ordinary posting paths then treat that period as unavailable. The close’s own revenue work uses a restricted exception supplied by Batch management. A reopen uses the corresponding reversal exception. Late reconciliation can still finish by posting into an eligible following month. It carries a late marker so the receiving month’s review can identify the effect. If no open month is available, reconciliation refuses the posting. Shared period locks prevent a posting and close step from passing each other. State updates also reject a stale writer.

## Relationships

- Close execution establishes the posting boundary.
- Deferred revenue processing uses the close-owned exception.
- Reconciliation readiness reviews effects carried into a later month.
