OCI Artifacts for AI Models, Verified
Package weights, tokenizer, runtime config, evaluation receipt, and signature references as a content-addressed OCI artifact with a verifiable closure.
OCI artifacts for AI models answer how to move weights, tokenizer, runtime settings, and evidence as one digest-verifiable bundle. This tutorial builds a tiny synthetic graph, mutates one byte, and traces which descriptor, manifest, and attached receipt must change.
OCI artifacts for AI models define a graph, not an image
An OCI manifest can describe non-container content through descriptors, artifact metadata, and related manifests. That makes the format useful for a model bundle, but it does not make weights executable or safe. Treat the object as a content-addressed package whose consumers understand declared media types, required files, and a separate runtime contract.
The OCI manifest guidance explains the manifest fields and artifact use. A model artifact manifest should name an artifact type, a small config object, and layers for weights, tokenizer, runtime configuration, and evaluation evidence. Media types in this teaching fixture use an example vendor namespace and are explicitly illustrative; production publishers should register or standardize them when ecosystem interoperability matters.
The committed artifact creates tiny UTF-8 blobs rather than redistributing a real model. It hashes their exact bytes with SHA-256, constructs descriptors, hashes the serialized manifest, changes one byte, and asserts the closure changes. Every number in the example is derived during that local run, not reported from a registry or production model pipeline.
Treat OCI artifacts for AI models as a bill of materials for bytes. Operators should be able to inspect the descriptor graph without downloading weights or starting a model runtime.
- Every orbit is addressed by a digest and declared media type.
- Descriptor size is checked before a blob is trusted.
- The manifest connects related files without pretending to be a runnable image.
| Signal | Interpretation |
|---|---|
| Content-addressed model constellation | A manifest star connects weights, tokenizer, runtime config, and evaluation receipt blobs whose radii indicate fixture byte size. |
Freeze the bundle's semantic inventory
Write down what is required to interpret the model before choosing layer order. Include weight shards, tokenizer vocabulary and rules, architecture or runtime configuration, license and source notices, evaluation receipt, and any adapter relationship. Decide which items are mandatory, optional, or platform-specific. A consumer should reject a bundle that lacks a mandatory role even if every remaining digest is valid.
The memory-mapped model loading path may consume shards differently from a training system, so preserve stable roles in annotations or a config schema rather than relying on filename order. OCI artifacts for AI models should separate identity-bearing content from convenience metadata. Changing a weight byte or tokenizer rule creates a new bundle; changing an external display label may not need to.
Record source, license, architecture, tensor format, tokenizer compatibility, and intended runtime constraints without claiming those declarations prove model quality. The bundle is transport and integrity evidence. Safety evaluation, authorization, and deployment qualification remain separate gates.
A bundle role schema also prevents accidental omission during automation: a release job can reject an otherwise valid manifest whose tokenizer or notice layer is absent.
Build descriptors from exact bytes
Each OCI descriptor carries a media type, digest, and byte size, with optional annotations and platform information where applicable. Calculate digest and size from the bytes that will actually be uploaded. Do not hash a parsed object and later serialize it differently. Canonicalize the files at their source or retain their original bytes as the addressed object.
The descriptor specification defines validation expectations. A puller should verify size and digest while streaming before exposing a blob to a parser. Apply independent limits to descriptor count, individual size, total bundle size, decompression, and nested references. A content-addressed model bundle still needs denial-of-service defenses.
OCI artifacts for AI models become reproducible when the build receipt lists the input path, role, media type, size, digest, and producing tool version. The local fixture sorts descriptors by a declared role only for deterministic demonstration. A real schema should define whether order has meaning instead of inheriting filesystem enumeration.
Normalize text line endings and JSON serialization before hashing only when that normalization is part of the producing contract. Never normalize after publication.
- The artifact type states the bundle's purpose.
- Config and layer descriptors name media type, digest, and size.
- A subject edge can attach evidence without mutating the original manifest.
| Signal | Interpretation |
|---|---|
| OCI manifest descriptor cutaway | A layered manifest cutaway separates artifact type, config descriptor, layers, annotations, and subject linkage. |
Use config for interpretation, layers for payloads
Keep the config small and machine-readable. It can declare schema version, model family, expected layer roles, dependency rules, and the digest of a higher-level inventory. Large weights and tokenizer data belong in layers so clients can select, cache, and verify them independently. Do not place secrets, access tokens, or environment-specific endpoints in either location.
An OCI artifactType communicates the purpose of the manifest, while every layer media type communicates the payload role. Because the example types are illustrative, the tutorial's consumer also checks explicit annotations and rejects unknown schema versions. OCI artifacts for AI models should prefer a boring, versioned contract over clever inference from filenames such as final-final-model.bin.
The distributed checkpointing guide is relevant when many shards are produced concurrently. Finalize the OCI manifest only after all shard digests and sizes are stable. An incomplete checkpoint must not receive the same artifact identity as a verified complete closure.
Keep architecture compatibility machine-readable but conservative. A loader should deny an unknown field combination rather than guessing from model-family marketing names.
Attach evaluation and signatures as related evidence
Evaluation receipts and signatures change on different schedules from model bytes. A receipt can be a layer in an immutable release bundle, or a separate artifact whose subject descriptor points at the model manifest. The separate approach lets new evidence attach without rewriting the original model identity. It also requires clients to decide which referrer types and signers they trust.
The OCI referrers API is defined through the Distribution Specification. Registry support and policy vary, so test the exact distribution target and preserve a fallback discovery contract if required. OCI artifacts for AI models should not claim that a discovered signature is valid merely because it is present.
The AI model weight signing article covers identity and verification policy. Verify the subject digest, signature envelope, signer identity, authority, timestamp, and revocation expectations. An evaluation receipt should likewise name dataset or fixture identity, code version, parameters, and result digest rather than offering a detached score with no reproducible context.
Referrer discovery must be followed by trust filtering. The registry can enumerate related evidence, but deployment policy chooses the allowed artifact types and authorities.
This model bundle fixture sorts descriptors, connects evaluation and signature evidence, and proves how one changed byte invalidates closure identity.
Runnable artifact — oci-model-bundle-fixture.mjs
import assert from "node:assert/strict";
import crypto from "node:crypto";
const hash = (value) => "sha256:" + crypto.createHash("sha256").update(value).digest("hex");
const descriptor = (role, bytes) => ({ mediaType: "application/vnd.example.ai." + role, size: Buffer.byteLength(bytes), digest: hash(bytes), annotations: { "ai.example/role": role } });
const canonical = (value) => JSON.stringify(value);
const build = (weights) => {
const unsorted = [descriptor("weights", weights), descriptor("tokenizer", "tok:v1"), descriptor("runtime", "dtype=f16")];
const layers = [...unsorted].sort((a, b) => a.annotations["ai.example/role"].localeCompare(b.annotations["ai.example/role"]));
const manifest = { schemaVersion: 2, mediaType: "application/vnd.oci.image.manifest.v1+json", artifactType: "application/vnd.example.ai.model", layers };
const digest = hash(canonical(manifest));
const evaluation = descriptor("evaluation", canonical({ subject: digest, corpus: "bounded-fixture-v1", pass: true }));
const signature = descriptor("signature", canonical({ subject: digest, signer: "fixture-key-id", algorithm: "fixture-only" }));
const referrers = [evaluation, signature].sort((a, b) => a.annotations["ai.example/role"].localeCompare(b.annotations["ai.example/role"])).map((item) => ({ ...item, subject: digest }));
return { layers, digest, referrers };
};
const before = build("weights:abc"), after = build("weights:abd");
assert.deepEqual(before.layers.map((item) => item.annotations["ai.example/role"]), ["runtime", "tokenizer", "weights"]);
assert.deepEqual(before.referrers.map((item) => item.annotations["ai.example/role"]), ["evaluation", "signature"]);
assert.ok(before.referrers.every((item) => item.subject === before.digest));
assert.notEqual(before.layers.at(-1).digest, after.layers.at(-1).digest);
assert.equal(before.layers[0].digest, after.layers[0].digest);
assert.notEqual(before.digest, after.digest);
assert.ok(before.referrers.every((item) => item.subject !== after.digest));
console.log(JSON.stringify({ layerOrder: before.layers.map((item) => item.annotations["ai.example/role"]), referrers: before.referrers.map((item) => item.annotations["ai.example/role"]), oldEvidenceMatchesNewSubject: false }));
console.log("PASS: one changed byte changes the model closure");
Run node oci-model-bundle-fixture.mjs. Expected receipt: PASS: one changed byte changes the model closure.
Trace a one-byte mutation through the closure
Change one byte in a frozen weights blob and compute the graph again. The blob digest changes. Its descriptor bytes inside the manifest change. The manifest digest changes. Any signature or evaluation artifact whose subject is the former manifest still refers to the old bundle, even if all other layers remain identical. That is the core value of content addressing.
Do not label the old evidence invalid in the abstract; it may remain perfectly valid for the old subject. It simply does not attest the new closure. OCI artifacts for AI models make this distinction precise and allow both versions to coexist. A mutable tag may move to the new manifest, while digest references keep old deployments reproducible.
The committed fixture asserts that unchanged tokenizer and config digests remain equal across the mutation, while weights and manifest digests differ. This bounded result is computed from its tiny strings. It is not a performance or security claim about a public registry, a commercial model, or a production signing service.
Tags remain useful human pointers, yet promotion should record the resolved digest. A rollback then selects an earlier closure without relying on mutable label history.
| Changed object | Consequence |
|---|---|
| weights blob | blob digest changes |
| descriptor | manifest bytes change |
| manifest | old referrers no longer attest new subject |
| Signal | Interpretation |
|---|---|
| One-byte tamper ripple | A changed weight blob sends digest ripples through its descriptor and manifest while an attached receipt points to the old subject. |
Push and pull with verification at every boundary
On push, upload blobs by digest, confirm registry acceptance, then publish the manifest after dependencies exist. Use least-privilege credentials and separate staging from release tags. On pull, resolve a tag once, record the manifest digest, fetch only allowed descriptors, verify bytes, and write through temporary files before atomic promotion. Never execute loaders against partially verified content.
The build provenance for releases pattern extends the graph back to source and build inputs. OCI artifacts for AI models can carry provenance references, but policy must require and validate them. Registry storage is not a substitute for an admission controller that checks artifact type, allowed media types, signer, source, license, evaluation requirements, and target environment.
Cache by digest rather than tag. Garbage collection needs reachability rules for manifests, subjects, and referrers so evidence is not silently removed while deployments still depend on it. Test registry-specific behavior before promising retention.
Quarantine a digest mismatch before parsing. Parsing corrupted or substituted bytes merely to produce a friendlier error expands the attack surface unnecessarily.
Publish one inspectable model-bundle contract
Ship the bundle schema beside example commands, a verifier, rejection cases, and an inventory view. Document how consumers handle unknown optional layers, missing mandatory roles, digest mismatch, excessive size, untrusted referrers, and unsupported runtime configuration. Keep the media-type status visible until the ecosystem contract is genuinely registered.
Rebuild from the same inputs and compare the manifest digest. If timestamps or nondeterministic serialization prevent equality, decide whether they belong outside the addressed core. OCI artifacts for AI models should let a reviewer answer exactly which bytes, interpretation rules, and evidence were authorized for deployment.
The finish line is not a green upload command. It is a verified closure that can be pulled by digest, inspected without execution, checked against policy, and connected to separately validated evidence. Package a toy bundle first; a small graph makes errors obvious before large shards and registry lifecycle costs make them expensive.
Publish negative fixtures beside the verifier: missing role, wrong size, altered digest, unknown schema, untrusted evidence, and excessive graph depth should all fail clearly.
Continue into release relationship inventory
Describe the packaged closure with an SPDX AI BOM that connects exact artifacts, datasets, licenses, suppliers, provenance, and evaluation evidence.