Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.PHONY: validate validate-resource-contract validate-measurement validate-value-type validate-source-locator validate-sourceos-repo-manifest validate-mesh-action-registry validate-control-plane-examples validate-nlboot-examples validate-lattice-data-governai-examples validate-ops-history-examples validate-runtime-observability-examples validate-interpretability-examples validate-lifecycle-boundary-examples validate-svf-contracts validate-sync-cycle-receipts validate-onboarding-examples validate-runtime-causality-examples validate-agentic-os-examples validate-triparty-examples validate-labor-market-examples validate-supply-chain-risk-examples validate-reasoning-examples validate-mpcc-event-examples validate-knowledge-nugget-examples validate-semantic-action-examples validate-epistemic-kernel-examples validate-ab-update-examples validate-device-service-examples validate-duplicate-schema-ids validate-lawful-dispatch-receipt validate-architectural-building-block validate-agent-passport-examples validate-seam-definition-examples validate-agent-system-vocabulary validate-genesis-inception-examples validate-measurement validate-world-model-examples validate-eval-item-examples validate-ingestion-pipeline-examples validate-data-acquisition-examples validate-glossary-alignment-examples validate-data-class-examples validate-table-keys validate-dag-loop validate-vocab-currency-loop vocab-currency-dogfood validate-glossary-promotion validate-agreement validate-stopword-analysis stopword-analysis-live validate-kgram-differential validate-learned-dictionary train-dataclass-classifiers validate-schema-references
.PHONY: validate validate-resource-contract validate-measurement validate-value-type validate-source-locator validate-sourceos-repo-manifest validate-mesh-action-registry validate-control-plane-examples validate-nlboot-examples validate-lattice-data-governai-examples validate-ops-history-examples validate-runtime-observability-examples validate-interpretability-examples validate-lifecycle-boundary-examples validate-svf-contracts validate-sync-cycle-receipts validate-onboarding-examples validate-runtime-causality-examples validate-agentic-os-examples validate-triparty-examples validate-labor-market-examples validate-supply-chain-risk-examples validate-reasoning-examples validate-mpcc-event-examples validate-knowledge-nugget-examples validate-semantic-action-examples validate-epistemic-kernel-examples validate-ab-update-examples validate-device-service-examples validate-duplicate-schema-ids validate-lawful-dispatch-receipt validate-architectural-building-block validate-agent-passport-examples validate-seam-definition-examples validate-agent-system-vocabulary validate-genesis-inception-examples validate-measurement validate-world-model-examples validate-eval-item-examples validate-ingestion-pipeline-examples validate-data-acquisition-examples validate-glossary-alignment-examples validate-data-class-examples validate-table-keys validate-dag-loop validate-vocab-currency-loop vocab-currency-dogfood validate-glossary-promotion validate-agreement validate-stopword-analysis stopword-analysis-live validate-kgram-differential validate-learned-dictionary train-dataclass-classifiers validate-schema-references validate-capture-receipt-examples

