v5.67.0 15 June 2026 Improvement Fix

Schema Coverage: Stored-Amount Bounds Extended to the Ledger, Verified Per Column

Why This Matters

Building toward the credit note surfaced a gap, not in the ledger, but in the layer that checks the ledger. A magnitude bound that keeps stored amounts inside their proven-safe range was enforced on one table while several others carried the same kind of amount unguarded. The deploy check that should have caught the divergence was a hand-maintained list, and a hand-maintained list does not grow with the schema. When a new amount-bearing table arrived, the check did not widen to cover it.

Before adding the credit note, that gap had to close, and close in a way that cannot quietly reopen. This release makes the verification layer a first-class part of the kernel. One source of truth records which stored amounts must carry a bound and which tenant boundaries must be guarded; the deploy checks derive what they enforce from it rather than from a hand-list; and a meta-check ensures a future amount cannot acquire the shape without being registered. The credit note, which reverses VAT already reported on a filed return, follows in the next release.


Coverage Made First-Class

  • One source of truth, derived not hand-listed Which stored amounts must carry a magnitude bound, and which tenant boundaries must be guarded, is now recorded in a single coverage manifest that the deploy checks read. The two earlier checks each covered a hand-picked subset, one table for amounts and a fixed list of pairs for tenancy. Both are retired and replaced by derivation against the live schema. (AX-COV-001, Class M; proof anchors: migration 108, a deploy-time coverage gate, and an executable verification battery in CI.)

  • Verified per column, by structure not by name Each required amount is matched to the actual bound on that column rather than to a constraint’s name. A bound that is renamed still passes; a bound that is weakened or removed reddens; and on a column carrying two required bounds, dropping one reddens that column alone. Names are never load-bearing.


Stored-Amount Bounds Extended to the Ledger

  • The ledger posting amount and its VAT now carry the bound The core ledger amounts, every posted entry and its VAT, now carry the same magnitude envelope that already protected document lines. A value outside the proven-safe range is rejected at the database rather than wrapping silently. (Class M, migration 108.)

  • Declared dividends and director-loan movements now carry the bound Two further declared financial amounts, dividends and director-loan account movements, gained the same protection at the database layer. (Class M, migration 108.)

  • Applied on census-clean data Each bound counted existing rows before it was applied; all four were clean, so nothing was rejected and no existing value sat outside the range. The census proved it rather than assuming it.


The Loop Closes, and Fails Closed

  • A future amount cannot escape coverage A meta-check holds that any table acquiring the magnitude shape without being registered reddens the deploy, and a constraint-level backstop holds that a safety-shaped constraint cannot sit on an unregistered table. The shape is detected by its bound, not its name, so an off-convention bound is still caught. (AX-COV-001, Class M.)

  • An absent check reddens rather than passing green The deploy gate fails closed. If the verification layer is ever absent, the deploy fails rather than passing every coverage check at once on an empty answer. This is verified by execution, including a case that removes the verification layer and confirms the gate reddens, so the property is proven rather than assumed.


Operational Impact

  • The ledger posting amount, the ledger VAT amount, declared dividends, and director-loan movements now reject values outside the proven-safe range at the database layer.
  • Coverage is verified per column against the live schema on every deploy, derived from one manifest rather than two hand-maintained lists.
  • A new stored amount cannot acquire the magnitude shape without registration without reddening the deploy.
  • The coverage gate fails closed: an absent verification layer reddens rather than passing green.
  • No change to existing behaviour and no API surface change. Existing data was census-clean, so nothing was rejected on apply.

Versioning

The kernel axiom registry moved to v2.27 across this release.

  • A new axiom was added: AX-COV-001 (Schema Coverage Manifest), Class M. Unlike the previous release, which carried amendments only, this is a new mechanically-enforced invariant, so the count of Class M invariants rises by one.
  • AX-COV-001 is Class M rather than operational because its coverage is proven by an executable verification battery in CI, not by a checklist. The decision to make the verification layer first-class is recorded in ADR-015.
  • The two retired deploy checks keep their database-layer enforcement; their deploy-time verification is now the manifest-derived coverage gate, broadened from a hand-scoped subset to the full live surface.

No breaking API changes.


Files Changed

Backend:

  • Schema coverage manifest with per-column coverage, the bound-keyed meta-check, and the constraint-level backstop (migration 108); the verification layer’s documentation registered as a migration so a replay reproduces it (migration 109).
  • Four stored-amount magnitude bounds added: the ledger posting amount, the ledger VAT amount, declared dividends, and director-loan movements (migration 108).
  • Kernel axiom registry: AX-COV-001 added, registry to v2.27; ADR-015 recorded.
  • Deploy pipeline: the two hand-scoped coverage checks replaced by the single manifest-derived coverage gate.

Frontend / Docs site: None.


The next release in the invoice-correction series adds the credit note, the instrument that reverses VAT on a filed return by moving the figures into the current period rather than reaching back.