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
219 changes: 108 additions & 111 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,111 +1,108 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
inputs:
ref:
description: "Branch or SHA to run CI on"
required: false
default: ""

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
os: [ubuntu-latest, windows-latest]

steps:
- uses: actions/checkout@v7

- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: python -m pip install --upgrade pip setuptools && pip install -e ".[dev]"

- name: Security scan
run: pip install bandit pip-audit && bandit -r src/ -c pyproject.toml && pip-audit

- name: Lint
run: ruff check src/ tests/

- name: Type check
run: mypy src/ca2a_runtime/ src/ca2a_verify/

- name: Test
run: pytest tests/unit/ tests/conformance/ -v --tb=short --cov=src --cov-report=xml

- name: Upload coverage report
uses: codecov/codecov-action@v7
with:
fail_ci_if_error: false

governance:
runs-on: ubuntu-latest
needs: test

steps:
- uses: actions/checkout@v7

- uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install dependencies
run: python -m pip install --upgrade pip setuptools && pip install -e ".[dev]" "agent-governance-toolkit>=4.1"

- name: Generate evidence file
run: python scripts/gen_agt_evidence.py

# Advisory until Tier 2 (runtime peer-delegation enforcement) lands. cA2A
# does not yet run the ASI coverage modules, so strict verify reports
# INCOMPLETE. This flips to blocking (drop continue-on-error) once the
# runtime enforces attenuated delegation on inbound peer calls. See ROADMAP.
- name: AGT governance verify (advisory)
continue-on-error: true
run: agt verify --evidence agt-evidence.json

- name: Save attestation JSON
continue-on-error: true
run: agt --json verify --evidence agt-evidence.json > agt-attestation.json

- name: Upload governance artifacts
uses: actions/upload-artifact@v7
with:
name: agt-governance-${{ github.sha }}
path: |
agt-evidence.json
agt-attestation.json
if-no-files-found: warn

benchmark:
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main'

steps:
- uses: actions/checkout@v7

- uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install dependencies
run: python -m pip install --upgrade pip setuptools && pip install -e ".[dev]"

- name: Run benchmark (software-only, CI gate p99 < 5ms)
run: python -m ca2a_runtime.benchmarks --provider software-only --hops 10000 --out benchmarks/

- name: Upload benchmark results
uses: actions/upload-artifact@v7
with:
name: benchmark-results
path: benchmarks/
if-no-files-found: warn
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
inputs:
ref:
description: "Branch or SHA to run CI on"
required: false
default: ""

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
os: [ubuntu-latest, windows-latest]

steps:
- uses: actions/checkout@v7

- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: python -m pip install --upgrade pip setuptools && pip install -e ".[dev]"

- name: Security scan
run: pip install bandit pip-audit && bandit -r src/ -c pyproject.toml && pip-audit

- name: Lint
run: ruff check src/ tests/

- name: Type check
run: mypy src/ca2a_runtime/ src/ca2a_verify/

- name: Test
run: pytest tests/unit/ tests/conformance/ -v --tb=short --cov=src --cov-report=xml

- name: Upload coverage report
uses: codecov/codecov-action@v7
with:
fail_ci_if_error: false

governance:
runs-on: ubuntu-latest
needs: test

steps:
- uses: actions/checkout@v7

- uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install dependencies
run: python -m pip install --upgrade pip setuptools && pip install -e ".[dev]" "agent-governance-toolkit[full]>=4.1"

- name: Generate evidence file
run: python scripts/gen_agt_evidence.py

# Blocking gate: the [full] toolkit provides the ASI coverage modules
# (10/10) and the evidence declares cA2A's governed capabilities, so strict
# verify is COMPLETE. A regression that drops coverage or governance fails CI.
- name: AGT governance verify (strict)
run: agt verify --evidence agt-evidence.json

- name: Save attestation JSON
run: agt --json verify --evidence agt-evidence.json > agt-attestation.json

- name: Upload governance artifacts
uses: actions/upload-artifact@v7
with:
name: agt-governance-${{ github.sha }}
path: |
agt-evidence.json
agt-attestation.json
if-no-files-found: warn

benchmark:
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main'

steps:
- uses: actions/checkout@v7

- uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install dependencies
run: python -m pip install --upgrade pip setuptools && pip install -e ".[dev]"

- name: Run benchmark (software-only, CI gate p99 < 5ms)
run: python -m ca2a_runtime.benchmarks --provider software-only --hops 10000 --out benchmarks/

- name: Upload benchmark results
uses: actions/upload-artifact@v7
with:
name: benchmark-results
path: benchmarks/
if-no-files-found: warn
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
python-version: "3.12"

- name: Install package and AGT
run: python -m pip install --upgrade pip && pip install -e "." agent-governance-toolkit-core
run: python -m pip install --upgrade pip && pip install -e "." "agent-governance-toolkit[full]>=4.1"

