1.0 blockers: auth-by-default listener, stdio scrub, harness hardening, compatibility promise, docs accuracy #37
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/release-1-0-blockers"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Lands the five remaining 1.0 blockers from design/release-1-0.md §2. B3: auth-by-default sse listener with Origin and Host guard plus a shared token provisioner across serve, up and init. B4: stdio removed from every user-visible surface. B7: harness configs written 0600 with refuse-to-clobber and git-exclude. B1: the compatibility promise in docs/releases.qmd. B8: two docs accuracy passes over every claim of protection. Each package was agent-implemented in an isolated worktree and reviewed. B3 was re-verified after its fix round. A /simplify pass and a final whole-branch review closed out, including the up --no-server tokenless seam. Deferred and tracked in the note: connect.sh in-container write lacks 0600 and git-exclude. Details per merge commit. Generated with Claude Code. https://claude.ai/code/session_01NA8scMaA7UJSmBzWsPpPYc
Review of the B3 branch found `wraptool init` still wrote a tokenless harness config: runInit derives its token from cfg.MCP.AuthTokenFile, and nothing persists the auto-provisioned default to config.yaml — so the upgrade remedy docs/security.qmd points at ("re-run wraptool init") generated another 401. Extract the provisioning decision into provisionDefaultMCPToken and route all three callers through it. init may run before any server has, so the helper creates the file rather than merely naming it. ensureTokenFile is now create-exclusive. Its read-then-write was reachable outside the runtime flock (a service-managed serve racing a concurrent up), and a lost race means one side hands a container a token the server never loaded. Once the file holds a value that value never changes; the one case O_EXCL alone would leave broken — a file created by an interrupted earlier run, still empty — is repaired explicitly. browserGuard now logs each rejection with the offending header and the configured bind: a 403 with no server-side trace leaves an operator guessing. Replaces the runServe boot test, which leaked the server goroutine AND its signal handler — signal.Notify plus os.Exit(0) turns a SIGTERM-killed test run into a false green — with a direct unit test of the shared helper (default path chosen only when unset and sse, file created 0600, an existing token never rewritten, a configured path untouched) plus an init test asserting the generated config carries the Authorization header. The wire-behaviour tests keep running against the real handler composition, now including /message. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NA8scMaA7UJSmBzWsPpPYccmd/init.go:L77: 🔴 bug: config-load errors—including a missing first-run config—are swallowed, producing a tokenless SSE harness config that will 401 once
serveprovisions auth. Scaffold/load the default config or return the load error before writing harness configs.cmd/init.go:L78: 🔴 bug: default SSE token provisioning makes
--harness allreach Roo’s auth rejection only after six earlier harness configs were written. Validate the expanded harness set before any writes, and define whetherallexcludes auth-incompatible harnesses.cmd/up.go:L517: 🟡 risk: the empty-file repair defeats
O_EXCLrace protection; a second process can observe the newly created but unwritten file, truncate/write it, then have the first writer overwrite that token. Serialize repair or use an atomic fully-written-file publication scheme.