# v0.5.3 — MCP Supply-Chain Response — Design Doc

Date: 2026-04-21
Branch: `feat/v0.5.3-mcp-supply-chain-response`
Previous release: v0.5.2 (`397b608`, 2026-04-20, "OAuth audit bundle")

## Scope decision (pre-flight)

The brief's **Task A "honesty bugs" carryover** was pre-flighted against the
actual v0.5.2 state on `main`:

| Claim | Reality | Action |
|---|---|---|
| A.1 — `oauth_audit_vercel_2026_defaults` not re-exported | FALSE. Already in `policy_presets.__all__` and importable. | **Skip.** |
| A.2 — 6 error classes missing from top-level `agent_airlock` | TRUE. Real bug. | **Fix.** |
| A.3 — stale `1,403 tests, 81.40%` badge | FALSE. No hardcoded badge exists in README. | **Add as new feature** (not a fix) — `scripts/update_test_badge.py` + TEST-BADGE block + `make test-badge`. |

Approved by the maintainer on 2026-04-21 via AskUserQuestion: "skip the
redundant and do all".

## Execution plan

Single branch → single PR. No push to main until maintainer review.

| # | Task | Priority | Size | Scope |
|---|---|---|---|---|
| A.2 | Top-level error re-exports + smoke test | P0 | XS | `__init__.py`, `tests/test_public_api.py` |
| A.3 | `test-badge` tooling (new feature) | P0 | XS | `scripts/`, `README.md`, `Makefile` or `pyproject` scripts entry, `CONTRIBUTING.md` |
| B | Azure MCP CVE-2026-32211 header-audit | P0 | M | `mcp_spec/header_audit.py`, `policy_presets`, `mcp_proxy_guard` hook, 6 tests |
| C | Log-redaction sink (CVE-2026-20205) | P0 | M | `integrations/log_redaction.py`, 12-pattern fixture, `CostTracker` + proxy hooks, 7 tests |
| D | OX MCP supply-chain dossier umbrella | P1 | M | `ox_mcp_supply_chain_2026_04_defaults()` + 3 micro-checks, fixture, 10 tests, docs |
| E | Agent Egress Bench | P1 | M | `scripts/egress_bench.py`, `make egress-bench`, CI job, `airlock egress-bench` CLI, docs |
| F | Auto Memory provenance chain | P1 | S | `claude_auto_memory.py` extend, HMAC, chain depth, 5 tests |
| G | NIST AI RMF v2 comment | P2 | S | `docs/regulatory/…md` only (portal submission is user-side) |

## Hard constraints (honored throughout)

- No new runtime deps. HMAC in Task F uses stdlib `hmac`.
- No secrets in tests/fixtures. Public CVE reference values may be
  embedded verbatim with URL citations.
- No behavior change for existing `@Airlock` users. Every new preset
  is opt-in.
- Every new test cites its CVE / primary-source URL in a module-level
  docstring.
- If any CI job fails and the fix is not obvious in 15 min: push the
  branch, comment on the PR with logs, stop.
- Do NOT reopen or modify v0.5.2 code beyond Task A.2 (additive only).

## Architectural notes

### Task B — header audit hook point

`MCPProxyGuard` currently has `validate_request()` (pre-tool) and
`validate_stdio_spawn()` / `audit_oauth_exchange()` for specific
flows. The new `audit_response_headers()` sits symmetrically — it's a
post-tool-call, pre-return check. Wiring it into the existing guard
as a method keeps the public-API surface consistent.

### Task C — log-redaction reuse

The brief mentions `auditlog.redact`. No such module exists in v0.5.2.
The canonical redaction path is `agent_airlock.sanitizer.sanitize_output`
(used by the session-snapshot guard in v0.5.2 and the auto-memory
write-redaction). The new `RedactingLogFilter` will delegate to
`sanitize_output` + extra caller-supplied patterns from the fixture
file, matching the spirit of the brief.

### Task D — umbrella composition

The umbrella preset composes existing primitives rather than
duplicating them. Three NEW micro-checks (tool-def tamper, MCP
bridge SSRF, LlamaIndex deserialization) are wired in alongside the
existing MCPwn / Flowise / Azure / Splunk checks.

### Task E — fixture contract

Every CVE fixture under `tests/cves/fixtures/*.json` must carry a
top-level `$schema` note and per-payload `source` attribution. The
bench walker reads this and refuses to run a fixture missing
attribution — keeps the dossier honest.

### Task F — HMAC key handling

Signing secret loaded from `AIRLOCK_MEMORY_HMAC_KEY` env var. No
key material in code or tests. Test fixtures use a known-fake key
via monkeypatch. `stdlib hmac` only — no new runtime deps.

## Acceptance

- `pytest tests/` green, coverage ≥ 81.78% (v0.5.2 floor)
- `ruff check` + `ruff format --check` clean
- `make egress-bench` green locally and in CI
- `CHANGELOG.md` has a complete `[0.5.3]` section with primary-source
  URLs per grouping (Honesty / Security presets / Integrations /
  Tooling / Docs)
- `pyproject.toml` + `src/agent_airlock/__init__.py` both at `0.5.3`
- PR open, reviewed, NOT merged to main by automation
