Skip to content

Commit 08cd43d

Browse files
feat(weight-custody-manifest): add WCM demo catalog (#61)
Relocate the Weight Custody Manifest demos into a per-product scenario folder, depending on the published PyPI package (weight-custody-manifest >=0.19.0) instead of the in-repo SDK. Mirrors the ca2a-delegation layout. Four demos: open_model_e2e (full 6-step flow on an open model), sovereign_self_custody (2-of-3 threshold release), snp_replay (offline SEV-SNP quote replay against a committed synthetic bundle), and real_open_model (downloads SmolLM2-135M and hashes real weights, run local). README adapted from the WCM tutorials. A CI job installs from PyPI and runs the three offline demos; real_open_model is excluded (network, heavy) with its extras in requirements-infer.txt. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 675c9a5 commit 08cd43d

10 files changed

Lines changed: 1026 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,28 @@ jobs:
145145

146146
- name: Run the delegation demo
147147
run: python delegation_agent.py
148+
149+
weight-custody-manifest:
150+
runs-on: ubuntu-latest
151+
defaults:
152+
run:
153+
working-directory: weight-custody-manifest
154+
steps:
155+
- uses: actions/checkout@v7
156+
157+
- name: Set up Python 3.11
158+
uses: actions/setup-python@v7
159+
with:
160+
python-version: "3.11"
161+
162+
- name: Install the WCM SDK from PyPI
163+
run: python -m pip install -r requirements.txt
164+
165+
- name: Run the end-to-end custody demo
166+
run: python open_model_e2e.py
167+
168+
- name: Run the sovereign threshold demo
169+
run: python sovereign_self_custody.py
170+
171+
- name: Replay a SEV-SNP quote offline
172+
run: python snp_replay.py

weight-custody-manifest/README.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# weight-custody-manifest: Custody for Model Weights
2+
3+
The other examples in this repo govern what an agent may **do**. This one governs the model **weights** themselves: when a builder deploys a model into a customer's own or sovereign infrastructure, how do you prove the weights running in the enclave are exactly the ones the builder shipped, release the decryption key only against a valid hardware attestation, wipe it when custody lapses, and carry the lineage of every derivative?
4+
5+
That is the [Weight Custody Manifest](https://pypi.org/project/weight-custody-manifest/) (WCM): an open protocol and reference SDK. These four demos run its real code.
6+
7+
For a public open-weight model, base-weight confidentiality is theater (anyone can download the weights), so the same flow does the work that still matters: **integrity and provenance** (is this the model the builder shipped, or a tampered copy), **license as a release condition**, **derivative custody and lineage**, and a **kill switch**.
8+
9+
> **Honest scope.** WCM does not claim silicon-enforced custody against an operator who physically owns the hardware. Cheap published memory-bus attacks (TEE.fail, BadRAM) extract keys from live confidential-computing memory, so against that adversary WCM is accountability-grade (cost, detection, containment, mandatory physical hardening), not cryptographic custody. It is custody-grade against software and remote adversaries. The demos below use a software (mock) attestation provider so they run with no hardware; the hardware-rooted step is validated separately on real SEV-SNP and TDX silicon.
10+
11+
---
12+
13+
## Setup
14+
15+
```bash
16+
git clone https://github.com/agentrust-io/examples.git
17+
cd examples/weight-custody-manifest
18+
pip install -r requirements.txt # weight-custody-manifest>=0.19.0, Python 3.11+
19+
```
20+
21+
The three offline demos need nothing else. `real_open_model.py` needs run-local extras (below).
22+
23+
---
24+
25+
## The demos
26+
27+
### 1. `open_model_e2e.py` -- the whole flow, end to end
28+
29+
The full six-step Weight Custody Manifest flow on an open-weight model with a mock attestation provider: sign the joint manifest (builder + custodian), run the attestation-gated key release, hold the key under a wipe-on-lapse custody lease, enforce the license as a release condition, then fine-tune into a derivative and verify its lineage back to the base. Narrated, and honest about which steps are real work versus theater for a public model. Runs anywhere.
30+
31+
```bash
32+
python open_model_e2e.py
33+
```
34+
35+
### 2. `sovereign_self_custody.py` -- threshold release, no single point of trust
36+
37+
Sovereign self-custody with a 2-of-3 threshold split-key (SPEC 3.5): the release key is split with Shamir secret sharing so no single party can release the weights alone. Real WCM code, software attestation, runs anywhere.
38+
39+
```bash
40+
python sovereign_self_custody.py
41+
```
42+
43+
### 3. `snp_replay.py` -- replay a real attestation, offline
44+
45+
The CPU half of Layer 2's composite verification (SPEC 3.2), run offline against a recorded AMD SEV-SNP quote. It exercises exactly what a key broker runs before releasing a key: parse the SNP report, verify the VCEK to ASK to ARK certificate chain to a trusted AMD root, verify the report's own signature, and confirm REPORT_DATA binds the challenge nonce (anti-replay). A synthetic bundle is committed in `fixtures/` so it runs anywhere; pass a captured bundle to replay genuine silicon.
46+
47+
```bash
48+
python snp_replay.py # committed synthetic bundle
49+
python snp_replay.py path/to/snp_quote.json # a bundle captured on a real Azure SEV-SNP CVM
50+
```
51+
52+
### 4. `real_open_model.py` -- run-local, over real weights
53+
54+
The same flow over a **real** open model's actual bytes: it downloads an open model (SmolLM2-135M by default, ~270MB), hashes its real safetensors into the manifest, includes a tamper demo (a one-byte-flipped fork no longer matches the manifest), and with `--infer` loads the model and generates so the certified serving stack is a real running model. Network and heavy, so it is run-local and excluded from CI.
55+
56+
```bash
57+
pip install -r requirements-infer.txt
58+
python real_open_model.py # download, hash, full flow, tamper demo
59+
python real_open_model.py --infer # also load the model and generate
60+
python real_open_model.py --local path/to/model.safetensors # skip the download
61+
```
62+
63+
---
64+
65+
## What runs in CI
66+
67+
The three offline demos (`open_model_e2e.py`, `sovereign_self_custody.py`, `snp_replay.py`) run in CI against the published PyPI package and must exit 0. `real_open_model.py` is not in CI (it downloads a model).
68+
69+
## Reference
70+
71+
- Package: [weight-custody-manifest on PyPI](https://pypi.org/project/weight-custody-manifest/)
72+
- `manifest.example.json` in this folder is a sample signed manifest for reference.
73+
74+
## License
75+
76+
Apache 2.0. See [LICENSE](../LICENSE) in the repo root.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"kind": "wcm-snp-quote-bundle/v1",
3+
"source": "synthetic",
4+
"note": "Self-consistent synthetic ARK->VCEK chain and report. NOT real hardware. Replace with tools/capture_snp_quote.py output for a genuine Azure SEV-SNP quote.",
5+
"report_b64": "AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACaLbLiPxUEzQVmBlU6wEnF5xjo+c6SM4dt8aehghr4hQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOVfr/UlF6aVEeNEtcgt1yVfTcnaevR3bh8NkO8NBC9ugKwnqgg4seL0yJuRGoDOMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAugtnFRQ0+9Ir8kMPO+NbzMBsl+B3RvfrmVwsW4klzwgY61mK2LM16sbWbMWhqExDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
6+
"vcek_pem": "-----BEGIN CERTIFICATE-----\nMIIBkjCCARigAwIBAgIUB28IzgyENEygWjv7jqffhGZpw7swCgYIKoZIzj0EAwMw\nNDEyMDAGA1UEAwwpc3ludGhldGljLXNucC1yb290IChzdGFuZC1pbiBmb3IgQU1E\nIEFSSykwIBcNMjAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMB8xHTAbBgNV\nBAMMFFNFVi1WQ0VLIChzeW50aGV0aWMpMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE\nfNprLZF3rSMcTK0kLOZfBlfX7+KVQEbq9kmJOjKxDF2T1bKC0kF0jeFT6aq574wx\nTiIqGq7MMPWAdSQKHcQ6s8mcQZBZtODpJwDF683MnNc7hnHqN/AdLq8v77WTc5gp\nMAoGCCqGSM49BAMDA2gAMGUCMQDrVxfCf2knshEQvL+vyUuTU/nk/+QHpWDP+WAk\naMNdRUrzh3SGlZIAwgtqq+seorgCMF0X9n1VutxigXAXaWkHje6BpuAoyKFWYdmN\n1gePcPp9kUJZ/nSu9RIl7NvwMueinw==\n-----END CERTIFICATE-----\n",
7+
"intermediates_pem": [],
8+
"root_pem": "-----BEGIN CERTIFICATE-----\nMIIBvTCCAUKgAwIBAgIUIB3+SQg0A8tekhc1NbDQ9LSCE8IwCgYIKoZIzj0EAwMw\nNDEyMDAGA1UEAwwpc3ludGhldGljLXNucC1yb290IChzdGFuZC1pbiBmb3IgQU1E\nIEFSSykwIBcNMjAwMTAxMDAwMDAwWhgPMjA5OTAxMDEwMDAwMDBaMDQxMjAwBgNV\nBAMMKXN5bnRoZXRpYy1zbnAtcm9vdCAoc3RhbmQtaW4gZm9yIEFNRCBBUkspMHYw\nEAYHKoZIzj0CAQYFK4EEACIDYgAEuUSltY1Uj1sQzYTsecVdrNq9x0sgogawXEOl\nG/hcShU4GgPfFxUhryvWyeujHsaaz05LXPXVf/wJujBIrSxrAfxHdkTlfjuLzP5P\nEimoco+iYXuBjgo+Sz7nJaL36ZBaoxMwETAPBgNVHRMBAf8EBTADAQH/MAoGCCqG\nSM49BAMDA2kAMGYCMQDmJrgizN8uN1kQbxV8qW+1yac3XBpoDxwzMVYWD/U+yHbY\npAdF3OgGvlH5MWxTcM0CMQC4spaNY5CzLmMctCIyHz8Js9wbDpfGTAdbYB1rTwUr\ndF/mAzWU2hWC53hx5/T8oxw=\n-----END CERTIFICATE-----\n",
9+
"expected_nonce": "abababababababababababababababababababababababababababababababab",
10+
"expected_measurement": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
11+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
{
2+
"manifest_version": "0.1",
3+
"weights_hash": "sha256:4a1c9b024a1c9b024a1c9b024a1c9b024a1c9b024a1c9b024a1c9b024a1c9b02",
4+
"builder": {
5+
"identity": "example-builder",
6+
"signing_key": "ed25519:builder-key-placeholder"
7+
},
8+
"release_terms": {
9+
"license": "customer-deployment-agreement-ref:CDA-2026-0091",
10+
"permitted_derivatives": "fine-tune-only, no re-export of base weights",
11+
"permitted_environments": ["opaque-cmcp-attested-enclave"],
12+
"jurisdiction_restriction": "US, EU"
13+
},
14+
"release_policy": {
15+
"required_assurance_tier": "hardware-attested",
16+
"physical_hardening": "not-required",
17+
"trusted_time_source": "secure-tsc",
18+
"memory_fingerprint_challenge": "not-required",
19+
"required_hw_platform": ["amd-sev-snp", "nvidia-cc-gpu"],
20+
"required_gpu_measurement": {
21+
"rim_pin": "nvidia-rim:driver+vbios golden measurement id",
22+
"note": "GPU attestation report is a separate evidence chain from the CVM report; verify both plus the serving-image measurement, bound by a nonce echo (SPEC 3.2)"
23+
},
24+
"tenancy": "shared",
25+
"required_serving_image": {
26+
"signer": "ed25519:builder-key-placeholder",
27+
"release_rule": "prefer-current: refuse a retiring image when a current one is available; require signed/attested time for retire_after, never the host clock",
28+
"accepted_measurements": [
29+
{
30+
"measurement": "sha256:5e2d5e2d5e2d5e2d5e2d5e2d5e2d5e2d5e2d5e2d5e2d5e2d5e2d5e2d5e2d5e2d",
31+
"status": "current"
32+
},
33+
{
34+
"measurement": "sha256:6f3e6f3e6f3e6f3e6f3e6f3e6f3e6f3e6f3e6f3e6f3e6f3e6f3e6f3e6f3e6f3e",
35+
"status": "retiring",
36+
"retire_after": "2026-07-16T00:00:00Z"
37+
},
38+
{
39+
"measurement": "sha256:70af70af70af70af70af70af70af70af70af70af70af70af70af70af70af70af",
40+
"status": "revoked"
41+
}
42+
],
43+
"note": "key decrypts only under a builder-signed serving stack whose measurement is current or retiring; status:revoked hard-fails immediately"
44+
},
45+
"key_release_mode": "attestation-gated",
46+
"replay_protection": "kbs-nonce-required",
47+
"attestation_revocation_check": "live-per-release, max-cache-age: short-window",
48+
"revocation_authority": "builder-and-opaque-joint",
49+
"sovereign_profile": {
50+
"enabled": false,
51+
"revocation_authority": "quorum",
52+
"sovereign_signer": null,
53+
"note": "when enabled, no single party (builder included) can revoke or dark the model unilaterally"
54+
}
55+
},
56+
"custody": {
57+
"custodian": "opaque-systems",
58+
"custodian_type": "opaque-hosted",
59+
"kbs_image": {
60+
"measurement": "sha256:abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234",
61+
"signer": "ed25519:opaque-key-placeholder",
62+
"note": "the key release service runs in an attested enclave in every profile, Opaque-hosted included"
63+
},
64+
"enclave_id": "did:opaque:example-enclave-04",
65+
"attestation_cadence": "24h",
66+
"kbs_attestation_cadence": "24h"
67+
},
68+
"base_confidentiality": "confidential",
69+
"deployment_model": "builder-to-customer",
70+
"signatures": []
71+
}

0 commit comments

Comments
 (0)