feat: phase 2 wave 4 — host-adapter extension point (ADR-0029, experimental) - #149
Merged
Conversation
…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).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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=1with 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:
canBePrimary/aqeProvider/commandStatusline) and a path-traversalguidanceFileare inexpressible, not merely refused; an external adapter may not name an npm package ak would install.effectiveHostRegistry()isHOST_REGISTRYby reference until something is admitted; built-in lifecycle loops stay opencode-shape-safe until external execution graduates.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