diff --git a/Makefile b/Makefile index 3ed5a5b..55c4820 100644 --- a/Makefile +++ b/Makefile @@ -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: 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: 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 @echo "OK: validate" validate-ingestion-pipeline-examples: @@ -213,3 +213,7 @@ validate-sync-cycle-receipts: validate-value-type: python3 tools/validate_value_type.py + +validate-multiverseal-twin-examples: + python3 -m pip install --user jsonschema >/dev/null + python3 tools/validate_multiverseal_twin_examples.py diff --git a/docs/adr/0014-multiverseal-twin-identity.md b/docs/adr/0014-multiverseal-twin-identity.md new file mode 100644 index 0000000..c279033 --- /dev/null +++ b/docs/adr/0014-multiverseal-twin-identity.md @@ -0,0 +1,64 @@ +# ADR-0014: Multiverseal Twin — the federation-facing identity/reputation projection + +Status: Accepted +Date: 2026-08-01 +Extends: ADR-0013 (digital-soul identity & reputation) + +## Context + +ADR-0013 gave us the private core (`DigitalSoulIdentity`), the reputation plane +(`ReputationDimension` / `SacredCapitalLedger` / `PortableReputationClaim`), and the +on-device `AscensionReading`. What it lacked was a principled, hardened object for the part +that actually touches the untrusted, federated world and carries imported non-first-party +reputation. The Multiverseal Twin spec supplies exactly that, on a single reference-gated +holographic substrate, with rigor-tiered guarantees. It also unifies three loose threads: +the "bind reputation to evidence" rule, the reversibility-distance privacy metric (from the +reidentification-economy dossier), and the "read movement not score" ambition. + +## Decisions + +1. **Core vs twin.** `DigitalSoulIdentity` is the sovereign, private, authoritative core. + `MultiversealTwin` is its federation-facing projection — the only object relying parties + watch. The core is never embedded in the twin; only reference-gated projections are. + +2. **Reference-at-ingest (Powell–Stetson) is mandatory.** A foreign attestation is admitted + only as `TwinAttestation` = `bind(object, r_c)` with a provenance envelope; a bare score is + never summed into reputation. Reconcilability is manufactured at ingest. This is the + holographic form of the capture-time receipt, and — per reidentification-economy §A.5 — the + *only* place the purpose/authorization bit can live, because it is provably unrecoverable + from the signal afterward. + +3. **One budget: ε = capacity = crosstalk = unlinkability = reversibility distance.** + `MultiversealTwin.unlinkability.epsilon` (Johnson–Lindenstrauss almost-orthogonality) is the + single knob. It is explicitly the reversibility-distance ledger from the reidentification + appendix — there is no separate "privacy parameter." + +4. **Access control is the code threshold.** QEC `[[n,k,d]]` sharing: `d` = policy. Any region + above `n−d` shares reconstructs; below reveals nothing. Resilience and privacy are one dial. + +5. **Mint/verify asymmetry via VRF, anchored to the verified core.** Only the subject's master + key mints; anyone verifies. The anchor is a `ProofOfSelfToken` (Identity-Is-Prime), tying + "who may mint this twin" to a proven subject. Forgery reduces to breaking VRF. + +6. **The impersonation wall is the top invariant.** A watchable persona of subject `u` mints + only under `u`'s key or a `u`-signed capability; phase-retrieval hardening is mandatory + (measurement starvation, per-view nonce, per-session references). This is the hard stop + against "author a replayable someone-else." + +7. **The primary read is the fringe, not the score.** `InterferometricDiff` reads phase drift + (`Δφ`) between two twin states — a leading indicator that moves below scalar-score + sensitivity, with global tamper-evidence for free. `AscensionReading` (ADR-0013) is the + on-device, self-directed special case: a live diff of the holder's own twin over time. This + is the operation that earns the name "prophet." + +## Consequences + +- New conformant contracts: `TwinAttestation`, `MultiversealTwin`, `InterferometricDiff`, with + canonical examples and an invariant validator wired into `make validate`. +- Reputation's "bind to the fabric" rule (ADR-0013) is sharpened to "bind-at-ingest against a + VRF reference," and `AscensionReading` is reframed as an interferometric read. +- The substrate is **linear by design**; Sybil-resistance and nonlinear trust policy stay in a + separate layer that never leaks back into the holographic medium (open problem, tracked). +- Rigor is tiered per the source spec: holographic⇄QEC isomorphism and VRF forgery-reduction + are theorems; the HRR/VSA substrate and coherence-length horizon are constructions/heuristics + to quantify before production trust. diff --git a/examples/interferometric_diff.json b/examples/interferometric_diff.json new file mode 100644 index 0000000..ec664cb --- /dev/null +++ b/examples/interferometric_diff.json @@ -0,0 +1,32 @@ +{ + "id": "urn:srcos:interferometric-diff:abc123:2026-08-01", + "type": "InterferometricDiff", + "specVersion": "2.0.0", + "capturedAt": "2026-08-01T00:00:00Z", + "twinRef": "urn:srcos:multiverseal-twin:abc123:v1", + "mode": "double-exposure", + "watcher": { + "contextRef": "vrf:rc:hiring-circle:sess-9", + "authorized": true + }, + "fringe": { + "deltaPhase": [ + 0.01, + -0.004, + 0.02, + 0.0 + ], + "magnitude": [ + 0.0, + 0.0, + 0.01, + 0.0 + ], + "subThreshold": true, + "tamperGlobalPerturbation": true, + "propagated": { + "horizon": "P30D", + "digest": "b3:forecast-abc" + } + } +} diff --git a/examples/multiverseal_twin.json b/examples/multiverseal_twin.json new file mode 100644 index 0000000..a56ff4e --- /dev/null +++ b/examples/multiverseal_twin.json @@ -0,0 +1,35 @@ +{ + "id": "urn:srcos:multiverseal-twin:abc123:v1", + "type": "MultiversealTwin", + "specVersion": "2.0.0", + "createdAt": "2026-08-01T00:00:00Z", + "coreRef": "urn:srcos:digital-soul:abc123:v1", + "space": { + "encoding": "hrr-vsa", + "dimension": 4096 + }, + "unlinkability": { + "epsilon": 0.03, + "isReversibilityBudget": true + }, + "sharing": { + "n": 5, + "k": 1, + "d": 3 + }, + "mintAnchor": { + "scheme": "vrf", + "verifyKeyRef": "key:vk:abc123", + "proofOfSelfRef": "urn:srcos:proof-of-self:abc123" + }, + "impersonationWall": { + "rule": "mint-only-under-subject-key-or-subject-signed-capability", + "phaseRetrievalHardened": true + }, + "bundle": { + "digest": "b3:H-abc", + "attestationRefs": [ + "urn:srcos:twin-attestation:abc123:math-commons:1" + ] + } +} diff --git a/examples/twin_attestation.json b/examples/twin_attestation.json new file mode 100644 index 0000000..bc66a16 --- /dev/null +++ b/examples/twin_attestation.json @@ -0,0 +1,34 @@ +{ + "id": "urn:srcos:twin-attestation:abc123:math-commons:1", + "type": "TwinAttestation", + "specVersion": "2.0.0", + "capturedAt": "2026-08-01T00:00:00Z", + "twinRef": "urn:srcos:multiverseal-twin:abc123:v1", + "contextRef": { + "contextId": "nh:math-commons", + "referenceId": "vrf:rc:math-commons:sess-1" + }, + "boundVector": { + "encoding": "hrr-vsa", + "digest": "b3:bound-abc", + "dimension": 4096 + }, + "envelope": { + "src": "nh:math-commons", + "method": "peer-review", + "issuedAt": "2026-08-01T00:00:00Z", + "weight": 0.8, + "evidenceRefs": [ + "urn:srcos:reasoning-receipt:work-1" + ], + "authorization": { + "declaredPurpose": "reputation-attestation", + "authorizationProof": "cap:signed:holder:abc123" + } + }, + "grounding": { + "state": "coherent", + "coherenceLength": 180.0, + "distance": 12.0 + } +} diff --git a/schemas/InterferometricDiff.json b/schemas/InterferometricDiff.json new file mode 100644 index 0000000..122b498 --- /dev/null +++ b/schemas/InterferometricDiff.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/InterferometricDiff.json", + "title": "InterferometricDiff", + "description": "The primary read over a MultiversealTwin: not 'return the score' but 'return the fringe' — the interference between two identity states. Reading phase (Delta-phi) detects change far below the magnitude at which a scalar score would move: it is the leading indicator, not the lagging one. This is the operation that earns 'SocioProphet' — the prophet reads fringes, not scores. It also yields tamper-evidence for free: because the encoding is holographic, a local unauthorized write perturbs the fringe globally, so tampering is detectable even without knowing what was altered. An AscensionReading (the holder's private reputation-state abstracted onto inner axes) is the on-device, self-directed special case of a live diff of the holder's own twin over time; this contract is the general, watch/replay-facing read.", + "type": "object", + "additionalProperties": false, + "required": ["id", "type", "specVersion", "capturedAt", "twinRef", "mode", "watcher", "fringe"], + "properties": { + "id": { "type": "string", "pattern": "^urn:srcos:interferometric-diff:", "description": "Stable URN for this read." }, + "type": { "const": "InterferometricDiff", "description": "Type discriminator; always 'InterferometricDiff'." }, + "specVersion": { "type": "string", "description": "Semantic version of the contract." }, + "capturedAt": { "type": "string", "format": "date-time", "description": "When the read was taken." }, + "twinRef": { "type": "string", "pattern": "^urn:srcos:multiverseal-twin:", "description": "The twin being read." }, + "mode": { + "type": "string", + "enum": ["live", "double-exposure", "time-averaged"], + "description": "live = Delta-phi(H_live, H_stored) real-time drift/tamper map; double-exposure = fringe(H(tau1), H(tau2)) the versioned changelog between two commits; time-averaged = spectrum of periodic behavior (fringe order = amplitude of each behavioral mode)." + }, + "watcher": { + "type": "object", + "additionalProperties": false, + "required": ["contextRef", "authorized"], + "description": "Who is reading, and with which reference. Each relying party unbinds with THEIR r_c to see THEIR angle; un-authored angles unbind to noise (rainbow angle-bounding). A watchable persona must be authorized under the subject key or a subject-signed capability (impersonation wall).", + "properties": { + "contextRef": { "type": "string", "description": "The reference r_c the watcher unbinds with (their sanctioned angle)." }, + "authorized": { "const": true, "description": "The watch is within a sanctioned reference subspace. Un-authored angles cannot be watched. Always true for a valid diff." } + } + }, + "fringe": { + "type": "object", + "additionalProperties": false, + "required": ["deltaPhase", "subThreshold", "tamperGlobalPerturbation"], + "description": "The fringe read itself. Phase is never collapsed to magnitude at ingest, so this read is available.", + "properties": { + "deltaPhase": { "type": "array", "items": { "type": "number" }, "description": "The interferometric fringe Delta-phi — where and how much state moved, per component." }, + "magnitude": { "type": "array", "items": { "type": "number" }, "description": "Optional raw-score magnitudes (the lagging indicator), for reference only." }, + "subThreshold": { "const": true, "description": "Asserts this read surfaces change below scalar-score movement (leading indicator). Always true — it is the point of the contract." }, + "tamperGlobalPerturbation": { "const": true, "description": "A local unauthorized write shows up as a global fringe perturbation; tamper is detectable without knowing what changed. Always true." }, + "propagated": { + "type": "object", + "additionalProperties": false, + "description": "Optional 'replay' = unbind then propagate forward to a prophet forecast of the reconstructed future state.", + "properties": { + "horizon": { "type": "string", "description": "Forecast horizon." }, + "digest": { "type": "string", "description": "Digest of the forecast reconstruction." } + } + } + } + } + } +} diff --git a/schemas/MultiversealTwin.json b/schemas/MultiversealTwin.json new file mode 100644 index 0000000..694f769 --- /dev/null +++ b/schemas/MultiversealTwin.json @@ -0,0 +1,79 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/MultiversealTwin.json", + "title": "MultiversealTwin", + "description": "The federation-facing projection of a sovereign private identity core (DigitalSoulIdentity). The core is authoritative and private; the twin is the object that touches the untrusted world, carries imported non-first-party reputation, and is watched/replayed by relying parties. It is one reference-gated holographic bundle: TwinAttestations bound-at-ingest against VRF-derived context references, superposed into a single vector that is opaque without a reference and reconstructed only by unbinding with it. Privacy, capacity, and reconstruction fidelity are one surface governed by a single unlinkability budget epsilon (= the reversibility-distance ledger of the reidentification economy). Minting is asymmetric: only the subject's master key (anchored to ProofOfSelfToken / Identity-Is-Prime) may mint a watchable persona of that subject.", + "type": "object", + "additionalProperties": false, + "required": ["id", "type", "specVersion", "createdAt", "coreRef", "space", "unlinkability", "sharing", "mintAnchor", "impersonationWall", "bundle"], + "properties": { + "id": { "type": "string", "pattern": "^urn:srcos:multiverseal-twin:", "description": "Stable URN for this twin." }, + "type": { "const": "MultiversealTwin", "description": "Type discriminator; always 'MultiversealTwin'." }, + "specVersion": { "type": "string", "description": "Semantic version of the contract." }, + "createdAt": { "type": "string", "format": "date-time", "description": "When the twin projection was created." }, + "coreRef": { "type": "string", "pattern": "^urn:srcos:digital-soul:", "description": "The private core (DigitalSoulIdentity) this twin projects. The core is never included in the twin; only reference-gated projections of it are." }, + "space": { + "type": "object", + "additionalProperties": false, + "required": ["encoding", "dimension"], + "description": "The holographic medium V = C^D (complex, so phase = provenance is literal).", + "properties": { + "encoding": { "type": "string", "enum": ["hrr-vsa"], "description": "Holographic Reduced Representation / Vector-Symbolic Algebra." }, + "dimension": { "type": "integer", "minimum": 1, "description": "D — the twin space dimension." } + } + }, + "unlinkability": { + "type": "object", + "additionalProperties": false, + "required": ["epsilon", "isReversibilityBudget"], + "description": "The single number governing capacity, crosstalk, AND cross-context unlinkability (Johnson-Lindenstrauss / almost-orthogonality). Two contexts are epsilon-unlinkable iff their reference inner product || <= epsilon. This IS the reversibility-distance budget from the reidentification-economy appendix: tightening epsilon buys unlinkability + fidelity at the cost of capacity. There is no separate privacy parameter.", + "properties": { + "epsilon": { "type": "number", "exclusiveMinimum": 0, "description": "Orthogonality tolerance = crosstalk bound = linkability leakage bound." }, + "isReversibilityBudget": { "const": true, "description": "Asserts epsilon is the reversibility-distance ledger, not a cosmetic knob. Always true." } + } + }, + "sharing": { + "type": "object", + "additionalProperties": false, + "required": ["n", "k", "d"], + "description": "QEC [[n,k,d]] erasure-style sharing. Resilience and access control are ONE threshold: any region holding more than n-d shares reconstructs; any region below threshold reveals nothing. d = policy (the access-control wedge IS the code distance).", + "properties": { + "n": { "type": "integer", "minimum": 1, "description": "Total shares." }, + "k": { "type": "integer", "minimum": 1, "description": "Logical payload dimension." }, + "d": { "type": "integer", "minimum": 1, "description": "Code distance = access/resilience threshold, set by policy." } + } + }, + "mintAnchor": { + "type": "object", + "additionalProperties": false, + "required": ["scheme", "verifyKeyRef", "proofOfSelfRef"], + "description": "Mint/verify asymmetry via a Verifiable Random Function. The core holds the master secret msk; the world holds the verify key vk. Context references r_c and their proofs are VRF_msk(context) — pseudorandom, near-orthogonal (they ARE the references §space/§unlinkability assume). A twin record is valid iff VRF.Verify(vk, context, r_c, proof)=1. Forging an un-minted record reduces to breaking VRF unforgeability.", + "properties": { + "scheme": { "type": "string", "enum": ["vrf"], "description": "Trust anchor scheme." }, + "verifyKeyRef": { "type": "string", "description": "Reference to the public verify key vk (relying parties verify freely; cannot mint)." }, + "proofOfSelfRef": { "type": "string", "pattern": "^urn:srcos:proof-of-self:", "description": "Anchors the master key to the verified-identity core (ProofOfSelfToken / Identity-Is-Prime). Binds 'who may mint this twin' to a proven subject." } + } + }, + "impersonationWall": { + "type": "object", + "additionalProperties": false, + "required": ["rule", "phaseRetrievalHardened"], + "description": "The tightest discipline in the system (twin spec §E.3). A watchable persona of subject u may be minted ONLY under u's own master key, or under a capability explicitly signed by u. No third party mints a replayable u. Phase-retrieval (reconstruct provenance from enough intensity-only views without the key) is the attack that erodes this wall, so hardening is mandatory.", + "properties": { + "rule": { "const": "mint-only-under-subject-key-or-subject-signed-capability", "description": "Always this value." }, + "phaseRetrievalHardened": { "const": true, "description": "Countermeasures active: measurement starvation (rate-limit per party), per-view phase nonce, per-session (non-reusable) references, non-generic served views. Always true." }, + "capabilityRef": { "type": "string", "description": "Optional: a subject-signed capability authorizing a specific third party to mint a bounded persona." } + } + }, + "bundle": { + "type": "object", + "additionalProperties": false, + "required": ["digest", "attestationRefs"], + "description": "The superposed twin vector H = bundle(t_k) and the attestations it holds. H is a hiding commitment: without a reference it is a sum of pseudo-random vectors.", + "properties": { + "digest": { "type": "string", "description": "Content digest of the bundled twin vector H." }, + "attestationRefs": { "type": "array", "items": { "type": "string", "pattern": "^urn:srcos:twin-attestation:" }, "description": "The TwinAttestations superposed into H (each bound-at-ingest)." } + } + } + } +} diff --git a/schemas/TwinAttestation.json b/schemas/TwinAttestation.json new file mode 100644 index 0000000..102853a --- /dev/null +++ b/schemas/TwinAttestation.json @@ -0,0 +1,71 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/TwinAttestation.json", + "title": "TwinAttestation", + "description": "A single foreign attestation admitted into a MultiversealTwin, bound-at-ingest against a context reference. Realizes the Powell-Stetson rule: an imported claim (object beam o) is admissible ONLY as t = bind(o, r_c) with a provenance envelope; a bare unbound score is never summed into reputation. The context reference r_c is VRF-derived (see TwinRecord.mintAnchor). Reconcilability is manufactured at ingest, not deferred. This is the holographic form of the capture-time receipt: purpose/authorization are bound to the event before it enters the reputation ledger.", + "type": "object", + "additionalProperties": false, + "required": ["id", "type", "specVersion", "capturedAt", "twinRef", "contextRef", "boundVector", "envelope", "grounding"], + "properties": { + "id": { "type": "string", "pattern": "^urn:srcos:twin-attestation:", "description": "Stable URN for this bound attestation." }, + "type": { "const": "TwinAttestation", "description": "Type discriminator; always 'TwinAttestation'." }, + "specVersion": { "type": "string", "description": "Semantic version of the contract." }, + "capturedAt": { "type": "string", "format": "date-time", "description": "Ingest time (record-beam time) — when binding occurred." }, + "twinRef": { "type": "string", "pattern": "^urn:srcos:multiverseal-twin:", "description": "The twin this attestation is bundled into." }, + "contextRef": { + "type": "object", + "additionalProperties": false, + "required": ["contextId", "referenceId"], + "description": "The context reference r_c this claim was bound against (VRF-derived; see TwinRecord.mintAnchor).", + "properties": { + "contextId": { "type": "string", "description": "The federation context/neighbourhood this binding is for." }, + "referenceId": { "type": "string", "description": "Identifier of the VRF-derived reference r_c used to bind." } + } + }, + "boundVector": { + "type": "object", + "additionalProperties": false, + "required": ["encoding", "digest"], + "description": "The bound record t = bind(o, r_c). The bare object o is NEVER stored here; only its binding against the reference.", + "properties": { + "encoding": { "type": "string", "enum": ["hrr-vsa"], "description": "Substrate: Holographic Reduced Representation / Vector-Symbolic Algebra over C^D. Phase carries provenance; magnitude carries raw score." }, + "digest": { "type": "string", "description": "Content digest of the bound vector (the stored, opaque-without-reference record)." }, + "dimension": { "type": "integer", "minimum": 1, "description": "D of the twin space (must match the twin's dimension)." } + } + }, + "envelope": { + "type": "object", + "additionalProperties": false, + "required": ["src", "method", "issuedAt", "authorization"], + "description": "Provenance envelope pi = (src, method, tau, w). Bound with the claim so purpose/authorization are sealed at capture, not inferred later.", + "properties": { + "src": { "type": "string", "description": "Source of the attestation (issuing neighbourhood / authority)." }, + "method": { "type": "string", "description": "How the claim was produced/measured." }, + "issuedAt": { "type": "string", "format": "date-time", "description": "tau: source time of the claim." }, + "weight": { "type": "number", "description": "w: source-assigned weight/confidence." }, + "evidenceRefs": { "type": "array", "items": { "type": "string", "pattern": "^urn:srcos:reasoning-receipt:" }, "description": "Works-receipts on the reasoning-evidence fabric substantiating the claim." }, + "authorization": { + "type": "object", + "additionalProperties": false, + "required": ["declaredPurpose", "authorizationProof"], + "description": "The purpose/consent bit — provably unrecoverable from the signal, so it must be bound here at ingest (reidentification-economy §A.5).", + "properties": { + "declaredPurpose": { "type": "string", "description": "The purpose under which this claim was captured/admitted." }, + "authorizationProof": { "type": "string", "description": "Proof of authorization for that purpose." } + } + } + } + }, + "grounding": { + "type": "object", + "additionalProperties": false, + "required": ["state"], + "description": "Coherence-length gate. If the context/temporal distance delta(o, r_c) exceeds the trust reference's coherence length L_c, the import is ungroundable — retained as inert evidence, never summed.", + "properties": { + "state": { "type": "string", "enum": ["coherent", "decohered"], "description": "coherent = groundable and summable into reputation; decohered = inert evidence only." }, + "coherenceLength": { "type": "number", "description": "L_c ~= c/Delta-nu, the derived trust horizon (replaces an arbitrary reputation-decay constant)." }, + "distance": { "type": "number", "description": "delta(o, r_c) — context/temporal distance from the reference." } + } + } + } +} diff --git a/tools/validate_multiverseal_twin_examples.py b/tools/validate_multiverseal_twin_examples.py new file mode 100644 index 0000000..ba3d9a8 --- /dev/null +++ b/tools/validate_multiverseal_twin_examples.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +"""Validate MultiversealTwin family examples + the invariants that make the twin safe. + +Beyond JSON Schema: + * URN prefix per contract; + * reference-at-ingest: a TwinAttestation stores only a boundVector (never a bare object) + and carries an authorization (declaredPurpose + proof) — the purpose bit is bound at + capture, not inferred later; + * unlinkability budget: epsilon > 0 and flagged as the reversibility-distance ledger; + * sharing threshold sane: 1 <= d <= n; + * impersonation wall: fixed rule + phase-retrieval hardened; + * mint asymmetry: VRF anchored to a ProofOfSelfToken; + * interferometric read: authorized watcher, sub-threshold + global-tamper asserted. +""" +from __future__ import annotations +import json, sys +from pathlib import Path +import jsonschema + +ROOT = Path(__file__).resolve().parents[1] +PAIRS = [ + ("schemas/TwinAttestation.json", "examples/twin_attestation.json"), + ("schemas/MultiversealTwin.json", "examples/multiverseal_twin.json"), + ("schemas/InterferometricDiff.json", "examples/interferometric_diff.json"), +] +EXPECTED_IDS = { + "TwinAttestation": "urn:srcos:twin-attestation:", + "MultiversealTwin": "urn:srcos:multiverseal-twin:", + "InterferometricDiff": "urn:srcos:interferometric-diff:", +} + + +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 + + t = doc.get("type") + pfx = EXPECTED_IDS.get(t) + if pfx and not str(doc.get("id", "")).startswith(pfx): + errors.append(f"{ex_rel}: id must start with '{pfx}'") + + if t == "TwinAttestation": + bv = doc.get("boundVector", {}) + if "object" in bv or "bareObject" in bv or "intensity" in bv: + errors.append(f"{ex_rel}: reference-at-ingest violation: a bare object was stored") + auth = doc.get("envelope", {}).get("authorization", {}) + if not auth.get("declaredPurpose") or not auth.get("authorizationProof"): + errors.append(f"{ex_rel}: attestation missing bound authorization (purpose+proof)") + if doc.get("grounding", {}).get("state") not in ("coherent", "decohered"): + errors.append(f"{ex_rel}: grounding.state must be coherent|decohered") + + if t == "MultiversealTwin": + u = doc.get("unlinkability", {}) + if not (u.get("epsilon", 0) > 0) or u.get("isReversibilityBudget") is not True: + errors.append(f"{ex_rel}: unlinkability epsilon must be >0 and flagged as reversibility budget") + s = doc.get("sharing", {}) + if not (1 <= s.get("d", 0) <= s.get("n", 0)): + errors.append(f"{ex_rel}: sharing must satisfy 1 <= d <= n") + w = doc.get("impersonationWall", {}) + if w.get("rule") != "mint-only-under-subject-key-or-subject-signed-capability" or w.get("phaseRetrievalHardened") is not True: + errors.append(f"{ex_rel}: impersonation wall not enforced") + m = doc.get("mintAnchor", {}) + if m.get("scheme") != "vrf" or not str(m.get("proofOfSelfRef", "")).startswith("urn:srcos:proof-of-self:"): + errors.append(f"{ex_rel}: mint anchor must be VRF anchored to a ProofOfSelfToken") + + if t == "InterferometricDiff": + if doc.get("watcher", {}).get("authorized") is not True: + errors.append(f"{ex_rel}: watcher must be authorized (rainbow angle-bounding)") + f = doc.get("fringe", {}) + if f.get("subThreshold") is not True or f.get("tamperGlobalPerturbation") is not True: + errors.append(f"{ex_rel}: fringe must assert sub-threshold + global tamper properties") + + 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 MultiversealTwin examples valid (schema + invariants).") + return 0 + + +if __name__ == "__main__": + sys.exit(main())