Skip to content

feat(e13-wsb): CaptureReceipt — universal bind-purpose-before-f() primitive - #282

Merged
mdheller merged 3 commits into
mainfrom
feat/e13-wsb-capture-receipt
Aug 4, 2026
Merged

feat(e13-wsb): CaptureReceipt — universal bind-purpose-before-f() primitive#282
mdheller merged 3 commits into
mainfrom
feat/e13-wsb-capture-receipt

Conversation

@mdheller

@mdheller mdheller commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Epoch E13 / WS-B — CaptureReceipt

Lands the keystone capture-time receipt as a universal primitive. It generalizes TwinAttestation.envelope.authorization (already on main in schemas/TwinAttestation.json) into a domain-agnostic object that binds a declared purpose + authorization to a datum before the transform f() that consumes it runs.

Why bind at capture

The reidentification-economy result: purpose is provably unrecoverable from the signal — I(purpose; Q) = 0 between a purpose bit and a quasi-identifier-bearing signal Q. Purpose cannot be inferred post-hoc, so it must be sealed at capture or it is gone. CaptureReceipt is that seal.

Contract

  • declaredPurpose, authorizationProof, boundBeforeTransform: true (all required) gate a named transform, optionally bound against a contextRef (reference-at-ingest / VRF).
  • Fail-closed disposition ∈ {admitted, refused, inert}: no valid purpose+proof ⇒ cannot be admitted.
  • reversibilityFloorBits ties WS-B to WS-D (ReversibilityDistance).

Machine-checked invariants (beyond schema)

  1. id starts with urn:srcos:capture-receipt:
  2. boundBeforeTransform is exactly true
  3. missing/empty declaredPurpose OR authorizationProof ⇒ disposition must be refused/inert
  4. disposition in the closed enum

Files

  • schemas/CaptureReceipt.json
  • examples/capture_receipt.json (admitted) · examples/capture_receipt_refused.json (refused)
  • tools/validate_capture_receipt_examples.py (wired into make validate)
  • docs/adr/0019-capture-receipt.md

Verification

$ python3 tools/validate_capture_receipt_examples.py
OK   examples/capture_receipt.json
OK   examples/capture_receipt_refused.json
All CaptureReceipt examples valid (schema + invariants).

$ python3 scripts/check_duplicate_schema_ids.py
OK: 353 unique schema $id values

🤖 Generated with Claude Code

@mdheller
mdheller force-pushed the feat/e13-wsb-capture-receipt branch 3 times, most recently from c3738aa to 2689b0a Compare August 4, 2026 19:59
…efore-f() primitive

Generalizes TwinAttestation.envelope.authorization into a domain-agnostic
capture-time receipt. Purpose is provably unrecoverable from the signal
(I(purpose;Q)=0), so it must be bound BEFORE the transform runs, at capture.
Fail-closed disposition; ties reversibilityFloorBits to WS-D.

Adds schemas/CaptureReceipt.json, examples/capture_receipt.json (admitted),
examples/capture_receipt_refused.json (refused), an invariant validator wired
into make validate, and ADR-0019.
contract-reconciliation CI requires the registry to be regenerated whenever a
schema is added; this PR's schema was missing from it.
@mdheller
mdheller force-pushed the feat/e13-wsb-capture-receipt branch from 2689b0a to 6cdc8bc Compare August 4, 2026 20:03
Previous commit's registry regen was run but never staged before push,
leaving a stale registry that failed contract-reconciliation CI.
@mdheller
mdheller merged commit 71d3f7d into main Aug 4, 2026
9 checks passed
@mdheller
mdheller deleted the feat/e13-wsb-capture-receipt branch August 4, 2026 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant