Skip to content

Latest commit

 

History

History
244 lines (189 loc) · 11.3 KB

File metadata and controls

244 lines (189 loc) · 11.3 KB

Ardur — Python Reference Implementation

The public Python runtime for Ardur lives here: a runtime governance and evidence layer for AI agents that issues signed mission passports, enforces them at execution time, and records receipts you can verify after the fact.

A note on names: the distribution and CLI are ardur, but the internal Python module is still vibap. That import name preserves protocol lineage without churning every integration. Treat vibap as an implementation detail; everything user-facing speaks ardur.

Install

Public-index availability is tracked in the repository's root STATUS.md. After it is marked public, install a release on Python 3.10 or newer with:

python -m pip install ardur

From a source checkout, install the same package metadata with:

python -m pip install -e python/

Quickstart (no API keys required)

# Issue a passport for a mission
ardur issue \
  --agent-id alice \
  --mission "summarize sales from sales/q1.csv into reports/" \
  --allowed-tools read_file write_report \
  --resource-scope 'sales/*' 'reports/*'

# Verify a passport (the issue command prints a JSON object containing "token")
ardur verify --token <token-from-issue-output>

That walks through key generation, mission compilation, ES256-signed passport issuance, and verification - all local, no LLM calls.

Run the conservative personal action-firewall proof with one command:

ardur personal-firewall demo

The provider-free demo preserves the agent's normal permission prompt for a safe workspace read, denies outside-workspace writes, secret-like arguments, and external network access, then verifies the signed receipt chain. Its session cap is measured in governed tool calls; monetary cost remains unknown unless an adapter supplies trusted signed cost telemetry. Absolute local scope paths are canonicalized before a permit, which rejects symlink escapes; the pre-dispatch hook still cannot prove hard-link identity or prevent post-check path replacement before the tool opens the path.

Every durable receipt sink also queues an idempotent local transparency-anchor sidecar. Network submission is a separate ardur anchor operation, and ardur verify --anchor-bundle ... verifies completed proofs offline with an independently supplied log public key. See docs/specs/transparency-anchor-v0.1.md.

The package also ships a no-service offline verifier and synthetic full-evidence fixture:

ardur offline-verification-fixture --output ./offline-fixture
ardur-verify ./offline-fixture/offline-verification-v0.1.json \
  --receipt-public-key ./offline-fixture/offline-verification-v0.1-receipt-public.pem \
  --transparency-log-key ./offline-fixture/offline-verification-v0.1-log-public.pem \
  --receiver-public-key ./offline-fixture/offline-verification-v0.1-receiver-public.pem \
  --html-report ./offline-fixture/verified.html

The evidence bundle never supplies its own trusted keys. The three public PEMs are explicit verifier inputs whose fingerprints must be checked out of band. See docs/specs/offline-verification-bundle-v0.1.md.

Correlate a verified receipt journal with an explicit local sensor format:

ardur evidence correlate \
  ../docs/specs/conformance/runtime-evidence-v0.1/receipts.jsonl \
  ../docs/specs/conformance/runtime-evidence-v0.1/tetragon.jsonl \
  --source-format tetragon \
  --receipt-public-key \
    ../docs/specs/conformance/runtime-evidence-v0.1/receipt-public.pem

This is a no-network offline inspection path. Imported Tetragon/Falco or normalized JSON is imported_unverified; match confidence does not authenticate the sensor or prove complete coverage. Reports exclude raw commands, paths, destinations, source identifiers, credentials, and local paths. See the Runtime Evidence Correlation Profile.

Export a verified receipt chain as redacted JSONL or standards-shaped OTLP/HTTP JSON traces and logs:

ardur telemetry export receipts.jsonl \
  --receipt-public-key receipt-public.pem \
  --format jsonl \
  --output governance-events.jsonl

Add --otlp-endpoint https://collector.example to post one trace request and one log request. Remote collectors require HTTPS; plain HTTP is limited to loopback. The exporter verifies signatures and chain linkage before projection and excludes raw prompts, tool arguments, targets, paths, and policy-reason prose. Collector credentials can be supplied through the standard OTEL_EXPORTER_OTLP*_HEADERS environment variables.

Actor and verifier IDs are signature-covered receipt claims. The exporter does not validate a SPIFFE SVID or bind the receipt signing key to workload identity; JSONL and OTLP output disclose that boundary explicitly.

Run the Linux governance-overhead smoke contract from a source checkout:

python ../scripts/run-linux-governance-benchmark.py \
  --mode smoke \
  --source-ref "$(git rev-parse HEAD)" \
  --output-dir /tmp/ardur-linux-benchmark

Smoke mode validates execution and report shape; it is not performance evidence. The manual Linux stress profile and optional paired-sensor contract are documented in the Linux Governance Overhead Harness.

Generate and self-verify the synthetic DRP draft-10 profile fixture:

ardur drp-profile-fixture --output ./drp-fixture

The output directory may be empty or contain only a prior copy of the six declared fixture artifacts; unexpected entries are rejected before writing.

The fixture emits a real root/child/grandchild P-256 chain and persists only public trust keys, receipts, a finite tool universe, explicitly preverified context facts, and a verification report. Its concrete action includes the resource, arguments, side-effect class, and cwd enforced by the profile. It is implementation evidence, not raw RFC 3161 proof, independent interoperability, IETF conformance, or current revocation evidence. See docs/specs/ardur-drp-profile-v0.1.md.

Ardur Personal Hub

The regular-user path uses the same package dependencies and CLI:

ardur profile init --template read-only --path ARDUR.md
ardur protect claude-code --profile ARDUR.md
ardur doctor-claude-code

The Hub is available when you want browser/desktop evidence and local receipt exports:

ardur setup
ardur hub
ardur status

Browser, desktop, and CLI adapters send observations to the Hub. The Hub uses the existing GovernanceProxy and Execution Receipt path, so adapters do not create their own policy authority.

ardur run -- <command> remains available for simple non-interactive commands, but Claude Code is the first-class RC path. Interactive Codex and Claude Desktop packaging are intentionally not presented as complete in this release candidate.

A heads-up on the CLI name: ardur is the canonical entrypoint going forward. ardur-proxy still works as a deprecated alias so existing scripts don't break, but new code should use ardur.

What's here

python/
├── vibap/                  # Core runtime package
│   ├── attestation.py           # Per-session attestation issuance + verify
│   ├── backends/                # Policy-engine adapters (Cedar, native, forbid-rules)
│   ├── biscuit_passport.py      # Biscuit AAT/DG implementation
│   ├── claude_code_hook.py      # Claude Code PreToolUse/PostToolUse adapter
│   ├── claude_code_telemetry.py # Claude Code tool → declared-telemetry mapper
│   ├── cli.py                   # ardur CLI entrypoint
│   ├── linux_benchmark.py       # Linux governance overhead report harness
│   ├── mission.py               # Mission Declaration parsing + cache
│   ├── passport.py              # Passport issuance + verify
│   ├── personal_hub.py          # Local Ardur Personal Hub service + adapter API
│   ├── policy_backend.py        # PolicyBackend protocol
│   ├── proxy.py                 # Governance proxy + session lifecycle
│   ├── receipt.py               # Execution Receipt issuance + verify
│   ├── risk_budget.py           # Typed impact contracts + atomic risk ledger
│   ├── runtime_evidence.py      # Offline normalized/Tetragon/Falco correlation
│   └── ...
└── tests/                  # Curated runtime, adapter, security, and release tests

A couple of pinned dependencies worth flagging: biscuit-python==0.4.0 (the Biscuit token format we use for delegated capabilities) and spiffe>=0.2,<0.4 (workload identity). These pins are deliberate — both libraries have had breaking minor releases, so we hold them until we explicitly retest.

Typed dangerous-action budgets

Library callers can register authenticated ToolRiskContract definitions before constructing GovernanceProxy. An optional signed risk_budget Mission Passport claim then enforces typed per-action caps and atomic session/agent/lineage ceilings before dispatch. Each governed call requires a unique risk_request_id; after PERMIT, the executor must call record_risk_outcome(..., outcome="committed") once execution may have started, or use outcome="released" only when it never started. Unresolved or quarantined reservations block session finalization. See the full risk-budget reference for schemas, failure behavior, privacy, and cost boundaries.

Library deployments that enable Biscuit JWT-SVID holder binding configure a server-owned Biscuit issuer key, TrustBundle, and expected audience on GovernanceProxy; clients present only peer_jwt_svid. Once configured, the SVID is mandatory and per-call inputs cannot replace the issuer, JWKS, trust domain, or audience. Without server trust configuration, Biscuit sessions remain explicitly svid_bound=false. JWT-SVID is still a bearer credential with a bounded replay window.

Protocol identifier rename

This implementation is a clean break on protocol identifiers — v0.1 receipts, passports, and attestations only emit and accept the new Ardur type strings. There is no dual-type backward-compat shim. If you have artifacts produced before the rename, they won't validate against this code, and that's intentional.

Full reasoning is in docs/specs/README.md under "Protocol identifier rename."

What's not here yet

A few things are documented gaps right now rather than oversights:

  • Live LLM tests — the semantic-judge and behavioral-fingerprint test lanes need real API keys, so the default test run uses local test doubles. To opt in, set ARDUR_SEMANTIC_JUDGE=anthropic and ANTHROPIC_API_KEY.
  • Corpus-heavy benchmark tests — AgentDojo, InjectAgent, R-Judge, STAC, and the telemetry-ablation harness stay in the private research tree. The cleaner subset that backs the public claims is what's curated here.
  • Docker images (rahulnutakki/ardur-demo:lang, :autogen) and re-recorded asciinema casts — these need a maintainer with Docker Hub credentials and an asciinema record session, neither of which an automated process can do.

One more caveat: the package imports cleanly and the AST parses. If something import-time looks off, file an issue.

License

MIT — see LICENSE.