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
97 changes: 97 additions & 0 deletions conformance/tests/test_manifest_ref_draft_vectors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
"""v0.3 draft fixtures for trace-spec#483: a signed record names the agent manifest it ran under.

No module implements the reference yet, so the draft rule is stated here as a small reference
checker. The record signature is verified first (§3.3 step 1); the manifest reference is then
appraised by recomputing sha256 over the bytes the resolver returns for ``manifest.id``. A
``manifest_verification_result`` the producer wrote is never read. Four wrong checkers must each
be caught by at least one fixture.
"""

import base64
import copy
import hashlib
import importlib.util
import json
from pathlib import Path

import pytest
import rfc8785
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey

VECTOR_DIR = Path(__file__).parent / "vectors" / "manifest-ref-v0.3-draft"
VECTORS = [json.loads(p.read_text()) for p in sorted(VECTOR_DIR.glob("[0-9][0-9]-*.json"))]
MUTANTS = (
"trusts_asserted_result",
"unresolved_is_pass",
"manifest_before_signature",
"rejects_record_on_unresolved",
)


def _b64u(s: str) -> bytes:
b = base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
if base64.urlsafe_b64encode(b).rstrip(b"=").decode() != s:
raise ValueError("non-canonical base64url")
return b


def _signature_ok(rec: dict) -> bool:
try:
jwk = rec["cnf"]["jwk"]
if jwk.get("kty") != "OKP" or jwk.get("crv") != "Ed25519":
return False
body = {k: v for k, v in rec.items() if k != "signature"}
Ed25519PublicKey.from_public_bytes(_b64u(jwk["x"])).verify(
_b64u(rec["signature"]), rfc8785.dumps(body)
)
return True
except Exception:
return False


def check(vector: dict, mutant: str | None = None) -> dict:
rec, store = vector["record"], vector["resolver"]
if mutant != "manifest_before_signature" and not _signature_ok(rec):
return {"record": "signature-invalid", "manifest": "not-evaluated"}
ref = rec.get("manifest")
if ref is None:
return {"record": "valid", "manifest": "no-manifest-named"}
if mutant == "trusts_asserted_result" and rec.get("manifest_verification_result") == "verified":
return {"record": "valid", "manifest": "established"}
if ref.get("id") not in store:
if mutant == "unresolved_is_pass":
return {"record": "valid", "manifest": "established"}
if mutant == "rejects_record_on_unresolved":
return {"record": "manifest-unresolved", "manifest": "not-evaluated"}
return {"record": "valid", "manifest": "manifest-unresolved"}
got = "sha256:" + hashlib.sha256(store[ref["id"]].encode("utf-8")).hexdigest()
return {
"record": "valid",
"manifest": "established" if got == ref.get("digest") else "manifest-digest-mismatch",
}


@pytest.mark.parametrize("vector", VECTORS, ids=lambda v: v["name"])
def test_manifest_reference_vector(vector):
assert check(vector) == vector["expected"]


@pytest.mark.parametrize("mutant", MUTANTS)
def test_each_wrong_checker_is_caught(mutant):
assert any(check(v, mutant) != v["expected"] for v in VECTORS)


def test_editing_the_signed_digest_fails_the_signature():
rec = copy.deepcopy(VECTORS[0]["record"])
d = rec["manifest"]["digest"]
rec["manifest"]["digest"] = d[:-1] + ("0" if d[-1] != "0" else "1")
assert not _signature_ok(rec)