validate: validate-data-class-examples validate-glossary-alignment-examples validate-data-acquisition-examples validate-ingestion-pipeline-examples validate-control-plane-examples validate-nlboot-examples validate-lattice-data-governai-examples validate-ops-history-examples validate-runtime-observability-examples validate-interpretability-examples validate-lifecycle-boundary-examples validate-svf-contracts validate-sync-cycle-receipts validate-onboarding-examples validate-runtime-causality-examples validate-agentic-os-examples validate-triparty-examples validate-labor-market-examples validate-supply-chain-risk-examples validate-reasoning-examples validate-mpcc-event-examples validate-knowledge-nugget-examples validate-semantic-action-examples validate-epistemic-kernel-examples validate-ab-update-examples validate-device-service-examples validate-duplicate-schema-ids validate-value-type validate-source-locator validate-sourceos-repo-manifest validate-mesh-action-registry validate-lawful-dispatch-receipt validate-architectural-building-block validate-agent-passport-examples validate-seam-definition-examples validate-agent-system-vocabulary validate-genesis-inception-examples validate-measurement validate-world-model-examples validate-eval-item-examples validate-resource-contract validate-table-keys validate-dag-loop validate-vocab-currency-loop validate-glossary-promotion validate-agreement validate-stopword-analysis validate-kgram-differential validate-learned-dictionary validate-trained-classifiers validate-multiverseal-twin-examples validate-schema-references
validate: validate-data-class-examples validate-glossary-alignment-examples validate-data-acquisition-examples validate-ingestion-pipeline-examples validate-control-plane-examples validate-nlboot-examples validate-lattice-data-governai-examples validate-ops-history-examples validate-runtime-observability-examples validate-interpretability-examples validate-lifecycle-boundary-examples validate-svf-contracts validate-sync-cycle-receipts validate-onboarding-examples validate-runtime-causality-examples validate-agentic-os-examples validate-triparty-examples validate-labor-market-examples validate-supply-chain-risk-examples validate-reasoning-examples validate-mpcc-event-examples validate-knowledge-nugget-examples validate-semantic-action-examples validate-epistemic-kernel-examples validate-ab-update-examples validate-device-service-examples validate-duplicate-schema-ids validate-value-type validate-source-locator validate-sourceos-repo-manifest validate-mesh-action-registry validate-lawful-dispatch-receipt validate-architectural-building-block validate-agent-passport-examples validate-seam-definition-examples validate-agent-system-vocabulary validate-genesis-inception-examples validate-measurement validate-world-model-examples validate-eval-item-examples validate-resource-contract validate-table-keys validate-dag-loop validate-vocab-currency-loop validate-glossary-promotion validate-agreement validate-stopword-analysis validate-kgram-differential validate-learned-dictionary validate-trained-classifiers validate-multiverseal-twin-examples validate-schema-references validate-capture-receipt-examples
@echo "OK: validate"

# General referential-integrity gate: every schema is a valid JSON Schema and every
Expand Down Expand Up @@ -226,3 +226,7 @@ validate-value-type:
validate-multiverseal-twin-examples:
python3 -m pip install --user jsonschema >/dev/null
python3 tools/validate_multiverseal_twin_examples.py

validate-capture-receipt-examples:
python3 -m pip install --user jsonschema >/dev/null
python3 tools/validate_capture_receipt_examples.py
36 changes: 36 additions & 0 deletions docs/adr/0019-capture-receipt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# ADR-0019: CaptureReceipt — the universal bind-purpose-before-f() primitive

Status: Accepted
Date: 2026-08-03
Relates-to: ADR-0014 (multiverseal twin identity)

## Context

Epoch E13 / workstream WS-B. `TwinAttestation.envelope.authorization` already binds a
declared purpose + proof at ingest, but only inside the twin family. The reidentification-
economy result makes that binding a universal necessity, not a twin-local nicety: purpose is
provably **unrecoverable** from the signal — the mutual information `I(purpose; Q)` between a
purpose bit and a quasi-identifier-bearing signal `Q` is `0`. So purpose cannot be inferred
after the fact; it has to be bound BEFORE the transform `f()` runs, at capture, or it is gone.
We need one domain-agnostic object that seals it — for any capture, not just twins.

## Decisions

1. **`CaptureReceipt` generalizes the twin authorization** into a standalone contract:
`declaredPurpose` + `authorizationProof` + `boundBeforeTransform: true`, gating a named
`transform` (the `f()`), optionally bound against a `contextRef` (reference-at-ingest / VRF).
2. **Fail-closed.** `disposition ∈ {admitted, refused, inert}`. A receipt with a missing/empty
purpose or proof MUST be `refused` or `inert` — you cannot be `admitted` without a bound
purpose+proof. Enforced in-schema (required fields) and machine-checked by the validator.
3. **Ties to WS-D.** `reversibilityFloorBits` records the reversibility-distance floor this
capture re-establishes, linking WS-B to `ReversibilityDistance`.
4. Canonical examples (`capture_receipt.json` admitted, `capture_receipt_refused.json` refused)
and an invariant validator wired into `make validate`.

## Consequences

