Skip to content

feat: phase 2 wave 4 — host-adapter extension point (ADR-0029, experimental) - #149

Merged
pacphi merged 4 commits into
developfrom
feat/phase-2-wave-4-adapter-door
Aug 15, 2026
Merged

feat: phase 2 wave 4 — host-adapter extension point (ADR-0029, experimental)#149
pacphi merged 4 commits into
developfrom
feat/phase-2-wave-4-adapter-door

Conversation

@pacphi

@pacphi pacphi commented Aug 15, 2026

Copy link
Copy Markdown
Owner

The adapter door: an external host adapter is a validated JSON manifest plus consented subprocess hooks — no third-party code ever runs in-process — behind AK_EXPERIMENTAL_HOST_ADAPTERS=1 with byte-zero default behavior. Design settled by the four-sweep research dossier; this is the ak-authored realization of PR #131's proposed ADR-0029.

What lands:

  • Strict-allowlist manifest schema — every level (top-level, host, install, legacy, capabilities, detection, driving, lifecycle, trust) rejects unknown keys, so the capability caps (canBePrimary/aqeProvider/commandStatusline) and a path-traversal guidanceFile are inexpressible, not merely refused; an external adapter may not name an npm package ak would install.
  • Fail-closed, per-adapter-isolated admission with a locale-independent content hash checked against a hash-pinned, edit-invalidated consent store (0600).
  • Supervised shell-free hook runner — env allowlist, process-group kill on timeout, bounded capture; the only path external code executes.
  • Frozen overlayeffectiveHostRegistry() is HOST_REGISTRY by reference until something is admitted; built-in lifecycle loops stay opencode-shape-safe until external execution graduates.
  • Conformance harness + fixture adapter — the graduation artifact: real subprocess hooks, real consent, exact-reason negative corpus.
  • ADR-0029 Accepted (experimental contract), superseding ADR-0016's closed-registry clause narrowly; graded Working/Demo/TBD table.

Security review: approve-with-nits, no RCE/escape/pollution — six of seven attacks HELD; the consent-forgery gap (#4) and checklist-not-allowlist finding closed by the strict allowlist, verified against the reviewer's exploit probes and pinned as regression tests. Full gate green (1,671 tests).

🤖 Generated with Claude Code

pacphi added 4 commits August 15, 2026 16:18
…ss hooks (ADR-0029)

Phase 2 Wave 4: an external host adapter is a validated JSON manifest plus
subprocess hooks; no third-party code ever runs in-process. Behind
AK_EXPERIMENTAL_HOST_ADAPTERS=1 with byte-zero default behavior.

- manifest.mjs: a STRICT allowlist at every level — top-level, host,
  install, legacy, capabilities, detection, driving, lifecycle, and trust
  reject any unknown key, so the structural caps (canBePrimary, aqeProvider,
  commandStatusline) and a path-traversal guidanceFile are inexpressible, not
  merely refused; an external adapter may not name an npm package ak would
  install, and its detection bin must be id-shaped.
- admission.mjs: fail-closed, per-adapter isolated admission — validate,
  cap-check, contract match, builtin-shadow refusal, then a locale-independent
  content hash checked against hash-pinned consent (edit-invalidated). One bad
  entry never affects built-ins or siblings.
- hook-runner.mjs: the only path external code executes — a supervised,
  shell-free subprocess with an env allowlist, process-group kill on timeout,
  and bounded capture.
- consent.mjs: the 0600 hash-pinned trust store.
- admitted.mjs: the frozen built-ins+admitted overlay; effectiveHostRegistry
  is HOST_REGISTRY by reference until something is admitted.
- Built-in lifecycle loops iterate builtinHostsWithLifecycle() so an admitted
  host can never enter an opencode-shaped teardown before external lifecycle
  execution graduates.

Security-reviewed (approve-with-nits, no RCE/escape/pollution): six of seven
attacks held; the consent-forgery gap and the checklist-not-allowlist finding
are closed by the strict allowlist above, verified against the reviewer's
exploit probes.
… regression corpus

The graduation artifact ADR-0029 names: a real fixture adapter under
tests/fixtures/adapters/acme with committed subprocess hooks, plus a
black-box conformance harness that admits it through the real consent store,
runs its declared hooks as real subprocesses against a marker file, and
proves each negative-corpus manifest is refused with its exact named reason.
Includes the allowlist, locale-hash, and consent-edit-invalidation regression
tests that pin the closed security findings.
…ed-registry clause

ADR-0029 (Accepted, experimental contract) records the data-plus-hooks
mechanism, credits @adrianco's PR #131 proposal and states what changed and
why (grounded in the four-sweep research), carries a graded Working/Demo/TBD
table, and formally supersedes ADR-0016's closed-registry clause — narrowly:
kit.json may name a manifest, but nothing under it is ever imported in-process,
so the clause's intent survives. PROVIDERS.md gains a brief current-state note.
kit.json entry shape corrected to {name, source, contract} to match the code.
NTFS carries no Unix permission bits, so mode & 0o777 never reflects the 0600
the consent store writes; the write still requests 0600. Guarded with the
repo's { skip: process.platform === 'win32' } idiom (windows-only CI failure).
@pacphi
pacphi merged commit 845fce9 into develop Aug 15, 2026
14 checks passed
@pacphi
pacphi deleted the feat/phase-2-wave-4-adapter-door branch August 16, 2026 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant