Skip to content

feat(ca-sandbox): ship the isolated-sandbox sibling plugin as Feature Forge preview (v0.1.0) - #111

Merged
SUaDtL merged 4 commits into
mainfrom
feat/ca-sandbox
Jun 20, 2026
Merged

feat(ca-sandbox): ship the isolated-sandbox sibling plugin as Feature Forge preview (v0.1.0)#111
SUaDtL merged 4 commits into
mainfrom
feat/ca-sandbox

Conversation

@SUaDtL

@SUaDtL SUaDtL commented Jun 20, 2026

Copy link
Copy Markdown
Collaborator

Ships ca-sandbox 0.1.0 — the sibling infrastructure plugin from ADR-0007 — into the marketplace and the README Feature Forge as a preview.

Readiness — verified, not assumed

Ran the full suite locally against real Docker: 178/178 tests green across 16 files (~171s), including every docker integration spec — host-FS isolation canary, network policy (offline / clone-then-cut / allowlist), multi-stack builds (node/py/go/rust), lifecycle create→destroy→prune, --with-claude reaching auth with a dummy token (real 401), and exec/cp/run isolation flags. Typecheck clean; sandbox.js artifact fresh.

What lands

  • The ca-sandbox plugin (plugins/ca-sandbox/, v0.1.0): ephemeral isolated container, content-hash dep cache, configurable egress, exec/cp seams, experimental --with-claude.
  • Marketplace registration (two-plugin shape per ADR-0007) + README Feature Forge entry.
  • New: a plugin-scoped CHANGELOG.md (the debut commit shipped without one).

Posture

Honest preview / not-yet-blessed: green suite, but unproven in real use; --with-claude verified only against a dummy token. Off by default. Promotes on real-world evidence.

CI

Path-scoped (ADR-0007): the docker-gated ca-sandbox-tools job runs; ca jobs skip. Per-plugin version-bump guard passes (no prior ca-sandbox tag).

After merge

Tag ca-sandbox-v0.1.0 and publish as a pre-release (beta).

https://claude.ai/code/session_018fLGikjkdB52vyGsDDooPu

SUaDtL and others added 4 commits June 20, 2026 11:08
…ted-repo sandbox (ADR-0007)

A locally-hosted GitHub-Codespace equivalent: pull an untrusted repo into an
ephemeral, isolated container (no host-FS access, configurable network, dep-cached
build), explore, tear down. Ships as a second sibling plugin in the marketplace
per ADR-0007 — independent of the ca governance kernel, with path-scoped CI and
per-plugin version bumps.

Tools (TS, esbuild-bundled to sandbox.js):
- mounts: bind-rejecting mount builder (volume/tmpfs only)
- dephash: deterministic, manifest/lockfile-sensitive build hash
- build: nixpacks wrap + dephash image cache + deps relocated to /deps
- run: cap-drop ALL, non-root, read-only root, no docker.sock, never privileged
- create/destroy/registry: named-volume clone + label-based lifecycle + prune
- network: offline default, clone-then-cut, experimental egress allowlist
- exec/cp/cli: JSON exec contract, host-out copy, subcommand dispatch
- claude-inside: env-token auth + named-volume HOME persistence, Anthropic-only default

Security review (auth-crypto + isolation reviewers) ran on the staged diff; two
HIGH findings fixed before commit:
- create.ts: validate the untrusted clone url (allowlist https/ssh/scp, reject
  ext::/fd::/file:// and leading-'-') + emit `git clone ... -- <url>` — closes a
  git argument-injection / transport-helper RCE surface in the clone container.
- claude-inside.ts: the --with-claude box now runs --cap-drop ALL + --user 1000:1000
  (was root + full caps despite the docstring); image chowns CLAUDE_HOME so the
  hardened, read-only box still persists credentials. Tests now assert the posture.
security-controls.md gains a Container-isolation section, the CLAUDE_CODE_OAUTH_TOKEN
secret, and the clone-trust + nixpacks-install boundary crossings.

178/178 tests pass (docker-gated behavioral ACs run real containers); typecheck
clean; sandbox.js fresh; multi-stack fixtures (node/py/go/rust).

Governance: ADR-0007 + spec + plan + spike notes; marketplace/CONTEXT/tech-stack/
README updated; check-plugin-refs parameterized over both plugins; CI path-scoped
(dorny/paths-filter, per-plugin tools/refs/version-bump jobs, ca-sandbox-v* tags).

Claude-Session: https://claude.ai/code/session_01TyodF13mUUNrGgcVTmGjgW
The ca-sandbox debut (7cce1a1) shipped the plugin, marketplace registration,
and README Feature Forge entry but no changelog. Add a plugin-scoped
CHANGELOG (ca-sandbox versions independently of ca per ADR-0007) documenting
the 0.1.0 preview surface and the honest not-yet-blessed posture.

Claude-Session: https://claude.ai/code/session_018fLGikjkdB52vyGsDDooPu
…duction

The ca-sandbox version-bump guard ran `git show origin/main:plugins/ca-sandbox/
.claude-plugin/plugin.json` to read the base version — but on a plugin's very
first PR that path does not exist on base, so git errors, pipes an empty string
to node, JSON.parse('') throws, and under `bash -e` the step dies before
reaching the tag-existence check that would correctly allow an unpublished
version. Treat a missing base plugin.json as a new-plugin introduction (nothing
published yet → no staleness trap → allowed). The already-published guard is
unchanged once the plugin exists on base.

Claude-Session: https://claude.ai/code/session_018fLGikjkdB52vyGsDDooPu
@SUaDtL
SUaDtL merged commit 7505b47 into main Jun 20, 2026
15 checks passed
@SUaDtL
SUaDtL deleted the feat/ca-sandbox branch June 20, 2026 21:23
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