Skip to content

Commit a91d313

Browse files
Merge pull request #37 from engineeredsoftware/v30/gate-5-testnet-ledger-projection-hardening
V30 Gate 5: Testnet Ledger Projection Hardening
2 parents 708214e + 790daeb commit a91d313

20 files changed

Lines changed: 1209 additions & 22 deletions

.github/workflows/bitcode-gate-quality.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ jobs:
8383
node scripts/check-v30-gate2-protocol-package-api-boundaries.mjs --skip-branch-check
8484
node scripts/check-v30-gate3-bitcoin-taproot-psbt-fee-rigor.mjs --skip-branch-check
8585
node scripts/check-v30-gate4-btd-assetpack-mint-read-receipts.mjs --skip-branch-check
86+
node scripts/check-v30-gate5-testnet-ledger-projection-hardening.mjs --skip-branch-check
8687
else
8788
echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2
8889
exit 1

BITCODE_SPEC_V30.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,9 @@ The canonical report is produced from:
353353

354354
- ledger observed facts: fee receipts, ledger anchors, journal entries, BTD ranges, ownership events, read licenses, and finality state;
355355
- database projected facts: the Supabase readback rows that claim those ledger facts are durable in the application projection;
356+
- object-storage artifact facts: source-safe preview, pipeline evidence, telemetry, delivery manifest, and ledger projection artifact roots that prove artifacts are durable without exposing protected source;
356357
- private metaphysical canonical facts: protected source metadata, need/fit context, access policy documents, encrypted storage pointers, disputes, and telemetry context represented only by roots;
358+
- staging-testnet readback facts: secret-free Supabase project reference, REST/DB hosts, out-of-band admin-credential state, table readback counts, and synchronized-or-blocked state;
357359
- settlement conservation checks: BTC debit/credit and fee/payment roots that must conserve before unlock;
358360
- delivery evidence: post-settlement pull-request visibility and recovery posture.
359361

@@ -363,24 +365,33 @@ Drift is classified before repair:
363365
- `ledger_root_mismatch`: the database projection points at a different root than the ledger observation;
364366
- `ledger_finality_mismatch`: the projected finality differs from the observed finality;
365367
- `database_orphan_projection`: the database projects a fact that has no matching ledger observation;
368+
- `missing_object_storage_artifact`: the ledger or projection expects an artifact root that is not durable yet;
369+
- `object_storage_root_mismatch`: the database projection and object-storage artifact root disagree;
370+
- `staging_testnet_readback_blocked`: staging-testnet Supabase readback cannot prove the expected rows without retry;
366371
- `settlement_conservation_drift`: BTC debit/credit or fee/payment accounting does not conserve.
367372

368373
Repair actions are canonical and auditable:
369374

370375
- `retry_database_readback`;
376+
- `retry_object_storage_write`;
377+
- `retry_staging_testnet_readback`;
371378
- `project_ledger_fact`;
372379
- `update_finality_state`;
373380
- `quarantine_database_projection`;
381+
- `quarantine_object_storage_artifact`;
374382
- `pause_settlement_unlock`;
375383
- `recover_delivery`.
376384

377385
The reconciliation state is one of aligned, retryable, repairable, approval required, or blocked.
378386
Confirmed ledger facts that are missing from the database require operator-approved projection repair.
379387
Reorged or failed finality, database-only orphan projection, or settlement conservation drift blocks unlock and delivery.
388+
Missing durable object-storage artifacts are retryable unlock blockers.
389+
Object-storage root mismatches require quarantine until the artifact and projection agree.
380390
Delivery recovery is allowed only when settlement is otherwise aligned and the full AssetPack delivery target is not visible.
381391

