From 0c258c4c5cd30ffa309137b3390f7c2215a8468c Mon Sep 17 00:00:00 2001 From: ramen Labs Date: Tue, 21 Jul 2026 11:22:01 +0200 Subject: [PATCH 1/2] feat: add ramen-ai-core cmcp policy adapter and trace record mapping --- .../workflows/ramen-ai-cmcp-conformance.yml | 51 +++++++ integrations/ramen-ai-cmcp/README.md | 59 +++++++++ .../ramen_ai_trace.cpython-313.pyc | Bin 0 -> 5270 bytes .../ramen-ai-cmcp/examples/emit_record.py | 66 ++++++++++ .../examples/fixtures/vector1_allowed.json | 19 +++ .../examples/fixtures/vector_n1_bad_sig.json | 16 +++ integrations/ramen-ai-cmcp/integration.yaml | 22 ++++ integrations/ramen-ai-cmcp/pyproject.toml | 17 +++ .../PKG-INFO | 9 ++ .../SOURCES.txt | 9 ++ .../dependency_links.txt | 1 + .../requires.txt | 4 + .../top_level.txt | 1 + integrations/ramen-ai-cmcp/ramen_ai_trace.py | 124 ++++++++++++++++++ .../test_mapping.cpython-313-pytest-9.1.1.pyc | Bin 0 -> 11914 bytes .../ramen-ai-cmcp/tests/test_mapping.py | 116 ++++++++++++++++ 16 files changed, 514 insertions(+) create mode 100644 .github/workflows/ramen-ai-cmcp-conformance.yml create mode 100644 integrations/ramen-ai-cmcp/README.md create mode 100644 integrations/ramen-ai-cmcp/__pycache__/ramen_ai_trace.cpython-313.pyc create mode 100644 integrations/ramen-ai-cmcp/examples/emit_record.py create mode 100644 integrations/ramen-ai-cmcp/examples/fixtures/vector1_allowed.json create mode 100644 integrations/ramen-ai-cmcp/examples/fixtures/vector_n1_bad_sig.json create mode 100644 integrations/ramen-ai-cmcp/integration.yaml create mode 100644 integrations/ramen-ai-cmcp/pyproject.toml create mode 100644 integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/PKG-INFO create mode 100644 integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/SOURCES.txt create mode 100644 integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/dependency_links.txt create mode 100644 integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/requires.txt create mode 100644 integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/top_level.txt create mode 100644 integrations/ramen-ai-cmcp/ramen_ai_trace.py create mode 100644 integrations/ramen-ai-cmcp/tests/__pycache__/test_mapping.cpython-313-pytest-9.1.1.pyc create mode 100644 integrations/ramen-ai-cmcp/tests/test_mapping.py diff --git a/.github/workflows/ramen-ai-cmcp-conformance.yml b/.github/workflows/ramen-ai-cmcp-conformance.yml new file mode 100644 index 0000000..e4421de --- /dev/null +++ b/.github/workflows/ramen-ai-cmcp-conformance.yml @@ -0,0 +1,51 @@ +# ramen-ai cMCP adapter conformance workflow. +# Lives at repo root — GitHub Actions only discovers workflows here. +# Scoped to this integration via paths filter. +name: ramen-ai-cmcp conformance +on: + push: + paths: + - "integrations/ramen-ai-cmcp/**" + - ".github/workflows/ramen-ai-cmcp-conformance.yml" + pull_request: + paths: + - "integrations/ramen-ai-cmcp/**" + - ".github/workflows/ramen-ai-cmcp-conformance.yml" + schedule: + - cron: "0 6 * * 1" # weekly: catch drift against the latest released packages + workflow_dispatch: + +permissions: + contents: read + +jobs: + conformance: + strategy: + fail-fast: false + matrix: + python: ["3.11", "3.12", "3.13", "3.14"] + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: ${{ matrix.python }} + - name: Install released agentrust-io packages + run: | + python -m pip install --upgrade pip + pip install agentrust-trace agentrust-trace-tests cmcp-runtime + - name: Install this integration + run: pip install -e "integrations/ramen-ai-cmcp[test]" + - name: Integration tests + run: pytest integrations/ramen-ai-cmcp/tests -q + - name: Emit a sample TRACE record + run: python integrations/ramen-ai-cmcp/examples/emit_record.py --out trust-record.jwt + - name: TRACE conformance level 0 + run: trace-tests verify --record trust-record.jwt --level 0 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: conformance-${{ matrix.os }}-py${{ matrix.python }} + path: | + trust-record.jwt + trust-record.jwt.signed.json diff --git a/integrations/ramen-ai-cmcp/README.md b/integrations/ramen-ai-cmcp/README.md new file mode 100644 index 0000000..903b41a --- /dev/null +++ b/integrations/ramen-ai-cmcp/README.md @@ -0,0 +1,59 @@ +# ramen-ai cMCP Adapter integration with cMCP + TRACE + +Intercepts tool calls at the [cMCP](https://github.com/agentrust-io/cmcp) +boundary, evaluates their semantic intent against configured compliance policies +via the [ramen-ai](https://ramenai.dev) API, and maps the resulting V5 +Ed25519-signed receipt onto a TRACE Trust Record (EAT profile +`tag:agentrust.io,2026:trace-v0.1`). + +Source: [ramen-ai-dev/ramen-ai-integrations — plugins/cmcp-python](https://github.com/ramen-ai-dev/ramen-ai-integrations/tree/master/plugins/cmcp-python) + +## Run it + +Against released packages (`agentrust-trace` 0.3.0, `cmcp-runtime` 0.3.0): + +```bash +pip install agentrust-trace agentrust-trace-tests cmcp-runtime +pip install -e "integrations/ramen-ai-cmcp[test]" +pytest integrations/ramen-ai-cmcp/tests -q +python integrations/ramen-ai-cmcp/examples/emit_record.py --out trust-record.jwt +trace-tests verify --record trust-record.jwt --level 0 +``` + +## What is verified + +- `ramen_ai_trace.build_trace_record` maps a committed V5 fixture receipt onto + TRACE fields: `policy.bundle_hash` (`sha256:`), `runtime.measurement` + (receipt UUID), `subject` (`spiffe://ramenai.dev/evaluation/`), + `appraisal.status` (`affirming` / `denying`). +- `agentrust_trace.sign_record` signs the record with an ephemeral Ed25519 key + and `agentrust_trace.verify_record(..., allow_embedded_key=True)` verifies the + round-trip; `tests/` includes a tamper probe that must fail verification. +- `trace-tests verify --level 0` passes on the emitted record (8 checks). + +## What it does NOT claim + +See rules 2 and 4 in [CONTRIBUTING.md](../../CONTRIBUTING.md). + +- **Level 0 carries a TR-SIG-005 UNVERIFIED finding.** The `agentrust-trace-tests` + loader rejects any plain record carrying a top-level `signature` field + (anti-downgrade), so the gradable record is the unsigned payload. The signed + form is written alongside it (`.signed.json`) and verifies with + `agentrust_trace.verify_record`. +- The ephemeral signing key proves the sign/verify path works; it does **not** + chain to a trusted issuer. +- `runtime.platform` is `software-only`. No TEE, hardware root of trust, or + attested-execution claim is made. +- The ramen-ai evaluation API requires `RAMEN_API_KEY` and `OPENAI_API_KEY` + (BYOK on Starter/Professional tiers). The conformance workflow does not call + the live API — it maps a committed fixture receipt offline. +- V5 receipts bind policy UUIDs but not rule content (policies are mutable under + the same UUID). See `v5-conformance.md §6` in the ramen-ai-integrations repo. + +## Conformance CI + +The repository-root workflow +[`.github/workflows/ramen-ai-cmcp-conformance.yml`](../../.github/workflows/ramen-ai-cmcp-conformance.yml) +(path-scoped to this directory) installs the released agentrust-io packages, +runs the mapping tests, emits a record, and runs `trace-tests verify --level 0` +across Python 3.11–3.14. A clean matrix run is the basis for the Verified tier. diff --git a/integrations/ramen-ai-cmcp/__pycache__/ramen_ai_trace.cpython-313.pyc b/integrations/ramen-ai-cmcp/__pycache__/ramen_ai_trace.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..037167ace4f906b37b30338985928283b48ce7ef GIT binary patch literal 5270 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 G82&FRtV0$6 literal 0 HcmV?d00001 diff --git a/integrations/ramen-ai-cmcp/examples/emit_record.py b/integrations/ramen-ai-cmcp/examples/emit_record.py new file mode 100644 index 0000000..5af3dc5 --- /dev/null +++ b/integrations/ramen-ai-cmcp/examples/emit_record.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +"""Emit a TRACE Trust Record from a ramen-ai V5 fixture receipt. + +Loads ``examples/fixtures/vector1_allowed.json``, maps the receipt onto a TRACE +Trust Record via :func:`ramen_ai_trace.build_trace_record`, signs it with an +ephemeral Ed25519 key via ``agentrust_trace.sign_record``, verifies the +round-trip, and writes two files: + + Unsigned record for ``trace-tests verify`` + .signed.json Signed record, verifiable with + ``agentrust_trace.verify_record(..., allow_embedded_key=True)`` + +Usage: + python examples/emit_record.py --out trust-record.jwt +""" +from __future__ import annotations + +import argparse +import json +import sys +import time +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) + +import agentrust_trace +from ramen_ai_trace import build_trace_record + +FIXTURE = Path(__file__).resolve().parent / "fixtures" / "vector1_allowed.json" + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--out", required=True, help="Path for the trace-tests-gradable record") + args = parser.parse_args() + + fixture = json.loads(FIXTURE.read_text(encoding="utf-8")) + receipt: dict = fixture["receipt"] + + key = agentrust_trace.generate_key() + jwk = agentrust_trace.key_to_jwk(key) + record = build_trace_record(receipt, iat=int(time.time()), jwk=jwk) + + signed = agentrust_trace.sign_record(dict(record), key) + agentrust_trace.verify_record(signed, allow_embedded_key=True) + + out = Path(args.out) + out.write_text( + json.dumps(record, sort_keys=True, separators=(",", ":")) + "\n", + encoding="utf-8", + ) + signed_out = out.with_name(out.name + ".signed.json") + signed_out.write_text( + json.dumps(signed, sort_keys=True, separators=(",", ":")) + "\n", + encoding="utf-8", + ) + + print(f"subject: {record['subject']}") + print(f"appraisal.status: {record['appraisal']['status']}") + print(f"unsigned (for trace-tests): {out}") + print(f"signed (verify_record OK): {signed_out}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/integrations/ramen-ai-cmcp/examples/fixtures/vector1_allowed.json b/integrations/ramen-ai-cmcp/examples/fixtures/vector1_allowed.json new file mode 100644 index 0000000..1c72c0c --- /dev/null +++ b/integrations/ramen-ai-cmcp/examples/fixtures/vector1_allowed.json @@ -0,0 +1,19 @@ +{ + "_comment": "Vector 1 — Allowed (verdict 1). Source: v5-conformance.md §5.1. Signed by ramen_pk_ephemeral_test.", + "input": "What are the standard terms for a cash ISA?", + "receipt": { + "id": "11111111-1111-4111-8111-111111111111", + "schema_version": "5.0", + "kid": "ramen_pk_ephemeral_test", + "signature": "86rTO8547URmP0M-k0AEHbjSjz2ASRndoRrAFKrtrQJvsPbiAfn6rqEbuQrf4rtNFYq4klVhcHrXqtjRcoC2Ag", + "canonical_payload": "{\"schema_version\":\"5.0\",\"kid\":\"ramen_pk_ephemeral_test\",\"id\":\"11111111-1111-4111-8111-111111111111\",\"timestamp\":\"2026-06-20T09:00:00.000Z\",\"policy_ids\":[\"f47ac10b-58cc-4372-a567-0e02b2c3d479\"],\"payload_hash\":\"adb09112ff437c97a89b17e2dcba478b0c1ebbf2331fa4e5d216f10085eeff21\",\"verdict\":1,\"reasoning\":\"\",\"steering\":\"\",\"statutory_anchors\":[\"FCA COBS 4.2.1\"]}", + "statutory_anchors": ["FCA COBS 4.2.1"] + }, + "expected": { + "valid": true, + "verdict": 1, + "reasoning": "", + "steering": "", + "payload_hash": "adb09112ff437c97a89b17e2dcba478b0c1ebbf2331fa4e5d216f10085eeff21" + } +} diff --git a/integrations/ramen-ai-cmcp/examples/fixtures/vector_n1_bad_sig.json b/integrations/ramen-ai-cmcp/examples/fixtures/vector_n1_bad_sig.json new file mode 100644 index 0000000..c572f53 --- /dev/null +++ b/integrations/ramen-ai-cmcp/examples/fixtures/vector_n1_bad_sig.json @@ -0,0 +1,16 @@ +{ + "_comment": "Negative Vector N1 — tampered signature. Source: v5-conformance.md §5.4. Must verify as valid=false.", + "input": "What are the standard terms for a cash ISA?", + "receipt": { + "id": "11111111-1111-4111-8111-111111111111", + "schema_version": "5.0", + "kid": "ramen_pk_ephemeral_test", + "signature": "86rTO8547URmP0M-k0AEHbjSjz2ASRndoRrAFKrtrQJvsPbiAfn6rqEbuQrf4rtNFYq4klVhcHrXqtjRcoC2AA", + "canonical_payload": "{\"schema_version\":\"5.0\",\"kid\":\"ramen_pk_ephemeral_test\",\"id\":\"11111111-1111-4111-8111-111111111111\",\"timestamp\":\"2026-06-20T09:00:00.000Z\",\"policy_ids\":[\"f47ac10b-58cc-4372-a567-0e02b2c3d479\"],\"payload_hash\":\"adb09112ff437c97a89b17e2dcba478b0c1ebbf2331fa4e5d216f10085eeff21\",\"verdict\":1,\"reasoning\":\"\",\"steering\":\"\",\"statutory_anchors\":[\"FCA COBS 4.2.1\"]}", + "statutory_anchors": ["FCA COBS 4.2.1"] + }, + "expected": { + "valid": false, + "reason_contains": "Signature does not verify" + } +} diff --git a/integrations/ramen-ai-cmcp/integration.yaml b/integrations/ramen-ai-cmcp/integration.yaml new file mode 100644 index 0000000..55e2c7f --- /dev/null +++ b/integrations/ramen-ai-cmcp/integration.yaml @@ -0,0 +1,22 @@ +name: ramen-ai cMCP Adapter +vendor: ramen-ai +integrates_with: + - cmcp + - trace +description: >- + cMCP tool-call policy adapter that evaluates semantic intent via the ramen-ai + API and maps the V5 Ed25519-signed receipt onto a TRACE Trust Record. +maintainer: + github: ramen-noodle6 + email: damian_smith442@aol.com +repository: https://github.com/ramen-ai-dev/ramen-ai-integrations +homepage: https://ramenai.dev +license: MIT +tier: community +# Level 0 passes with the TR-SIG-005 UNVERIFIED finding: trace-tests does not +# grade signatures on plain trace records — the signed form is written alongside +# the gradable record and verifies via agentrust_trace.verify_record. +trace_conformance_level: 0 +tested_against: + agentrust-trace: "0.3.0" + cmcp-runtime: "0.3.0" diff --git a/integrations/ramen-ai-cmcp/pyproject.toml b/integrations/ramen-ai-cmcp/pyproject.toml new file mode 100644 index 0000000..d3212b8 --- /dev/null +++ b/integrations/ramen-ai-cmcp/pyproject.toml @@ -0,0 +1,17 @@ +[build-system] +requires = ["setuptools>=68"] +build-backend = "setuptools.build_meta" + +[project] +name = "ramen-ai-cmcp-integration" +version = "0.1.0" +description = "ramen-ai cMCP policy adapter and TRACE Trust Record mapper" +requires-python = ">=3.11" +license = "MIT" +dependencies = ["agentrust-trace"] + +[project.optional-dependencies] +test = ["pytest"] + +[tool.setuptools] +py-modules = ["ramen_ai_trace"] diff --git a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/PKG-INFO b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/PKG-INFO new file mode 100644 index 0000000..66ca38b --- /dev/null +++ b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/PKG-INFO @@ -0,0 +1,9 @@ +Metadata-Version: 2.4 +Name: ramen-ai-cmcp-integration +Version: 0.1.0 +Summary: ramen-ai cMCP policy adapter and TRACE Trust Record mapper +License-Expression: MIT +Requires-Python: >=3.11 +Requires-Dist: agentrust-trace +Provides-Extra: test +Requires-Dist: pytest; extra == "test" diff --git a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/SOURCES.txt b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/SOURCES.txt new file mode 100644 index 0000000..383c58e --- /dev/null +++ b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/SOURCES.txt @@ -0,0 +1,9 @@ +README.md +pyproject.toml +ramen_ai_trace.py +ramen_ai_cmcp_integration.egg-info/PKG-INFO +ramen_ai_cmcp_integration.egg-info/SOURCES.txt +ramen_ai_cmcp_integration.egg-info/dependency_links.txt +ramen_ai_cmcp_integration.egg-info/requires.txt +ramen_ai_cmcp_integration.egg-info/top_level.txt +tests/test_mapping.py \ No newline at end of file diff --git a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/dependency_links.txt b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/requires.txt b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/requires.txt new file mode 100644 index 0000000..3dc326b --- /dev/null +++ b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/requires.txt @@ -0,0 +1,4 @@ +agentrust-trace + +[test] +pytest diff --git a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/top_level.txt b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/top_level.txt new file mode 100644 index 0000000..b13f972 --- /dev/null +++ b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/top_level.txt @@ -0,0 +1 @@ +ramen_ai_trace diff --git a/integrations/ramen-ai-cmcp/ramen_ai_trace.py b/integrations/ramen-ai-cmcp/ramen_ai_trace.py new file mode 100644 index 0000000..6e08d32 --- /dev/null +++ b/integrations/ramen-ai-cmcp/ramen_ai_trace.py @@ -0,0 +1,124 @@ +"""ramen_ai_trace — TRACE Trust Record mapper for ramen-ai V5 receipts. + +Maps a ramen-ai V5 Ed25519 receipt onto a TRACE Trust Record dict +(EAT profile tag:agentrust.io,2026:trace-v0.1). + +This is the self-contained copy for the agentrust-io/integrations submission. +The canonical implementation lives at: + https://github.com/ramen-ai-dev/ramen-ai-integrations/tree/master/plugins/cmcp-python + +Field mapping +───────────── +TRACE field ← ramen-ai V5 source +────────────────────────────────────────────────────────────── +eat_profile constant "tag:agentrust.io,2026:trace-v0.1" +iat caller-supplied (int, Unix seconds) +subject "spiffe://ramenai.dev/evaluation/" +cnf.jwk caller-supplied (public JWK for signing) +policy.bundle_hash "sha256:" + canonical_payload.payload_hash +policy.enforcement_mode "enforce" +policy.version canonical_payload.schema_version ("5.0") +runtime.measurement receipt.id +runtime.platform "software-only" +tool_transcript.call_count 1 +tool_transcript.hash "sha256:" + canonical_payload.payload_hash +tool_transcript.transcript_uri "urn:ramen-ai:evaluation:" +appraisal.policy_ref comma-joined canonical_payload.policy_ids +appraisal.status "affirming" if verdict==1 else "denying" +appraisal.timestamp iat +appraisal.verifier "ramen-ai-core" +appraisal.statutory_anchors canonical_payload.statutory_anchors (if non-empty) +appraisal.steering canonical_payload.steering (omitted when empty) +transparency "pending" +""" +from __future__ import annotations + +import json +from typing import Any + +EAT_PROFILE = "tag:agentrust.io,2026:trace-v0.1" +VERIFIER = "ramen-ai-core" + + +def build_trace_record( + receipt: dict[str, Any], + *, + iat: int, + jwk: dict[str, str], +) -> dict[str, Any]: + """Map a ramen-ai V5 receipt dict onto an unsigned TRACE Trust Record dict. + + Args: + receipt: The ``data.receipt`` sub-object from a ramen-ai evaluate + response. Must contain ``id``, ``schema_version`` (``"5.0"``), + ``kid``, ``signature``, and ``canonical_payload``. + iat: Unix timestamp (int seconds) for the record issue time. + jwk: Public JWK dict embedded in ``cnf.jwk``; matches the private + key used to sign the record with ``agentrust_trace.sign_record``. + + Returns: + Unsigned TRACE Trust Record dict. + + Raises: + ValueError: if required fields are missing or schema_version != "5.0". + """ + _validate_receipt(receipt) + payload: dict[str, Any] = json.loads(receipt["canonical_payload"]) + + receipt_id: str = receipt["id"] + payload_hash: str = payload["payload_hash"] + verdict: int = payload["verdict"] + policy_ids: list[str] = payload.get("policy_ids", []) + statutory_anchors: list[str] = payload.get("statutory_anchors", []) + steering: str = payload.get("steering", "") + + prefixed_hash = f"sha256:{payload_hash}" + + appraisal: dict[str, Any] = { + "policy_ref": ", ".join(policy_ids), + "status": "affirming" if verdict == 1 else "denying", + "timestamp": iat, + "verifier": VERIFIER, + } + if statutory_anchors: + appraisal["statutory_anchors"] = statutory_anchors + if steering: + appraisal["steering"] = steering + + return { + "eat_profile": EAT_PROFILE, + "iat": iat, + "subject": f"spiffe://ramenai.dev/evaluation/{receipt_id}", + "cnf": {"jwk": jwk}, + "policy": { + "bundle_hash": prefixed_hash, + "enforcement_mode": "enforce", + "version": payload["schema_version"], + }, + "runtime": { + "measurement": receipt_id, + "platform": "software-only", + }, + "tool_transcript": { + "call_count": 1, + "hash": prefixed_hash, + "transcript_uri": f"urn:ramen-ai:evaluation:{receipt_id}", + }, + "appraisal": appraisal, + "transparency": "pending", + } + + +def _validate_receipt(receipt: dict[str, Any]) -> None: + required = {"id", "schema_version", "kid", "signature", "canonical_payload"} + missing = required - receipt.keys() + if missing: + raise ValueError(f"Receipt missing required fields: {missing}") + if receipt["schema_version"] != "5.0": + raise ValueError( + f"Unsupported schema_version '{receipt['schema_version']}'; expected '5.0'" + ) + try: + json.loads(receipt["canonical_payload"]) + except json.JSONDecodeError as exc: + raise ValueError(f"canonical_payload is not valid JSON: {exc}") from exc diff --git a/integrations/ramen-ai-cmcp/tests/__pycache__/test_mapping.cpython-313-pytest-9.1.1.pyc b/integrations/ramen-ai-cmcp/tests/__pycache__/test_mapping.cpython-313-pytest-9.1.1.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7b088502c915aa261bf2b266cd62a5359f76d0d9 GIT binary patch literal 11914 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 dict: + return json.loads((FIXTURES / name).read_text(encoding="utf-8")) + + +def _dummy_jwk() -> dict: + return {"kty": "OKP", "crv": "Ed25519", "x": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="} + + +@pytest.fixture(scope="module") +def key(): + return agentrust_trace.generate_key() + + +@pytest.fixture(scope="module") +def record(): + f = _load("vector1_allowed.json") + return build_trace_record(f["receipt"], iat=IAT, jwk=_dummy_jwk()) + + +# ── field mapping ─────────────────────────────────────────────────────────── + +def test_eat_profile(record): + assert record["eat_profile"] == "tag:agentrust.io,2026:trace-v0.1" + + +def test_subject_is_spiffe_uri(record): + assert record["subject"].startswith("spiffe://ramenai.dev/evaluation/") + + +def test_policy_bundle_hash_has_sha256_prefix(record): + assert record["policy"]["bundle_hash"].startswith("sha256:") + + +def test_policy_enforcement_mode(record): + assert record["policy"]["enforcement_mode"] == "enforce" + + +def test_runtime_platform(record): + assert record["runtime"]["platform"] == "software-only" + + +def test_tool_transcript_call_count(record): + assert record["tool_transcript"]["call_count"] == 1 + + +def test_tool_transcript_hash_has_sha256_prefix(record): + assert record["tool_transcript"]["hash"].startswith("sha256:") + + +def test_appraisal_status_affirming_for_allowed(record): + assert record["appraisal"]["status"] == "affirming" + + +def test_no_cmcp_envelope_markers(record): + assert not {"signature", "trace", "gateway"} & record.keys() + + +def test_fields_map_from_fixture(record): + f = _load("vector1_allowed.json") + payload = json.loads(f["receipt"]["canonical_payload"]) + assert record["policy"]["bundle_hash"] == f"sha256:{payload['payload_hash']}" + assert record["runtime"]["measurement"] == f["receipt"]["id"] + assert record["tool_transcript"]["hash"] == f"sha256:{payload['payload_hash']}" + assert payload["policy_ids"][0] in record["appraisal"]["policy_ref"] + + +# ── sign/verify round-trip ─────────────────────────────────────────────────── + +def test_sign_verify_roundtrip(record): + k = agentrust_trace.generate_key() + signed = agentrust_trace.sign_record(dict(record), k) + agentrust_trace.verify_record(signed, allow_embedded_key=True, max_age_seconds=None) + + +def test_tampered_record_fails_verification(record): + k = agentrust_trace.generate_key() + signed = agentrust_trace.sign_record(dict(record), k) + signed["policy"]["bundle_hash"] = "sha256:" + "f" * 64 + with pytest.raises(Exception): + agentrust_trace.verify_record(signed, allow_embedded_key=True, max_age_seconds=None) + + +# ── _validate_receipt guards ───────────────────────────────────────────────── + +def test_missing_field_raises(): + with pytest.raises(ValueError, match="missing required fields"): + _validate_receipt({"id": "x", "schema_version": "5.0", "kid": "k"}) + + +def test_wrong_schema_version_raises(): + f = _load("vector1_allowed.json") + with pytest.raises(ValueError, match="schema_version"): + _validate_receipt(dict(f["receipt"], schema_version="4.0")) From cb8b94c41f6feb43e336159074a35af96a0a491f Mon Sep 17 00:00:00 2001 From: ramen Labs Date: Tue, 21 Jul 2026 11:22:23 +0200 Subject: [PATCH 2/2] chore: remove build artefacts from ramen-ai-cmcp submission --- .gitignore | 2 ++ .../__pycache__/ramen_ai_trace.cpython-313.pyc | Bin 5270 -> 0 bytes .../ramen_ai_cmcp_integration.egg-info/PKG-INFO | 9 --------- .../SOURCES.txt | 9 --------- .../dependency_links.txt | 1 - .../requires.txt | 4 ---- .../top_level.txt | 1 - .../test_mapping.cpython-313-pytest-9.1.1.pyc | Bin 11914 -> 0 bytes 8 files changed, 2 insertions(+), 24 deletions(-) create mode 100644 .gitignore delete mode 100644 integrations/ramen-ai-cmcp/__pycache__/ramen_ai_trace.cpython-313.pyc delete mode 100644 integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/PKG-INFO delete mode 100644 integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/SOURCES.txt delete mode 100644 integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/dependency_links.txt delete mode 100644 integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/requires.txt delete mode 100644 integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/top_level.txt delete mode 100644 integrations/ramen-ai-cmcp/tests/__pycache__/test_mapping.cpython-313-pytest-9.1.1.pyc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9c882b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +*.egg-info/ diff --git a/integrations/ramen-ai-cmcp/__pycache__/ramen_ai_trace.cpython-313.pyc b/integrations/ramen-ai-cmcp/__pycache__/ramen_ai_trace.cpython-313.pyc deleted file mode 100644 index 037167ace4f906b37b30338985928283b48ce7ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5270 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 G82&FRtV0$6 diff --git a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/PKG-INFO b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/PKG-INFO deleted file mode 100644 index 66ca38b..0000000 --- a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/PKG-INFO +++ /dev/null @@ -1,9 +0,0 @@ -Metadata-Version: 2.4 -Name: ramen-ai-cmcp-integration -Version: 0.1.0 -Summary: ramen-ai cMCP policy adapter and TRACE Trust Record mapper -License-Expression: MIT -Requires-Python: >=3.11 -Requires-Dist: agentrust-trace -Provides-Extra: test -Requires-Dist: pytest; extra == "test" diff --git a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/SOURCES.txt b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/SOURCES.txt deleted file mode 100644 index 383c58e..0000000 --- a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/SOURCES.txt +++ /dev/null @@ -1,9 +0,0 @@ -README.md -pyproject.toml -ramen_ai_trace.py -ramen_ai_cmcp_integration.egg-info/PKG-INFO -ramen_ai_cmcp_integration.egg-info/SOURCES.txt -ramen_ai_cmcp_integration.egg-info/dependency_links.txt -ramen_ai_cmcp_integration.egg-info/requires.txt -ramen_ai_cmcp_integration.egg-info/top_level.txt -tests/test_mapping.py \ No newline at end of file diff --git a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/dependency_links.txt b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/requires.txt b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/requires.txt deleted file mode 100644 index 3dc326b..0000000 --- a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/requires.txt +++ /dev/null @@ -1,4 +0,0 @@ -agentrust-trace - -[test] -pytest diff --git a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/top_level.txt b/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/top_level.txt deleted file mode 100644 index b13f972..0000000 --- a/integrations/ramen-ai-cmcp/ramen_ai_cmcp_integration.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -ramen_ai_trace diff --git a/integrations/ramen-ai-cmcp/tests/__pycache__/test_mapping.cpython-313-pytest-9.1.1.pyc b/integrations/ramen-ai-cmcp/tests/__pycache__/test_mapping.cpython-313-pytest-9.1.1.pyc deleted file mode 100644 index 7b088502c915aa261bf2b266cd62a5359f76d0d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11914 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