From 9b7144798b3d96a81b43b496a5322ed817641d6c Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Tue, 21 Jul 2026 09:34:27 -0700 Subject: [PATCH] feat: add azure-cvm-sev-snp platform (v0.4.0) Azure confidential VMs run AMD SEV-SNP behind a Hyper-V paravisor: the SNP report is read from the vTPM and the guest does not control REPORT_DATA, so the runtime binding rides a vTPM AK-signed quote rather than the SNP report_data. Give it a distinct runtime.platform value so a consumer keying on runtime.platform knows the root of trust is vTPM-rooted, not direct-silicon. Adds the value to the RuntimeInfo model and both JSON schema enums, docs, and bumps the version to 0.4.0. Hardware-validated on a live Azure SEV-SNP VM via cMCP. Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 4 ++++ docs/schema.md | 4 ++-- pyproject.toml | 2 +- schema/trace-claim.json | 3 ++- src/agentrust_trace/models.py | 14 ++++++++++---- src/agentrust_trace/schema/trace-v0.1.json | 3 ++- 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d175f1d..6f20a29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,12 @@ Format: [Semantic Versioning](https://semver.org/). Spec versions follow `MAJOR. ## [Unreleased] +## [0.4.0] + ### Added +- **`azure-cvm-sev-snp` platform** — Azure confidential VMs run AMD SEV-SNP behind a Hyper-V paravisor: the SNP report is read from the vTPM (the guest does not control `REPORT_DATA`), so the runtime binding rides a vTPM AK-signed quote rather than the SNP `report_data`. Given its own `runtime.platform` value (distinct from `amd-sev-snp`) so a consumer keying on `runtime.platform` knows the root of trust is vTPM-rooted, not direct-silicon. Added to the `RuntimeInfo` model and the JSON schema enum. Hardware-validated on a live Azure SEV-SNP VM via cMCP. + - `delegation` (optional object): the A2A profile delegation-link block, carrying `parent_record_hash` (digest of the parent hop's Trust Record) and `credential_id` (the delegation credential this hop acted under). A chain of records linked this way forms an offline-verifiable delegation DAG. Backward-compatible: existing records without `delegation` remain valid. This is a MINOR (additive) change and the foundation of the forthcoming A2A profile; A2A is now stable at v1.x, clearing the prior blocker. --- diff --git a/docs/schema.md b/docs/schema.md index f063ad9..d7ae299 100644 --- a/docs/schema.md +++ b/docs/schema.md @@ -19,7 +19,7 @@ JSON Schema for the TRACE v0.1 Trust Record. Source: [`schema/trace-claim.json`] | `appraisal` | object | **yes** | Verifier judgment | | `transparency` | string | **yes** | SCITT transparency log anchor URI (empty string if not anchored) | | `cnf` | object | **yes** | Confirmation method — contains the `jwk` signing key | -| `signature` | string | **yes** | Base64url Ed25519 / ES256 / ES384 signature over the canonical record with only `signature` absent; `cnf` is included | +| `signature` | string | **yes** | Base64url Ed25519 / ES256 / ES384 signature over the canonical record with only `signature` absent; `cnf` is included | ## `model` @@ -39,7 +39,7 @@ Binds the execution environment. Platform-specific fields vary by TEE type. | Field | Type | Required | Description | |---|---|---|---| -| `platform` | string | **yes** | One of: `amd-sev-snp`, `intel-tdx`, `nvidia-h100`, `nvidia-blackwell`, `tpm-2.0`, `software-only` | +| `platform` | string | **yes** | One of: `amd-sev-snp`, `azure-cvm-sev-snp`, `intel-tdx`, `nvidia-h100`, `nvidia-blackwell`, `tpm-2.0`, `software-only` | | `measurement` | string | **yes** | Hardware measurement hash (`sha384:` for SEV-SNP/TDX, `sha256:` for TPM) | | `rim_uri` | string | no | Reference Integrity Manifest URI for hardware verification | | `firmware_version` | string | no | TEE firmware version | diff --git a/pyproject.toml b/pyproject.toml index 9d5a233..e0d9813 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "agentrust-trace" -version = "0.3.0" +version = "0.4.0" description = "TRACE v0.1 — hardware-attested governance records for AI agents" readme = "README.md" license = { text = "Apache-2.0" } diff --git a/schema/trace-claim.json b/schema/trace-claim.json index d6292ad..4ab2a8a 100644 --- a/schema/trace-claim.json +++ b/schema/trace-claim.json @@ -73,6 +73,7 @@ "enum": [ "intel-tdx", "amd-sev-snp", + "azure-cvm-sev-snp", "nvidia-h100", "nvidia-blackwell", "aws-nitro", @@ -276,7 +277,7 @@ }, "signature": { "type": "string", - "description": "OPTIONAL embedded signature: base64url (no padding) signature by the cnf key over the canonical JSON form of the record with only this field absent. Every Trust Record MUST be signature-bound per spec section 3.2.2, but enveloped profiles (e.g. JWS, cMCP RuntimeClaim) carry the signature outside the record, so this field is not required by the schema.", + "description": "OPTIONAL embedded signature: base64url (no padding) signature by the cnf key over the canonical JSON form of the record with only this field absent. Every Trust Record MUST be signature-bound per spec section 3.2.2, but enveloped profiles (e.g. JWS, cMCP RuntimeClaim) carry the signature outside the record, so this field is not required by the schema.", "pattern": "^[A-Za-z0-9_-]+$" } }, diff --git a/src/agentrust_trace/models.py b/src/agentrust_trace/models.py index 695e919..a324c7f 100644 --- a/src/agentrust_trace/models.py +++ b/src/agentrust_trace/models.py @@ -25,6 +25,12 @@ class RuntimeInfo(BaseModel): platform: Literal[ "intel-tdx", "amd-sev-snp", + # Azure confidential VM: AMD SEV-SNP behind a Hyper-V paravisor. The SNP + # report is read from the vTPM (the guest does not control REPORT_DATA), + # so the runtime binding rides a vTPM AK-signed quote rather than the SNP + # report_data. Distinct from amd-sev-snp so a consumer keying on + # runtime.platform knows the binding is vTPM-rooted, not direct-silicon. + "azure-cvm-sev-snp", "nvidia-h100", "nvidia-blackwell", "aws-nitro", @@ -154,7 +160,7 @@ class TrustRecord(BaseModel): transparency: Annotated[str, Field(min_length=1)] cnf: ConfirmationKey signature: Annotated[str, Field(pattern=r"^[A-Za-z0-9_-]+$")] | None = None - """Optional embedded signature (base64url, no padding) by the cnf key over the - canonical JSON form of the record with only this field absent. Every Trust Record must - be signature-bound per spec section 3.2.2; enveloped profiles carry the signature - outside the record instead of in this field.""" + """Optional embedded signature (base64url, no padding) by the cnf key over the + canonical JSON form of the record with only this field absent. Every Trust Record must + be signature-bound per spec section 3.2.2; enveloped profiles carry the signature + outside the record instead of in this field.""" diff --git a/src/agentrust_trace/schema/trace-v0.1.json b/src/agentrust_trace/schema/trace-v0.1.json index b0f5ded..ae1018e 100644 --- a/src/agentrust_trace/schema/trace-v0.1.json +++ b/src/agentrust_trace/schema/trace-v0.1.json @@ -73,6 +73,7 @@ "enum": [ "intel-tdx", "amd-sev-snp", + "azure-cvm-sev-snp", "nvidia-h100", "nvidia-blackwell", "aws-nitro", @@ -276,7 +277,7 @@ }, "signature": { "type": "string", - "description": "OPTIONAL embedded signature: base64url (no padding) signature by the cnf key over the canonical JSON form of the record with only this field absent. Every Trust Record MUST be signature-bound per spec section 3.2.2, but enveloped profiles (e.g. JWS, cMCP RuntimeClaim) carry the signature outside the record, so this field is not required by the schema.", + "description": "OPTIONAL embedded signature: base64url (no padding) signature by the cnf key over the canonical JSON form of the record with only this field absent. Every Trust Record MUST be signature-bound per spec section 3.2.2, but enveloped profiles (e.g. JWS, cMCP RuntimeClaim) carry the signature outside the record, so this field is not required by the schema.", "pattern": "^[A-Za-z0-9_-]+$" } },