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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ python demo-02-policy-swap/run.py
What you see:
- v1 and v2 bundle hashes printed (visibly different SHA-256 values)
- `write_file` is DENIED under v2 policy (new Cedar forbid rule)
- `cmcp verify` on the v1 claim with v2 hash -> POLICY_HASH_MISMATCH
- `cmcp verify` on the v1 claim with v1 hash -> passes
- `cmcp verify` on the v2 claim with the pinned v1 hash -> `policy_bundle.hash` FAILS (POLICY_HASH_MISMATCH)
- `cmcp verify` on the v2 claim with the v2 hash -> `policy_bundle.hash` PASSES (overall result stays `partially_verified` in software-only mode, because only `hardware_attestation` is left unchecked)

---

Expand All @@ -81,7 +81,7 @@ python demo-03-offline-trace/run.py
What you see:
- Claim fields printed: `runtime.platform`, `runtime.measurement`, `policy.bundle_hash`
- All cryptographic checks pass (schema, signature, policy hash, catalog hash, audit chain)
- `hardware_attestation` is in `unverified_fields` (software-only mode -- on real TDX it would also be verified)
- `hardware_attestation` is in `unverified_fields`, so the status reads `partially_verified` (software-only mode -- on real TDX that field verifies too and the status becomes `verified`)
- No connection made to any server

---
Expand Down
8 changes: 6 additions & 2 deletions demo-02-policy-swap/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,18 @@ def main() -> None:
print()
print("-- Step 5: Verify v2 claim with v1 (pinned) hash -> POLICY_HASH_MISMATCH --")
print(" A verifier that approved v1 now rejects any claim from the v2 Runtime.")
print(" Watch the policy_bundle.hash line below: it FAILS.")
sys.stdout.flush()
subprocess.run(
[cmcp, "verify", str(V2_CLAIM_PATH), "--policy-hash", v1_hash_out, "--catalog-hash", cat_hash],
)

print()
print("-- Step 6: Verify v2 claim with v2 hash -> passes --")
print(" (Confirms the v2 claim itself is well-formed; only the pinned hash differs.)")
print("-- Step 6: Verify v2 claim with v2 hash -> policy_bundle.hash now PASSES --")
print(" Same claim, correct pinned hash: the policy_bundle.hash line flips")
print(" FAIL -> PASS. The policy swap is fully accounted for.")
print(" The overall result stays partially_verified only because software-only")
print(" dev mode has no hardware_attestation to check. On real TDX it verifies.")
sys.stdout.flush()
subprocess.run(
[cmcp, "verify", str(V2_CLAIM_PATH), "--policy-hash", v2_hash_out, "--catalog-hash", cat_hash],
Expand Down
29 changes: 12 additions & 17 deletions demo-03-offline-trace/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,27 @@

**Duration:** ~60 seconds

A signed Trust Record is verified using only the record and the issuer's public key. No server, no cMCP runtime, no registry connection required. This is the portability property of TRACE: verification is fully self-contained.
The signed TRACE claim from demo-01 is verified using only the claim itself and the hashes embedded in it. No running cMCP runtime, no server, no network call. This is the portability property of TRACE: verification is fully self-contained.

## Setup

Run demo-01 first to produce a signed record, then copy the artifacts here:

```bash
cp ../demo-01-cmcp-in-action/trace_record.json ./trust_record.json
cp ../demo-01-cmcp-in-action/issuer_pub.pem ./issuer_pub.pem
```
**Requires demo-01 to have run first** (reads `../workspace/trace-claim.json`).

## Run

```bash
bash run.sh
```
python run.py
```

## What to show the audience

1. The `verify.py` script loads the record and the public key — nothing else
2. All TRACE fields are printed: subject, model, runtime, policy, transparency
3. `Signature: VALID` — no network call was made
4. Point out: `runtime.measurement` and `policy.bundle_hash` are committed in the signature
1. `verify.py` loads only `workspace/trace-claim.json` and the hashes committed inside it
2. All cryptographic checks pass: schema, signature, policy hash, catalog hash, attestation freshness, audit chain
3. `hardware_attestation` lands in `unverified_fields`, so the status reads `partially_verified`
- This is expected under `CMCP_DEV_MODE=1` (software-only TEE, no hardware to attest)
- On real Intel TDX or AMD SEV-SNP, that field verifies too and the status becomes `verified`
4. Point out: `runtime.measurement` and `policy.bundle_hash` are committed in the Ed25519 signature
- Changing either field would break the signature
- The verifier needs no connection to the operator who produced the record
- No connection to the operator who produced the claim is needed

## Key takeaway

The TRACE record is a portable proof. A regulator, auditor, or counterparty who holds the issuer's public key can verify any record independently — the operator who produced it does not need to be online or trusted.
The TRACE claim is a portable proof. A regulator, auditor, or counterparty who holds the issuer's public key can verify any claim independently. The operator who produced it does not need to be online or trusted. Software-only mode proves the whole chain except the hardware root; hardware mode closes that last gap.