Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: build test validate validate-portable-ai validate-model-carry-boundary dist release-dry-run clean
.PHONY: build test validate validate-portable-ai validate-model-carry-boundary validate-model-carry-manifest dist release-dry-run clean

BIN := sourceos-ai
DIST_DIR := dist
Expand All @@ -23,7 +23,10 @@ validate-portable-ai:
validate-model-carry-boundary:
python3 tools/validate_model_carry_authorization_boundaries.py

validate: build validate-portable-ai validate-model-carry-boundary
validate-model-carry-manifest:
python3 tools/validate_model_carry_manifests.py

validate: build validate-portable-ai validate-model-carry-boundary validate-model-carry-manifest
python3 tools/validate_carry_refs.py
bin/$(BIN) carry validate --refs examples
bin/$(BIN) carry list --refs examples
Expand Down
117 changes: 117 additions & 0 deletions contracts/model-carry-manifest.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.srcos.ai/model-carry/model-carry-manifest.schema.json",
"title": "SourceOS Model Carry Manifest",
"description": "A content-addressed, hash-chained model manifest for the SourceOS model-router carry layer. Names every carried model and adapter with a base-version binding, a targeting predicate, an authoritative SHA-256 content hash, and a policy hash. This is the model-layer analogue of Exodus provenance: model identity is verifiable, not asserted. Integrity failure is a hard stop, not a routing hint. SHA-256 is the authoritative content-hash algorithm (FIPS 180-4).",
"type": "object",
"additionalProperties": false,
"required": [
"schemaVersion",
"kind",
"manifestId",
"version",
"prevManifestSha256",
"integrity",
"entries"
],
"properties": {
"schemaVersion": { "const": "v0.1" },
"kind": { "const": "ModelCarryManifest" },
"manifestId": { "type": "string", "pattern": "^urn:srcos:model-carry-manifest:" },
"version": {
"type": "integer",
"minimum": 1,
"description": "Monotonic manifest version. version 1 is the genesis manifest and MUST have a null prevManifestSha256; every later version MUST link the previous manifest by SHA-256."
},
"prevManifestSha256": {
"type": ["string", "null"],
"pattern": "^[a-f0-9]{64}$",
"description": "SHA-256 of the previous manifest in the chain, or null for the genesis manifest (version 1)."
},
"integrity": {
"type": "object",
"additionalProperties": false,
"required": [
"contentHashAlgorithm",
"transportMustBeIntegrityChecked",
"integrityFailureIsHardStop"
],
"properties": {
"contentHashAlgorithm": {
"const": "sha256",
"description": "Authoritative content-hash algorithm. SHA-256 (FIPS 180-4) only."
},
"transportMustBeIntegrityChecked": {
"const": true,
"description": "Carried artifacts MUST arrive through integrity-checked transport; unchecked transport is non-conformant."
},
"integrityFailureIsHardStop": {
"const": true,
"description": "A carried artifact whose content hash does not match its manifest entry MUST be rejected. Integrity failure is a hard stop surfaced as an uncertainty signal to the decision surface, never a silent fallback."
}
}
},
"entries": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"entryId",
"entryKind",
"modelRef",
"contentSha256",
"policySha256",
"targeting",
"baseEntryRef",
"baseContentSha256"
],
"properties": {
"entryId": { "type": "string", "pattern": "^urn:srcos:model-carry-entry:" },
"entryKind": { "type": "string", "enum": ["base", "adapter"] },
"modelRef": { "type": "string", "minLength": 1 },
"contentSha256": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "Authoritative SHA-256 of the carried artifact content. Never null: content-addressing is not optional at the manifest layer."
},
"policySha256": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "SHA-256 of the policy object bound to this entry."
},
"targeting": {
"type": "object",
"additionalProperties": false,
"required": ["deviceClass"],
"description": "Targeting predicate deciding which device class, OS version range, and locale this entry applies to.",
"properties": {
"deviceClass": {
"type": "array",
"minItems": 1,
"items": { "type": "string", "enum": ["laptop", "workstation", "field-kit", "server", "any"] }
},
"osVersionRange": { "type": ["string", "null"] },
"locale": {
"type": ["array", "null"],
"items": { "type": "string" }
}
}
},
"baseEntryRef": {
"type": ["string", "null"],
"pattern": "^urn:srcos:model-carry-entry:",
"description": "For entryKind=adapter: the entryId of the base this adapter is registered against. Null for entryKind=base."
},
"baseContentSha256": {
"type": ["string", "null"],
"pattern": "^[a-f0-9]{64}$",
"description": "For entryKind=adapter: the pinned SHA-256 of the base content this adapter was registered against. Must equal the referenced base entry contentSha256. Null for entryKind=base."
}
}
}
},
"notes": { "type": "string" }
}
}
51 changes: 51 additions & 0 deletions docs/model-carry-manifest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Model Carry Manifest

