v5.28.0 25 May 2026 Improvement

Milestone 7 — Deterministic Infrastructure

Kernel Milestone: 7 of 8 Previous: Milestone 6 — Cryptographic Ledger (v5.27.0) Next: Milestone 8 — State Reproducibility

System Impact
-------------
Ledger integrity:         strengthened — external anchor provides independent tamper evidence
Ledger mutation:          unchanged
Tenant isolation:         unchanged
Financial immutability:   unchanged
State machine:            unchanged
Breaking changes:         none
Replay determinism:       strengthened — migration sequence now mechanically verified
Invariant Change
----------------
The complete migration history is now scanned for nondeterministic patterns on every
deploy. The terminal state of every organisation's audit chain is anchored daily to a
public, GPG-signed, externally hosted record that the database server cannot modify.

Why This Matters

M6 made the ledger tamper-evident inside the database. M7 makes it tamper-evident outside it. A sufficiently privileged actor who could rewrite the audit chain and recompute all hashes would still produce a self-consistent internal record — AX-GOV-001 closes most of that vector via pgaudit, but the audit log itself lives on the same server. The external anchor removes the remaining trust dependency: a daily cryptographic snapshot of all organisation chain states is committed to a public repository the database server cannot reach, signed with a key it does not hold. Any rewrite of the internal chain that occurred after an anchor point is detectable by any party with access to the published anchor and a database connection.

The migration scanner closes a quieter gap. Every migration that has ever run is part of the system’s reproducible history. A migration containing an unordered backfill or a wall-clock dependency means re-running the migration sequence against the same starting snapshot could produce a different database state. That property was previously untested. It is now enforced on every deploy.


Proof Anchors

CI / Deploy layer:
  check-migration-determinism.ts — scans all SQL migrations for nondeterministic
  patterns on every deploy (Phase 1 of api/deploy.sh). Fails deploy if any
  unannotated violation is found. 61 migrations scanned, 0 violations.

Runtime layer:
  anchor-chain.ts — computes deterministic SHA-256 digest over all org chain
  terminal states using domain-prefixed, newline-separated hash inputs.
  json-stable-stringify guarantees byte-identical serialisation across runtimes.

  verify-anchor.ts — recomputes anchor hash from current DB state and compares
  against published anchor file. Per-org divergence reported on mismatch.

  run-anchor.sh — daily cron script: produces anchor, appends to append-only
  transparency log, commits with GPG signature, pushes to public repository.

Ops layer:
  speybooks-anchors (github.com/SpeyTech/speybooks-anchors) — public repository,
  append-only in practice, GPG-signed commits, daily cadence.

  latest-anchor.txt — secondary transparency surface: append-only log of every
  anchor date and hash. Rewriting Git history and resigning commits would also
  require consistent rewriting of this log.

  speybooks_anchor database role — dedicated read-only role with BYPASSRLS,
  no superuser privileges, SELECT on two tables only. Used by anchor scripts
  without requiring superuser credentials or app-role RLS context.

Migration Replay Determinism (AX-MIG-002)

Every database migration is part of the system’s reproducible history. Re-running the complete migration sequence against the same starting snapshot must produce an identical database state — this property is called migration replay determinism.

The scanner detects six categories of nondeterministic pattern: random(), gen_random_uuid(), clock_timestamp(), NOW()/CURRENT_TIMESTAMP in backfill contexts, ROW_NUMBER() OVER () without ORDER BY, and UPDATE ... LIMIT. It reads whole-file buffers (not line-by-line), strips SQL comments before scanning, and uses statement-bounded regex to catch patterns that span multiple lines.

Legitimate exceptions are documented inline with a -- MIGRATION-DETERMINISM: allowed annotation carrying a rationale. The 49 annotated violations in historical migrations are all safe: UUID primary keys on new tables with no downstream ordering dependency, and now() backfills filling nullable timestamp columns. These migrations have already run in production and cannot be changed. The annotation records that the exception is deliberate and understood.

The scanner runs as Phase 1 of the API deploy pipeline. A new migration introducing an unannotated nondeterministic pattern fails the deploy before the TypeScript build begins.


External Audit Chain Anchoring (AX-CRY-001)

A daily cron job computes a cryptographic snapshot of all organisation chain states and publishes it to a public Git repository. Each anchor record contains the terminal chain hash, last audit record ID, and ledger sequence high-water mark for every organisation — binding the anchor to both audit trail integrity and transaction completeness. No silent post-anchor append is possible without producing a detectable divergence.

The anchor hash uses domain-prefixed, newline-separated inputs (org:, chain:, audit:, ledger:) to prevent concatenation ambiguity. Serialisation uses json-stable-stringify to guarantee byte-identical output across JS engine versions. Commits are GPG-signed. A secondary latest-anchor.txt append-only log provides a second transparency surface — rewriting both the Git history and this log consistently would require detectable coordination.

Verification is independent: any party with the anchor file, the verification script, and a database connection can confirm that the ledger state they observe matches the state at the time of the anchor. A mismatch is proof of post-anchor tampering, regardless of whether the internal chain is self-consistent.

Scope: Anchors are periodic (daily), not continuous. Events between the last anchor and a detected discrepancy are not independently verifiable at anchor resolution. This is accepted and documented.


Threat Closure

