ADR-0211: Tiny-model registry schema + Sigstore --tiny-model-verify¶
- Status: Accepted
- Date: 2026-04-29
- Deciders: Lusoris, Claude (Anthropic)
- Tags: ai, dnn, security, supply-chain, fork-local, t6-9
Context¶
The fork's tiny-AI surface ships ONNX models in-tree under model/tiny/, indexed by model/tiny/registry.json. ADR-0173 / ADR-0174 (PTQ audit) added quant_mode and int8_sha256 to the registry; ADR-0010 set the project-wide policy of keyless Sigstore signing for releases. The two strands had not yet met: the registry carried sha256 pins but no link to its Sigstore bundles, and docs/ai/security.md advertised a future --tiny-model-verify flag that did not exist.
T6-9 lands both halves in one PR — formalising the registry schema with license + Sigstore-bundle metadata and wiring --tiny-model-verify through to cosign verify-blob. Landing them together avoids a registry-schema flip-flop where a follow-up PR would otherwise need to extend the schema again to accommodate the verify flow.
Decision¶
We adopt JSON Schema (Draft 2020-12) as the formal registry contract, extend the per-entry shape with license, license_url, and sigstore_bundle, and wire a new --tiny-model-verify CLI flag that calls cosign verify-blob via posix_spawnp(3p). The verifier short-circuits model load on any failure (missing registry entry, missing bundle file, missing cosign, non-zero exit). Bundle files are declared in-tree per the registry but populated at release time by the existing supply-chain workflow; absence of a real bundle pre-release is benign because the flag is opt-in. schema_version bumps to 1; the loader accepts both 0 and 1 so the change is backward-compatible with already-shipped registries.
Alternatives considered¶
| Option | Pros | Cons | Why not chosen |
|---|---|---|---|
| In-tree custom validator (no JSON Schema) | Zero deps, smallest patch | Re-invents what JSON Schema already covers; no IDE / editor integration | Rejected — JSON Schema is the industry standard and jsonschema is a one-line pip install |
| JSON Schema (chosen) | Tooling, IDE completion, Draft 2020-12 widely supported | One optional Python dep | Selected — falls back to a structural check when jsonschema isn't installed so CI on minimal images still gets coverage |
| External schema-spec language (e.g. CUE, Pkl) | More expressive | Adds a non-Python toolchain dep; overkill for ~6-field shape | Rejected |
cosign as a runtime dep (chosen) | Reuses the Sigstore-canonical CLI; no in-tree Rekor / Fulcio code to maintain | Operator must install cosign | Selected — the binary is widely distributed; a missing cosign is detected and reported with -EACCES |
| Vendored cosign code (libcosign / Go-link) | No external dep | Pulls Go toolchain into the C build; large binary growth | Rejected |
| Build-time signing only (no runtime verify) | Simplest | Defeats the threat model — model substitution at deploy time goes undetected | Rejected |
| SHA-256 (chosen) | Already in use throughout the registry | — | Selected — switching to SHA-512 would add no real bits given the supply-chain bundle is the trust anchor |
| SHA-512 | Slightly larger digest | Cost without benefit; mismatches the existing int8_sha256 convention | Rejected |
| In-process verification (link cosign-go via cgo) | Skips fork/exec | Embeds Go runtime in libvmaf; cross-platform compat nightmare | Rejected |
Shell out via system(3) | Simplest spawn API | Banned by CLAUDE.md §6 (rule 30 on principles.md) — shell-injection risk | Rejected — using posix_spawnp(3p) with an explicit argv array dodges shell parsing entirely |
Consequences¶
- Positive: the registry now carries every field needed for an end-to-end supply-chain check (license metadata, sha256 pin, Sigstore bundle path) and
--tiny-model-verifyis a real one-line CLI gate for production deployments. - Positive: the JSON Schema is editor-discoverable via
"$schema": "./registry.schema.json", so adding a new model with a malformedkindenum is caught at lint time. - Negative:
cosignbecomes a soft runtime dep for any caller that passes--tiny-model-verify. Documented indocs/ai/security.mdanddocs/ai/model-registry.md. - Negative: a
schema_version: 1registry parsed by an older loader that rejects unknown fields would break — mitigated by the bounded enum ({0, 1}) and the "additionalProperties: false" set: the loader drops new fields silently and the JSON Schema warns. - Neutral / follow-ups: the supply-chain workflow (
.github/workflows/supply-chain.yml) needs a follow-up PR to drop generated<onnx>.sigstore.jsonbundles next to the artifacts at release time; the verifier already finds them via the registry path. The MCP server (T6-12 onward) inherits the registry surface and can expose averify_modelJSON-RPC method on top ofvmaf_dnn_verify_signature().
References¶
- Source: backlog item T6-9 (
.workingdir2/BACKLOG.md). - Related ADRs: ADR-0010 (Sigstore policy), ADR-0042 (tiny-AI doc requirement), ADR-0166 (cosign verify usage in the MCP release channel), ADR-0173 / ADR-0174 (PTQ-era registry fields).
- Roadmap reference:
docs/ai/roadmap.md§"Sigstore verification". - Supply chain doc:
docs/ai/security.mdLayer 4.