---
id: ATS-ACC-CLS-003
scope: CAP-ACC-CLS-003
product_area: accounting
module: close
revision: 1
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-ACC-CLS-003-01
    title: Refuse protected batch creation and carry reconciliation forward
    level: api
    proves:
      - BR-CAP-ACC-CLS-003-03
    preconditions: A run retains one month and the following month is open.
    steps: >-
      Attempt batch creation dated in the retained month and finalize
      reconciliation for that month.
    expected: >-
      Batch creation is refused and reconciliation uses the following month’s
      first day with a late marker.
    negative: true
    data_needs: A retained close and following open period.
    bound_to:
      - >-
        services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#refuses
        a batch dated in the closing period
      - >-
        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
      - TST-ACC-CLS-020
    provenance: test
    source: >-
      services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#posting
      into a closing period
    category: interaction
    binding_note: >-
      The batch-creation refusal does not prove ordinary posting or unposting;
      those variants remain in the coverage finding.
  - id: ATS-ACC-CLS-003-02
    title: Permit close-owned posting and its reopen reversal
    level: api
    proves:
      - BR-CAP-ACC-CLS-003-02
    preconditions: Scheduled revenue is due.
    steps: Complete the close and then reopen.
    expected: >-
      Recognition posts under the closing exception and reversal uses the
      reopening exception.
    negative: false
    data_needs: A due recognition schedule.
    bound_to:
      - >-
        services-accounting:modules/fiscal-close/tests/integration/services/jobs/revenue-recognition.integration.spec.js#posts
        July's deferred revenue system batch, named and dated as 1.0 did
      - >-
        services-accounting:modules/fiscal-close/tests/integration/services/jobs/revenue-recognition.integration.spec.js#reverses
        the close’s posting by its event key, the batch open again with no count
        or total
      - TST-ACC-CLS-023
    provenance: test
    source: >-
      services-accounting:modules/fiscal-close/tests/integration/services/jobs/revenue-recognition.integration.spec.js#revenue
      recognition in the close and reopen jobs (integration)
    category: interaction
  - id: ATS-ACC-CLS-003-03
    title: Refuse late effects without an open destination
    level: api
    proves:
      - BR-CAP-ACC-CLS-003-04
      - BR-CAP-ACC-CLS-003-01
    preconditions: All generated periods are closed.
    steps: Attempt late reconciliation finalization and protected batch actions.
    expected: No eligible late destination exists and protected actions return refusals.
    negative: true
    data_needs: A fully closed generated calendar.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-accounting:modules/reconciliation/services/close-readiness/assess-period.ts:assertPeriodWritable
      - >-
        services-accounting:modules/batches/services/posting-period-guard.ts:POSTING_PERIOD_RULES
    category: edge
  - id: ATS-ACC-CLS-003-04
    title: Serialize posting and closing
    level: api
    proves:
      - BR-CAP-ACC-CLS-003-05
      - INV-DOM-ACC-CLS-001-09
    preconditions: A posting transaction holds the period’s shared row lock.
    steps: >-
      Invoke close finalization from another connection and then release the
      holder.
    expected: Finalization waits and completes only after the shared lock is released.
    negative: false
    data_needs: Separate holder and close database connections.
    bound_to:
      - >-
        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
      - >-
        services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#leaves
        the period closing while it waits
      - >-
        services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#closes
        the period once the holder commits
      - TST-ACC-CLS-020
    provenance: test
    source: >-
      services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#finalize
      and a transaction holding the period FOR SHARE
    category: concurrency
  - id: ATS-ACC-CLS-003-05
    title: Refuse invalid and stale state changes
    level: unit
    proves:
      - BR-CAP-ACC-CLS-003-06
      - BR-CAP-ACC-CLS-003-07
      - INV-DOM-ACC-CLS-001-03
    preconditions: Periods are available in each state.
    steps: >-
      Attempt all transitions and repeat an expected-state update after another
      writer moves the period.
    expected: Only permitted transitions succeed and the stale writer is refused.
    negative: true
    data_needs: Period-state fixtures and two competing updates.
    bound_to:
      - >-
        services-accounting:modules/fiscal-close/tests/unit/rules/transitions.spec.js#may
        make exactly the six moves of a close and a reopen
      - >-
        services-accounting:modules/fiscal-close/tests/unit/rules/transitions.spec.js#is
        refused every other move between two statuses, by name
      - >-
        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
      - >-
        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
      - TST-ACC-CLS-047
      - TST-ACC-CLS-026
    provenance: test
    source: >-
      services-accounting:modules/fiscal-close/tests/unit/rules/transitions.spec.js#fiscal
      close transitions
    category: transition
  - id: ATS-ACC-CLS-003-06
    title: Keep financial exceptions inside the closing boundary
    category: interaction
    level: api
    proves:
      - BR-CAP-ACC-CLS-003-01
      - BR-CAP-ACC-CLS-003-02
      - BR-CAP-ACC-CLS-003-03
      - BR-CAP-ACC-CLS-003-05
    preconditions: >-
      Due revenue and late reconciliation effects belong to an ended month with
      a following open month.
    steps: >-
      Take the month for closing; try ordinary batch work, complete recognition,
      finalize late reconciliation and finish the close.
    expected: >-
      Close-owned work uses its permitted state window while late effects reach
      the following month; ordinary work does not bypass the protected boundary.
    negative: false
    data_needs: >-
      Due revenue and late reconciliation effects belong to an ended month with
      a following open month.
    bound_to: []
    provenance: proposed
    source:
      - >-
        rhythm-v2-docs:specs/accounting/close/design/workflows/WF-ACC-CLS-006-keep-ordinary-postings-out-of-a-protected-month.md#What
        It Does
      - >-
        services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#refuses
        a batch dated in the closing period
      - >-
        services-accounting:modules/batches/services/posting-period-guard.ts:POSTING_PERIOD_RULES
      - >-
        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
      - >-
        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
    exercises:
      - CAP-ACC-CLS-003
      - CAP-ACC-CLS-008
      - CAP-ACC-CLS-009
      - CAP-ACC-CLS-006
      - CAP-ACC-CLS-010
      - CAP-ACC-CLS-014
      - CAP-ACC-CLS-015
    workflows:
      - WF-ACC-CLS-001
      - WF-ACC-CLS-006
  - id: ATS-ACC-CLS-003-07
    title: Refuse an unknown period state
    category: invariant
    level: api
    proves:
      - INV-DOM-ACC-CLS-001-01
    preconditions: A generated period is available under its database constraints.
    steps: Attempt to write a period state outside the recognized state set.
    expected: The database rejects the invalid state without changing the period.
    negative: true
    data_needs: A generated period is available under its database constraints.
    bound_to:
      - TST-ACC-CLS-018
      - >-
        services-accounting:modules/fiscal-close/tests/integration/db/fiscal-close.table.integration.spec.js#refuses
        a status that is not one of the four
    provenance: test
    source: >-
      services-accounting:modules/fiscal-close/tests/integration/db/fiscal-close.table.integration.spec.js#refuses
      a status that is not one of the four
evidence:
  - >-
    services-accounting examination inputs: the bound integration and unit
    files.
  - 'react-console examination inputs: the posting-lock browser journey.'
  - >-
    Testing back-fill: pinned executable files are inspected; no backend or
    browser result is claimed.
coverage:
  rule: 'gap: FND-ACC-CLS-059'
  transition: covered
  validation: 'gap: FND-ACC-CLS-059'
  permission: not-applicable
  edge: covered
  failure: 'gap: FND-ACC-CLS-059'
  boundary: 'gap: FND-ACC-CLS-059'
  concurrency: covered
  invariant: covered
  interaction: covered
coverage_notes:
  rule:
    reason: >-
      Ordinary post and unpost in every protected state are not proved by a
      batch-creation refusal; the absent late destination also remains unbound.
    provenance: unknown
    source: FND-ACC-CLS-059
  transition:
    scenarios:
      - ATS-ACC-CLS-003-05
    provenance: inferred
    source:
      - ATS-ACC-CLS-003-05
    note: Specified coverage does not establish that all variants execute or pass.
  validation:
    reason: >-
      Ordinary post and unpost in every protected state are not proved by a
      batch-creation refusal; the absent late destination also remains unbound.
    provenance: unknown
    source: FND-ACC-CLS-059
  permission:
    reason: >-
      This capability declares no independent action grant; entry-point
      authority is exercised by the calling capability.
    provenance: inferred
    source:
      - CAP-ACC-CLS-003
      - WF-ACC-CLS-001
      - WF-ACC-CLS-006
  edge:
    scenarios:
      - ATS-ACC-CLS-003-03
    provenance: inferred
    source:
      - ATS-ACC-CLS-003-03
    note: Specified coverage does not establish that all variants execute or pass.
  failure:
    reason: >-
      Ordinary post and unpost in every protected state are not proved by a
      batch-creation refusal; the absent late destination also remains unbound.
    provenance: unknown
    source: FND-ACC-CLS-059
  boundary:
    reason: >-
      Ordinary post and unpost in every protected state are not proved by a
      batch-creation refusal; the absent late destination also remains unbound.
    provenance: unknown
    source: FND-ACC-CLS-059
  concurrency:
    scenarios:
      - ATS-ACC-CLS-003-04
    provenance: inferred
    source:
      - ATS-ACC-CLS-003-04
    note: Specified coverage does not establish that all variants execute or pass.
  invariant:
    scenarios:
      - ATS-ACC-CLS-003-07
    provenance: inferred
    source:
      - ATS-ACC-CLS-003-07
    note: Specified coverage does not establish that all variants execute or pass.
  interaction:
    scenarios:
      - ATS-ACC-CLS-003-01
      - ATS-ACC-CLS-003-02
      - ATS-ACC-CLS-003-06
    provenance: inferred
    source:
      - ATS-ACC-CLS-003-01
      - ATS-ACC-CLS-003-02
      - ATS-ACC-CLS-003-06
    note: Specified coverage does not establish that all variants execute or pass.