ThreatStatus BeforeStatus AfterEnforcement Layer
Nondeterministic migration pattern introduced silentlyOpenClosed (Class M)Deploy pipeline scanner — fails deploy on violation
Internal chain rewrite undetectable externallyOpenClosed (Class M)Daily external anchor — GPG-signed, public, append-only
Anchor scripts requiring superuser credentialsOpenClosed (Class M)Dedicated anchor role — BYPASSRLS, read-only, no superuser

Kernel Closure Statement

Axioms: AX-MIG-002, AX-CRY-001

Status: CLOSED as of SpeyBooks v5.28.0

Enforcement layers verified:
  CI/Deploy layer  — check-migration-determinism.ts as Phase 1 of deploy.sh
                     61 migrations scanned, 0 violations
  Runtime layer    — anchor-chain.ts, verify-anchor.ts, run-anchor.sh
                     json-stable-stringify, domain-separated hash inputs
  Ops layer        — github.com/SpeyTech/speybooks-anchors (public, signed)
                     latest-anchor.txt secondary transparency log
                     speybooks_anchor dedicated database role

Deploy verification:
  check-migration-determinism.ts — PASS (61 migrations, 0 violations)
  anchor-chain.ts                — PASS (14 orgs anchored)
  verify-anchor.ts               — PASS (14 orgs match published anchor)

Residual risk:
  Anchors are daily, not continuous. Post-anchor, pre-detection events
  are not externally verifiable at anchor resolution. Accepted and
  documented in AX-CRY-001 scope note.

  Historical migrations (pre-M7) contain annotated nondeterministic
  patterns. These have already run in production and cannot be changed.
  The annotation records the exception as deliberate. Future migrations
  are enforced clean.

Next dependent axiom:
  AX-SYS-001 — Deterministic System Reconstruction (M8)

Security Posture Change

The external anchor closes the final trust dependency on the database server for integrity verification. Before M7, an actor who could rewrite the internal audit chain and pgaudit log simultaneously could produce a self-consistent falsified record. The published anchor is committed to a location the database server cannot reach and signed with a key it does not hold — any rewrite of the chain after an anchor point is detectable by any independent party. This is not a database-level guarantee; it is an independently verifiable one.


Verification Record

Migration 083:
  COMMIT
  Role creation verified: BYPASSRLS=true, superuser=false
  Grants applied: CONNECT, USAGE, SELECT on audit_chain_heads, transactions

Scanner:
  61 migrations scanned
  49 historical violations annotated (all safe, pre-M6 legacy)
  0 unannotated violations

Anchor chain:
  First anchor produced: 2026-05-25
  14 organisations anchored
  verify-anchor.ts PASS against published anchor
  GPG-signed commit pushed to github.com/SpeyTech/speybooks-anchors
  Cron active: daily 01:00 UTC

Adversarial review:
  Two audit passes across three document versions (v1.0 → v1.2).
  Eight findings resolved (R1–R8) before implementation.
  Production Gold — Final.

Deployment notes:
  anchor-chain.ts and verify-anchor.ts require ANCHOR_DATABASE_URL
  pointing to speybooks_anchor role — app DATABASE_URL insufficient
  (RLS context not set at connection time for anchor queries).

Architectural Context

M7 sits between the cryptographic ledger (M6) and the state reconstruction proof (M8). M6 established that the ledger is tamper-evident from inside the database. M7 establishes that it is tamper-evident from outside it, and that the migration history that produced the schema is itself deterministic. M8 will close the final gap: a single executable proof that the complete financial state is reproducible from the migration sequence and ledger events alone.

The post-restore verification protocol now has four steps: restore integrity, audit chain, ledger replay, and anchor verification. All four must pass before the API accepts traffic after any restore event.


Operational Impact

Deploy pipeline: Migration determinism check runs before every build. A new migration with an unannotated nondeterministic pattern fails the deploy immediately.

Daily anchor: Runs at 01:00 UTC via cron. Output logged to /var/log/speybooks-anchor.log. Anchor files retained locally in anchors/ and published to github.com/SpeyTech/speybooks-anchors.

Independent verification: Any party with the verification script and a database connection can run verify-anchor.ts against any published anchor file and confirm ledger state integrity at that point in time.


Kernel Status

MilestoneDescriptionStatus
M1Tenant IsolationComplete
M2Financial Immutability and State MachinesComplete
M3Monetary DomainComplete
M4ProvenanceComplete
M5Schema-Derived Categorical BoundaryComplete
M6Cryptographic LedgerComplete
M7Deterministic InfrastructureComplete
M8State ReproducibilityPending

Files Changed

Backend:

  • api/db/migrations/083-anchor-role.sql — dedicated anchor role with BYPASSRLS, read-only
  • api/src/lib/anchor.ts — new: anchor payload computation library
  • scripts/check-migration-determinism.ts — new: AX-MIG-002 migration scanner
  • scripts/anchor-chain.ts — new: daily anchor publication script
  • scripts/verify-anchor.ts — new: independent anchor verification
  • scripts/run-anchor.sh — new: cron wrapper (produce, commit, push)
  • api/deploy.sh — Phase 1 added: migration determinism check

M8 will close the final gap in the kernel sequence: a single executable proof that the complete financial state is deterministically reproducible from the migration sequence and ordered ledger events alone.