From c15f12a249b86b7f9a90b6e1611ae7a499f4c52d Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Wed, 17 Jun 2026 15:18:05 -0700 Subject: [PATCH 1/5] =?UTF-8?q?docs:=20full=20doc=20site=20upgrade=20?= =?UTF-8?q?=E2=80=94=20Getting=20Started,=20Integration,=20Platforms,=20sc?= =?UTF-8?q?hema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 8 new documentation pages and overhaul mkdocs.yml: New pages: - docs/quickstart.md: 5-minute guide — keygen, emit, verify - docs/verification.md: five-step offline verification protocol with code examples for signature, key resolution, hardware chain - docs/schema.md: full field reference for all TRACE v0.1 claims - docs/integration/agt.md: AGT integration — TraceConfig, key mgmt, Level 0 → Level 2 upgrade path - docs/integration/cmcp.md: cMCP integration — architecture, Cedar policy example, MCP agent connection, platform matrix - docs/platforms/amd-sev-snp.md: AMD SEV-SNP fields, verification, cloud instance table, on-premises support - docs/platforms/intel-tdx.md: Intel TDX fields, PCCS verification - docs/platforms/nvidia-h100.md: NVIDIA H100 CC, combined CPU+GPU attestation, GTC Berlin reference mkdocs.yml: - Expand nav: Getting Started / Integration / Platforms top-level tabs - Add navigation.footer, navigation.expand, content.code.annotate, content.tooltips, search.share, navigation.instant.progress - Add social links: PyPI, Discord, GitHub - Add copyright, feedback ratings, version provider (mike) - Set site_url to https://agentrust.io/trace (target domain) - Remove examples/ from exclude_docs - Add pymdownx.tasklist, pymdownx.keys, footnotes extensions - custom_dir: docs/overrides for theme customisation workflow: add concurrency group, pages/id-token permissions, git config step, CNAME path trigger CNAME: agentrust.io (custom domain for GitHub Pages) Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/docs.yml | 14 ++- CNAME | 1 + docs/integration/agt.md | 102 +++++++++++++++++++++ docs/integration/cmcp.md | 138 ++++++++++++++++++++++++++++ docs/platforms/amd-sev-snp.md | 65 ++++++++++++++ docs/platforms/intel-tdx.md | 56 ++++++++++++ docs/platforms/nvidia-h100.md | 76 ++++++++++++++++ docs/quickstart.md | 82 +++++++++++++++++ docs/schema.md | 165 ++++++++++++++++++++++++++++++++++ docs/verification.md | 126 ++++++++++++++++++++++++++ mkdocs.yml | 62 +++++++++++-- 11 files changed, 879 insertions(+), 8 deletions(-) create mode 100644 CNAME create mode 100644 docs/integration/agt.md create mode 100644 docs/integration/cmcp.md create mode 100644 docs/platforms/amd-sev-snp.md create mode 100644 docs/platforms/intel-tdx.md create mode 100644 docs/platforms/nvidia-h100.md create mode 100644 docs/quickstart.md create mode 100644 docs/schema.md create mode 100644 docs/verification.md diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index edbd941..ef9d8f1 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -14,10 +14,17 @@ on: - "GOVERNANCE.md" - "ROADMAP.md" - "LIMITATIONS.md" + - "CNAME" workflow_dispatch: permissions: contents: write + pages: write + id-token: write + +concurrency: + group: docs-deploy + cancel-in-progress: false jobs: deploy: @@ -39,5 +46,10 @@ jobs: pip install -r requirements-docs.txt pip install -e ".[dev]" + - name: Configure git for gh-deploy + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + - name: Build and deploy to GitHub Pages - run: mkdocs gh-deploy --force --clean + run: mkdocs gh-deploy --force --clean --verbose diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..9884b64 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +agentrust.io diff --git a/docs/integration/agt.md b/docs/integration/agt.md new file mode 100644 index 0000000..5a3d72c --- /dev/null +++ b/docs/integration/agt.md @@ -0,0 +1,102 @@ +# Integration: AGT + +[AGT (Agent Governance Toolkit)](https://github.com/microsoft/agent-governance-toolkit) is the most widely adopted agent governance framework (4,200+ stars, 100+ contributors). It provides Cedar policy enforcement, SPIFFE/SVID identity, and Merkle-chained audit logs for any agent framework. + +AGT emits TRACE v0.1 Trust Records via `TRACEAuditSink` — see [ADR 0032](https://github.com/microsoft/agent-governance-toolkit/blob/main/docs/adr/0032-agt-emits-trace-v01-trust-records.md) for the full design. + +## What AGT emits + +AGT emits **Level 0 (software-only)** TRACE records. The record is signed with an Ed25519 key held in the operator's key store — not a TEE-bound key. For Level 2 hardware-rooted records, deploy AGT inside [cMCP](cmcp.md) or another TEE runtime. + +| TRACE field | Source in AGT | +|---|---| +| `subject` | `agent_did` passed to `govern()` | +| `policy.bundle_hash` | SHA-256 of the Cedar policy bundle bytes at session start | +| `policy.enforcement_mode` | Always `enforce` (Phase 1) | +| `tool_transcript.hash` | SHA-256 of the canonical JSON of the Merkle `AuditEntry` list | +| `tool_transcript.call_count` | Count of `AuditEntry` items in the session | +| `runtime.platform` | `software-only` | +| `runtime.measurement` | SHA-256 of the Merkle chain tip | +| `appraisal.status` | `affirming` (Phase 1) | +| `model`, `data_class`, `build_provenance` | Injected from `TraceConfig` | + +## Install + +```bash +pip install agentmesh agentrust-trace +``` + +## Basic usage + +```python +from agentmesh.governance import govern, GovernanceConfig +from agentmesh.governance.trace_sink import TraceConfig + +trace_config = TraceConfig( + output_path="session.trace.json", + model_provider="anthropic", + model_id="claude-sonnet-4-6", + model_version="20251001", + data_class="confidential", + build_provenance_slsa_level=2, + build_provenance_digest="sha256:e5f6a7b8...", +) + +config = GovernanceConfig( + policy_path="policy.cedar", + trace=trace_config, +) + +governed_fn = govern( + my_tool, + agent_did="spiffe://trust.example.org/agent/my-agent", + config=config, +) + +result = governed_fn(input) +path = governed_fn.close_session() +print(f"Trust Record written to: {path}") +``` + +## Key management + +Key material is managed entirely by `agentrust_trace.load_signing_key()`. AGT does not hold keys directly. + +```bash +# Set the signing key path via environment variable +export AGENTRUST_TRACE_KEY_PATH=/run/secrets/trace-signing-key.pem +``` + +For production, store the key in a secrets manager (AWS Secrets Manager, HashiCorp Vault, Kubernetes Secret) and inject via environment variable or volume mount. + +## Verifying the emitted record + +```bash +agentrust-trace verify session.trace.json --pubkey trace-key.pem.pub +``` + +## Upgrading to Level 2 (hardware-rooted) + +Deploy your AGT-governed agent inside cMCP. The cMCP runtime: + +1. Measures the Cedar policy bundle into the TEE before any code runs +2. Generates a TEE-bound key for the TRACE record +3. Emits a Level 2 record that supersedes AGT's Level 0 record for the same session + +The two records are linked by a shared `subject` and `tool_transcript.hash` — AGT's record and cMCP's record are mutually verifiable. + +→ [Integration guide: cMCP](cmcp.md) + +## Framework support + +AGT instruments any Python callable via `govern()`. Confirmed compatible frameworks: + +| Framework | Notes | +|---|---| +| LangGraph | Wrap tool nodes with `govern()` | +| CrewAI | Wrap task tools | +| AutoGen | Wrap function tools | +| Mastra | Via adapter contract | +| Raw Python | Direct function wrapping | + +For the full integration list, see the [AGT integrations repo](https://github.com/agentrust-io/integrations). diff --git a/docs/integration/cmcp.md b/docs/integration/cmcp.md new file mode 100644 index 0000000..919e6c7 --- /dev/null +++ b/docs/integration/cmcp.md @@ -0,0 +1,138 @@ +# Integration: cMCP + +[Confidential MCP (cMCP)](https://github.com/agentrust-io/cmcp) is the reference implementation of TRACE Level 2. It is an MCP gateway that: + +1. Intercepts every tool call from any MCP-compatible agent +2. Evaluates Cedar policy inside a hardware TEE (AMD SEV-SNP, Intel TDX, NVIDIA H100) +3. Measures the policy bundle into the TEE before any code runs +4. Signs the TRACE Trust Record with a TEE-bound Ed25519 key +5. Anchors the record in the TRACE transparency registry (optional) + +The result: a hardware-verifiable governance record for every agent session — signed by silicon, not by an operator process. + +## Architecture + +``` + Agent (LangGraph, CrewAI, AutoGen, ...) + │ MCP tool call + ▼ + ┌─────────────────────────────────────┐ + │ cMCP Gateway (TEE boundary) │ + │ ┌────────────────────────────────┐ │ + │ │ Cedar policy evaluation │ │ + │ │ → allow / deny / escalate │ │ + │ └────────────────────────────────┘ │ + │ ┌────────────────────────────────┐ │ + │ │ Tool-call transcript signing │ │ + │ │ TEE-bound key (cnf.jwk) │ │ + │ └────────────────────────────────┘ │ + │ ┌────────────────────────────────┐ │ + │ │ TRACE Level 2 record emission │ │ + │ └────────────────────────────────┘ │ + └─────────────────────────────────────┘ + │ Forwarded tool call + ▼ + MCP Tool Server (outside TEE) +``` + +## Conformance level + +cMCP emits **TRACE Level 2** records: + +| Property | Level 0 (AGT) | Level 2 (cMCP) | +|---|---|---| +| Policy hash | ✓ SHA-256 | ✓ SHA-256, TEE-measured | +| Signing key | Software key | TEE-bound key (never leaves enclave) | +| `runtime.platform` | `software-only` | `amd-sev-snp` / `intel-tdx` / `nvidia-h100` | +| Hardware measurement | ✗ | ✓ `runtime.measurement` | +| Independent verifiability | Key management by operator | Hardware endorsement chain | + +## Quick start + +```bash +docker pull ghcr.io/agentrust-io/cmcp:latest + +docker run --device /dev/sev \ + -e CEDAR_POLICY_PATH=/policies/my-policy.cedar \ + -e UPSTREAM_MCP_URL=http://my-mcp-server:8080 \ + -p 8443:8443 \ + -v $(pwd)/policies:/policies \ + ghcr.io/agentrust-io/cmcp:latest +``` + +Your agent points at `https://localhost:8443` instead of the upstream MCP server. Zero code change. + +## Cedar policy example + +```cedar +// Allow credit-risk agent to call financial tools — deny if data class is secret +permit( + principal == Agent::"spiffe://trust.example.org/agent/credit-risk", + action == Action::"call_tool", + resource in Tools::"financial" +) +when { + context.data_class != "secret" +}; +``` + +Cedar policies are versioned, code-reviewable, and their SHA-256 hash is bound into the TRACE record at the TEE measurement step — before any code runs. + +## Connect an MCP-compatible agent + +```python +import anthropic + +# Point at cMCP gateway instead of your MCP server +client = anthropic.Anthropic() +response = client.beta.messages.create( + model="claude-sonnet-4-6", + max_tokens=1024, + tools=[{ + "type": "mcp", + "server_url": "https://localhost:8443", # cMCP gateway + }], + messages=[{"role": "user", "content": "Analyze this credit application"}], + betas=["mcp-client-2025-04-04"], +) +``` + +## Retrieve the TRACE record + +After the session, fetch the TRACE record from the gateway: + +```python +import httpx + +record = httpx.get("https://localhost:8443/trace/latest").json() +# → full TRACE v0.1 Trust Record, Level 2, signed by TEE-bound key +``` + +Or let cMCP push it to the transparency registry automatically: + +```yaml +# cmcp.yaml +trace: + emit: true + registry: https://registry.agentrust.io + scitt_anchor: true +``` + +## Hardware platform support + +| Platform | Status | +|---|---| +| AMD SEV-SNP | ✓ GA | +| Intel TDX | ✓ GA | +| NVIDIA H100 Confidential | ✓ GA (demonstrated at GTC Berlin) | +| NVIDIA Blackwell | Preview | +| TPM 2.0 (software-only TEE) | ✓ GA — development mode, no memory encryption | +| Azure CVM (SEV-SNP) | ✓ GA | +| GCP Confidential VM (TDX) | ✓ GA | +| AWS Nitro Enclave | Preview | + +## Relationship to AGT + +cMCP embeds AGT. The Cedar policy engine, SPIFFE identity, and Merkle audit chain are AGT. cMCP adds the TEE boundary, hardware key generation, and Level 2 TRACE emission. + +When cMCP emits a Level 2 record for a session, it supersedes any Level 0 record AGT might have emitted for the same session. The two records are linked by shared `subject` and `tool_transcript.hash`. diff --git a/docs/platforms/amd-sev-snp.md b/docs/platforms/amd-sev-snp.md new file mode 100644 index 0000000..929e801 --- /dev/null +++ b/docs/platforms/amd-sev-snp.md @@ -0,0 +1,65 @@ +# Platform: AMD SEV-SNP + +AMD SEV-SNP (Secure Encrypted Virtualization - Secure Nested Paging) is the primary hardware root of trust for TRACE Level 2 records on AMD-based cloud instances and on-premises servers. + +## What AMD SEV-SNP provides + +| Property | Detail | +|---|---| +| Memory encryption | AES-128 per-VM encrypted memory | +| Attestation report | Signed by AMD's VCEK (chip-unique key) | +| Measurement | SHA-384 of the VM image + policy | +| Replay protection | Nonce-based freshness | + +## TRACE fields populated by SEV-SNP + +```json +{ + "runtime": { + "platform": "amd-sev-snp", + "measurement": "sha384:c9e4b1d2e3f4a5b6...", + "rim_uri": "https://kdsintf.amd.com/vcek/v1/Milan/cert_chain", + "firmware_version": "1.53.0", + "nonce": "ZRVkXG1w..." + } +} +``` + +- `measurement` — SHA-384 of the SNP attestation report's `measurement` field (the VM image digest) +- `rim_uri` — AMD Key Distribution Service URL for VCEK certificate chain verification +- `firmware_version` — SNP firmware version embedded in the attestation report +- `nonce` — replay-protection nonce from the attestation challenge + +## Verification flow + +To verify a SEV-SNP TRACE record offline: + +1. Parse `runtime.rim_uri` and fetch the VCEK certificate chain from AMD KDS +2. Verify the VCEK chain up to AMD's root CA (publicly available) +3. Verify the SNP attestation report signature using the VCEK certificate +4. Compare `runtime.measurement` against the report's `measurement` field +5. Confirm `cnf.jwk` was generated inside the enclave at that measurement + +```bash +# cMCP does steps 1-5 automatically and embeds the result in the TRACE record +agentrust-trace verify-hardware session.trace.json \ + --platform amd-sev-snp \ + --check-rim +``` + +## Supported cloud instances + +| Cloud | Instance family | +|---|---| +| Azure | DCasv5, ECasv5, DCadsv5, ECadsv5 | +| GCP | C3 (with AMD SEV-SNP enabled) | +| AWS | Not supported (AWS uses Nitro — separate profile) | +| On-premises | Any server with EPYC Genoa / Bergamo or newer | + +## On-premises deployment + +For on-premises SEV-SNP (e.g., Supermicro H13 with EPYC Genoa), Opaque ships the verifier with the platform — same cryptographic guarantees as cloud deployments, no cloud attestation service dependency. See [agentrust-io/cmcp](https://github.com/agentrust-io/cmcp) for the Helm chart. + +## Example record + +See [`examples/amd-sev-snp.json`](https://github.com/agentrust-io/trace-spec/blob/main/examples/amd-sev-snp.json) for a complete TRACE Level 2 record from an AMD SEV-SNP deployment. diff --git a/docs/platforms/intel-tdx.md b/docs/platforms/intel-tdx.md new file mode 100644 index 0000000..20754a4 --- /dev/null +++ b/docs/platforms/intel-tdx.md @@ -0,0 +1,56 @@ +# Platform: Intel TDX + +Intel TDX (Trust Domain Extensions) provides hardware-isolated Trust Domains (TDs) — VMs with encrypted memory, isolated register state, and hardware-signed attestation. TRACE Level 2 on TDX is supported on GCP Confidential VM (N2D-TDX) and select on-premises Intel Xeon Scalable deployments. + +## What Intel TDX provides + +| Property | Detail | +|---|---| +| Memory encryption | AES-256-XTS per-TD | +| Attestation report | TD Quote, signed by Intel's QE (Quoting Enclave) | +| Measurement | SHA-384 MRTD (TD measurement register) | +| Extensible registers | RTMR0–3 for measuring additional components | + +## TRACE fields populated by TDX + +```json +{ + "runtime": { + "platform": "intel-tdx", + "measurement": "sha384:a1b2c3d4e5f6a7b8...", + "rim_uri": "https://api.trustedservices.intel.com/tdx/certification/v4/", + "firmware_version": "5.35.1", + "nonce": "dGRhY2Uzz..." + } +} +``` + +- `measurement` — SHA-384 of the TDX TD Quote's MRTD field +- `rim_uri` — Intel Trust Authority / PCCS URL for TDX certificate chain +- `firmware_version` — TDX firmware version from the TD Quote header + +## Verification flow + +```bash +agentrust-trace verify-hardware session.trace.json \ + --platform intel-tdx \ + --check-rim +``` + +The verifier: +1. Fetches the TDX certificate chain from Intel's PCCS or Trust Authority +2. Verifies the TD Quote using Intel's SGX QVL (Quote Verification Library) +3. Compares `runtime.measurement` against the TD Quote MRTD +4. Validates that `cnf.jwk` was generated inside the TD at that measurement + +## Supported cloud instances + +| Cloud | Instance type | +|---|---| +| GCP | C3 Confidential VM (TDX) | +| Azure | DCesv5, ECesv5 (Intel TDX preview) | +| On-premises | Intel Xeon Scalable 4th Gen (Sapphire Rapids) and newer | + +## Example record + +See [`examples/intel-tdx.json`](https://github.com/agentrust-io/trace-spec/blob/main/examples/intel-tdx.json). diff --git a/docs/platforms/nvidia-h100.md b/docs/platforms/nvidia-h100.md new file mode 100644 index 0000000..013dd6f --- /dev/null +++ b/docs/platforms/nvidia-h100.md @@ -0,0 +1,76 @@ +# Platform: NVIDIA H100 Confidential Computing + +NVIDIA H100 (and Blackwell) GPUs support Confidential Computing — hardware-isolated GPU execution with attestation rooted in NVIDIA's Attestation Root Certificate Authority (NRAS). TRACE Level 2 on NVIDIA CC is the first hardware-verifiable governance record for GPU-based AI inference. + +## What NVIDIA H100 CC provides + +| Property | Detail | +|---|---| +| Memory protection | GPU memory encrypted and isolated per VM | +| Attestation | NVIDIA RIM Service attestation, signed by NVIDIA NRAS | +| Measurement | GPU firmware + driver measurement | +| Combined attestation | CPU TEE + GPU CC — one unified attestation report | + +TRACE on H100 is the first open standard to combine CPU TEE attestation and GPU CC attestation into a single signed governance record. This was demonstrated at GTC Berlin. + +## TRACE fields populated by NVIDIA H100 CC + +```json +{ + "runtime": { + "platform": "nvidia-h100", + "measurement": "sha256:f0e9d8c7b6a5f4e3d2c1b0a9...", + "rim_uri": "https://nras.nvidia.com/rims/H100_SXM5/fw_v551.81", + "firmware_version": "551.81" + } +} +``` + +- `measurement` — Combined CPU+GPU measurement hash +- `rim_uri` — NVIDIA RIM Service URL for firmware Reference Integrity Manifest +- `firmware_version` — NVIDIA GPU driver/firmware version + +## Verification flow + +```bash +agentrust-trace verify-hardware session.trace.json \ + --platform nvidia-h100 \ + --check-rim +``` + +1. Fetches the GPU RIM from NVIDIA's RIM Service at `runtime.rim_uri` +2. Verifies firmware measurement against the RIM +3. Verifies the GPU attestation report using NVIDIA NRAS root certificate +4. Validates that the combined CPU+GPU measurement matches `runtime.measurement` +5. Confirms `cnf.jwk` is endorsed by both CPU TEE and GPU CC attestation + +## Combined CPU+GPU attestation + +For maximum assurance, run the agent in a combined AMD SEV-SNP + NVIDIA H100 CC deployment. The TRACE record carries both measurements: + +```json +{ + "runtime": { + "platform": "nvidia-h100", + "measurement": "sha256:combined-cpu-gpu-measurement...", + "rim_uri": "https://nras.nvidia.com/rims/...", + "extensions": { + "cpu_platform": "amd-sev-snp", + "cpu_measurement": "sha384:cpu-only-measurement..." + } + } +} +``` + +## Supported configurations + +| Configuration | Status | +|---|---| +| H100 SXM5 + AMD EPYC (SEV-SNP) | ✓ GA | +| H100 PCIe + Intel Xeon (TDX) | ✓ GA | +| H100 SXM5 + AMD EPYC (bare metal) | Preview | +| NVIDIA Blackwell B200 | Preview | + +## Example record + +See [`examples/nvidia-h100.json`](https://github.com/agentrust-io/trace-spec/blob/main/examples/nvidia-h100.json). diff --git a/docs/quickstart.md b/docs/quickstart.md new file mode 100644 index 0000000..d2b534a --- /dev/null +++ b/docs/quickstart.md @@ -0,0 +1,82 @@ +# Quickstart + +Get your first TRACE Trust Record in five minutes. + +## Install + +```bash +pip install agentrust-trace +``` + +## Generate a signing key + +```bash +# Ed25519 key — store the private key securely; distribute only the public key +python -m agentrust_trace keygen --out trace-key.pem +``` + +## Emit a Trust Record from AGT + +```python +from agentmesh.governance import govern, GovernanceConfig +from agentmesh.governance.trace_sink import TraceConfig + +config = GovernanceConfig( + policy_path="policy.cedar", + trace=TraceConfig( + output_path="session.trace.json", + model_provider="anthropic", + model_id="claude-sonnet-4-6", + model_version="20251001", + ), +) + +governed_fn = govern(my_tool, agent_did="spiffe://trust.example.org/agent/my-agent", config=config) + +# Your agent runs normally — TRACE record is emitted on session close +result = governed_fn(input) +governed_fn.close_session() +# → writes session.trace.json +``` + +## Verify offline + +```bash +agentrust-trace verify session.trace.json --pubkey trace-key.pem.pub +``` + +Output: + +``` +✓ Signature valid (Ed25519) +✓ eat_profile tag:agentrust.io,2026:trace-v0.1 +✓ subject spiffe://trust.example.org/agent/my-agent +✓ policy sha256:b2c3d4e5... (enforce) +✓ data_class internal +✓ tool_calls 3 +✓ appraisal affirming + +Trust Record verified. No issuer callback required. +``` + +## What you now have + +| Claim | What it proves | +|---|---| +| `policy.bundle_hash` | Exact Cedar policy hash that governed the session | +| `tool_transcript.hash` | Merkle-chained audit log of every tool invocation | +| `subject` | Workload identity (SPIFFE or DID) | +| `appraisal.status` | Verifier judgment: affirming / contraindicated | +| `signature` | Ed25519 over the full record — verifiable offline | + +## Add hardware attestation (Level 2) + +For TEE-rooted records (AMD SEV-SNP, Intel TDX, NVIDIA H100), use cMCP as the runtime — it issues Level 2 TRACE records with a TEE-bound key and a SCITT transparency anchor automatically. + +→ [Integration guide: cMCP](integration/cmcp.md) + +## Next steps + +- [Full Specification](../spec/trace-v0.1.md) — all claims, wire formats, conformance +- [Verification Protocol](verification.md) — five-step offline verification +- [Schema Reference](schema.md) — JSON Schema with field descriptions diff --git a/docs/schema.md b/docs/schema.md new file mode 100644 index 0000000..facbae0 --- /dev/null +++ b/docs/schema.md @@ -0,0 +1,165 @@ +# Schema Reference + +JSON Schema for the TRACE v0.1 Trust Record. Source: [`schema/trace-claim.json`](https://github.com/agentrust-io/trace-spec/blob/main/schema/trace-claim.json). + +## Top-level fields + +| Field | Type | Required | Description | +|---|---|---|---| +| `eat_profile` | string | **yes** | EAT profile URI. Must be `tag:agentrust.io,2026:trace-v0.1` | +| `iat` | integer | **yes** | Issued-at timestamp (Unix epoch seconds) | +| `subject` | string | **yes** | Workload identity. SPIFFE SVID (`spiffe://`) or DID (`did:`) | +| `model` | object | **yes** | Model artifact binding | +| `runtime` | object | **yes** | Execution environment binding | +| `policy` | object | **yes** | Governance policy binding | +| `data_class` | string | **yes** | Data sensitivity classification | +| `tool_transcript` | object | **yes** | Tool-call audit summary | +| `build_provenance` | object | **yes** | Build-time artifact provenance | +| `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 record | + +## `model` + +Binds the model artifact used in this session. + +| Field | Type | Required | Description | +|---|---|---|---| +| `provider` | string | **yes** | Model provider (e.g., `anthropic`, `openai`, `meta`) | +| `model_id` | string | **yes** | Model identifier (e.g., `claude-sonnet-4-6`) | +| `version` | string | **yes** | Model version or date stamp | +| `weights_digest` | string | no | SHA-256 digest of model weights artifact | +| `aibom_uri` | string | no | URI to the AI Bill of Materials (SPDX/CycloneDX) | + +## `runtime` + +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` | +| `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 | +| `nonce` | string | no | Freshness nonce — ties this record to a specific attestation challenge | + +## `policy` + +Binds the governance policy in force during this session. + +| Field | Type | Required | Description | +|---|---|---|---| +| `bundle_hash` | string | **yes** | `sha256:` digest of the Cedar policy bundle bytes | +| `enforcement_mode` | string | **yes** | `enforce` or `silent` (advisory) | +| `version` | string | no | Policy bundle version string | +| `policy_uri` | string | no | URI to the policy bundle for inspection | + +## `data_class` + +String. Sensitivity classification applied to the data processed in this session. + +Defined values: `public`, `internal`, `confidential`, `restricted`, `secret`. + +Custom values are allowed and SHOULD follow your organization's data classification policy. + +## `tool_transcript` + +Audit summary of tool invocations during the session. + +| Field | Type | Required | Description | +|---|---|---|---| +| `hash` | string | **yes** | `sha256:` of the canonical JSON of the full `AuditEntry` list | +| `call_count` | integer | **yes** | Number of tool invocations recorded | +| `transcript_uri` | string | no | URI to the full per-call transcript (may be encrypted) | + +## `build_provenance` + +Build-time provenance binding the deployed artifact. + +| Field | Type | Required | Description | +|---|---|---|---| +| `slsa_level` | integer | **yes** | SLSA provenance level (0–3) | +| `builder` | string | **yes** | Builder identity URI (e.g., GitHub Actions SLSA generator) | +| `digest` | string | **yes** | `sha256:` digest of the built artifact | +| `provenance_uri` | string | no | URI to the SLSA provenance document (e.g., Rekor entry) | + +## `appraisal` + +Verifier judgment on the evidence in this record. + +| Field | Type | Required | Description | +|---|---|---|---| +| `status` | string | **yes** | One of: `affirming`, `warning`, `contraindicated`, `none` | +| `verifier` | string | **yes** | URI of the verifier that produced this appraisal | +| `policy_ref` | string | no | URI to the appraisal policy applied | +| `timestamp` | integer | no | Unix epoch seconds when appraisal was performed | + +## `transparency` + +String. URI of the SCITT transparency log entry anchoring this record. Empty string (`""`) if not anchored at issuance — anchoring may happen asynchronously. + +## `cnf` + +Confirmation method. Contains the signing key bound to this record. + +| Field | Type | Description | +|---|---|---| +| `jwk` | object | JWK-format public key used to verify `signature` | + +For TEE-issued records, this key was generated inside the measured enclave and its private half never leaves it. The hardware measurement in `runtime` cryptographically binds this key to the TEE. + +## Wire formats + +TRACE v0.1 supports two wire formats: + +**JSON** (primary): signed JSON object with `signature` as a top-level field. + +**CBOR-COSE** (constrained devices): COSE_Sign1 structure with TRACE claims as the payload. Defined in §3.2 of the spec — deferred to a future profile for constrained-device deployments. + +## Example — AMD SEV-SNP + +```json +{ + "eat_profile": "tag:agentrust.io,2026:trace-v0.1", + "iat": 1750676142, + "subject": "spiffe://trust.example.org/agent/payments-processor/prod", + "model": { + "provider": "anthropic", + "model_id": "claude-sonnet-4-6", + "version": "20251001" + }, + "runtime": { + "platform": "amd-sev-snp", + "measurement": "sha384:c9e4b1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6...", + "rim_uri": "https://kdsintf.amd.com/vcek/v1/Milan/cert_chain", + "firmware_version": "1.53.0" + }, + "policy": { + "bundle_hash": "sha256:b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1...", + "enforcement_mode": "enforce", + "version": "1.2.0" + }, + "data_class": "confidential", + "tool_transcript": { + "hash": "sha256:d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3...", + "call_count": 3 + }, + "build_provenance": { + "slsa_level": 2, + "builder": "https://github.com/slsa-framework/slsa-github-generator/...", + "digest": "sha256:e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4..." + }, + "appraisal": { + "status": "affirming", + "verifier": "https://trust-authority.example.org" + }, + "transparency": "https://registry.agentrust.io/claim/trace-2026-06-23T09:15:42Z", + "cnf": { + "jwk": { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." } + }, + "signature": "base64url..." +} +``` + +See the full example files in [`examples/`](https://github.com/agentrust-io/trace-spec/tree/main/examples). diff --git a/docs/verification.md b/docs/verification.md new file mode 100644 index 0000000..580b8a3 --- /dev/null +++ b/docs/verification.md @@ -0,0 +1,126 @@ +# Verification Protocol + +TRACE Trust Records are independently verifiable offline — no call to the issuer, no API, no trust-me-the-log-is-real. + +## Five-step verification + +This is the normative protocol from [§3.3 of the spec](../spec/trace-v0.1.md). + +### Step 1 — Parse the envelope + +A TRACE Trust Record is a signed JSON object. The `signature` field contains a base64url-encoded Ed25519 (or ES256/ES384) signature over the canonical JSON of the record with `signature` and `cnf` removed. + +```python +import json, base64 +from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey + +record = json.load(open("session.trace.json")) +sig_bytes = base64.urlsafe_b64decode(record["signature"] + "==") +payload = {k: v for k, v in record.items() if k not in ("signature", "cnf")} +payload_bytes = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode() +``` + +### Step 2 — Resolve the public key + +The `cnf.jwk` field embeds the public key. For TEE-issued records, this key is TEE-bound — its private half never leaves the measured enclave. + +```python +from cryptography.hazmat.primitives.serialization import load_der_public_key + +jwk = record["cnf"]["jwk"] +# For ES256/ES384: reconstruct EC key from x/y +# For Ed25519: decode x directly +pub_key = Ed25519PublicKey.from_public_bytes( + base64.urlsafe_b64decode(jwk["x"] + "==") +) +``` + +### Step 3 — Verify the signature + +```python +pub_key.verify(sig_bytes, payload_bytes) +# Raises InvalidSignature if tampered — silent if valid +print("✓ Signature valid") +``` + +### Step 4 — Check the EAT profile + +```python +assert record["eat_profile"] == "tag:agentrust.io,2026:trace-v0.1", "Unknown profile" +print("✓ eat_profile correct") +``` + +### Step 5 — Appraise the claims + +Interpret `appraisal.status` against your policy: + +| Status | Meaning | +|---|---| +| `affirming` | All evidence passed verifier appraisal | +| `warning` | Evidence passed but with conditions | +| `contraindicated` | Evidence failed — treat as untrusted | +| `none` | No appraisal performed (software-only Level 0) | + +```python +status = record["appraisal"]["status"] +assert status == "affirming", f"Appraisal failed: {status}" +print(f"✓ Appraisal: {status}") +``` + +## Verifying hardware-rooted records + +For Level 2 records (TEE-issued), additionally verify that the `cnf.jwk` key is bound to the hardware measurement in `runtime`: + +1. Fetch the Reference Integrity Manifest at `runtime.rim_uri` +2. Compare `runtime.measurement` against the RIM +3. Verify that `cnf.jwk` was endorsed by the TEE at that measurement + +This chain proves the key that signed the TRACE record was generated *inside* the attested enclave — not by an operator process. + +## CLI verification + +```bash +# Install +pip install agentrust-trace + +# Verify a record +agentrust-trace verify session.trace.json --pubkey issuer.pub + +# Verify with hardware check (fetches RIM from AMD/Intel/NVIDIA) +agentrust-trace verify session.trace.json --pubkey issuer.pub --check-hardware + +# Batch verify +agentrust-trace verify *.trace.json --pubkey issuer.pub --summary +``` + +## SCITT-anchored records + +If `transparency` is set, the record is anchored in an append-only transparency log. Verify the anchor: + +```bash +agentrust-trace verify-scitt session.trace.json \ + --transparency-log https://registry.agentrust.io +``` + +A valid SCITT receipt proves the record was included in the log and cannot be retroactively removed or modified. + +## What verification proves + +| Claim verified | What it means | +|---|---| +| Signature valid | The record was not tampered with after issuance | +| `cnf.jwk` hardware-bound | The signing key was generated inside a measured TEE | +| `policy.bundle_hash` | This exact Cedar policy was in force — not an approximate | +| `tool_transcript.hash` | The audit log is intact and matches the record | +| SCITT receipt valid | The record is in an append-only log — cannot be quietly deleted | + +## What verification does NOT prove + +Verification proves *what happened during the recorded session* under the stated policy, in the stated environment. It does not: + +- Prove the agent's internal reasoning was sound +- Prove the policy was correctly authored for the intent +- Prove tool call *contents* (only the hash of the transcript is in v0.1) +- Replace ongoing monitoring + +See [Limitations](../LIMITATIONS.md) for the full list. diff --git a/mkdocs.yml b/mkdocs.yml index bd47baa..bdd3577 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,17 +1,18 @@ site_name: TRACE site_description: Trust Runtime Attestation and Compliance Evidence — open attestation standard for agentic AI governance -site_url: https://agentrust-io.github.io/trace-spec +site_url: https://agentrust.io/trace repo_url: https://github.com/agentrust-io/trace-spec repo_name: agentrust-io/trace-spec edit_uri: edit/main/ docs_dir: . +copyright: "© 2026 Opaque Systems — CC BY 4.0" + exclude_docs: | .github/ node_modules/ src/ tests/ schema/ - examples/ LICENSE NOTICE ANTITRUST.md @@ -21,11 +22,13 @@ exclude_docs: | CHARTER.md CODE_OF_CONDUCT.md pyproject.toml + CNAME theme: name: material logo: docs/assets/icon.svg favicon: docs/assets/icon.svg + custom_dir: docs/overrides palette: - scheme: slate primary: custom @@ -41,26 +44,30 @@ theme: name: Switch to dark mode features: - navigation.instant + - navigation.instant.progress - navigation.tracking - navigation.tabs - navigation.tabs.sticky - navigation.sections + - navigation.expand - navigation.top - navigation.path + - navigation.footer - search.suggest - search.highlight + - search.share - content.code.copy + - content.code.annotate - content.tabs.link + - content.tooltips - toc.follow - - header.autohide + - announce.dismiss icon: repo: fontawesome/brands/github - font: - text: Inter, system-ui, -apple-system, sans-serif - code: JetBrains Mono, Cascadia Code, monospace plugins: - - search + - search: + lang: en - minify: minify_html: true - mkdocstrings: @@ -92,29 +99,70 @@ markdown_extensions: alternate_style: true - pymdownx.highlight: anchor_linenums: true + use_pygments: true + linenums_style: pymdownx-inline - pymdownx.inlinehilite - pymdownx.snippets - pymdownx.emoji: emoji_index: !!python/name:material.extensions.emoji.twemoji emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.keys - attr_list - md_in_html - tables + - footnotes - toc: permalink: true + toc_depth: 3 extra: social: - icon: fontawesome/brands/github link: https://github.com/agentrust-io/trace-spec + name: trace-spec on GitHub + - icon: fontawesome/brands/python + link: https://pypi.org/project/agentrust-trace/ + name: agentrust-trace on PyPI + - icon: fontawesome/brands/discord + link: https://discord.gg/9JWNpH7E + name: Join the Discord + version: + provider: mike generator: false + analytics: + feedback: + title: Was this page helpful? + ratings: + - icon: material/emoticon-happy-outline + name: This page was helpful + data: 1 + note: >- + Thanks for your feedback! + - icon: material/emoticon-sad-outline + name: This page could be improved + data: 0 + note: >- + Thanks for your feedback — open an issue to let us know. extra_css: - docs/stylesheets/extra.css nav: - Home: README.md + - Getting Started: + - Quickstart: docs/quickstart.md + - Verification: docs/verification.md + - Schema Reference: docs/schema.md - Specification: spec/trace-v0.1.md + - Integration: + - AGT: docs/integration/agt.md + - cMCP: docs/integration/cmcp.md + - Platforms: + - AMD SEV-SNP: docs/platforms/amd-sev-snp.md + - Intel TDX: docs/platforms/intel-tdx.md + - NVIDIA H100: docs/platforms/nvidia-h100.md - Crosswalks: - OWASP Agentic Top 10: docs/crosswalks/owasp-agentic-top-10.md - Project: From e51a8af2b4468d07c4abe56017e79644fdbbe9f7 Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Wed, 17 Jun 2026 15:24:25 -0700 Subject: [PATCH 2/5] fix(docs): fix docs_dir build error + improve workflow The original docs_dir: . caused a hard error in mkdocs >=1.6: 'docs_dir should not be the parent directory of the config file' Fix: workflow now assembles a .docs_build/ directory with the correct layout before invoking mkdocs, then generates a build-time config that overrides docs_dir. All nav paths are preserved unchanged. Also: - Add pre-build Python assembly step to workflow - Add concurrency group to prevent parallel deploys - Add git config step - Remove empty custom_dir from mkdocs.yml theme (would cause error) - Keep docs_dir: . in source config (the workflow overrides it) - Add social links, footer nav, better features to mkdocs.yml Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/docs.yml | 47 +++++++++++++++++++++++++++++++++++--- mkdocs.yml | 9 ++------ 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index ef9d8f1..8e32d91 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -19,8 +19,6 @@ on: permissions: contents: write - pages: write - id-token: write concurrency: group: docs-deploy @@ -51,5 +49,48 @@ jobs: git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" + - name: Assemble docs build directory + run: | + python3 << 'PYEOF' + import os, shutil, yaml + + BUILD = '.docs_build' + os.makedirs(BUILD, exist_ok=True) + + # Copy docs/ (keeps paths like docs/crosswalks/..., docs/integration/..., etc.) + if os.path.exists('docs'): + shutil.copytree('docs', os.path.join(BUILD, 'docs'), dirs_exist_ok=True) + + # Copy spec/ and examples/ (keeps paths like spec/trace-v0.1.md) + for d in ['spec', 'examples', 'assets', 'crosswalks']: + if os.path.exists(d): + shutil.copytree(d, os.path.join(BUILD, d), dirs_exist_ok=True) + + # Root-level markdown files (nav references them by name) + for fname in ['README.md', 'CHANGELOG.md', 'CONTRIBUTING.md', + 'GOVERNANCE.md', 'ROADMAP.md', 'LIMITATIONS.md', 'CNAME']: + if os.path.exists(fname): + shutil.copy(fname, os.path.join(BUILD, fname)) + + # Generate build-specific mkdocs config + with open('mkdocs.yml', encoding='utf-8') as f: + config = yaml.safe_load(f) + + config['docs_dir'] = BUILD + config['site_dir'] = '/tmp/trace-spec-site' + config.pop('exclude_docs', None) # build dir is already clean + config.pop('custom_dir', None) # remove theme custom_dir from nested theme + + # Fix theme custom_dir if present + if isinstance(config.get('theme'), dict): + config['theme'].pop('custom_dir', None) + + with open('.mkdocs_build.yml', 'w', encoding='utf-8') as f: + yaml.dump(config, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + + print(f'Build directory: {BUILD}') + print(f'Files: {sum(len(fs) for _, _, fs in os.walk(BUILD))}') + PYEOF + - name: Build and deploy to GitHub Pages - run: mkdocs gh-deploy --force --clean --verbose + run: mkdocs gh-deploy --force --clean --config-file .mkdocs_build.yml diff --git a/mkdocs.yml b/mkdocs.yml index bdd3577..b9a489f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -28,7 +28,6 @@ theme: name: material logo: docs/assets/icon.svg favicon: docs/assets/icon.svg - custom_dir: docs/overrides palette: - scheme: slate primary: custom @@ -128,8 +127,6 @@ extra: - icon: fontawesome/brands/discord link: https://discord.gg/9JWNpH7E name: Join the Discord - version: - provider: mike generator: false analytics: feedback: @@ -138,13 +135,11 @@ extra: - icon: material/emoticon-happy-outline name: This page was helpful data: 1 - note: >- - Thanks for your feedback! + note: Thanks for your feedback! - icon: material/emoticon-sad-outline name: This page could be improved data: 0 - note: >- - Thanks for your feedback — open an issue to let us know. + note: Thanks for your feedback — open an issue to let us know. extra_css: - docs/stylesheets/extra.css From a789188dd6c7c1b230b837eeb7eb26760c9f633b Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Wed, 17 Jun 2026 15:27:03 -0700 Subject: [PATCH 3/5] fix(docs): use yaml.full_load to handle !!python/name tags in mkdocs.yml yaml.safe_load rejects the Python-specific YAML tags used by mkdocs-material (e.g. !!python/name:material.extensions.emoji.twemoji). Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 8e32d91..e57832f 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -74,7 +74,7 @@ jobs: # Generate build-specific mkdocs config with open('mkdocs.yml', encoding='utf-8') as f: - config = yaml.safe_load(f) + config = yaml.full_load(f) config['docs_dir'] = BUILD config['site_dir'] = '/tmp/trace-spec-site' From 56bb340fb6d0052fdbee75eed38f61c087b2f393 Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Wed, 17 Jun 2026 15:29:49 -0700 Subject: [PATCH 4/5] fix(docs): use sed for docs_dir override, avoid !!python/name yaml issue yaml.full_load also fails (tries to import material.extensions.emoji at parse time). Replace Python-based config generation with a simple sed substitution and a shell-based file copy assembly step. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/docs.yml | 52 +++++++++++++------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e57832f..c8ba101 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -51,46 +51,28 @@ jobs: - name: Assemble docs build directory run: | - python3 << 'PYEOF' - import os, shutil, yaml + BUILD=.docs_build + mkdir -p $BUILD - BUILD = '.docs_build' - os.makedirs(BUILD, exist_ok=True) + # Copy docs/ subtree (preserves paths: docs/crosswalks/, docs/integration/, etc.) + if [ -d docs ]; then cp -r docs $BUILD/docs; fi - # Copy docs/ (keeps paths like docs/crosswalks/..., docs/integration/..., etc.) - if os.path.exists('docs'): - shutil.copytree('docs', os.path.join(BUILD, 'docs'), dirs_exist_ok=True) + # Copy spec/ and examples/ + if [ -d spec ]; then cp -r spec $BUILD/spec; fi + if [ -d examples ]; then cp -r examples $BUILD/examples; fi - # Copy spec/ and examples/ (keeps paths like spec/trace-v0.1.md) - for d in ['spec', 'examples', 'assets', 'crosswalks']: - if os.path.exists(d): - shutil.copytree(d, os.path.join(BUILD, d), dirs_exist_ok=True) + # Root-level files referenced in nav + for fname in README.md CHANGELOG.md CONTRIBUTING.md GOVERNANCE.md ROADMAP.md LIMITATIONS.md CNAME; do + if [ -f "$fname" ]; then cp "$fname" "$BUILD/$fname"; fi + done - # Root-level markdown files (nav references them by name) - for fname in ['README.md', 'CHANGELOG.md', 'CONTRIBUTING.md', - 'GOVERNANCE.md', 'ROADMAP.md', 'LIMITATIONS.md', 'CNAME']: - if os.path.exists(fname): - shutil.copy(fname, os.path.join(BUILD, fname)) + echo "Build dir contains $(find $BUILD -type f | wc -l) files" - # Generate build-specific mkdocs config - with open('mkdocs.yml', encoding='utf-8') as f: - config = yaml.full_load(f) - - config['docs_dir'] = BUILD - config['site_dir'] = '/tmp/trace-spec-site' - config.pop('exclude_docs', None) # build dir is already clean - config.pop('custom_dir', None) # remove theme custom_dir from nested theme - - # Fix theme custom_dir if present - if isinstance(config.get('theme'), dict): - config['theme'].pop('custom_dir', None) - - with open('.mkdocs_build.yml', 'w', encoding='utf-8') as f: - yaml.dump(config, f, allow_unicode=True, default_flow_style=False, sort_keys=False) - - print(f'Build directory: {BUILD}') - print(f'Files: {sum(len(fs) for _, _, fs in os.walk(BUILD))}') - PYEOF + - name: Generate build config + run: | + # Avoid yaml.safe_load / !!python/name: tag issues — just text-substitute docs_dir + sed 's|^docs_dir: \.$|docs_dir: .docs_build|' mkdocs.yml > .mkdocs_build.yml + echo "Build config written to .mkdocs_build.yml" - name: Build and deploy to GitHub Pages run: mkdocs gh-deploy --force --clean --config-file .mkdocs_build.yml From 1003536d8f0bd7f8c7cca681fac22319144e25c1 Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Wed, 17 Jun 2026 16:16:32 -0700 Subject: [PATCH 5/5] style: align visual theme with Agent Governance Toolkit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Primary color → #8251EE (AGT NextGen Purple) across light + dark - Add teal→purple→violet gradient accent strip to header top edge - Switch to GitHub Primer system font stack (font: false disables Roboto) - Dark mode bg → #0d1117 (GitHub-neutral, matching AGT slate scheme) - Update icon.svg gradient: teal→#8251EE→#C661F7 (teal→purple→violet) - Add Primer-style h2 border-bottom, semibold headings - Header: plain canvas + border-bottom (no gradient bg), same as AGT - Tables, admonitions, code blocks: Primer border-radius + border style Co-Authored-By: Claude Sonnet 4.6 --- docs/assets/icon.svg | 8 +- docs/stylesheets/extra.css | 303 +++++++++++++++++++++++++++++++++++-- mkdocs.yml | 1 + 3 files changed, 296 insertions(+), 16 deletions(-) diff --git a/docs/assets/icon.svg b/docs/assets/icon.svg index 47b7847..9d5b3ab 100644 --- a/docs/assets/icon.svg +++ b/docs/assets/icon.svg @@ -2,14 +2,16 @@ - + - - + + + + diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 022fcf4..152c3be 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -1,24 +1,301 @@ -:root { - --md-primary-fg-color: #7c3aed; - --md-primary-fg-color--light: #a78bfa; - --md-primary-fg-color--dark: #5b21b6; - --md-accent-fg-color: #0ea5e9; +/* + * TRACE spec — visual theme aligned with Agent Governance Toolkit (AGT) + * Primary brand: NextGen Purple (#8251EE), accent strip: teal→purple→violet + * Font stack: GitHub Primer system fonts (no Google Fonts) + */ + +/* ========================================================================== + 1. Color tokens + ========================================================================== */ + +:root, +[data-md-color-scheme="default"] { + --md-primary-fg-color: #8251EE; + --md-primary-fg-color--light: #9B7AF2; + --md-primary-fg-color--dark: #6A3FD9; + --md-accent-fg-color: #8251EE; + --md-accent-fg-color--transparent: rgba(130, 81, 238, 0.10); + --md-typeset-a-color: #8251EE; + + --md-default-bg-color: #ffffff; + --md-default-bg-color--light: #f6f8fa; + + --trace-text: #1f2328; + --trace-text-muted: #59636e; + --trace-border: #d1d9e0; + --trace-surface: #f6f8fa; + --trace-code-bg: #f6f8fa; } [data-md-color-scheme="slate"] { - --md-primary-fg-color: #818cf8; - --md-primary-fg-color--light: #a5b4fc; - --md-primary-fg-color--dark: #6366f1; - --md-accent-fg-color: #38bdf8; - --md-default-bg-color: #0f0a1e; - --md-default-bg-color--light: #1a1033; - --md-code-bg-color: #1e1533; + --md-primary-fg-color: #9B7AF2; + --md-primary-fg-color--light: #C661F7; + --md-primary-fg-color--dark: #8251EE; + --md-accent-fg-color: #5BD2BE; + --md-accent-fg-color--transparent: rgba(91, 210, 190, 0.15); + --md-typeset-a-color: #9B7AF2; + + --md-default-bg-color: #0d1117; + --md-default-bg-color--light: #151b23; + --md-code-bg-color: #151b23; + + --trace-text: #f0f6fc; + --trace-text-muted: #9198a1; + --trace-border: #3d444d; + --trace-surface: #151b23; + --trace-code-bg: #151b23; +} + + +/* ========================================================================== + 2. Typography — GitHub Primer system font stack + ========================================================================== */ + +:root { + --trace-font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", + Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; + --trace-font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, + "Liberation Mono", monospace; +} + +body, +.md-typeset, +.md-header, +.md-tabs, +.md-nav, +.md-footer { + font-family: var(--trace-font-sans); +} + +.md-typeset code, +.md-typeset pre, +.md-typeset kbd, +.md-code__content, +.highlight pre { + font-family: var(--trace-font-mono); +} + +.md-typeset { + font-size: 16px; + line-height: 1.5; + color: var(--trace-text); +} + +.md-typeset h1 { + font-weight: 600; + letter-spacing: -0.015em; + line-height: 1.25; + color: var(--trace-text); +} + +[data-md-color-scheme="slate"] .md-typeset h1 { + color: #ffffff; } +.md-typeset h2 { + font-weight: 600; + letter-spacing: -0.01em; + line-height: 1.25; + border-bottom: 1px solid var(--trace-border); + padding-bottom: 0.4rem; + margin-top: 2rem; +} + +.md-typeset h3 { + font-weight: 600; + line-height: 1.25; + margin-top: 1.5rem; +} + + +/* ========================================================================== + 3. Header — plain canvas + 2px gradient accent strip (teal→purple→violet) + ========================================================================== */ + .md-header { - background: linear-gradient(135deg, #0d0a1f 0%, #071828 100%); + background-color: var(--md-default-bg-color); + color: var(--trace-text); + border-bottom: 1px solid var(--trace-border); + box-shadow: none; + position: sticky; + top: 0; + z-index: 4; +} + +[data-md-color-scheme="slate"] .md-header { + background-color: var(--md-default-bg-color); + color: var(--trace-text); +} + +/* Teal → Purple → Violet — same family as AGT's accent strip */ +.md-header::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2px; + background: linear-gradient(90deg, #5BD2BE 0%, #8251EE 50%, #C661F7 100%); + z-index: 1; +} + +.md-tabs { + background-color: var(--md-default-bg-color); + color: var(--trace-text); + border-bottom: 1px solid var(--trace-border); + box-shadow: none; + position: sticky; + top: 65px; + z-index: 3; +} + +[data-md-color-scheme="slate"] .md-tabs { + background-color: var(--md-default-bg-color); + color: var(--trace-text); +} + +.md-header__title, +.md-header__topic, +.md-header__button, +.md-header__option { + color: var(--trace-text); +} + +.md-search__input { + background-color: var(--trace-surface); + color: var(--trace-text); +} + +.md-search__input::placeholder { + color: var(--trace-text-muted); +} + + +/* ========================================================================== + 4. Navigation + ========================================================================== */ + +.md-nav__title { + font-weight: 600; + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--trace-text-muted); +} + +.md-nav__link--active { + font-weight: 600; + color: var(--md-primary-fg-color) !important; +} + +.md-tabs__link--active { + font-weight: 600; + color: var(--md-primary-fg-color) !important; +} + + +/* ========================================================================== + 5. Code blocks + ========================================================================== */ + +.md-typeset pre > code, +.md-typeset .highlight pre { + background-color: var(--trace-code-bg); + border: 1px solid var(--trace-border); + border-radius: 6px; } +.md-typeset code:not(pre code) { + background-color: var(--trace-code-bg); + border: 1px solid var(--trace-border); + border-radius: 4px; + padding: 0.1em 0.35em; + color: var(--md-primary-fg-color); +} + + +/* ========================================================================== + 6. Tables — GitHub Primer style + ========================================================================== */ + +.md-typeset table:not([class]) { + border-collapse: collapse; + width: 100%; + border: 1px solid var(--trace-border); + border-radius: 6px; + overflow: hidden; +} + +.md-typeset table:not([class]) th { + background-color: var(--trace-surface); + font-weight: 600; + font-size: 0.85rem; + color: var(--trace-text); + border-bottom: 1px solid var(--trace-border); + padding: 0.5rem 0.75rem; +} + +.md-typeset table:not([class]) td { + border-bottom: 1px solid var(--trace-border); + padding: 0.5rem 0.75rem; + vertical-align: top; +} + +.md-typeset table:not([class]) tr:last-child td { + border-bottom: none; +} + + +/* ========================================================================== + 7. Admonitions + ========================================================================== */ + +.md-typeset .admonition, +.md-typeset details { + border-radius: 6px; + border: 1px solid var(--trace-border); +} + +.md-typeset .admonition.note, +.md-typeset details.note { + border-color: var(--md-primary-fg-color); +} + +.md-typeset .admonition.warning, +.md-typeset details.warning { + border-color: #d29922; +} + +.md-typeset .admonition.danger, +.md-typeset details.danger { + border-color: #da3633; +} + +.md-typeset .admonition.tip, +.md-typeset details.tip { + border-color: #5BD2BE; +} + + +/* ========================================================================== + 8. Footer + ========================================================================== */ + +.md-footer { + background-color: var(--trace-surface); + border-top: 1px solid var(--trace-border); + color: var(--trace-text-muted); +} + +.md-footer-meta { + background-color: var(--trace-surface); +} + + +/* ========================================================================== + 9. Hero section + ========================================================================== */ + .md-hero__inner { padding-top: 2rem; } diff --git a/mkdocs.yml b/mkdocs.yml index b9a489f..b07e0bb 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -26,6 +26,7 @@ exclude_docs: | theme: name: material + font: false logo: docs/assets/icon.svg favicon: docs/assets/icon.svg palette: