Skip to content

Commit 3d371cb

Browse files
Merge pull request #40 from engineeredsoftware/v30/gate-8-protocol-telemetry-proof-hooks
V30 Gate 8: Protocol Telemetry And Proof Hooks
2 parents 54abbbe + 0791894 commit 3d371cb

15 files changed

Lines changed: 1135 additions & 3 deletions

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ jobs:
8686
node scripts/check-v30-gate5-testnet-ledger-projection-hardening.mjs --skip-branch-check
8787
node scripts/check-v30-gate6-source-to-shares-proof-cleanup.mjs --skip-branch-check
8888
node scripts/check-v30-gate7-bridge-readiness-research-boundaries.mjs --skip-branch-check
89+
node scripts/check-v30-gate8-protocol-telemetry-proof-hooks.mjs --skip-branch-check
8990
else
9091
echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2
9192
exit 1

BITCODE_SPEC_V30.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ V30 closes through ten gates:
205205
5. **Gate 5: Testnet Ledger Projection Hardening** hardens ledger/database/object-storage projection, repair classes, and staging-testnet readback.
206206
6. **Gate 6: Source-To-Shares Proof Cleanup** cleans contribution measurement, settlement conservation, zero-cell/refit tail, ancestry, and no-overpayment/no-underpayment proof.
207207
7. **Gate 7: Bridge Readiness Research Boundaries** records bridge research without admitting any bridge as chain-of-record truth.
208-
8. **Gate 8: Protocol Telemetry And Proof Hooks** adds source-safe telemetry and proof hooks for receipts, fee states, projection, and source-to-shares facts.
208+
8. **Gate 8: Protocol Telemetry And Proof Hooks** adds source-safe telemetry and proof hooks for receipts, fee states, projection, source-to-shares facts, and bridge-readiness posture.
209209
9. **Gate 9: Interface Integration And Regression Proof** proves current interfaces consume package-owned objects without V29 behavior regression.
210210
10. **Gate 10: V30 Promotion Readiness** validates local/staging proof, generated artifacts, V30 promotion workflow support, and post-promotion V30 active / V31 draft posture.
211211

@@ -262,6 +262,31 @@ Gate 7 bridge-readiness research boundaries:
262262
research evidence, but they must fail closed on any payload attempting to
263263
set `chainOfRecordAdmitted` or to mark a bridge as current BTD truth.
264264

265+
Gate 8 Protocol telemetry proof hooks:
266+
267+
- `BtdProtocolTelemetryEnvelope` is the package-owned source-safe carrier for
268+
Protocol/BTD observability that V32 provation and V35 documentation can
269+
replay without reading protected source or secrets.
270+
- `BtdProtocolTelemetryRecord` rows cover exactly these V30 subjects:
271+
`btd_receipt`, `btc_fee_state`, `ledger_projection`,
272+
`source_to_shares_proof`, and `bridge_readiness_posture`.
273+
- `BtdProtocolProofHook` binds each record to theorem ids, replay step ids,
274+
witness artifact paths, optional generated artifact paths, the evidence root,
275+
and the telemetry root.
276+
- Telemetry events must match subject kinds; a BTC fee event cannot be emitted
277+
as a receipt, a ledger projection cannot be emitted as a bridge posture, and
278+
every mismatch fails closed.
279+
- Telemetry metadata is scalar and source-safe. Payloads with protected source,
280+
private source text, API keys, service-role keys, JWT-looking secrets, or
281+
private keys fail closed before becoming Terminal, API, or generated proof
282+
evidence.
283+
- The BTD API exposes `/btd/protocol-telemetry` as the source-safe boundary for
284+
these records. It returns a Terminal journal `proof_admission` entry and does
285+
not commit generated proof artifacts or source-bearing material.
286+
- Gate 8 creates the generated-artifact inventory slot
287+
`.bitcode/v30-protocol-telemetry-proof-hooks.json`; promotion may generate
288+
it only from source-safe telemetry/proof-hook facts.
289+
265290
## V30 whole Bitcode operator chain
266291

267292
The V30 Terminal operator chain is:
@@ -783,6 +808,7 @@ V30 continues operator-quality proof: Terminal workflow claims must be backed by
783808
| `.bitcode/v30-spec-family-report.json` | yes | yes | validates the hand-authored V30 family shape |
784809
| `.bitcode/v30-canonical-input-report.json` | yes | yes | records canonical input closure for active V29 plus V30 draft |
785810
| `.bitcode/v30-canon-posture-drift-report.json` | gate-dependent | yes | proves runtime/docs active/draft posture |
811+
| `.bitcode/v30-protocol-telemetry-proof-hooks.json` | gate-dependent | yes | records source-safe Protocol telemetry and proof-hook inventory for provation/documentation |
786812
| `BITCODE_SPEC_V30_PROVEN.md` | no | yes | generated proof appendix for promoted V30 |
787813

788814
### V30 specifying generated artifacts

BITCODE_SPEC_V30_DELTA.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,24 @@ Closure acceptance:
277277
- telemetry avoids protected source and secrets;
278278
- proof hooks are compatible with V32 provation and V35 documentation/observability work.
279279

280+
Gate 8 implementation centers:
281+
282+
- `packages/btd/src/telemetry.ts` owns `BtdProtocolTelemetryEnvelope`,
283+
`BtdProtocolTelemetryRecord`, `BtdProtocolProofHook`, source-safety checks,
284+
event/subject matching, and V32/V35 proof compatibility markers.
285+
- `packages/btd/src/api-boundaries.ts` owns
286+
`buildBtdProtocolTelemetrySettlement`, binding telemetry envelopes into a
287+
Terminal journal `proof_admission` row without committing source-bearing
288+
artifacts.
289+
- `packages/api/src/routes/btd-crypto.ts` and
290+
`/btd/protocol-telemetry` expose the JSON-safe route boundary.
291+
- `packages/btd/__tests__/telemetry.test.ts` and the BTD crypto route tests
292+
prove typed emission, source/secret rejection, proof-hook replay facts, and
293+
route JSON safety.
294+
- `.bitcode/v30-protocol-telemetry-proof-hooks.json` is reserved as a
295+
generated source-safe inventory artifact for promotion proof; it is not a
296+
protected-source carrier.
297+
280298
### Gate 9: Interface Integration And Regression Proof
281299

282300
Gate 9 proves existing interfaces can consume the hardened Protocol/BTD rails.

BITCODE_SPEC_V30_NOTES.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,26 @@ No Gate 7 code may mint, wrap, transfer, settle, or unlock BTD through a bridge.
231231
The only current chain-of-record posture is `bitcoin_btd_registry` plus
232232
`no_bridge_chain_of_record`.
233233

234+
## Gate 8 Protocol telemetry notes
235+
236+
Gate 8 turns Protocol/BTD observability into package-owned typed telemetry
237+
instead of leaving receipts, fee states, ledger projections, source-to-shares
238+
proofs, and bridge-readiness posture as unrelated payload fragments.
239+
240+
The accepted implementation is `BtdProtocolTelemetryEnvelope` in
241+
`packages/btd/src/telemetry.ts`. It contains source-safe telemetry records and
242+
`BtdProtocolProofHook` rows that name theorem ids, replay step ids, witness
243+
artifact paths, generated artifact paths, evidence roots, and telemetry roots.
244+
The envelope is compatible with V32 provation and V35 documentation/
245+
observability because it carries replayable source-safe proof facts without
246+
requiring protected source.
247+
248+
Gate 8 rejects event/subject mismatches and secret-shaped metadata before a row
249+
can reach Terminal, API, generated proof, or persistence surfaces. The API
250+
boundary exposes `/btd/protocol-telemetry` as a JSON-safe proof-admission route;
251+
it does not commit source-bearing artifacts, and it does not replace existing
252+
crypto telemetry rows used for deployment readiness health.
253+
234254
## Gate 1 working notes
235255

236256
Gate 1 is complete only when the V30 family exists, validates in draft mode over active V29, and makes the roadmap truthful enough to drive V31 through V37 without stale V27/V28/V29 posture.

BITCODE_SPEC_V30_PARITY_MATRIX.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ No `_legacy/` source is active source truth.
6161
| 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 | `packages/btd/src/source-to-shares.ts`, API route boundary, focused BTD/API tests, gate checker | drafted | Measurement contribution, fee allocation, zero-cell/refit tail, ancestry evidence, and conservation invariants are testable. |
6363
| Bridge-readiness research boundaries | Gate 7 | `packages/btd/src/bridge-readiness.ts`, BTD/API tests, route boundary, docs, gate checker | drafted | Bridge paths are typed research-only records until admitted by explicit future proof and policy. |
64-
| 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. |
64+
| Protocol telemetry/proof hooks | Gate 8 | `packages/btd/src/telemetry.ts`, API route boundary, focused BTD/API tests, gate checker | drafted | Receipts, fee states, projections, source-to-shares proofs, and bridge-readiness posture emit source-safe telemetry and proof hooks. |
6565
| Interface integration regression | Gate 9 | Terminal/API/MCP/ChatGPT App adapters and tests | pending | Existing interfaces consume package-owned objects without regressing V29 behavior. |
6666
| Promotion readiness | Gate 10 | V30 promotion workflow, generated `.bitcode/v30-*`, `BITCODE_SPEC_V30_PROVEN.md` | pending | `version/v30` can promote to `main` only after all V30 checks pass and promotion automation can commit generated canon. |
6767

@@ -210,6 +210,25 @@ No `_legacy/` source is active source truth.
210210
- Gate 7 may expose source-safe research posture to Terminal/API callers for operator review.
211211
- Gate 7 does not promote V30 or change the active canon pointer.
212212

213+
## Gate 8 Parity
214+
215+
| Requirement | Source evidence | Current V30 judgment |
216+
| --- | --- | --- |
217+
| Protocol telemetry is package-owned | `packages/btd/src/telemetry.ts`, `packages/btd/src/index.ts` | drafted |
218+
| Receipt, BTC fee, ledger projection, source-to-shares, and bridge-readiness subjects are typed | `BTD_PROTOCOL_TELEMETRY_SUBJECT_KINDS`, `packages/btd/__tests__/telemetry.test.ts` | drafted |
219+
| Telemetry rows and proof hooks reject protected source and secrets | `sourceSafety`, metadata source-safety tests | drafted |
220+
| Proof hooks carry theorem, replay, witness, generated artifact, evidence, and telemetry roots | `BtdProtocolProofHook`, `buildBtdProtocolProofHook`, focused tests | drafted |
221+
| API and Terminal boundary expose JSON-safe proof-admission telemetry | `buildBtdProtocolTelemetrySettlement`, `buildPostBtdProtocolTelemetryRoute`, `uapi/app/api/btd/protocol-telemetry/route.ts` | drafted |
222+
| Gate checker protects telemetry/proof-hook boundaries | `scripts/check-v30-gate8-protocol-telemetry-proof-hooks.mjs`, `pnpm run check:v30-gate8`, gate-quality workflow | drafted |
223+
224+
## Gate 8 accepted boundaries
225+
226+
- Gate 8 does not expose protected source, prompt bodies, private source text, private keys, service-role keys, OpenAI keys, JWT-looking secrets, or database passwords in telemetry.
227+
- Gate 8 does not replace deployment-readiness crypto telemetry persistence; it adds Protocol/BTD source-safe proof hooks that later V32 and V35 work can consume.
228+
- Gate 8 does not generate promotion artifacts yet; it reserves `.bitcode/v30-protocol-telemetry-proof-hooks.json` as a source-safe generated inventory.
229+
- Gate 8 may expose telemetry/proof hooks to Terminal/API callers for operator review.
230+
- Gate 8 does not promote V30 or change the active canon pointer.
231+
213232
## completion condition
214233

215234
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
@@ -61,6 +61,7 @@
6161
"check:v30-gate5": "node scripts/check-v30-gate5-testnet-ledger-projection-hardening.mjs",
6262
"check:v30-gate6": "node scripts/check-v30-gate6-source-to-shares-proof-cleanup.mjs",
6363
"check:v30-gate7": "node scripts/check-v30-gate7-bridge-readiness-research-boundaries.mjs",
64+
"check:v30-gate8": "node scripts/check-v30-gate8-protocol-telemetry-proof-hooks.mjs",
6465
"check:spec-quality": "node scripts/run-bitcode-spec-quality.mjs --mode basic",
6566
"check:spec-quality:title": "node scripts/run-bitcode-spec-quality.mjs --mode strict-from-title",
6667
"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: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ import {
2525
buildBtdLicensedReadRevenueSettlement,
2626
buildBtdMintDraft,
2727
buildBtdOrganizationInterfaceAuthorityDecision,
28+
buildBtdProtocolTelemetrySettlement,
2829
buildBtdReadAccessDecision,
2930
buildBtdSourceToSharesProofSettlement,
3031
buildBtdTerminalJournalSettlement,
32+
buildBtdProtocolTelemetryRecord,
3133
buildBtcFeeQuote,
3234
createBtdMeasureMintState,
3335
} from '@bitcode/btd';
@@ -43,6 +45,7 @@ import {
4345
buildPostBtdLicensedReadRevenueRoute,
4446
buildPostBtdMintDraftRoute,
4547
buildPostBtdOrganizationInterfaceAuthorityRoute,
48+
buildPostBtdProtocolTelemetryRoute,
4649
buildPostBtdReadAccessRoute,
4750
buildPostBtdSourceToSharesProofRoute,
4851
buildPostBtdTerminalJournalRoute,
@@ -217,6 +220,45 @@ function bridgeReadinessResearchBody(overrides: Record<string, unknown> = {}) {
217220
};
218221
}
219222

223+
function protocolTelemetryBody(overrides: Record<string, unknown> = {}) {
224+
const telemetry = {
225+
event: 'btd.source_to_shares_proof.emitted' as const,
226+
subjectKind: 'source_to_shares_proof' as const,
227+
subjectId: 'source-to-shares-api-1',
228+
root: 'source-to-shares-api-root',
229+
receiptRoot: 'source-to-shares-api-receipt-root',
230+
proofRoot: 'source-to-shares-api-proof-root',
231+
artifactPath: '.bitcode/source-to-shares-api-proof.json',
232+
metadata: {
233+
sourceSafe: true,
234+
settlementAdmissible: true,
235+
},
236+
issuedAt,
237+
};
238+
const record = buildBtdProtocolTelemetryRecord(telemetry);
239+
240+
return {
241+
telemetry: [telemetry],
242+
proofHooks: [
243+
{
244+
proofFamily: 'source_to_shares' as const,
245+
subjectKind: 'source_to_shares_proof' as const,
246+
subjectId: 'source-to-shares-api-1',
247+
evidenceRoot: 'source-to-shares-api-root',
248+
telemetryRoot: record.telemetryRoot,
249+
theoremIds: ['source-safe', 'settlement-conserved'],
250+
replayStepIds: ['emit-telemetry', 'bind-source-to-shares-proof'],
251+
witnessArtifactPaths: ['.bitcode/source-to-shares-api-proof.json'],
252+
generatedArtifactPath: '.bitcode/generated/source-to-shares-api-proof.json',
253+
issuedAt,
254+
},
255+
],
256+
exchangeSequence: '20',
257+
issuedAt,
258+
...overrides,
259+
};
260+
}
261+
220262
describe('BTD crypto API builders', () => {
221263
it('builds a deterministic mint draft from accepted Read-Fit semantic units', () => {
222264
const draft = buildBtdMintDraft(mintDraftInput());
@@ -1002,6 +1044,32 @@ describe('BTD crypto API builders', () => {
10021044
expect(settlement.terminalJournalEntry.receiptRoots).toContain(settlement.posture.proofRoot);
10031045
});
10041046

1047+
it('builds Protocol telemetry settlements with source-safe proof hooks', () => {
1048+
const settlement = buildBtdProtocolTelemetrySettlement({
1049+
actorId: 'user-1',
1050+
...protocolTelemetryBody(),
1051+
exchangeSequence: 20n,
1052+
} as any);
1053+
1054+
expect(settlement.kind).toBe('btd_protocol_telemetry_settlement');
1055+
expect(settlement.committed).toBe(false);
1056+
expect(settlement.envelope.compatibleWith).toEqual(['V32', 'V35']);
1057+
expect(settlement.envelope.sourceSafety.sourceSafe).toBe(true);
1058+
expect(settlement.envelope.telemetry[0]).toMatchObject({
1059+
event: 'btd.source_to_shares_proof.emitted',
1060+
subjectKind: 'source_to_shares_proof',
1061+
});
1062+
expect(settlement.envelope.telemetry[0].sourceSafety.containsProtectedSource).toBe(false);
1063+
expect(settlement.envelope.proofHooks[0]).toMatchObject({
1064+
proofFamily: 'source_to_shares',
1065+
subjectKind: 'source_to_shares_proof',
1066+
});
1067+
expect(settlement.terminalJournalEntry.transactionKind).toBe('proof_admission');
1068+
expect(settlement.terminalJournalEntry.receiptRoots).toContain(
1069+
settlement.envelope.telemetryRoot,
1070+
);
1071+
});
1072+
10051073
it('builds deployment readiness, telemetry, and upgrade settlements', () => {
10061074
const readiness = buildBtdDeploymentReadinessSettlement({
10071075
actorId: 'user-1',
@@ -1592,6 +1660,28 @@ describe('BTD crypto API builders', () => {
15921660
expect(body.terminalJournalEntry.exchangeSequence).toBe('19');
15931661
});
15941662

1663+
it('returns JSON-safe Protocol telemetry proof hooks from the route boundary', async () => {
1664+
const route = buildPostBtdProtocolTelemetryRoute({
1665+
resolveAuthenticatedUser: async () => ({ userId: 'user-1' }),
1666+
});
1667+
const response = await route(
1668+
new Request('https://bitcode.test/api/btd/protocol-telemetry', {
1669+
method: 'POST',
1670+
body: JSON.stringify(protocolTelemetryBody()),
1671+
}),
1672+
);
1673+
const body = await response.json();
1674+
1675+
expect(response.status).toBe(200);
1676+
expect(body.kind).toBe('btd_protocol_telemetry_settlement');
1677+
expect(body.committed).toBe(false);
1678+
expect(body.envelope.compatibleWith).toEqual(['V32', 'V35']);
1679+
expect(body.envelope.sourceSafety.containsSecret).toBe(false);
1680+
expect(body.envelope.telemetry[0].event).toBe('btd.source_to_shares_proof.emitted');
1681+
expect(body.envelope.proofHooks[0].proofFamily).toBe('source_to_shares');
1682+
expect(body.terminalJournalEntry.exchangeSequence).toBe('20');
1683+
});
1684+
15951685
it('returns JSON-safe deployment readiness settlements and persists telemetry or upgrades', async () => {
15961686
const insertCryptoTelemetryEvent = jest.fn(async (row) => ({
15971687
event: row.event,

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import {
2626
type BtdMintDraft,
2727
type BtdMintDraftInput,
2828
type BtdOrganizationInterfaceAuthorityRouteInput,
29+
type BtdProtocolTelemetryBoundaryInput,
30+
type BtdProtocolTelemetrySettlement,
2931
type BtdReadAccessInput,
3032
type BtdReadAccessDecision,
3133
type BtdReadLicense,
@@ -49,6 +51,7 @@ import {
4951
buildBtdLicensedReadRevenueSettlement,
5052
buildBtdMintDraft,
5153
buildBtdOrganizationInterfaceAuthorityDecision,
54+
buildBtdProtocolTelemetrySettlement,
5255
buildBtdReadAccessDecision,
5356
buildBtdRegistrySnapshot,
5457
buildBtdSourceToSharesProofSettlement,
@@ -72,6 +75,7 @@ export {
7275
buildBtdLicensedReadRevenueSettlement,
7376
buildBtdMintDraft,
7477
buildBtdOrganizationInterfaceAuthorityDecision,
78+
buildBtdProtocolTelemetrySettlement,
7579
buildBtdReadAccessDecision,
7680
buildBtdRegistrySnapshot,
7781
buildBtdSourceToSharesProofSettlement,
@@ -638,6 +642,39 @@ export function buildPostBtdBridgeReadinessResearchRoute(options: BtdRouteOption
638642
});
639643
}
640644

645+
export function buildPostBtdProtocolTelemetryRoute(options: BtdRouteOptions = {}) {
646+
return traceRoute('/btd/protocol-telemetry', async (request: Request) => {
647+
const user = await (options.resolveAuthenticatedUser ?? defaultResolveAuthenticatedUser)(
648+
request,
649+
);
650+
if (!user) {
651+
return createJsonResponse({ error: 'Unauthorized' }, 401);
652+
}
653+
654+
let body: Omit<BtdProtocolTelemetryBoundaryInput, 'actorId' | 'exchangeSequence'> & {
655+
exchangeSequence: string | number;
656+
};
657+
try {
658+
body = await request.json();
659+
} catch {
660+
return createJsonResponse({ error: 'Invalid JSON body' }, 400);
661+
}
662+
663+
let settlement: BtdProtocolTelemetrySettlement;
664+
try {
665+
settlement = buildBtdProtocolTelemetrySettlement({
666+
...body,
667+
actorId: user.userId,
668+
exchangeSequence: parseBtdRequiredBigInt(body.exchangeSequence, 'exchangeSequence'),
669+
});
670+
} catch (error) {
671+
return createJsonResponse({ error: toBadRequestMessage(error) }, 400);
672+
}
673+
674+
return createJsonResponse(toJsonSafe(settlement));
675+
});
676+
}
677+
641678
export function buildPostBtdDeploymentReadinessRoute(options: BtdRouteOptions = {}) {
642679
return traceRoute('/btd/deployment-readiness', async (request: Request) => {
643680
const user = await (options.resolveAuthenticatedUser ?? defaultResolveAuthenticatedUser)(
@@ -699,6 +736,7 @@ export const postBtdLedgerDatabaseReconciliation =
699736
buildPostBtdLedgerDatabaseReconciliationRoute();
700737
export const postBtdSourceToSharesProof = buildPostBtdSourceToSharesProofRoute();
701738
export const postBtdBridgeReadinessResearch = buildPostBtdBridgeReadinessResearchRoute();
739+
export const postBtdProtocolTelemetry = buildPostBtdProtocolTelemetryRoute();
702740
export const postBtdDeploymentReadiness = buildPostBtdDeploymentReadinessRoute();
703741

704742
function toBadRequestMessage(error: unknown): string {

0 commit comments

Comments
 (0)