382-
Terminal must show drift classes, blockers, repair actions, proof roots, observed facts, projected facts, canonical facts, journal entries, and repair receipts before raw payloads.
392+
Terminal must show drift classes, blockers, repair actions, proof roots, observed facts, projected facts, object-storage facts, canonical facts, journal entries, and repair receipts before raw payloads.
383393
The Vercel Sandbox harness must store the reconciliation report as settlement evidence when it claims ledger readback.
394+
Supabase staging-testnet readback receipts must never store service-role JWTs, `sb_secret__` keys, OpenAI keys, database passwords, or any raw secret in tracked code or persisted proof payloads; only host/project identifiers, credential presence state, and proof roots are admissible.
384395
The API may persist schema-compatible repair receipts while richer repair actions and proof roots remain report evidence until the registry schema is formally expanded.
385396

386397
## V30 canonical subsystem surfaces

BITCODE_SPEC_V30_DELTA.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,39 @@ Closure acceptance:
178178
- Supabase staging-testnet readback can prove synchronized or blocked state without secrets in tracked files;
179179
- reconciliation tests cover drift, quarantine, retry, and unlock blocking.
180180

181+
Gate 5 implementation centers on `packages/btd/src/reconciliation.ts`.
182+
`LedgerDatabaseReconciliationReport` now carries distinct ledger-observed
183+
facts, database-projected facts, object-storage artifact facts, private
184+
metaphysical facts, settlement-conservation checks, and optional
185+
`SupabaseStagingTestnetProjectionReadback` evidence. Object-storage facts name
186+
artifact kind, source visibility, durable root, protected-source/encryption
187+
posture, and manifest root. Supabase readback receipts name only safe project
188+
and host identifiers, table counts, synchronized-or-blocked state, credential
189+
presence, and proof roots; secret-looking values are rejected.
190+
191+
The deterministic repair surface now includes
192+
`missing_object_storage_artifact`, `object_storage_root_mismatch`, and
193+
`staging_testnet_readback_blocked` drift classes plus
194+
`retry_object_storage_write`, `retry_staging_testnet_readback`, and
195+
`quarantine_object_storage_artifact` repair actions. Missing durable artifacts
196+
block unlock as retryable repairs, object-storage root mismatches require
197+
quarantine/approval, and staging-testnet readback failures remain blocked until
198+
the table readback proves synchronized.
199+
200+
The Sandbox harness emits object-storage artifact roots and secret-free
201+
staging-testnet readback receipts into settlement reconciliation evidence.
202+
Terminal reconciliation now renders object-storage artifacts as a fourth fact
203+
group beside ledger, database, and metaphysical facts and includes report proof
204+
roots and repair actions in the existing journal repair cockpit.
205+
206+
Gate 5 evidence is covered by
207+
`packages/btd/__tests__/reconciliation.test.ts`,
208+
`packages/api/src/routes/__tests__/btd-crypto.test.ts`,
209+
`packages/pipeline-hosts/src/__tests__/asset-pack-harness.test.ts`,
210+
`uapi/tests/terminalJournalReconciliation.test.ts`,
211+
`uapi/tests/terminalTransactionDetailSnapshot.test.ts`, and
212+
`scripts/check-v30-gate5-testnet-ledger-projection-hardening.mjs`.
213+
181214
### Gate 6: Source-To-Shares Proof Cleanup
182215

183216
Gate 6 cleans contribution measurement and settlement conservation.

BITCODE_SPEC_V30_NOTES.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,36 @@ coerce receipt payloads under camelCase or database-style snake_case keys, and
137137
the transaction read model counts receipt payloads in closure and journal
138138
availability.
139139

140+
## Gate 5 testnet ledger projection notes
141+
142+
Gate 5 extends the V29 reconciliation cockpit from ledger/database/private-root
143+
separation into a four-fact projection model:
144+
145+
- ledger observed facts remain fee, anchor, journal, range, ownership, license,
146+
and finality observations;
147+
- database projected facts remain Supabase rows and projected roots/finality;
148+
- object-storage artifact facts now carry source-safe preview, evidence,
149+
telemetry, delivery, and ledger-projection roots separately from database
150+
rows;
151+
- private metaphysical facts remain root-only protected source and policy
152+
context.
153+
154+
Object storage may prove a durable artifact exists, but it may not leak
155+
protected source before settlement. Unencrypted protected source artifacts are
156+
rejected. Encrypted protected source artifacts are admissible only as roots and
157+
encrypted posture, not visible source.
158+
159+
Supabase staging-testnet readback is an explicit receipt. It records project
160+
ref, REST host, optional DB host, admin credential presence state, table readback
161+
counts, synchronized-or-blocked state, and proof root. It rejects secret-shaped
162+
values so tracked files, telemetry, and persisted proof payloads cannot carry
163+
service-role JWTs, `sb_secret__` keys, OpenAI keys, or database passwords.
164+
165+
Gate 5 keeps the existing registry table shape for repair rows. The API
166+
persists schema-compatible repair receipts; richer drift classes, repair
167+
actions, readback receipts, and proof roots remain in the report payload until a
168+
future schema expansion admits more columns.
169+
140170
4. **Gate 4: BTD AssetPack Mint And Read Receipts**
141171
- Make BTD mint, read, and rights-transfer receipts typed, proof-rooted, stored, streamed, and source-safe.
142172

BITCODE_SPEC_V30_PARITY_MATRIX.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ No `_legacy/` source is active source truth.
5858
| Protocol package API boundaries | Gate 2 | `packages/btd/src/api-boundaries.ts`, `packages/api/src/routes/btd-crypto.ts`, package READMEs/tests | drafted | Shared Protocol/BTD objects have package-owned builders, parsers, validators, JSON-safe serializers, and tests. |
5959
| Bitcoin Taproot PSBT fee rigor | Gate 3 | `packages/btd/src/btc-fee-operation.ts`, `packages/btd/src/bitcoin-fees.ts`, BTD/API tests, gate checker | drafted | BTC fee and signer states are typed, testnet/mainnet-safe, no-custody, Taproot/PSBT aware, and proof-rooted. |
6060
| BTD AssetPack mint/read receipts | Gate 4 | `packages/btd/src/receipts.ts`, `packages/btd/src/api-boundaries.ts`, asset-pack harness evidence, Terminal detail snapshot/read model tests, gate checker | drafted | Mint, read, and rights-transfer receipts bind BTD range, preview, paid unlock, delivery, and ledger projection. |
61-
| Testnet ledger projection hardening | Gate 5 | BTD reconciliation, Supabase readback, object-storage evidence, repair tests | pending | Ledger/database/object-storage projections are synchronized or blocked with deterministic repair posture. |
61+
| Testnet ledger projection hardening | Gate 5 | `packages/btd/src/reconciliation.ts`, API route tests, asset-pack harness evidence, Terminal journal reconciliation UI/tests, gate checker | drafted | Ledger/database/object-storage/private facts are distinct; staging-testnet readback is secret-free; drift, quarantine, retry, and unlock blocking are tested. |
6262
| Source-to-shares proof cleanup | Gate 6 | BTD/source-to-shares proof primitives, settlement conservation tests | pending | Measurement contribution, fee allocation, zero-cell/refit tail, and conservation invariants are testable. |
6363
| Bridge-readiness research boundaries | Gate 7 | Protocol/BTD research notes, policy posture tests, docs | pending | Bridge paths are documented as research until admitted by explicit future proof and policy. |
6464
| Protocol telemetry/proof hooks | Gate 8 | telemetry schema, proof hooks, generated-artifact inventory, tests | pending | Receipts, fee states, projections, and source-to-shares facts emit source-safe telemetry and proof hooks. |
@@ -150,6 +150,15 @@ No `_legacy/` source is active source truth.
150150
| Tests cover package and Terminal receipt posture | `packages/btd/__tests__/api-boundaries.test.ts`, `uapi/tests/terminalTransactionDetailSnapshot.test.ts`, and `uapi/tests/terminalTransactionReadModel.test.ts` | drafted |
151151
| Gate checker protects the receipt surface | `scripts/check-v30-gate4-btd-assetpack-mint-read-receipts.mjs`, `pnpm run check:v30-gate4`, gate-quality workflow | drafted |
152152

153+
## Gate 5 Parity
154+
155+
| Requirement | Source evidence | Current V30 judgment |
156+
| --- | --- | --- |
157+
| Ledger projection report separates four fact classes | `packages/btd/src/reconciliation.ts`, `uapi/app/terminal/terminal-journal-reconciliation.ts`, `uapi/app/terminal/TerminalTransactionJournalReconciliationCard.tsx` | drafted |
158+
| Object-storage and staging-testnet repair classes are deterministic | `packages/btd/__tests__/reconciliation.test.ts`, `packages/api/src/routes/__tests__/btd-crypto.test.ts` | drafted |
159+
| Harness and Terminal consume the same report evidence | `packages/pipeline-hosts/src/asset-pack-harness.ts`, `packages/pipeline-hosts/src/__tests__/asset-pack-harness.test.ts`, `uapi/tests/terminalJournalReconciliation.test.ts`, `uapi/tests/terminalTransactionDetailSnapshot.test.ts` | drafted |
160+
| Gate checker protects projection hardening | `scripts/check-v30-gate5-testnet-ledger-projection-hardening.mjs`, `pnpm run check:v30-gate5`, gate-quality workflow | drafted |
161+
153162
## Gate 4 accepted boundaries
154163

155164
- Gate 4 does not require production-mainnet BTC settlement.
@@ -158,6 +167,14 @@ No `_legacy/` source is active source truth.
158167
- Gate 4 does not harden all ledger/database/object-storage projection repair; Gate 5 owns that.
159168
- Gate 4 does not finish source-to-shares contribution cleanup; Gate 6 owns that.
160169

170+
## Gate 5 accepted boundaries
171+
172+
- Gate 5 does not expand the physical reconciliation repair registry schema.
173+
- Gate 5 does not store or print Supabase service-role JWTs, `sb_secret__` keys, OpenAI keys, database passwords, or Vercel tokens.
174+
- Gate 5 does not make protected AssetPack source visible before paid unlock and delivery admission.
175+
- Gate 5 does not implement source-to-shares contribution accounting; Gate 6 owns that.
176+
- Gate 5 does not promote V30 or change the active canon pointer.
177+
161178
## completion condition
162179

163180
Gate 1 is complete when the V30 draft family validates, `check:v30-gate1` passes, workflow posture is V30-aware, README and roadmap reflect V30 initiation, V31-V37 scopes are current enough to guide future gates, diff hygiene passes, and the gate branch is committed and pushed for review into `version/v30`.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"check:v30-gate2": "node scripts/check-v30-gate2-protocol-package-api-boundaries.mjs",
5959
"check:v30-gate3": "node scripts/check-v30-gate3-bitcoin-taproot-psbt-fee-rigor.mjs",
6060
"check:v30-gate4": "node scripts/check-v30-gate4-btd-assetpack-mint-read-receipts.mjs",
61+
"check:v30-gate5": "node scripts/check-v30-gate5-testnet-ledger-projection-hardening.mjs",
6162
"check:spec-quality": "node scripts/run-bitcode-spec-quality.mjs --mode basic",
6263
"check:spec-quality:title": "node scripts/run-bitcode-spec-quality.mjs --mode strict-from-title",
6364
"check:spec-quality:v24": "node scripts/run-bitcode-spec-quality.mjs --mode strict-version --version V24",