The model carry manifest is the content-addressed, hash-chained catalog the
SourceOS model-router carries. It names every base model and adapter with a
verifiable identity, a targeting predicate, and the policy bound to it. It is the
model-layer analogue of Exodus provenance: model identity is verifiable, not
asserted.

- Contract: `contracts/model-carry-manifest.schema.json`
- Validator: `tools/validate_model_carry_manifests.py` (`make validate-model-carry-manifest`)
- Example: `examples/model-carry-manifest.laptop-safe.json`

## Why

This closes three gaps identified in the SourceOS-vs-Apple model-carry analysis,
where Apple's delivery discipline exposed missing primitives in our carry path:

1. **No content-addressed model manifest.** The router routed, but nothing named
every model+adapter with its targeting predicate and integrity hash. Without
it, provenance at the model layer was asserted, not verifiable.
2. **Adapter/base version binding was not enforced.** A base update did not
mechanically force adapter re-delivery, inviting silent drift between an
adapter and the base it was trained against.
3. **Encrypted, integrity-checked transport was not an invariant.** Integrity was
optional rather than a hard stop.

## Invariants (enforced by the validator)

| Invariant | Rule |
|---|---|
| Authoritative hash | `integrity.contentHashAlgorithm` is `sha256` (FIPS 180-4). |
| Content-addressed | Every entry carries a non-null `contentSha256` and `policySha256`. |
| Integrity is a hard stop | `integrityFailureIsHardStop` and `transportMustBeIntegrityChecked` are `true`. |
| Hash chain | `version` 1 has null `prevManifestSha256`; every later version links the previous manifest by SHA-256. |
| Adapter/base binding | Every adapter references an existing base entry and pins a `baseContentSha256` that equals that base's `contentSha256`. Drift is rejected by construction. |
| Base entries | A base entry sets `baseEntryRef` and `baseContentSha256` to null. |
| Targeting predicate | Every entry carries a `targeting` predicate with at least a `deviceClass`. |

## Carry boundary

The manifest is a reference/verification object. It does not authorize runtime
execution, prompt egress, tool use, model download, training, or promotion. Those
remain outside the mutable workstation image, consistent with the carry-only
doctrine in `repo.maturity.yaml`.

## Not yet in scope (tracked as issues)