- name: Generate evidence file
run: python scripts/gen_agt_evidence.py
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- cA2A-compatible conformance suite: `tests/conformance/` with a normative README (stable MUST/SHOULD test IDs across delegation, scope-policy, attestation, sealed channel, provenance, and the inbound pipeline) and runnable checks that exercise every MUST-level requirement. Wired into CI and documented at `docs/spec/conformance.md`; ties to the CHARTER trademark language.
- TPM 2.0 attestation backend: `ca2a_runtime.tee.tpm` (TPMS_ATTEST parsing, `TpmProvider`) and `ca2a_verify.tpm.verify_tpm_quote` (AK chain to a caller-supplied vendor root, AK signature over the attest blob (ECDSA or RSA), magic/type checks, and qualifying-data/PCR-digest binding), all fail-closed. Synthetic-vector validated; TPM AK roots are per-vendor so the caller supplies its trusted roots. Quote generation requires a real TPM.
- Intel TDX attestation backend: `ca2a_runtime.tee.tdx` (DCAP Quote v4 parsing, `TdxProvider`) and `ca2a_verify.tdx.verify_tdx_quote` (PCK chain to a trusted Intel root, QE report signature, attestation-key binding, quote signature, and MRTD/report-data binding), all fail-closed. Chain path validated against the genuine Intel SGX Root CA; multi-level signature path validated with a synthetic self-consistent quote. Quote generation requires a real TDX guest.
- AGT governance gate is now **blocking** (was advisory): CI installs `agent-governance-toolkit[full]`, so the OWASP ASI 2026 coverage modules load and `agt verify` reports 10/10 coverage with 6/6 runtime checks (COMPLETE). The enforcement descriptor now declares cA2A's `governed_capabilities`, reported as the registered-tools inventory. A governance or coverage regression now fails CI.
- Real Cedar policy engine binding: `ca2a_runtime.cedar.CedarPolicy` (backed by `cedarpy`, the engine cMCP runs) evaluates each capability as a Cedar authorization request. A new `ca2a_runtime.policy.Policy` protocol makes `LocalPolicy` (allow set) and `CedarPolicy` interchangeable in the peer path. Adds the `cedarpy` dependency.
- Transport-agnostic inbound peer request handler: `ca2a_runtime.peer.handle_peer_request` with `PeerRequest` / `PeerResult`. Composes the full pipeline (verify chain, intersect scope and enforce, open a sealed payload with the enclave key, emit a linked provenance record) fail-closed. A transport parses its wire format into a `PeerRequest`; cA2A does not define the transport (profile, not protocol).
- RFC 8785 (JSON Canonicalization Scheme) canonicalization: `ca2a_runtime.canonical.canonicalize`. Credential and provenance bodies are now signed over the JCS encoding (UTF-16 key ordering, JCS string escaping, literal non-ASCII, shortest-decimal integers), so cA2A signatures are cross-verifiable with agent-manifest. ASCII credentials are byte-identical to the previous encoding, so existing signatures still verify.
Expand Down
10 changes: 10 additions & 0 deletions governance/ca2a-enforcement.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ hardware_roots:
- intel-tdx
- tpm2

# The capability actions this deployment governs. A delegated scope is honored
# only when its capabilities appear here AND the local Cedar policy permits them
# (effective = delegated scope INTERSECT local policy). This is the callee's
# declared, version-controlled inventory of governable actions.
governed_capabilities:
- delegate.invoke
- delegate.read
- delegate.write
- delegate.admin

owasp_coverage:
ASI-03: scope attenuation, a child grant cannot exceed its parent's authority
ASI-06: linked TRACE records per hop, tamper-evident delegation DAG
Expand Down
19 changes: 18 additions & 1 deletion scripts/gen_agt_evidence.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,26 @@
from datetime import datetime, timezone
from pathlib import Path

import yaml

REPO_ROOT = Path(__file__).parent.parent


def _governed_capabilities() -> list[str]:
"""The governed-capability inventory the enforcement descriptor declares.

These are cA2A's registered actions: a delegated scope is honored only when
its capabilities appear here and the local Cedar policy permits them.
"""
path = REPO_ROOT / "governance" / "ca2a-enforcement.yaml"
try:
doc = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
except (FileNotFoundError, yaml.YAMLError):
return []
caps = doc.get("governed_capabilities", [])
return [str(c) for c in caps] if isinstance(caps, list) else []


def _pkg_version(package: str) -> str:
try:
return importlib.metadata.version(package)
Expand All @@ -44,7 +61,7 @@ def generate_evidence() -> dict:
"policy_files_loaded": [
"governance/ca2a-enforcement.yaml",
],
"registered_tools": [],
"registered_tools": _governed_capabilities(),
"audit_sink": {
"enabled": True,
"target": "src/ca2a_runtime/delegation/credential.py",
Expand Down