Commit graph

2 commits

Author SHA1 Message Date
Gergo Magyar
1a2c480847 fix(devcontainer): set persist-credentials:false on CI checkouts + prettier
- zizmor `artipacked` (CodeQL/GitHub Advanced Security) flagged both
  actions/checkout steps in ci-devcontainer.yml: checkout defaults to
  persist-credentials:true, leaving GITHUB_TOKEN in .git/config where it
  can leak into uploaded artifacts. Both jobs are read-only (run tests /
  build smoke, never push), so persist-credentials:false is correct —
  matches the repo convention in codeql.yml / ci-tests.yml.
- Ran prettier 3.8.0 over the new .cjs modules + test (single-quote/style
  normalization to match the repo). JSON/YAML were already compliant;
  README is in .prettierignore; .sh has no prettier parser. Behavior
  unchanged — 12/12 transform unit tests still pass.
2026-05-28 21:51:55 +01:00
Gergo Magyar
1008b0dcf9 fix(devcontainer): resolve ce-code-review findings (doc drift, chown scope, .cjs extraction, CI smoke)
Multi-agent review (9 reviewers) found the devcontainer files carried
comments + README from the abandoned read-only-symlink design, plus real
behavioral gaps. Resolved all actionable findings (no deferrals).

Documentation drift (the headline — stale comments described a security
model opposite to what shipped):
- README "Trust boundary" claimed a malicious dep "cannot write back …
  the read-only /host mount blocks the write." FALSE — the shareable dirs
  are RW-bound. Rewrote to document the bidirectional write-through, what
  stays one-way (credentials never flow back), and how to close it.
- devcontainer.json mount group-1 comment described "selectively symlinks
  … read-only eliminates write-through" — replaced with the RW-bind reality.
- Header "Windows-native is unsupported" -> supported (auto HOME setup).
- containerEnv comment "credentials persist in host-bind-mounted dirs" ->
  they live in the named volumes.
- hooks.json exclusion documented honestly as a partial mitigation, not a
  clean boundary (commands/agents/skills/rules are equally executing).
- ~/.local "named volume" -> image directory.

Behavioral fixes:
- chown -R recursed into the RW host binds (could rewrite host ownership /
  EPERM-abort provisioning on non-UID-aligned Linux). Switched to
  `find -xdev` per dir so chown stays on the volume filesystem.
- Cursor installer wrapped in `timeout 300` — its inner binary download
  isn't covered by curl --max-time and could hang docker build forever.
- Removed dead CURSOR_VERSION ARG/ENV/build-arg (never consumed; "latest"
  implied a pin the installer can't honor). Documented why Cursor is unpinned.

Extraction + tests (the two inline post-create.sh node heredocs were
unlintable and untestable; the path regex had had bugs):
- seed-claude-config.cjs — installMethod-strip seed, now with a non-object
  guard (a bare-value/array host .claude.json could otherwise slip the
  try/catch and silently re-trigger onboarding) and labeled write errors.
- translate-plugin-registries.cjs — plugin-registry path translation with
  labeled errors.
- translate-plugin-registries.test.cjs — 12 tests (Windows/POSIX paths,
  cross-CLI isolation, nested objects, non-object/empty-config guard).
- post-create.sh calls the modules via $SCRIPT_DIR.

CI:
- .github/workflows/ci-devcontainer.yml — runs the unit tests + shell
  syntax checks + a `@devcontainers/cli build` smoke on .devcontainer/**
  changes. Conforms to the repo concurrency convention (validator passes).

Documented (real gaps, fixes are honest docs since no correct auto-fix
exists): user-scope MCP servers with absolute host command paths don't
resolve in-container; user-scope config is copy-on-create so host edits
need a rebuild; in-container plugin installs get shadowed by an empty host
bind on rebuild (recovery noted); plugin installs are single-writer across
checkouts; gh/docker RW-vs-ssh/aws/azure-RO rationale.

Verified: fresh `@devcontainers/cli up` succeeds; installMethod stripped,
registry translated to Linux paths, credentials node:node, 12/12 tests pass.
2026-05-28 21:48:37 +01:00