design_coverage:
  objects:
    - DOM-ACC-CLS-001
  invariants:
    - id: INV-DOM-ACC-CLS-001-01
      scenarios:
        - ATS-ACC-CLS-003-07
      provenance: test
      source:
        - >-
          services-accounting:modules/fiscal-close/tests/integration/db/fiscal-close.table.integration.spec.js#refuses
          a status that is not one of the four
    - id: INV-DOM-ACC-CLS-001-02
      scenarios: []
      gap: FND-ACC-CLS-059
      provenance: unknown
      source: FND-ACC-CLS-059
    - id: INV-DOM-ACC-CLS-001-03
      scenarios:
        - ATS-ACC-CLS-003-05
      provenance: test
      source:
        - >-
          services-accounting:modules/fiscal-close/tests/unit/rules/transitions.spec.js#fiscal
          close transitions
    - id: INV-DOM-ACC-CLS-001-04
      scenarios: []
      gap: FND-ACC-CLS-059
      provenance: unknown
      source: FND-ACC-CLS-059
    - id: INV-DOM-ACC-CLS-001-05
      scenarios: []
      gap: FND-ACC-CLS-059
      provenance: unknown
      source: FND-ACC-CLS-059
    - id: INV-DOM-ACC-CLS-001-06
      scenarios: []
      gap: FND-ACC-CLS-059
      provenance: unknown
      source: FND-ACC-CLS-059
    - id: INV-DOM-ACC-CLS-001-07
      scenarios: []
      gap: FND-ACC-CLS-059
      provenance: unknown
      source: FND-ACC-CLS-059
    - id: INV-DOM-ACC-CLS-001-08
      scenarios: []
      gap: FND-ACC-CLS-059
      provenance: unknown
      source: FND-ACC-CLS-059
    - id: INV-DOM-ACC-CLS-001-09
      scenarios:
        - ATS-ACC-CLS-003-04
      provenance: test
      source:
        - >-
          services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#finalize
          and a transaction holding the period FOR SHARE
    - id: INV-DOM-ACC-CLS-001-10
      scenarios: []
      gap: FND-ACC-CLS-059
      provenance: unknown
      source: FND-ACC-CLS-059
  permissions: []
  workflows:
    - WF-ACC-CLS-001
    - WF-ACC-CLS-006
  state_models:
    - STATE-ACC-CLS-001
  transitions:
    - model: STATE-ACC-CLS-001
      from: open
      to: closing
      provenance: unknown
      source: FND-ACC-CLS-059
      gap: FND-ACC-CLS-059
      note: >-
        Writer and workflow scenarios supply selected outcomes; full guard,
        side-effect and race variants require qualification.
    - model: STATE-ACC-CLS-001
      from: closing
      to: closed
      provenance: unknown
      source: FND-ACC-CLS-059
      gap: FND-ACC-CLS-059
      note: >-
        Writer and workflow scenarios supply selected outcomes; full guard,
        side-effect and race variants require qualification.
    - model: STATE-ACC-CLS-001
      from: closing
      to: open
      provenance: unknown
      source: FND-ACC-CLS-059
      gap: FND-ACC-CLS-059
      note: >-
        Writer and workflow scenarios supply selected outcomes; full guard,
        side-effect and race variants require qualification.
    - model: STATE-ACC-CLS-001
      from: closed
      to: reopening
      provenance: unknown
      source: FND-ACC-CLS-059
      gap: FND-ACC-CLS-059
      note: >-
        Writer and workflow scenarios supply selected outcomes; full guard,
        side-effect and race variants require qualification.
    - model: STATE-ACC-CLS-001
      from: reopening
      to: open
      provenance: unknown
      source: FND-ACC-CLS-059
      gap: FND-ACC-CLS-059
      note: >-
        Writer and workflow scenarios supply selected outcomes; full guard,
        side-effect and race variants require qualification.
    - model: STATE-ACC-CLS-001
      from: reopening
      to: closed
      provenance: unknown
      source: FND-ACC-CLS-059
      gap: FND-ACC-CLS-059
      note: >-
        Writer and workflow scenarios supply selected outcomes; full guard,
        side-effect and race variants require qualification.
  interactions:
    - with: CAP-ACC-CLS-008
      scenario: ATS-ACC-CLS-003-06
      provenance: proposed
      source:
        - >-
          rhythm-v2-docs:specs/accounting/close/design/workflows/WF-ACC-CLS-006-keep-ordinary-postings-out-of-a-protected-month.md#What
          It Does
        - >-
          services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#refuses
          a batch dated in the closing period
        - >-
          services-accounting:modules/batches/services/posting-period-guard.ts:POSTING_PERIOD_RULES
        - >-
          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
        - >-
          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
    - with: CAP-ACC-CLS-009
      scenario: ATS-ACC-CLS-003-06
      provenance: proposed
      source:
        - >-
          rhythm-v2-docs:specs/accounting/close/design/workflows/WF-ACC-CLS-006-keep-ordinary-postings-out-of-a-protected-month.md#What
          It Does
        - >-
          services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#refuses
          a batch dated in the closing period
        - >-
          services-accounting:modules/batches/services/posting-period-guard.ts:POSTING_PERIOD_RULES
        - >-
          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
        - >-
          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
    - with: CAP-ACC-CLS-006
      scenario: ATS-ACC-CLS-003-06
      provenance: proposed
      source:
        - >-
          rhythm-v2-docs:specs/accounting/close/design/workflows/WF-ACC-CLS-006-keep-ordinary-postings-out-of-a-protected-month.md#What
          It Does
        - >-
          services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#refuses
          a batch dated in the closing period
        - >-
          services-accounting:modules/batches/services/posting-period-guard.ts:POSTING_PERIOD_RULES
        - >-
          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
        - >-
          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
    - with: CAP-ACC-CLS-010
      scenario: ATS-ACC-CLS-003-06
      provenance: proposed
      source:
        - >-
          rhythm-v2-docs:specs/accounting/close/design/workflows/WF-ACC-CLS-006-keep-ordinary-postings-out-of-a-protected-month.md#What
          It Does
        - >-
          services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#refuses
          a batch dated in the closing period
        - >-
          services-accounting:modules/batches/services/posting-period-guard.ts:POSTING_PERIOD_RULES
        - >-
          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
        - >-
          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
    - with: CAP-ACC-CLS-014
      scenario: ATS-ACC-CLS-003-06
      provenance: proposed
      source:
        - >-
          rhythm-v2-docs:specs/accounting/close/design/workflows/WF-ACC-CLS-006-keep-ordinary-postings-out-of-a-protected-month.md#What
          It Does
        - >-
          services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#refuses
          a batch dated in the closing period
        - >-
          services-accounting:modules/batches/services/posting-period-guard.ts:POSTING_PERIOD_RULES
        - >-
          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
        - >-
          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
    - with: CAP-ACC-CLS-015
      scenario: ATS-ACC-CLS-003-06
      provenance: proposed
      source:
        - >-
          rhythm-v2-docs:specs/accounting/close/design/workflows/WF-ACC-CLS-006-keep-ordinary-postings-out-of-a-protected-month.md#What
          It Does
        - >-
          services-accounting:modules/fiscal-close/tests/integration/services/jobs/close-concurrency.integration.spec.js#refuses
          a batch dated in the closing period
        - >-
          services-accounting:modules/batches/services/posting-period-guard.ts:POSTING_PERIOD_RULES
        - >-
          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
        - >-
          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