def test_fixtures_are_reproducible():
spec = importlib.util.spec_from_file_location(
"manifest_ref_generator", VECTOR_DIR / "generate.py"
)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
assert module.vectors() == VECTORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "01-digest-matches",
"status": "v0.3-draft",
"proposal": "agentrust-io/trace-spec#483",
"record": {
"eat_profile": "tag:agentrust-io.com,2026:trace-v0.2",
"iat": 1785000000,
"subject": "spiffe://factory.example/agent/payments/prod",
"model": {
"provider": "example-provider",
"model_id": "example-model-1"
},
"runtime": {
"platform": "software-only",
"measurement": "sha256:0000000000000000000000000000000000000000000000000000000000000000"
},
"policy": {
"bundle_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"enforcement_mode": "enforce"
},
"data_class": "confidential",
"build_provenance": {
"slsa_level": 0,
"digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
},
"appraisal": {
"status": "affirming",
"verifier": "https://verifier.example/v1"
},
"cnf": {
"jwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": "mcKFJmGaHdWlVL-4I-ETFbbmCsVheweKmgdxHkcqEBc"
}
},
"manifest": {
"id": "urn:example:agent-manifest:payments-agent",
"digest": "sha256:a773501007076390d7532a16294e4ee8c1ae07aa030f90c85cf513fdeeeeb472",
"media_type": "application/json"
},
"signature": "wnkUTs2U7NvWLbQb5baCkvn3TtiuP5Wb5ktJ_yVT-SO77noVRCACo5-upQJqoveMTrwnrN_i8RtL5Ta0zV8nDw"
},
"resolver": {
"urn:example:agent-manifest:payments-agent": "{\"manifest_id\":\"urn:example:agent-manifest:payments-agent\",\"version\":\"1.4.0\",\"tools\":[\"refund\",\"lookup_payment\"],\"model_id\":\"example-model-1\"}"
},
"expected": {
"record": "valid",
"manifest": "established"
},
"why": "the signed digest equals sha256 of the manifest bytes the verifier resolved"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "02-digest-mismatch",
"status": "v0.3-draft",
"proposal": "agentrust-io/trace-spec#483",
"record": {
"eat_profile": "tag:agentrust-io.com,2026:trace-v0.2",
"iat": 1785000000,
"subject": "spiffe://factory.example/agent/payments/prod",
"model": {
"provider": "example-provider",
"model_id": "example-model-1"
},
"runtime": {
"platform": "software-only",
"measurement": "sha256:0000000000000000000000000000000000000000000000000000000000000000"
},
"policy": {
"bundle_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"enforcement_mode": "enforce"
},
"data_class": "confidential",
"build_provenance": {
"slsa_level": 0,
"digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
},
"appraisal": {
"status": "affirming",
"verifier": "https://verifier.example/v1"
},
"cnf": {
"jwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": "mcKFJmGaHdWlVL-4I-ETFbbmCsVheweKmgdxHkcqEBc"
}
},
"manifest": {
"id": "urn:example:agent-manifest:payments-agent",
"digest": "sha256:a773501007076390d7532a16294e4ee8c1ae07aa030f90c85cf513fdeeeeb472",
"media_type": "application/json"
},
"signature": "wnkUTs2U7NvWLbQb5baCkvn3TtiuP5Wb5ktJ_yVT-SO77noVRCACo5-upQJqoveMTrwnrN_i8RtL5Ta0zV8nDw"
},
"resolver": {
"urn:example:agent-manifest:payments-agent": "{\"manifest_id\":\"urn:example:agent-manifest:payments-agent\",\"version\":\"1.5.0\",\"tools\":[\"refund\",\"lookup_payment\",\"wire_transfer\"],\"model_id\":\"example-model-1\"}"
},
"expected": {
"record": "valid",
"manifest": "manifest-digest-mismatch"
},
"why": "the id now resolves to a later deployment (1.5.0 adds wire_transfer); the record ran under 1.4.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"name": "03-mismatch-with-asserted-result",
"status": "v0.3-draft",
"proposal": "agentrust-io/trace-spec#483",
"record": {
"eat_profile": "tag:agentrust-io.com,2026:trace-v0.2",
"iat": 1785000000,
"subject": "spiffe://factory.example/agent/payments/prod",
"model": {
"provider": "example-provider",
"model_id": "example-model-1"
},
"runtime": {
"platform": "software-only",
"measurement": "sha256:0000000000000000000000000000000000000000000000000000000000000000"
},
"policy": {
"bundle_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"enforcement_mode": "enforce"
},
"data_class": "confidential",
"build_provenance": {
"slsa_level": 0,
"digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
},
"appraisal": {
"status": "affirming",
"verifier": "https://verifier.example/v1"
},
"cnf": {
"jwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": "mcKFJmGaHdWlVL-4I-ETFbbmCsVheweKmgdxHkcqEBc"
}
},
"manifest": {
"id": "urn:example:agent-manifest:payments-agent",
"digest": "sha256:a773501007076390d7532a16294e4ee8c1ae07aa030f90c85cf513fdeeeeb472",
"media_type": "application/json"
},
"manifest_verification_result": "verified",
"signature": "6i9nltz5j8ZeiVN-_Htg8v5qrmfm8w82EeKRHj-3rz3BB8EK68pWrKM96kY_U2ZvEtgahRUArceT1oSeYQy_AQ"
},
"resolver": {
"urn:example:agent-manifest:payments-agent": "{\"manifest_id\":\"urn:example:agent-manifest:payments-agent\",\"version\":\"1.5.0\",\"tools\":[\"refund\",\"lookup_payment\",\"wire_transfer\"],\"model_id\":\"example-model-1\"}"
},
"expected": {
"record": "valid",
"manifest": "manifest-digest-mismatch"
},
"why": "the producer also signed manifest_verification_result=verified; the verifier recomputes and does not carry it"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"name": "04-unresolvable",
"status": "v0.3-draft",
"proposal": "agentrust-io/trace-spec#483",
"record": {
"eat_profile": "tag:agentrust-io.com,2026:trace-v0.2",
"iat": 1785000000,
"subject": "spiffe://factory.example/agent/payments/prod",
"model": {
"provider": "example-provider",
"model_id": "example-model-1"
},
"runtime": {
"platform": "software-only",
"measurement": "sha256:0000000000000000000000000000000000000000000000000000000000000000"
},
"policy": {
"bundle_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"enforcement_mode": "enforce"
},
"data_class": "confidential",
"build_provenance": {
"slsa_level": 0,
"digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
},
"appraisal": {
"status": "affirming",
"verifier": "https://verifier.example/v1"
},
"cnf": {
"jwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": "mcKFJmGaHdWlVL-4I-ETFbbmCsVheweKmgdxHkcqEBc"
}
},
"manifest": {
"id": "urn:example:agent-manifest:payments-agent",
"digest": "sha256:a773501007076390d7532a16294e4ee8c1ae07aa030f90c85cf513fdeeeeb472",
"media_type": "application/json"
},
"signature": "wnkUTs2U7NvWLbQb5baCkvn3TtiuP5Wb5ktJ_yVT-SO77noVRCACo5-upQJqoveMTrwnrN_i8RtL5Ta0zV8nDw"
},
"resolver": {},
"expected": {
"record": "valid",
"manifest": "manifest-unresolved"
},
"why": "not a pass, and not a reason to reject the record (the §3.1.2 rule 3 posture for pointers)"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "05-added-after-signing",
"status": "v0.3-draft",
"proposal": "agentrust-io/trace-spec#483",
"record": {
"eat_profile": "tag:agentrust-io.com,2026:trace-v0.2",
"iat": 1785000000,
"subject": "spiffe://factory.example/agent/payments/prod",
"model": {
"provider": "example-provider",
"model_id": "example-model-1"
},
"runtime": {
"platform": "software-only",
"measurement": "sha256:0000000000000000000000000000000000000000000000000000000000000000"
},
"policy": {
"bundle_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"enforcement_mode": "enforce"
},
"data_class": "confidential",
"build_provenance": {
"slsa_level": 0,
"digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
},
"appraisal": {
"status": "affirming",
"verifier": "https://verifier.example/v1"
},
"cnf": {
"jwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": "mcKFJmGaHdWlVL-4I-ETFbbmCsVheweKmgdxHkcqEBc"
}
},
"signature": "1MgcfqL71SogLyNuz1p1a5xcqlBbdZDu8ffG_K4gvl8SAUEE-iUM5vkKMIMD6DiqkEeqUB-escskzwoSgVM9CQ",
"manifest": {
"id": "urn:example:agent-manifest:payments-agent",
"digest": "sha256:a773501007076390d7532a16294e4ee8c1ae07aa030f90c85cf513fdeeeeb472",
"media_type": "application/json"
}
},
"resolver": {
"urn:example:agent-manifest:payments-agent": "{\"manifest_id\":\"urn:example:agent-manifest:payments-agent\",\"version\":\"1.4.0\",\"tools\":[\"refund\",\"lookup_payment\"],\"model_id\":\"example-model-1\"}"
},
"expected": {
"record": "signature-invalid",
"manifest": "not-evaluated"
},
"why": "manifest is outside the signed bytes; §3.3 step 1 fails before any field is trusted"
}
Loading
Loading