Metadata-Version: 2.4
Name: pact-passport
Version: 0.5.2
Summary: PACT Passport — agent ID. Self-certifying identity, holder-bound capabilities, audit receipts.
Author: Benjamin Easington
License: MIT
Keywords: agent,trust,capability,protocol,identity,ed25519,pact
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: System :: Networking
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pynacl>=1.5.0
Requires-Dist: zeroconf>=0.131.0
Provides-Extra: cbor
Requires-Dist: cbor2>=5.6.0; extra == "cbor"
Provides-Extra: fast
Requires-Dist: uvicorn>=0.30.0; extra == "fast"
Provides-Extra: lak
Requires-Dist: local-agent-kit>=0.1.0; extra == "lak"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
Requires-Dist: coverage>=7.0; extra == "dev"
Dynamic: license-file

# PACT Passport

**The agent ID.**

[![Tests](https://github.com/bene-art/pact-passport/actions/workflows/test.yml/badge.svg)](https://github.com/bene-art/pact-passport/actions/workflows/test.yml)
[![PyPI](https://img.shields.io/pypi/v/pact-passport)](https://pypi.org/project/pact-passport/)
[![Python](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

Self-certifying identity, holder-bound capabilities, and unilateral audit receipts for agent-to-agent systems. Three message types — REQ, RES, RES_CHUNK. Everything else is built at the edges.

> **Status:** v0.5.2 — feature-complete for v0.x scope. All actionable issues from the v0.1 case study are closed (auth-bypass triangle #2/#3/#8, durability #5, rotation refresh #4, wire-level delegation #10, streaming #11, DoS hardening #9, Windows compat #6, dispatch readability #13). v0.5.2 closes four gaps surfaced by two-node cluster testing: signed `outcome=failed` receipts on dispatch errors, `HandlerFailure` exception for explicit handler-failure signaling, `cap_envelope` foot-gun closed (now requires `cap_id`), and a server-side `max_deadline_seconds` ceiling. 0 documented xfails. Three-platform tested (macOS, Linux, Windows).

> **Breaking changes from v0.1 → v0.5:**
> - `holder_proof` is mandatory when `cap_id` is present (v0.2.0, issue #3)
> - REQs from unknown peers are rejected unless they include `identity_doc` for trust-on-first-use (v0.2.0, issue #2)
> - `verify_capability` fails closed when delegation chain keys are missing (v0.2.0, issue #8)
> - `cap_id` claimed without local cap or `cap_envelope` is rejected explicitly instead of silently falling through (v0.4.0, issue #10)
> - `auto_grant` constructor parameter is now a no-op (v0.5.1) — was always dead code, kept for back-compat
> - `build_req(cap_envelope=...)` without an explicit `cap_id` now auto-derives `cap_id` from the envelope, or raises `ValueError` if the envelope lacks one. Previously the envelope was silently transported without verification (v0.5.2)
> - REQs with deadlines further than `max_deadline_seconds` (default 3600s) in the future are rejected with new fault code `deadline_too_far`. Bump the constructor arg for long-running streaming intents (v0.5.2)

## What is PACT Passport?

If MCP and A2A are how agents *talk*, PACT Passport is how they *prove who they are*. Each agent gets a self-certifying identity (Ed25519 keypair, agent_id derived from the public key). Authority is granted via holder-bound capability tokens that can only be tightened down a delegation chain, never widened. Every exchange produces signed audit receipts on both sides — independently verifiable, no central registry required.

PACT (Protocol for Agent Capability and Trust) sits **below** orchestration protocols like MCP and A2A as the **trust substrate** — the layer where identity is self-certifying, authority is holder-bound and attenuable, ordering is causal, and failure is explicit.

### Three Primitives

1. **Agent Identity** — Ed25519 keypair with self-certifying agent ID and pre-rotation key commitment. Identity survives key rotation without a central registry.

2. **Capability Token** — Signed, holder-bound proof of authority with delegation chains. Caveats can only restrict, never expand. Stolen tokens are useless without the holder's private key.

3. **Message** — Two types: REQ (request with capability proof) and RES (result or error). Message references form a causal DAG. Deadlines and idempotency keys are mandatory.

Plus: **unilateral audit receipts** — each agent signs their own view, no cooperation required.

## Install

```bash
pip install pact-passport
```

Or directly from this repo:
```bash
pip install git+https://github.com/bene-art/pact-passport.git
```

Optional extras:
```bash
pip install pact-passport[cbor]    # CBOR encoding support
pip install pact-passport[fast]    # Async uvicorn server
pip install pact-passport[lak]     # local-agent-kit integration
```

The Python module is `pact` regardless of the distribution name — `from pact import PACTAgent` works either way.

## Quick Start

### CLI

```bash
# Terminal 1: Create and serve an agent
pact init alice
pact serve --agent alice --capabilities get_weather

# Terminal 2: Create another agent, discover, and ask
pact init bob
pact discover
pact ask alice get_weather '{"city": "Chicago"}'
pact receipts
```

### Python API

```python
from pact import PACTAgent

agent = PACTAgent("alice", capabilities=["get_weather"])

@agent.handle("get_weather")
def weather(payload):
    return {"temp": 72, "condition": "clear"}

agent.serve()
```

### Demo

```bash
python examples/demo.py
```

Runs two agents in-process, exchanges a capability-scoped task, and verifies receipts.

## CLI Commands

| Command | Purpose |
|---------|---------|
| `pact init <name>` | Create agent identity with pre-rotation key commitment |
| `pact serve` | Start HTTP server + mDNS broadcast |
| `pact discover` | Find agents on local network |
| `pact ask <target> <action> [payload]` | Send a task (auto-handshake on first contact) |
| `pact grant <holder> <action>` | Issue a capability token |
| `pact revoke <cap_id>` | Revoke a capability |
| `pact caps` | List issued capabilities |
| `pact rotate` | Rotate keys using pre-rotation |
| `pact doctor` | Validate keys, event log, permissions |
| `pact trace <msg_id>` | Walk the causal message DAG |
| `pact receipts` | List audit receipts |
| `pact identity` | Show public identity document |
| `pact peers` | List known peers |

## Architecture

```
crypto.py                All PyNaCl in one file (post-quantum swap = one file change)
identity.py              Ed25519 identity, agent_id, key event log, rotation
capability.py            Token issue, attenuate, verify, delegation chains
message.py               REQ/RES builder, signer, verifier
receipt.py               Unilateral signed audit receipts
store.py                 Filesystem storage (~/.pact/)
transport/
  server.py              HTTP server with CBOR content negotiation
  async_server.py        Optional async server via uvicorn
  client.py              HTTP client with CBOR support
  discovery.py           mDNS via zeroconf
agent.py                 PACTAgent high-level API
cli.py                   `pact` command (13 subcommands)
contrib/
  lak_channel.py         local-agent-kit integration
```

## Features by Release

| Release | Feature | Status |
|---|---|---|
| v0.1 | Identity, capabilities, REQ/RES, receipts, mDNS, CLI, formal spec, test vectors | Done |
| v0.2.0 | Auth-bypass-by-default closed: TOFU handshake (`identity_doc`), mandatory holder-proof, fail-closed chain verification | Done |
| v0.2.1 | Request size limit + read timeout (slow-loris defense), Windows compat, dispatch decomposition (pipeline of validators) | Done |
| v0.3.0 | Durable idempotency cache + invocation counts (per-agent JSON, LRU bound) | Done |
| v0.3.1 | Rotation peer refresh via KERI continuity check | Done |
| v0.4.0 | Cap envelope inline (`cap_envelope`) — three-agent delegation works end-to-end over the wire | Done |
| v0.5.0 | Streaming RES_CHUNK responses (NDJSON over chunked transfer encoding) | Done |
| v0.5.1 | Polish: docs, exports, async-server parity, CI matrix | Done |
| v0.5.2 | Honesty patch: signed `outcome=failed` receipts (E1), `HandlerFailure` for explicit failure signaling (E2), `cap_envelope` foot-gun closed (E11), server-side `max_deadline_seconds` ceiling (E7). All four gaps surfaced by cluster testing. | Done |

## Tests

```bash
pip install -e ".[dev,cbor,fast]"
pytest -v
```

149 tests, 0 xfails covering: crypto, identity, capabilities, attenuation, messages, receipts, storage, HTTP transport, CBOR content negotiation, async server, key rotation, rate limiting, doctor validation, test vector verification, two-agent integration, three-agent delegation chain (over the wire), determinism, 5 race-condition scenarios under concurrent dispatch, the v0.2 auth hardening triangle, durable idempotency across restarts, rotation refresh, cap envelope verification, RES_CHUNK streaming, and the v0.5.2 honesty-patch suite (signed-failed-receipts, HandlerFailure, cap_envelope auto-derive, deadline ceiling).

### Platform support

| Platform | Status |
|---|---|
| **macOS** | 149 passed |
| **Linux** (CI + Alpine on WSL2) | 149 passed |
| **Windows 11** | 145 passed, 4 skipped (POSIX-only checks) |

### Concurrency stress mode

Set `PACT_CHAOS=1` to inject random delays at race-prone code paths. Useful for catching idempotency / rate-limit races that would otherwise surface 1-in-1000:

```bash
PACT_CHAOS=1 pytest -v
```

## Specification

- **Concept document:** [docs/PACT_Specification.md](docs/PACT_Specification.md)
- **Formal v1 spec:** [spec/PACT_v1.md](spec/PACT_v1.md) — sufficient for independent implementation
- **Test vectors:** [tests/vectors/pact_v1_vectors.json](tests/vectors/pact_v1_vectors.json) — deterministic, reproducible
- **Case study (v0.1.3):** [docs/EXPERIMENTS.md](docs/EXPERIMENTS.md) — what 23 stress experiments found, including 5 real bugs in this implementation

### Theoretical Foundations

| Paper | Contribution |
|-------|-------------|
| Saltzer, Reed, Clark — *End-to-End Arguments* (1984) | Push verification to agents, not transport |
| Waldo et al. — *A Note on Distributed Computing* (1994) | Failure is explicit, never abstracted away |
| Lamport — *Time, Clocks, and the Ordering of Events* (1978) | Causal ordering via message DAG |
| Birgisson et al. — *Macaroons* (2014) | Attenuable, context-bound capability tokens |
| Smith — *KERI* (2019) | Self-certifying identity with pre-rotation |
| Miller — *Robust Composition* (2006) | Capability discipline, no ambient authority |

## License

MIT
