Skip to content
Closed
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
6 changes: 3 additions & 3 deletions adapters/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Under the hood it drives two complementary layers:

**2. Emission conformance** — each adapter's `tests/integrations/<framework>/test_emission.py` runs the **production adapter** (the real subprocess for Claude Code / Cursor; the real `pre_invoke` / `post_invoke` / lifecycle-observer middleware for NAT) against a validating **CaptureGuardian** and asserts the *exact bytes it sends* pass the canonical schemas. Two layers of checks:

- *Per-event:* each Core method is emitted exactly once, envelope + payload validate against the canonical schemas, and per-envelope invariants hold — UUID `request_id`, RFC 3339 `timestamp`, `agent_id`/`session_id`/`platform` metadata, the `{value: …}` argument wrapper, and an **independently-recomputed** HMAC-SHA256 signature (a from-scratch HKDF+HMAC+JCS verifier in `acs/testing/capture_guardian.py`, *not* the adapters' own `acs._common` code, so a shared signing+verifying bug can't pass both sides; pinned by a frozen known-answer vector).
- *Per-event:* each Core method is emitted exactly once, envelope + payload validate against the canonical schemas, and per-envelope invariants hold — UUID `request_id`, RFC 3339 `timestamp`, `agent_id`/`session_id`/`platform` metadata, the `{value: …}` argument wrapper, and an **independently-recomputed** HMAC-SHA256 signature (a from-scratch HKDF+HMAC+JCS verifier in `acs/testing/capture_guardian.py`, *not* the adapters' own `acs.core` signing code, so a shared signing+verifying bug can't pass both sides; pinned by a frozen known-answer vector).
- *Per-session* (`*SequentialSession`, one Guardian + one handshake cache across an ordered sequence): the handshake fires exactly once, all `request_id`s are unique, `toolCallResult.request_id_ref` links back to its `toolCallRequest`, and — the real honesty check — the handshake's advertised `methods_implemented` **equals** the set of methods **actually emitted in the run** (equality, not just subset: catches over- *and* under-advertising), not merely methods that happen to have a schema.

Breaking any adapter's method mapping, envelope/payload field, or signing turns the suite red against the schema files themselves. The oracle is proven non-vacuous by `tests/common/test_capture_guardian.py` (feed it broken envelopes, assert it flags each defect class + the signature KAT). Schemas load from the copy bundled in the package, or from `specification/v0.1.0/` in a source checkout (`ACS_SPEC_DIR` overrides); missing schemas are a hard FAIL. Format checking (`uuid`, `date-time`) is enforced via `rfc3339-validator`.
Expand Down Expand Up @@ -226,8 +226,8 @@ adapters/
├── pyproject.toml # distribution, extras, console scripts, entry points
├── uv.lock # exact dependency versions, with hashes
├── src/acs/
│ ├── core/ # the ACS v0.1.0 schemas, bundled into the wheel
│ ├── _common.py # shared signing, handshake, session and audit code
│ ├── core/ # no I/O: envelopes, signing, decisions, error codes, bundled schemas
│ ├── client/ # I/O: the secret, the handshake, transport, session state, audit
│ ├── integrations/<framework>/
│ │ ├── adapter.py # the hook, or the NAT middleware
│ │ └── wire.py # writes the framework's own config
Expand Down
2 changes: 1 addition & 1 deletion adapters/SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This document is the threat model for the three reference adapters
(`src/acs/integrations/`), the example Guardian (`src/acs/guardian/`),
and the shared helpers in `src/acs/_common.py`. It says what attacks the code defends
and the shared helpers in `src/acs/core/` and `src/acs/client/`. It says what attacks the code defends
against, how, and what is explicitly out of scope.

ACS is a security project — the whole point of the standard is to
Expand Down
4 changes: 2 additions & 2 deletions adapters/docs/claude_code/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ python3 -c "import json, os; d=json.load(open(os.path.expanduser('~/.claude/sett

echo "=== Guardian responds to system/ping? ==="
cd "$ACS_REPO/adapters" && uv run python -c "
from acs._common import ping; import json
from acs.client import ping; import json
r = ping('http://127.0.0.1:8787/acs'); print(json.dumps(r, indent=2)[:200] if r else 'no response')
"
```
Expand All @@ -249,7 +249,7 @@ r = ping('http://127.0.0.1:8787/acs'); print(json.dumps(r, indent=2)[:200] if r
- `tests/integrations/claude_code/`: round-trip, schema and live integration tests.
- `docs/claude_code/example_payloads.md`: masked real-world payload examples showing exactly what Claude Code emits.

The adapter shares `src/acs/_common.py` with the Cursor and NAT adapters (signing, handshake cache, audit events, URL allowlist).
The adapter shares `acs.core` (signing, decision rules, error codes) and `acs.client` (handshake cache, session state, audit events, URL allowlist) with the Cursor and NAT adapters.

## Configuration

Expand Down
4 changes: 2 additions & 2 deletions adapters/docs/cursor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ python3 -c "import json, os; d=json.load(open(os.path.expanduser('~/.cursor/hook

echo "=== Guardian responds to system/ping? ==="
cd "$ACS_REPO/adapters" && uv run python -c "
from acs._common import ping; import json
from acs.client import ping; import json
r = ping('http://127.0.0.1:8787/acs'); print(json.dumps(r, indent=2)[:200] if r else 'no response')
"
```
Expand All @@ -258,7 +258,7 @@ r = ping('http://127.0.0.1:8787/acs'); print(json.dumps(r, indent=2)[:200] if r
- `docs/cursor/example_payloads.md`: masked real-world payload examples showing exactly what Cursor emits.
- `docs/cursor/live_verification.md`: manual reproduction procedure (Cursor has no headless mode).

The adapter shares `src/acs/_common.py` with the Claude Code and NAT adapters (signing, handshake cache, audit events, URL allowlist).
The adapter shares `acs.core` (signing, decision rules, error codes) and `acs.client` (handshake cache, session state, audit events, URL allowlist) with the Claude Code and NAT adapters.

## How it differs from the Claude Code adapter

Expand Down
2 changes: 1 addition & 1 deletion adapters/docs/nat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ Have your Guardian log every received envelope's `method` and the source (middle
- `tests/integrations/nat/test_failure_modes.py` — transport failures, signature checks, replay, timestamp skew, JSON-RPC errors.
- `docs/nat/example_payloads.md` — masked real-world payload examples showing the in-process `InvocationContext` shape and what the adapter sends.

The adapter shares `src/acs/_common.py` with the Claude Code and Cursor adapters (signing, handshake cache, audit events, URL allowlist, JSON-RPC error code → cause mapping).
The adapter shares `acs.core` (signing, decision rules, JSON-RPC error code → cause mapping) and `acs.client` (handshake cache, audit events, URL allowlist) with the Claude Code and Cursor adapters.

## How it differs from the Claude Code / Cursor adapters

Expand Down
Loading
Loading