- Governed staged pre-load plus atomic swap under a disk/CPU resource governor.
- Tiered escalation contract: local-by-default to an attested confidential-compute
target, with the escalation decision and its confidence propagated as a
first-class provenance record.
35 changes: 35 additions & 0 deletions examples/model-carry-manifest.adapter-base-drift.invalid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"schemaVersion": "v0.1",
"kind": "ModelCarryManifest",
"manifestId": "urn:srcos:model-carry-manifest:laptop-safe",
"version": 2,
"prevManifestSha256": "4888b1850bddd6715434b02a37378ba12fab3102a20277d2434c92082a749e1a",
"integrity": {
"contentHashAlgorithm": "sha256",
"transportMustBeIntegrityChecked": true,
"integrityFailureIsHardStop": true
},
"entries": [
{
"entryId": "urn:srcos:model-carry-entry:llama32-3b-base",
"entryKind": "base",
"modelRef": "llama3.2:3b",
"contentSha256": "7372678075509b60673cfe1df40dc56801ace22cad6e56277cf4a0b4a359d8e7",
"policySha256": "af853ebc3648bc457c414e81b29f88c40931d5c744a89ac42dbd0dacc3aa23b0",
"targeting": { "deviceClass": ["laptop"], "osVersionRange": null, "locale": null },
"baseEntryRef": null,
"baseContentSha256": null
},
{
"entryId": "urn:srcos:model-carry-entry:office-rewrite-adapter",
"entryKind": "adapter",
"modelRef": "office-rewrite@llama3.2:3b",
"contentSha256": "d2a13f41da9fe4b1c1ac77bd73f18db1ff393a2c570706e9d0308018ef82f256",
"policySha256": "5ebc47cbb9475e64eb84aae73b2f4e39cee5a4eba4486cf4012c171a5693a0c2",
"targeting": { "deviceClass": ["laptop"], "osVersionRange": null, "locale": null },
"baseEntryRef": "urn:srcos:model-carry-entry:llama32-3b-base",
"baseContentSha256": "326bf933ccae9bd3e98fe7e85dc4dea4124436199e298200c5f86abc62b43df8"
}
],
"notes": "INVALID: adapter pins a base content hash that does not match the base entry (silent adapter/base drift)."
}
25 changes: 25 additions & 0 deletions examples/model-carry-manifest.adapter-missing-base.invalid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"schemaVersion": "v0.1",
"kind": "ModelCarryManifest",
"manifestId": "urn:srcos:model-carry-manifest:laptop-safe",
"version": 1,
"prevManifestSha256": null,
"integrity": {
"contentHashAlgorithm": "sha256",
"transportMustBeIntegrityChecked": true,
"integrityFailureIsHardStop": true
},
"entries": [
{
"entryId": "urn:srcos:model-carry-entry:office-rewrite-adapter",
"entryKind": "adapter",
"modelRef": "office-rewrite@llama3.2:3b",
"contentSha256": "d2a13f41da9fe4b1c1ac77bd73f18db1ff393a2c570706e9d0308018ef82f256",
"policySha256": "5ebc47cbb9475e64eb84aae73b2f4e39cee5a4eba4486cf4012c171a5693a0c2",
"targeting": { "deviceClass": ["laptop"], "osVersionRange": null, "locale": null },
"baseEntryRef": "urn:srcos:model-carry-entry:llama32-3b-base",
"baseContentSha256": "7372678075509b60673cfe1df40dc56801ace22cad6e56277cf4a0b4a359d8e7"
}
],
"notes": "INVALID: adapter is bound to a base entry that is not present in the manifest."
}
25 changes: 25 additions & 0 deletions examples/model-carry-manifest.integrity-not-hardstop.invalid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"schemaVersion": "v0.1",
"kind": "ModelCarryManifest",
"manifestId": "urn:srcos:model-carry-manifest:laptop-safe",
"version": 1,
"prevManifestSha256": null,
"integrity": {
"contentHashAlgorithm": "sha256",
"transportMustBeIntegrityChecked": true,
"integrityFailureIsHardStop": false
},
"entries": [
{
"entryId": "urn:srcos:model-carry-entry:llama32-3b-base",
"entryKind": "base",
"modelRef": "llama3.2:3b",
"contentSha256": "7372678075509b60673cfe1df40dc56801ace22cad6e56277cf4a0b4a359d8e7",
"policySha256": "af853ebc3648bc457c414e81b29f88c40931d5c744a89ac42dbd0dacc3aa23b0",
"targeting": { "deviceClass": ["laptop"], "osVersionRange": null, "locale": null },
"baseEntryRef": null,
"baseContentSha256": null
}
],
"notes": "INVALID: integrityFailureIsHardStop is false; integrity failure must be a hard stop."
}
43 changes: 43 additions & 0 deletions examples/model-carry-manifest.laptop-safe.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"schemaVersion": "v0.1",
"kind": "ModelCarryManifest",
"manifestId": "urn:srcos:model-carry-manifest:laptop-safe",
"version": 2,
"prevManifestSha256": "4888b1850bddd6715434b02a37378ba12fab3102a20277d2434c92082a749e1a",
"integrity": {
"contentHashAlgorithm": "sha256",
"transportMustBeIntegrityChecked": true,
"integrityFailureIsHardStop": true
},
"entries": [
{
"entryId": "urn:srcos:model-carry-entry:llama32-3b-base",
"entryKind": "base",
"modelRef": "llama3.2:3b",
"contentSha256": "7372678075509b60673cfe1df40dc56801ace22cad6e56277cf4a0b4a359d8e7",
"policySha256": "af853ebc3648bc457c414e81b29f88c40931d5c744a89ac42dbd0dacc3aa23b0",
"targeting": {
"deviceClass": ["laptop", "workstation"],
"osVersionRange": ">=1.0.0",
"locale": ["en_US", "en_GB"]
},
"baseEntryRef": null,
"baseContentSha256": null
},
{
"entryId": "urn:srcos:model-carry-entry:office-rewrite-adapter",
"entryKind": "adapter",
"modelRef": "office-rewrite@llama3.2:3b",
"contentSha256": "d2a13f41da9fe4b1c1ac77bd73f18db1ff393a2c570706e9d0308018ef82f256",
"policySha256": "5ebc47cbb9475e64eb84aae73b2f4e39cee5a4eba4486cf4012c171a5693a0c2",
"targeting": {
"deviceClass": ["laptop", "workstation"],
"osVersionRange": ">=1.0.0",
"locale": ["en_US"]
},
"baseEntryRef": "urn:srcos:model-carry-entry:llama32-3b-base",
"baseContentSha256": "7372678075509b60673cfe1df40dc56801ace22cad6e56277cf4a0b4a359d8e7"
}
],
"notes": "Genuine carry manifest: base plus one task adapter bound to the exact base content hash it was registered against."
}
Loading
Loading