- A single primitive now carries the capture-time purpose bit across every domain; the twin's
`envelope.authorization` becomes one specialization of it rather than the only home.
- The purpose bit is sealed where it is the only place it can live — at capture — closing the
post-hoc-inference gap the reidentification result proves is otherwise unrecoverable.
- Downstream consumers can gate `f()` on a resolvable receipt and refuse fail-closed.
20 changes: 20 additions & 0 deletions examples/capture_receipt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"id": "urn:srcos:capture-receipt:abc123:qie:1",
"type": "CaptureReceipt",
"specVersion": "2.0.0",
"capturedAt": "2026-08-03T00:00:00Z",
"subjectRef": "pseudo:abc123",
"transform": {
"name": "quasi-identifier-extraction",
"inputRef": "urn:srcos:capture-input:abc123:raw"
},
"contextRef": "urn:srcos:context-ref:abc123:math-commons",
"declaredPurpose": "research-cohort-linkage-under-consent",
"authorizationProof": "sig:consent:abc123:0xdeadbeef",
"boundBeforeTransform": true,
"evidenceRefs": [
"urn:srcos:reasoning-receipt:abc123:consent-check:1"
],
"disposition": "admitted",
"reversibilityFloorBits": 12.5
}
15 changes: 15 additions & 0 deletions examples/capture_receipt_refused.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"id": "urn:srcos:capture-receipt:def456:qie:1",
"type": "CaptureReceipt",
"specVersion": "2.0.0",
"capturedAt": "2026-08-03T00:00:00Z",
"subjectRef": "pseudo:def456",
"transform": {
"name": "quasi-identifier-extraction"
},
"contextRef": "urn:srcos:context-ref:def456:unknown",
"declaredPurpose": "",
"authorizationProof": "",
"boundBeforeTransform": true,
"disposition": "refused"
}
41 changes: 41 additions & 0 deletions schemas/CaptureReceipt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.srcos.ai/v2/CaptureReceipt.json",
"title": "CaptureReceipt",
"description": "The universal capture-time receipt: the primitive that binds a declared purpose + authorization to a datum BEFORE the transform f() that would consume it runs. It generalizes TwinAttestation.envelope.authorization into a domain-agnostic object. The reidentification-economy result is the reason it must exist: purpose is provably unrecoverable from the signal — the mutual information I(purpose; Q) between a purpose bit and a quasi-identifier-bearing signal Q is 0 — so purpose CANNOT be inferred post-hoc from the captured data. It has to be bound at capture, sealed into a receipt, or it is gone forever. CaptureReceipt is that seal: it is fail-closed (no valid purpose+proof ⇒ not admitted) and it re-establishes a reversibility-distance floor tying capture to WS-D (ReversibilityDistance).",
"type": "object",
"additionalProperties": false,
"required": ["id", "type", "specVersion", "capturedAt", "declaredPurpose", "authorizationProof", "boundBeforeTransform", "disposition"],
"properties": {
"id": { "type": "string", "pattern": "^urn:srcos:capture-receipt:", "description": "Stable URN for this capture receipt." },
"type": { "const": "CaptureReceipt", "description": "Type discriminator; always 'CaptureReceipt'." },
"specVersion": { "type": "string", "description": "Semantic version of the contract." },
"capturedAt": { "type": "string", "format": "date-time", "description": "When capture occurred and this receipt was sealed — necessarily BEFORE the transform f() ran." },
"subjectRef": { "type": "string", "description": "Pseudonymous, agent-centric reference to whom/what is captured. Never a real-world identifier." },
"transform": {
"type": "object",
"additionalProperties": false,
"required": ["name"],
"description": "The transform f() this receipt gates — the operation the capture authorizes and precedes.",
"properties": {
"name": { "type": "string", "description": "The f() this receipt gates, e.g. 'quasi-identifier-extraction'." },
"inputRef": { "type": "string", "description": "Optional reference to the input the transform will consume." }
}
},
"contextRef": { "type": "string", "description": "The reference the capture is bound against (ties to reference-at-ingest / the VRF-derived context reference). Optional but recommended." },
"declaredPurpose": { "type": "string", "description": "The purpose under which capture is authorized. Bound at capture because it is provably unrecoverable afterward (I(purpose; Q) = 0)." },
"authorizationProof": { "type": "string", "description": "Proof of authorization for the declared purpose." },
"boundBeforeTransform": { "const": true, "description": "Asserts the receipt was bound BEFORE f() ran. Always true — the purpose bit cannot be recovered post-hoc, so it must be sealed at capture." },
"evidenceRefs": {
"type": "array",
"description": "Works-receipts on the evidence fabric supporting this capture.",
"items": { "type": "string", "pattern": "^urn:srcos:reasoning-receipt:" }
},
"disposition": {
"type": "string",
"enum": ["admitted", "refused", "inert"],
"description": "admitted = capture proceeds; refused = no valid authorization, capture blocked (fail-closed); inert = retained but never summed/used."
},
"reversibilityFloorBits": { "type": "number", "description": "The reversibility-distance floor (bits) this capture re-establishes; ties WS-B to WS-D (ReversibilityDistance)." }
}
}
77 changes: 77 additions & 0 deletions tools/validate_capture_receipt_examples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env python3
"""Validate CaptureReceipt examples + the invariants that make the receipt safe.

CaptureReceipt (Epoch E13 / WS-B) is the universal bind-purpose-before-f() primitive:
it seals a declared purpose + authorization onto a datum BEFORE the transform that would
consume it runs. It generalizes TwinAttestation.envelope.authorization. The reason it must
exist at capture — not later — is the reidentification-economy result that purpose is
provably unrecoverable from the signal (I(purpose; Q) = 0).

Beyond JSON Schema:
* URN prefix per contract (urn:srcos:capture-receipt:);
* boundBeforeTransform is exactly true (the whole point — sealed before f());
* fail-closed: missing/empty declaredPurpose OR authorizationProof ⇒ disposition
MUST be 'refused' or 'inert' (you cannot be 'admitted' without a bound purpose+proof);
* disposition ∈ {admitted, refused, inert}.
"""
from __future__ import annotations
import json, sys
from pathlib import Path
import jsonschema

ROOT = Path(__file__).resolve().parents[1]
PAIRS = [
("schemas/CaptureReceipt.json", "examples/capture_receipt.json"),
("schemas/CaptureReceipt.json", "examples/capture_receipt_refused.json"),
]
EXPECTED_ID_PREFIX = "urn:srcos:capture-receipt:"
VALID_DISPOSITIONS = {"admitted", "refused", "inert"}


def main() -> int:
errors: list[str] = []
for schema_rel, ex_rel in PAIRS:
schema = json.loads((ROOT / schema_rel).read_text())
doc = json.loads((ROOT / ex_rel).read_text())
try:
jsonschema.validate(doc, schema, cls=jsonschema.Draft202012Validator)
except jsonschema.ValidationError as e:
errors.append(f"{ex_rel}: schema invalid: {e.message} @ {list(e.absolute_path)}")
continue

# 1. URN prefix.
if not str(doc.get("id", "")).startswith(EXPECTED_ID_PREFIX):
errors.append(f"{ex_rel}: id must start with '{EXPECTED_ID_PREFIX}'")

# 2. boundBeforeTransform is exactly true.
if doc.get("boundBeforeTransform") is not True:
errors.append(f"{ex_rel}: boundBeforeTransform must be exactly true (sealed before f())")

# 4. disposition in the closed set.
disp = doc.get("disposition")
if disp not in VALID_DISPOSITIONS:
errors.append(f"{ex_rel}: disposition must be one of {sorted(VALID_DISPOSITIONS)}")

# 3. Fail-closed: no bound purpose+proof ⇒ cannot be admitted.
purpose = str(doc.get("declaredPurpose", "")).strip()
proof = str(doc.get("authorizationProof", "")).strip()
if (not purpose or not proof) and disp == "admitted":
errors.append(
f"{ex_rel}: fail-closed violation: disposition 'admitted' requires a "
f"non-empty declaredPurpose AND authorizationProof"
)

if not any(e.startswith(ex_rel) for e in errors):
print(f"OK {ex_rel}")

if errors:
print("\nVALIDATION FAILED:")
for e in errors:
print(f" - {e}")
return 1
print("\nAll CaptureReceipt examples valid (schema + invariants).")
return 0


if __name__ == "__main__":
sys.exit(main())
Loading