---
# Protect periods from ordinary postings during close: Capability Test Specification

## Coverage

The table maps each required rule to its specified cases or an explicit finding. Category coverage describes the specification; executable bindings and recorded run results establish different kinds of evidence. Proposed cases remain unqualified.

| Rule | Scenarios or Finding |
|---|---|
| `BR-CAP-ACC-CLS-003-01` | `ATS-ACC-CLS-003-03`, `ATS-ACC-CLS-003-06` |
| `BR-CAP-ACC-CLS-003-02` | `ATS-ACC-CLS-003-02`, `ATS-ACC-CLS-003-06` |
| `BR-CAP-ACC-CLS-003-03` | `ATS-ACC-CLS-003-01`, `ATS-ACC-CLS-003-06` |
| `BR-CAP-ACC-CLS-003-04` | `ATS-ACC-CLS-003-03` |
| `BR-CAP-ACC-CLS-003-05` | `ATS-ACC-CLS-003-04`, `ATS-ACC-CLS-003-06` |
| `BR-CAP-ACC-CLS-003-06` | `ATS-ACC-CLS-003-05` |
| `BR-CAP-ACC-CLS-003-07` | `ATS-ACC-CLS-003-05` |

## Interactions With Related Capabilities

Posting protection sits between ordinary ledger work, close-owned financial work and reconciliation. The interaction cases distinguish those entry points. A guard returning an eligible date does not establish that the caller actually writes a ledger entry there.
