security: control-plane bearer auth, dependency audit gate, secrets hardening - #1
Open
DanielSoCra wants to merge 20 commits into
Open
security: control-plane bearer auth, dependency audit gate, secrets hardening#1DanielSoCra wants to merge 20 commits into
DanielSoCra wants to merge 20 commits into
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mples, docs; fix creds validation log perms
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Move RUNFORGE_CONTROL_TOKEN resolution into a shared helper (packages/daemon/src/control-plane/resolve-control-token.ts) so both main.ts and the stub cli.ts use identical logic. - Locate the repo root by walking up from the module file to a pnpm-workspace.yaml or .git marker, instead of using process.cwd(). This fixes status/pause/resume CLI failures when invoked via pnpm --filter (cwd = packages/daemon). - Add unit tests covering env precedence, cwd independence, and empty-value handling. - Update traceability.yml for the new files.
Restore the legacy /halt behavior so Authorization: bearer <token> and Authorization: BEARER <token> are accepted. Prevents external clients that send lowercase schemes from getting 403 after the hardening migration.
app/api/metrics/escalation and app/api/decisions/pending were treating DaemonAuthError the same as DaemonConfigError and silently returning a degraded 200, masking misconfigured RUNFORGE_CONTROL_TOKEN. Now they log and return a 500 JSON response with the actionable RUNFORGE_CONTROL_TOKEN message, matching every mutating daemon proxy route. - Add regression tests for both GET proxies. - Update traceability.yml for the new metrics escalation test file.
- install-daemon.sh: check .env.mac for a RUNFORGE_CONTROL_TOKEN line directly, instead of sourcing the file and trusting inherited shell env. Fixes a daemon/dashboard token mismatch when the operator has RUNFORGE_CONTROL_TOKEN exported in their shell but .env.mac lacks it. Also chmod 600 the env file on every run, not only on generation. - sync-claude-creds.sh: mkdir -p CREDS_DIR before creating the validation log with mktemp, so a fresh bind-mount dir no longer aborts the script before credentials are written.
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.
Summary
This PR addresses the production-readiness findings from the 2026-07-07 external engineering review in four focused hardening areas:
Authorization: Bearer $RUNFORGE_CONTROL_TOKENon every route exceptGET /health(both control and degraded servers). A startup bind-host gate refuses non-loopback binds without a token; loopback-without-token keeps working in legacy mode with loud deprecation warnings.X-Requested-Byis retained as a CSRF/provenance defense on mutating methods. All clients (dashboard, briefing-summarizer, concierge, daemon CLI) forward the bearer token.nextto 16.2.10,honoto 4.12.28, andbetter-authto 1.6.23; added rootpackage.jsonpnpm.overridesfor remaining high-severity transitive packages (picomatch, path-to-regexp, fast-uri, vite, undici) sopnpm audit --prod --audit-level highexits 0.scripts/install-daemon.shnow provisionsRUNFORGE_CONTROL_TOKENinto.env.mac(0600) and the launchd plist;scripts/sync-claude-creds.shwrites its validation log to a 0600 file instead of world-readable/tmp.STACK-AC-OPERATOR-AUTH(and its ARCH/FUNC parents) to own the daemon-side bearer model, bind-host gate, legacy loopback mode, and/healthexemption; updated.specify/traceability.ymlwith the new control-plane auth files.Design spec:
docs/superpowers/specs/2026-07-07-control-plane-hardening-design.mdImplementation plan:
docs/superpowers/plans/2026-07-07-control-plane-hardening.mdTest plan
pnpm --filter @runforge/daemon exec vitest run src/control-plane/__acceptance__) passserver.test.ts,control-auth.test.ts,degraded-server.test.ts) covers token set/unset × mutating/sensitive/health/halt routesdaemon-fetchunit tests cover bearer injection, non-overridability, and 401/403 →DaemonAuthErrorRUNFORGE_ENV_MAC_PATHoverride produces identical token and 0600 mode on re-runpnpm audit --prod --audit-level highexits 0gitleaks detect --redactis cleannode scripts/check-ci-workflows.mjsexits 0pnpm typecheck && pnpm lint && pnpm test && pnpm buildpluspnpm check:traceability && pnpm check:workflowsNotes
0.0.0.0; the compose file now requiresRUNFORGE_CONTROL_TOKENvia${RUNFORGE_CONTROL_TOKEN:?…}. This is a deliberate fail-closed upgrade: deployments without a token will fail fast at compose time until the operator sets the token in the selected env file.🤖 Generated with Claude Code