From 88f4071718ed1d65fb420b235b57af0f7816c0dc Mon Sep 17 00:00:00 2001 From: mdheller Date: Mon, 3 Aug 2026 01:54:39 -0400 Subject: [PATCH] feat(model-plane): native InferenceReceipt emitter shim for inferenced (T7-12 emitter slice) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit source-os is a downstream emitter for the Tranche 7 Model Plane. This adds the smallest real slice that proves source-os can emit a spec-conformant, hash-chained InferenceReceipt natively when a completion finishes, into the estate's single ledger (SEAM-011: no local-only ledger). Consume-not-fork: the canonical emitter and schema are vendored BYTE-VERBATIM from prophet-platform apps/receipt-gateway (provenance + source sha256 in modules/model-plane/tools/VENDOR.md and the schema $comment). The only source-os code is inferenced_shim.py, the serving-path caller — it delegates all chaining to emit_receipt() and re-implements nothing. Teeth (.github/workflows/model-plane-receipts.yml): a produced receipt validates against InferenceReceipt.schema.json and chains (prevHash continuity); a tampered entry and a local-only (unchained) entry are both rejected; and the vendored emitter is asserted to match the canonical sha256 (consume-not-fork guard). The full daemon set (T7-9..15) and seam-registry (T7-20) remain; see the T7 follow-up issue. docs/model-plane/architecture.md (T7-9 stub) tracks status. --- .github/workflows/model-plane-receipts.yml | 48 +++ docs/model-plane/architecture.md | 47 +++ .../inferenced_shim.cpython-312.pyc | Bin 0 -> 8886 bytes modules/model-plane/inferenced_shim.py | 144 +++++++ .../model-plane/InferenceReceipt.schema.json | 361 ++++++++++++++++++ modules/model-plane/tools/VENDOR.md | 27 ++ .../inference_receipt_emitter.cpython-312.pyc | Bin 0 -> 10650 bytes .../tools/inference_receipt_emitter.py | 171 +++++++++ 8 files changed, 798 insertions(+) create mode 100644 .github/workflows/model-plane-receipts.yml create mode 100644 docs/model-plane/architecture.md create mode 100644 modules/model-plane/__pycache__/inferenced_shim.cpython-312.pyc create mode 100755 modules/model-plane/inferenced_shim.py create mode 100644 modules/model-plane/schemas/model-plane/InferenceReceipt.schema.json create mode 100644 modules/model-plane/tools/VENDOR.md create mode 100644 modules/model-plane/tools/__pycache__/inference_receipt_emitter.cpython-312.pyc create mode 100755 modules/model-plane/tools/inference_receipt_emitter.py diff --git a/.github/workflows/model-plane-receipts.yml b/.github/workflows/model-plane-receipts.yml new file mode 100644 index 0000000..b1cb851 --- /dev/null +++ b/.github/workflows/model-plane-receipts.yml @@ -0,0 +1,48 @@ +name: model-plane-receipts + +# Teeth for the Model Plane (Tranche 7) receipt emitter shim: proves source-os emits +# spec-conformant, hash-chained InferenceReceipts and that tampered / local-only receipts +# are rejected (SEAM-011). CI needs no model — the emitter path is what is under test. + +on: + pull_request: + paths: + - 'modules/model-plane/**' + - '.github/workflows/model-plane-receipts.yml' + push: + branches: + - main + paths: + - 'modules/model-plane/**' + - '.github/workflows/model-plane-receipts.yml' + +jobs: + inferenced-receipt-teeth: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install jsonschema + run: python -m pip install --quiet 'jsonschema>=4.22,<5' + + - name: Assert emitter is vendored byte-verbatim (consume-not-fork) + run: | + set -euo pipefail + expected=6881246b8e41a515fb1b29df645faeb9be17d8195d22a7e0d5ce15f8477d8e6a + actual=$(sha256sum modules/model-plane/tools/inference_receipt_emitter.py | awk '{print $1}') + if [ "$actual" != "$expected" ]; then + echo "ERR: vendored emitter diverged from canonical (expected $expected, got $actual)." + echo " Refresh from prophet-platform apps/receipt-gateway; do not fork (SEAM-011)." + exit 1 + fi + echo "OK: emitter matches canonical sha256:$expected" + + - name: inferenced emit-shim teeth + run: python modules/model-plane/inferenced_shim.py --selftest + + - name: Canonical emitter self-test + run: python modules/model-plane/tools/inference_receipt_emitter.py --selftest diff --git a/docs/model-plane/architecture.md b/docs/model-plane/architecture.md new file mode 100644 index 0000000..a2d63d7 --- /dev/null +++ b/docs/model-plane/architecture.md @@ -0,0 +1,47 @@ +# Model Plane on source-os (Tranche 7) + +The Model Plane is source-os's tiered, on-device inference substrate: placement tiers +**T0–T4** where a tier boundary *is* a data-residency boundary, with provenance receipts, +consent-gated escalation, and governed distillation. The canonical contracts are owned by +`SourceOS-Linux/sourceos-spec` (Tranche 7); source-os is a downstream **emitter**. + +## Status + +This directory currently ships the **emitter shim** for the serving path — the smallest +real slice that proves source-os can emit a spec-conformant, hash-chained +`InferenceReceipt` natively. The full daemon set is not yet built. + +| Slice | Item | State | +|-------|------|-------| +| T7-9 | `docs/model-plane/architecture.md` | this stub | +| T7-10 | `profiles/model-plane/{constrained,standard,workstation,cluster-node}.nix` | not built | +| T7-11 | `modules/modelplaned/` (catalog + residency) | not built | +| T7-12 | `modules/inferenced/` (serving) | **emitter shim only** (`modules/model-plane/inferenced_shim.py`) | +| T7-13 | `modules/embeddingd/` | not built | +| T7-14 | `modules/visiond/` (no network namespace) | not built | +| T7-15 | `modules/distilld/` (governed distillation) | not built | +| T7-20 | `docs/seam-registry.md` — SEAM-014..017 | not built | + +Everything not built here is tracked in the T7 follow-up issue. + +## Receipt spine (SEAM-011) + +Every completion a serving daemon finishes must leave an `InferenceReceipt` in the estate's +single **hash-chained** ledger — a local-only ledger is not permitted (SEAM-011). source-os +**consumes** the canonical emitter (`prophet-platform apps/receipt-gateway`, +vendored byte-verbatim under `modules/model-plane/tools/`); it does not re-implement the +chain. `modules/model-plane/inferenced_shim.py` is the serving-path caller: given the +content-addressed base-model digest and the input/output of a finished completion, it +appends an on-device receipt via the vendored `emit_receipt()`. + +Teeth (`.github/workflows/model-plane-receipts.yml`): a produced receipt validates against +`InferenceReceipt.schema.json` and chains (prevHash continuity); a tampered entry and a +local-only (unchained) entry are both rejected; and the vendored emitter is asserted to +match the canonical sha256 (consume-not-fork guard). + +## Off-device escalation + +An on-device (`on_device_only`) completion carries no lease and no escalation. A completion +served off-device (`sovereign_cluster` / `external_permitted`) crosses a data boundary and +must carry an authorizing capability lease and a non-empty escalation chain (SEAM-015); +the schema enforces this. Off-device serving is out of scope for the emitter shim. diff --git a/modules/model-plane/__pycache__/inferenced_shim.cpython-312.pyc b/modules/model-plane/__pycache__/inferenced_shim.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c496b815e0bc02b1bc53fcce159d49ee67ecb586 GIT binary patch literal 8886 zcmb_iZEPDydfp|MU&{}XA|+9>Wv?t*5@k`Jwv)%^gal`IX(J z9I@0v$sG_GXTUacXcY7gQGxrRzyhKI1)2j6sBxj^C;g?Ib#Uun zeP@A%skJmKDFCf3a-`eRP+~KiuxVSXqQQSpdT&K6!k78 zPytGy1zn7e>jF9&KkH-qfS%l$07LGEfPvhN0VCX*m?>@!m}yE!Av3bvgLd#0tyAxn z>AhkmT3=bJJ_l^b5N&$4JlgzhnLtBdHOM9yGFFPxdc3DoC27i{>g^0TK|f2ZE?ys~ zk2eGw;@*Ha-WX_%HwBttY%YQQ5fj)USOwcpX$#aU{|U8%{YS>YPQfiWK&Dyn2sLou zg?0zx!OdO-sZ{C0uX$DY-&q*KuvZ_zXQRtmY=D6yGXs#Y*U&Gu(&E}P2ZzOex` zbR;p!2|S8J^PQ?V7m>I`Qs%CuBQcqq0(H2~h>T0G#gd`xNc6{e0VRgmQ51`v68Y2= z7em4%bW7R`fmYXe3Hjqh&sZdc5)$;%&4ok+_2dX2lYBkg#1ynhMg(^m^cz1reCEu^ z_yj8=KE_G7B9!womlBiH2xOCKF@*d{i3{-wGE|P|q!bGIL&-!qDaQGP+zmsQru?BP zK9WEJ``Vah&P%E-U*paVPmH}ha^?zmV+tjpflxA@iXj=BHylYsq$wl~aWGt&zYcw3 zy~2D*mOxTfOEno=G#T{9frb^0$dNeM3)cg!WEifW7X%SW5)vxSB19&U1nOcznU}72 zb9_R;IX03=rRCmaT85jCl=7(*N(j(Vf=ed+0-DB_DFz28CrKO77%!s^>8bG-{la#R zj|`vn_x1M=fnzyvA|LZ76S0}%dmJDqk_jmtM}Ba;A8dJjh~ptzh#kRqyIbP?ymVlvJ`9Hgd@>`%pb8T*?9!$`f_EWy3s;AgbR3P)my1JmPJR>uJY zpNxd?w1|K|lQ$B0*k{IuSdJ^HA_Q?nf&!f1UkvKQDPEp>0rKUb_N(55=;a3v92`1) zaQ_r~;{~qj<@aOva))F5H59|m5dZp#dWXZfKy`JgEdHoRAk3&?QI3d)lRtocxSXxAfxB)IL z@sp@mKsfkdMVjG|C?>@o_G`St`Dn$;Cm>o#1W4x~&s+dQDF)))O!LU4OG8{#g0O<+ zDbAA>C6a(Bje$lVfHbzi*LZ#R85HCAiP4d>!-}O8EQ$>WgBBTzQ8l$amga@R2B)_jcyJohuz{-l0|d zp}7|~7{@x(nrB+qnZ7*Jw^F~xJilSBTeo)QtzAn8SFHm%X5bODK`HuBDh;|h@QRw2 zQBYm&LYgzN+pzJ8qhZs2%F$UWOJ{XieHLRHUDmLyzgKh_7?sIf9)XC06%PL zV=#(4Kr#fs(pB=qZ^0{-6Hdc~vw+!VX&HQ_UQqxz+b>P_05z+Vi^vrwPHFlHI*bQr z_2ua!=(Q<%l6v(jyklf+9&&;20lf-_Ec18N&vb%Oy#xL#PWM@ZT$-j?Dq5q}E8nvQ zt#$1#(YN-?E=@u(<2D7$&-8MwRu=VWPv!eETgH5VORe~?Try*0D7itC2CXUW-Cx0C zHEWzTWsOp2MX&a(36JQz_X&9UnLaDpbExfUW2C99K8hn|+a=U2J2jao4uEZ!=Dk_7 zT*CCxUE72pn>7nI+`QJ-tVPB#OfJEtm1ZqM?O`aBaa5BlTjCzL1^f>5#38%w65P>_ zZAFmHmT$QMpC z717ViKFvy5R?}q`xKh?C>>$>)M)zqF<-4%6GIsyZ8D!O3*6vcJHJiVmHNpRQ$Jutl zIB}#FeG6-eEo+PRZWDrRMP!w1J;uZT#a zXNHfD0C7CYjbAx8F*-6ac7kwWfc+{171IfzMbOzH&<3bVkxl|uE-?}e@w*8`1&(#* z%vlcV^khyI@jd@NuS|UjAQVYO4+d+oukp^Pm^EOZag`A~=onAQT&AvER319#W2!-b zO#O?)V`o&CVIrn6#7qsRB0ZoU1iOhCCY<{kW2#KET8G#g_)Ib#1Dc9BA~(ck>d&99 zbn-qTH^hl}=M4#n@YxzFEa|mDXUtX14tMudZkR_ zMDAKro&tezS_1Bx;7W5qodOx(h2imWIGrfLO%lLUz*0?rk)jN&QG zw3ONjcuI=AICC-rkpYBYM#OkbF~A8D9Nu6=s4&3qWyJ~&h(W^kB*l;tBMDj2OEVHM z1{n~lC}IpHV$h?oQYsdaV{q6ai5L%wZk*U~g5jaU-VmWN72-0{WF(<5LL>yurIIOy zNdmQ03`E3dS1cuBp%{yxnHEI6uPby!p+!ZPysqfu(j-tI+@YdF{R)GTw!#wo2JxAO zLWd=+p9+JEsfvazL2asu7eL|#_(|_Wm=gT!+VPHUZmeK$0lH#wty|jimbNuZ`%=q> ztL_f}PD5_TVBR%2Z`^Rz-+BFSz4OBx&W?h!eyM#WQ)up4dVMLB+cA(kemVEbmE7e( z?%35WgU3sPS(&>vCRFYh`z?e)u!}=j0fDGsms+q_sh^fM}HB0 zU>hsAJ&zmJid#*T#gTKiFG`Cj=jdKD`!|i0t6|;A<(=G8N6yKuItSLBNAk`itInhI zh9YfSFf8!znOE&C^SXZwe-v0fIJ!8n7|XW~Zn$?YTzcooykVZdX$F$8Zf?w*8yDK% z_r2#^99eDZTAIi=^?!6KXKq|GpWLu|7wQ)qSFQV&hQF}(U~Owpem3~|&?iF=Y%gOq z{Y5oGRAdnFqE2 zR;g(6&05OgxqbEK)dlzBjrpr<_TH8Lg3W&W)Xh^r8C!_1g8xqDJ$-Ao{>OUC(f9i* zLp`_l(ktsP1@kWjAJ|^QP46g*a?alS2Q?WZaI$Gse+zw-7&`Y*M|2jKQ^b}LTz4?lOhQU9C$ zZb&~d?K*8Ye6n{Co`2h7h4fR(aGEuJYB!v&w|rV_!X=G{(|b%MUJX6KQF)P9e*yba zC7-KyfKquxGD~OaXpv#zhO|r23(T@XLuJ4*s!JK=(h*GMN%^-(moWXewpZc|-zvfW zSv^|+ENPoyUv@k-=F-8BW*1;4z(oYAsmzCTSzWbbA(1VkZH;S?axlY61P^*fSzC*3Ha(mj-a{ayHY?w8cttOY)Z4~d* z+perpa4$D#Hqo@AsTpqwkbDSyFsr{o`5Mn<_EtcLF%3mrQa_ETP#Ml;SR#5o4X_4qoHz;JZ!)@W zj-Xr-9{`ros?SgjI2TXZ6k`M*bjt*}`sx%jw3XsTfESKoaS}d`B;*S?3n!`YT_Ff> zNtueGSR#oFB@t6-f-nepDfg(I{t-N;o&MpBID~5)#mOO@U@A@k839>DJ%X+jgOHA= zBzzPM9Zf4b9zYcCQlS$HJ*}9E<`74r0STX`J%xXmI1nlk;l}ZM94K&Ti@^?;w{SWC z#G2)$x#I=K`1biX&)+$-v~%t}-kys2zx??G&UY2_IghWLxih-PG;4zAmOWUoN6VjI zZo~QBQpNTagW9sye*4JHBMY7de&O1Jch$OQ?&L$0_3hcWW;bfQKmMDXx#{6<-_rgM z4}EYbx9hpw(D~fOm)0*%<}Xg>{$i@I8+P~)8$W2w?HXK3+!ubG{5Y9A@N!{y&kD2N zcP!s`EVpa;8-s4w33`jt)m)^%q44wFi8~h;=!Y+!x*z$2fpWSwN$K1vc#CC>l(}ZZ zY|lBnmnJ^E^1+pr8>{}Kx$a{*hX&Hj#>gk zhBdr<^zPAhcX!_1y)v0|cdxo%D0sZQFZQaw8_w;;Z%6WQLJ;w?SJJuVz@(o>E z7RJ&&H@w9HB)HXfyX$5bsQCIC+p@;&0dVj?j~cORKAmC| zk(?G2nU;?77l58>9{@Uh4mBV#>?ctPs9qM;gXAe(hSxcfJmHl|eZuE@>eD2CItGbP zC*o&C55xedXb_$=7R(&3LUXT@cVYy~wJ4@wP)LS?LHKMC45vX)6by<0FDUU9oDj-D zLjC|`6%*#+vB))bO2HuUJfh)TxChl){eBNI-{1-~*V_SXv0RBXRBHBl)mG$O}1jSGf!!JosyeIx8`I zAoB=2BEiS;ps*D_pvWn?$~Mf0)h{Y9h;P6vOtz)}f@D)q)ATothi3lRMbWLlqiVjQ ztY1;=S5(cvQ{MkDS?5Q8_=9y*bKcavYTCVSYR{Y6=a>Sef7|?~`R$rFYwpl@2k*!W zlXrix>TX}7IyM=G_I}0GJ!W;Z?vE5Ck61lDxap(@pZ~^Srj3QpeVclGA38$r54(Fe zarwi;#~$JPqxyc@{%DGBqV1bQ6l0sue4%grlJ(r3SZIB}^S#b@{(6;d%Q0=6dWvcK z@6F44%Iy9F^yB@KvE*3aivFM2e_$UlhoH)xi$C_~n1)RQynP~J8u;;E=6EmltKK~) HT>Ae76v}|M literal 0 HcmV?d00001 diff --git a/modules/model-plane/inferenced_shim.py b/modules/model-plane/inferenced_shim.py new file mode 100755 index 0000000..9cf7e28 --- /dev/null +++ b/modules/model-plane/inferenced_shim.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +"""`inferenced` receipt-emission shim (Model Plane, Tranche 7 — emitter half of T7-12). + +The full `inferenced` serving daemon (T7-12) is not built here (it is blocker-laden: +HellGraph ledger service, base-model licensing, credentials). This shim is the SMALLEST +real slice that proves source-os can emit a spec-conformant, hash-chained +`InferenceReceipt` NATIVELY when a completion finishes: it takes the facts a real serving +daemon has at completion time (the content-addressed base-model digest, the task, and the +input/output) and appends an on-device receipt to the estate's hash-chained ledger +(SEAM-011: no local-only ledger). + +Consume-not-fork: all chaining/canonicalisation/verification is delegated to the vendored +canonical emitter (tools/inference_receipt_emitter.py, byte-verbatim from +prophet-platform apps/receipt-gateway). This file adds no chain logic of its own. + +CLI: + inferenced_shim.py --ledger --base-model-digest sha256:<64hex> \ + --task