Skip to content

Commit 9af2ed6

Browse files
mdhellermdheller
andauthored
feat(model-plane): emit hash-chained InferenceReceipts natively (T7-16) (#124)
Agent Machine grants a model-plane capability to an agent pod and authenticates the local inference socket; every completion over that socket must leave a provenance receipt (its InferenceProvider contract declares receiptRequired). This makes Agent Machine emit spec-conformant, hash-chained InferenceReceipts natively into the estate's single ledger (SEAM-011: no local-only ledger). Consume-not-fork: the schema and the hash-chain/canonical-JSON/ledger machinery are vendored VERBATIM from the canonical emitter in prophet-platform apps/receipt-gateway (source commit + sha256 recorded in provenance). The only addition is emit_socket_inference_receipt(), which binds requestingAgentRef + capabilityLeaseRef (what socket auth resolves) into the receipt before chaining. Teeth (scripts/validate-inference-receipt.py, wired into make validate): a produced receipt validates against InferenceReceipt.schema.json and chains (prevHash continuity); a tampered entry and a local-only unchained entry are both rejected; an off-device receipt without lease+escalation is schema-rejected (SEAM-015). Co-authored-by: mdheller <charles.peterson@socioprophet.ai>
1 parent 8160a80 commit 9af2ed6

5 files changed

Lines changed: 728 additions & 2 deletions

File tree

Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: validate-no-merge-duplication validate validate-json validate-yaml validate-quadlet validate-render validate-evidence validate-governance validate-policy-fabric validate-agent-registry validate-superconscious-runtime-plan validate-activation validate-attestation validate-supply-chain validate-release-bundle validate-sourceos-projections validate-package validate-cli validate-formula validate-runtime-install-receipts doctor probe validate-artifact-digest-honesty validate-consent-before-staging
1+
.PHONY: validate-no-merge-duplication validate validate-json validate-yaml validate-quadlet validate-render validate-evidence validate-governance validate-policy-fabric validate-agent-registry validate-superconscious-runtime-plan validate-activation validate-attestation validate-supply-chain validate-release-bundle validate-sourceos-projections validate-package validate-cli validate-formula validate-runtime-install-receipts doctor probe validate-artifact-digest-honesty validate-consent-before-staging validate-inference-receipt
22

33
PYTHON ?= python3
44
RUBY ?= ruby
@@ -22,7 +22,7 @@ DECIDED_AT := 2026-05-04T12:51:00Z
2222
PYCLI := PYTHONPATH=src $(PYTHON) -m agent_machine.cli
2323
PYMOD := PYTHONPATH=src $(PYTHON) -m
2424

25-
validate: validate-no-merge-duplication validate-json validate-yaml validate-quadlet validate-render validate-evidence validate-governance validate-policy-fabric validate-agent-registry validate-superconscious-runtime-plan validate-activation validate-attestation validate-supply-chain validate-release-bundle validate-sourceos-projections validate-package validate-cli validate-formula validate-runtime-install-receipts validate-artifact-digest-honesty validate-consent-before-staging
25+
validate: validate-no-merge-duplication validate-json validate-yaml validate-quadlet validate-render validate-evidence validate-governance validate-policy-fabric validate-agent-registry validate-superconscious-runtime-plan validate-activation validate-attestation validate-supply-chain validate-release-bundle validate-sourceos-projections validate-package validate-cli validate-formula validate-runtime-install-receipts validate-artifact-digest-honesty validate-consent-before-staging validate-inference-receipt
2626

2727
validate-no-merge-duplication:
2828
$(PYTHON) scripts/validate-no-merge-duplication.py
@@ -34,6 +34,9 @@ validate-artifact-digest-honesty:
3434
validate-consent-before-staging:
3535
$(PYTHON) scripts/validate-consent-before-staging.py
3636

37+
validate-inference-receipt:
38+
$(PYTHON) scripts/validate-inference-receipt.py
39+
3740
validate-json:
3841
$(PYTHON) scripts/validate-json.py
3942

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://schemas.srcos.ai/v2/InferenceReceipt.json",
4+
"$comment": "VENDORED VERBATIM (do not edit) from SocioProphet/prophet-platform apps/receipt-gateway/schemas/model-plane/InferenceReceipt.schema.json @ commit abd98805, sha256:3d4c2a55070d65dbc902ba0880ea61c9ae6cbbca2b675c559a01a18a8b734499. Canonical owner: SourceOS-Linux/sourceos-spec (Tranche 7). Refresh via: cp from prophet-platform; do not diverge (SEAM-011).",
5+
"title": "InferenceReceipt",
6+
"description": "VENDORED from SourceOS-Linux/sourceos-spec (Tranche 7, canonical owner). Provenance receipt emitted for every model-plane completion (Tranche 7 / Model Plane). Identifies the tier, the content-addressed base model / adapter / tokenizer digests, the serving daemon and provider, the data-residency class the request was served under, and the escalation chain if any. This is the provenance primitive that makes on-device inference auditable: it references the existing Model Carry family (InferenceProvider, ModelResidency, SourceOSModelCarryRef) rather than restating it. Receipts are ledger-bound; a local-only ledger is not permitted (SEAM-011).",
7+
"type": "object",
8+
"additionalProperties": false,
9+
"required": [
10+
"id",
11+
"type",
12+
"specVersion",
13+
"issuedAt",
14+
"providerDaemon",
15+
"tier",
16+
"baseModelDigest",
17+
"task",
18+
"inputHash",
19+
"outputHash",
20+
"dataResidencyClass",
21+
"ledgerSeq"
22+
],
23+
"properties": {
24+
"id": {
25+
"type": "string",
26+
"pattern": "^urn:srcos:inference-receipt:",
27+
"description": "Stable URN identifier. Pattern: urn:srcos:inference-receipt:<local-id>"
28+
},
29+
"type": {
30+
"const": "InferenceReceipt",
31+
"description": "Discriminator constant \u2014 always \"InferenceReceipt\"."
32+
},
33+
"specVersion": {
34+
"type": "string",
35+
"description": "Spec version of this document, e.g. \"2.1.0\"."
36+
},
37+
"issuedAt": {
38+
"type": "string",
39+
"format": "date-time",
40+
"description": "Timestamp when the completion finished and the receipt was issued."
41+
},
42+
"requestingAgentRef": {
43+
"type": [
44+
"string",
45+
"null"
46+
],
47+
"pattern": "^urn:srcos:agent-passport:",
48+
"description": "AgentPassport URN of the agent that requested the inference. Null only for internal system-initiated inference."
49+
},
50+
"requestingAgentClass": {
51+
"type": [
52+
"string",
53+
"null"
54+
],
55+
"enum": [
56+
"system_core",
57+
"intelligence_automation",
58+
"app_helper",
59+
"legacy_bridge",
60+
"third_party",
61+
null
62+
],
63+
"description": "Mirror of the requesting agent's AgentPassport.agent_class, for at-a-glance audit. Authoritative source is the referenced passport."
64+
},
65+
"capabilityLeaseRef": {
66+
"type": [
67+
"string",
68+
"null"
69+
],
70+
"pattern": "^urn:srcos:lease:",
71+
"description": "AgentCapabilityLease URN authorizing this provider connection. Null is only valid for on_device_only T0 system inference; any non-on_device_only receipt MUST carry a lease (enforced below)."
72+
},
73+
"providerDaemon": {
74+
"type": "string",
75+
"enum": [
76+
"inferenced",
77+
"embeddingd",
78+
"visiond",
79+
"distilld"
80+
],
81+
"description": "The model-plane serving daemon that produced this completion. Note: modelplaned is a catalog authority and does not perform inference, so it never emits an InferenceReceipt."
82+
},
83+
"providerRef": {
84+
"type": [
85+
"string",
86+
"null"
87+
],
88+
"pattern": "^urn:srcos:inference-provider:",
89+
"description": "InferenceProvider URN backing the serving daemon."
90+
},
91+
"tier": {
92+
"type": "string",
93+
"enum": [
94+
"T0",
95+
"T1",
96+
"T2",
97+
"T3",
98+
"T4"
99+
],
100+
"description": "Placement tier that served the request. Tier boundaries are data-residency boundaries (Model Plane \u00a7II)."
101+
},
102+
"baseModelDigest": {
103+
"type": "string",
104+
"pattern": "^sha256:[a-fA-F0-9]{64}$",
105+
"description": "Content-addressed digest of the base model weights that served the request."
106+
},
107+
"adapterDigest": {
108+
"type": [
109+
"string",
110+
"null"
111+
],
112+
"pattern": "^sha256:[a-fA-F0-9]{64}$",
113+
"description": "Content-addressed digest of the active LoRA adapter, or null when the base model served the request with no adapter."
114+
},
115+
"tokenizerDigest": {
116+
"type": [
117+
"string",
118+
"null"
119+
],
120+
"pattern": "^sha256:[a-fA-F0-9]{64}$",
121+
"description": "Content-addressed digest of the tokenizer used."
122+
},
123+
"modelCarryRef": {
124+
"type": [
125+
"string",
126+
"null"
127+
],
128+
"pattern": "^urn:srcos:model-carry-ref:",
129+
"description": "SourceOSModelCarryRef URN under which the model was carried/authorized."
130+
},
131+
"modelResidencyRef": {
132+
"type": [
133+
"string",
134+
"null"
135+
],
136+
"pattern": "^urn:srcos:model-residency:",
137+
"description": "ModelResidency URN observed at serving time."
138+
},
139+
"task": {
140+
"type": "string",
141+
"description": "Task label the request was routed as, e.g. summarization, embedding, agent_classification, ocr-recognize."
142+
},
143+
"inputHash": {
144+
"type": "string",
145+
"pattern": "^sha256:[a-fA-F0-9]{64}$",
146+
"description": "Hash of the canonical input. The receipt records that an inference occurred and over what, not the content."
147+
},
148+
"inputTokenCount": {
149+
"type": [
150+
"integer",
151+
"null"
152+
],
153+
"minimum": 0,
154+
"description": "Input token count, or null for non-text modalities."
155+
},
156+
"outputHash": {
157+
"type": "string",
158+
"pattern": "^sha256:[a-fA-F0-9]{64}$",
159+
"description": "Hash of the canonical output."
160+
},
161+
"outputTokenCount": {
162+
"type": [
163+
"integer",
164+
"null"
165+
],
166+
"minimum": 0,
167+
"description": "Output token count, or null for non-text modalities."
168+
},
169+
"confidence": {
170+
"type": [
171+
"number",
172+
"null"
173+
],
174+
"minimum": 0,
175+
"maximum": 1,
176+
"description": "Model-reported confidence used for the escalation trigger, or null when not estimated."
177+
},
178+
"confidenceMethod": {
179+
"type": [
180+
"string",
181+
"null"
182+
],
183+
"enum": [
184+
"logit-entropy",
185+
"verbalized",
186+
"calibration-head",
187+
"downstream-validation",
188+
"none",
189+
null
190+
],
191+
"description": "How `confidence` was derived. REVIEW HARDENING (Model Plane OQ1 / finding: confidence is the load-bearing escalation gate and is self-reported): recording the method makes the number auditable and lets downstream calibration checks run. A null method with a non-null confidence should be treated as uncalibrated."
192+
},
193+
"latencyMs": {
194+
"type": [
195+
"integer",
196+
"null"
197+
],
198+
"minimum": 0,
199+
"description": "End-to-end serving latency in milliseconds."
200+
},
201+
"escalatedFrom": {
202+
"type": [
203+
"string",
204+
"null"
205+
],
206+
"enum": [
207+
"T0",
208+
"T1",
209+
"T2",
210+
"T3",
211+
null
212+
],
213+
"description": "The tier this request was escalated FROM, or null if served at first placement. Must be null when dataResidencyClass is on_device_only (enforced below)."
214+
},
215+
"escalationChain": {
216+
"type": "array",
217+
"description": "Ordered EscalationDecision URNs recording each tier/residency boundary this request crossed. Empty when served at first placement.",
218+
"items": {
219+
"type": "string",
220+
"pattern": "^urn:srcos:escalation-decision:"
221+
}
222+
},
223+
"dataResidencyClass": {
224+
"type": "string",
225+
"enum": [
226+
"on_device_only",
227+
"sovereign_cluster",
228+
"external_permitted"
229+
],
230+
"description": "The residency class this completion was served under. Any class other than on_device_only means the input crossed a data boundary and MUST be accompanied by a lease and a non-empty escalation chain (enforced below; SEAM-015)."
231+
},
232+
"computeDevice": {
233+
"type": [
234+
"string",
235+
"null"
236+
],
237+
"enum": [
238+
"ane",
239+
"gpu",
240+
"cpu",
241+
"npu",
242+
"remote",
243+
null
244+
],
245+
"description": "Hardware path that executed the compute."
246+
},
247+
"ledgerSeq": {
248+
"type": "integer",
249+
"minimum": 0,
250+
"description": "Monotonic sequence number of this receipt in the append-only ledger."
251+
},
252+
"ledgerPrevHash": {
253+
"type": [
254+
"string",
255+
"null"
256+
],
257+
"pattern": "^sha256:[a-fA-F0-9]{64}$",
258+
"description": "REVIEW HARDENING (finding: the ledger is the trust anchor for every Model Plane provenance claim but `ledgerSeq` alone does not bind entry N to N-1). Hash of the prior ledger entry, making the ledger tamper-evident/hash-chained so an enumerated contribution list cannot be retroactively rewritten."
259+
},
260+
"evidenceHash": {
261+
"type": [
262+
"string",
263+
"null"
264+
],
265+
"pattern": "^sha256:[a-fA-F0-9]{64}$",
266+
"description": "Hash of the canonical receipt evidence payload."
267+
},
268+
"evidenceRefs": {
269+
"type": "array",
270+
"description": "Additional evidence URNs or content hashes.",
271+
"items": {
272+
"type": "string"
273+
}
274+
}
275+
},
276+
"allOf": [
277+
{
278+
"$comment": "SEAM-015: a completion served off-device (not on_device_only) must carry both an authorizing capability lease and a non-empty escalation chain. Possession of the output is not authorization for the crossing.",
279+
"if": {
280+
"properties": {
281+
"dataResidencyClass": {
282+
"enum": [
283+
"sovereign_cluster",
284+
"external_permitted"
285+
]
286+
}
287+
},
288+
"required": [
289+
"dataResidencyClass"
290+
]
291+
},
292+
"then": {
293+
"required": [
294+
"capabilityLeaseRef",
295+
"escalatedFrom",
296+
"escalationChain"
297+
],
298+
"properties": {
299+
"capabilityLeaseRef": {
300+
"type": "string"
301+
},
302+
"escalatedFrom": {
303+
"type": "string",
304+
"enum": [
305+
"T0",
306+
"T1",
307+
"T2",
308+
"T3"
309+
]
310+
},
311+
"escalationChain": {
312+
"minItems": 1
313+
}
314+
}
315+
}
316+
},
317+
{
318+
"$comment": "An on_device_only completion cannot have been escalated from a lower tier.",
319+
"if": {
320+
"properties": {
321+
"dataResidencyClass": {
322+
"const": "on_device_only"
323+
}
324+
},
325+
"required": [
326+
"dataResidencyClass"
327+
]
328+
},
329+
"then": {
330+
"properties": {
331+
"escalatedFrom": {
332+
"const": null
333+
}
334+
}
335+
}
336+
},
337+
{
338+
"$comment": "REVIEW HARDENING (ledger tamper-evidence): any non-genesis entry (ledgerSeq >= 1) must carry the prior entry's hash, so the append-only ledger is hash-chained and an enumerated contribution list cannot be retroactively rewritten.",
339+
"if": {
340+
"properties": {
341+
"ledgerSeq": {
342+
"minimum": 1
343+
}
344+
},
345+
"required": [
346+
"ledgerSeq"
347+
]
348+
},
349+
"then": {
350+
"required": [
351+
"ledgerPrevHash"
352+
],
353+
"properties": {
354+
"ledgerPrevHash": {
355+
"type": "string"
356+
}
357+
}
358+
}
359+
}
360+
]
361+
}

0 commit comments

Comments
 (0)