packages/api/src/routes/__tests__/btd-crypto.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,24 @@ describe('BTD crypto API builders', () => {
13381338
projectedLedgerRoot: 'confirmed-root',
13391339
projectedFinalityState: 'broadcast',
13401340
},
1341+
{
1342+
factId: 'artifact-api-1',
1343+
projectedLedgerRoot: 'artifact-ledger-root',
1344+
projectedFinalityState: 'prepared',
1345+
projectedObjectStorageRoot: 'artifact-database-root',
1346+
},
1347+
],
1348+
objectStorageArtifacts: [
1349+
{
1350+
factId: 'artifact-api-1',
1351+
artifactId: 'artifact-api-1',
1352+
artifactKind: 'pipeline_evidence',
1353+
storageRoot: 'artifact-storage-root',
1354+
sourceVisibility: 'proof_public',
1355+
durable: true,
1356+
containsProtectedSource: false,
1357+
encrypted: false,
1358+
},
13411359
],
13421360
metaphysicalFacts: [
13431361
{
@@ -1348,6 +1366,27 @@ describe('BTD crypto API builders', () => {
13481366
private: true,
13491367
},
13501368
],
1369+
stagingTestnetReadback: {
1370+
kind: 'btd.supabase_projection_readback',
1371+
readbackId: 'staging-readback-api-1',
1372+
lane: 'staging-testnet',
1373+
supabaseProjectRef: 'tkpyosihuouusyaxtbau',
1374+
restHost: 'tkpyosihuouusyaxtbau.supabase.co',
1375+
adminCredentialState: 'provided_out_of_band',
1376+
secretValuesStored: false,
1377+
tableReadbacks: [
1378+
{
1379+
table: 'btd_asset_pack_ranges',
1380+
expectedCount: 1,
1381+
observedCount: 1,
1382+
synchronized: true,
1383+
},
1384+
],
1385+
state: 'synchronized',
1386+
blockingReasons: [],
1387+
proofRoot: 'btd-proof-root:supabase-projection-readback:api',
1388+
issuedAt,
1389+
},
13511390
settlementConservationChecks: [
13521391
{
13531392
checkId: 'settlement-conservation-api-1',
@@ -1369,6 +1408,9 @@ describe('BTD crypto API builders', () => {
13691408
expect(body.report.blocking).toBe(true);
13701409
expect(body.report.state).toBe('blocked');
13711410
expect(body.report.driftKindCounts.settlement_conservation_drift).toBe(1);
1411+
expect(body.report.driftKindCounts.object_storage_root_mismatch).toBe(1);
1412+
expect(body.report.objectStorageArtifacts[0].storageRoot).toBe('artifact-storage-root');
1413+
expect(body.report.stagingTestnetReadback.secretValuesStored).toBe(false);
13721414
expect(body.report.metaphysicalFacts[0].canonicalRoot).toBe('private-source-root');
13731415
expect(body.committed).toBe(true);
13741416
expect(insertReconciliationRepair).toHaveBeenCalledWith(

packages/btd/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ This package owns:
1515
Reader and Depositor identities, source-safe preview roots, paid unlock,
1616
delivery admission, and ledger projection roots without leaking protected
1717
source before settlement
18+
- ledger/database/object-storage projection reconciliation, including
19+
deterministic repair classes, source-safe object artifact roots,
20+
secret-free Supabase staging-testnet readback receipts, quarantine/retry
21+
actions, and settlement-unlock blocking posture
1822
- BTC fee operation posture, including quote lifecycle, signer recovery,
1923
no-server-custody PSBT handoff, Taproot/script posture, broadcast/finality
2024
observation, replacement/reorg repair, and testnet/mainnet network policy
@@ -44,6 +48,8 @@ import {
4448
buildBtdReadReceiptBoundarySettlement,
4549
buildBtdRightsTransferReceipt,
4650
buildBtdRegistrySnapshot,
51+
buildSupabaseStagingTestnetProjectionReadback,
52+
reconcileLedgerDatabaseProjection,
4753
toBtdJsonSafe,
4854
calculateLlmBtcFeeEstimate,
4955
buildLicensedReadRevenueRoute,

0 commit comments

Comments
 (0)