Trust Runtime
PROTOTYPEEverything else here measures trust. This is the piece that enforces it: a policy gate that sits in front of an inference, reads the model's signed passport, and decides whether the request proceeds.
log_only is the default mode, so a decision is computed and recorded but nothing is blocked. It does not proxy real traffic, it is not a hosted service, and it does not execute the fallback it names. See plan_d/docs/RUNTIME-SPEC.md §2 for the regulatory reasoning behind each of those choices.Policy
A worked illustration of gating a deployment on the acquisition envelope: where does the scanner this request came from sit, relative to the acquisition conditions the evidence was actually measured under? Every rule reads within_envelope, the one operator that compares two documents rather than two values. The first rule is the instructive one — the operator fails open, so an absent or incomparable fingerprint is false rather than a match, and only an exists pairing turns that into a refusal instead of a silent pass. Runs in log_only: the decision is computed and recorded in full, and nothing is blocked.
author: EXAMPLE — not a NakedSignal recommendation. Every routing choice below is illustrative. In deployment the policy is authored by the operating institution, with its thresholds, reviewed under its clinical governance.
- 1no-comparable-site-fingerprint→ defer_to_humanfired
NOT (inference.site_fingerprint exists undefined AND passport.envelope exists undefined AND (inference.site_fingerprint within_envelope passport.envelope OR inference.site_fingerprint within_envelope passport.envelope OR inference.site_fingerprint within_envelope passport.envelope))
“there is no answer here to gate on, and that must stop the request rather than pass it. within_envelope fails open: an absent acquisition envelope, an absent site fingerprint, or a pair that cannot be compared at all — a fingerprint computed by a different version of the feature code, or an envelope fitted over a generator's knobs rather than over physics features — every one of those is false rather than a match, so none of the rules below could fire and the request would go through unexamined. Pairing the operator with exists, and with the three verdicts that exhaust every comparable answer, is what makes missing evidence fail closed.” - 2site-outside-acquisition-envelope→ route_to_fallback
inference.site_fingerprint within_envelope passport.envelope
“at least one acquisition feature of this site sits beyond the band and beyond its grace margin, so the acquisition conditions this evidence was measured under do not cover the scanner the request came from. outside is the only verdict strong enough to route a case away on, and it is a statement about where the site sits, not a prediction that the model will perform badly here.” - 3fingerprint-client-incomplete→ defer_to_human
inference.site_fingerprint within_envelope passport.envelope
“the fingerprint carries no reading at all for a band the acquisition envelope declares. That is a statement about the client software that computed the fingerprint — not about the scanner and not about the sample — so the fix is to update the fingerprint client and run it again, and nothing should be concluded about this site until it has been.” - 4sample-too-small-to-place-the-site→ defer_to_human
inference.site_fingerprint within_envelope passport.envelope
“the sample could not place at least one acquisition feature: the interval around the site's own reading is still too wide to sit it inside the band or outside it. That is a statement about the sample, not about the scanner. Upload more images and run it again. Routing this the way a marginal site is routed would tell a hospital its scanner is unusual when the truth is that it uploaded fifty images.” - 5site-marginal-on-acquisition-envelope→ allow
inference.site_fingerprint within_envelope passport.envelope
“every acquisition feature was placed and at least one sits just outside the band, inside the grace margin the publisher declared. That is a statement about the site and it is the mildest of the three warnings, so the request proceeds and the marginal reading goes on the record — the point of a log_only gate is that the pattern is visible before anyone has to argue about a single case.” - default_action→ allow
Inference
per requestThe runtime does not verify signatures — it consumes the result from verify_passport.py or from the in-browser check on Evidence Passport. Two jobs, two modules.
Decision log
hash-chained · in-memoryNothing logged yet. Each entry carries the hash of the one before it, built the same way plan_d/src/heldout/ledger.py builds the held-out ledger — so editing history breaks every subsequent hash. This log lives in the tab and is not persisted anywhere; the CLI writes the real one to plan_d/logs/runtime/decisions.jsonl.
Two implementations, one behaviour
The gate above is TypeScript, because a static site has no server. The reference implementation is Python, in plan_d/src/runtime/, and it is what a hospital would actually call. Two evaluators that disagree is a bug you find in front of an audience, so they are held to a shared file of (policy, passport, envelope) → decision fixtures that both run:
python plan_d/src/runtime/check_agreement.py --live
It runs both, compares the canonical decisions field by field — including the envelope hash — and exits non-zero on any divergence.
One engine, two binding times
The same evaluator run without an inference envelope answers a different question: may we buy this at all? Select example-procurement-filter above and the inference controls go dark — the policy reads only the passport, and returns a verdict at contract time rather than at request time.
The procurement filter that the original plan made a separate product is a policy file with binding_time: procurement.
What the panel is reading
Policies are the JSON files in site-data/policies/, unmodified. Passports are the signed documents in site-data/passports/, reduced at build time to identity, expiry, issuer, the cross-site block without its full matrix, and the scalar metrics of each evaluation — a page that inlined 42 complete passports would ship close to a megabyte of JSON. Fields are copied or dropped, never re-derived. The document of record is the full signed one on the Evidence Passport page.