release: v4.4.1 — isolate runner OAuth credential from shared /root/.claude/#308
Merged
Merged
Conversation
The v4.2.2 walkthrough seeded the runner's credential at /root/.claude/.credentials.json. On boxes where that path is also mounted into other CC clients — docker services, operator SSH sessions — both clients use the same access/refresh tokens. When either refreshes, the other's bearer can be silently invalidated. We hit one 401 during v4.2.2 setup; the 30-min cron cadence absorbed it but it's a real failure mode. Fix: both runner workflows now pin HOME=/root/.claude-runner on every step that spawns CC. Setup writes the runner's credential under /root/.claude-runner/.claude/.credentials.json, isolated from the platform path. - cc-drift-template-watch.yml: Run drift check + Auto-rebake + open PR steps both get env HOME=/root/.claude-runner - compat-test-self-hosted.yml: Start dario proxy step gets the same - docs/drift-monitor.md: documents the isolated flow as the recommended pattern for shared boxes; default ~/.claude/ still works for runner-only hosts Verified end-to-end on the production runner: generated fresh credential via HOME=/root/.claude-runner dario login --manual, mirrored dario's ~/.dario/credentials.json to CC's ~/.claude/.credentials.json (same JSON format, top-level claudeAiOauth key), confirmed `claude --print` returns PONG and --check reports no drift. Platform's /root/.claude/ untouched. Pure operational hardening. No src/ changes. 74/74 default suite green.
Contributor
Compat test: ✅ PASSEDRan Output |
5 tasks
askalf
added a commit
that referenced
this pull request
May 17, 2026
Both compat-test-self-hosted.yml and cc-billing-classifier-canary.yml were silently piggybacking on the platform's existing dario instance (askalf-dario docker container at :3456), not the freshly-built dist they were supposed to test. Mechanism: dario proxy's EADDRINUSE handler probes /health when its target port is occupied, sees an existing dario, prints "dario — already running" and exits 0 (intentional: makes `dario login` / `dario proxy` idempotent for users). On the production runner the docker askalf-dario already binds :3456, so the workflow's `dario proxy` short-circuits and the workflow's curls hit the platform's dario using PLATFORM credentials. For the canary: produced 401 + claim='' because the platform's account is in a different state right now. For compat-test: every PR check on PRs #303, #304, #306, #308, #310, #311 was validating the platform dario, not the PR's freshly-built dist. The PR-time gate was measuring the wrong thing. Fix: both workflows now bind --port 3457 and the harnesses read DARIO_TEST_URL=http://127.0.0.1:3457. Eliminates the port collision. Validated locally on the production runner: HOME=/root/.claude- runner dario proxy --port 3457 starts clean, /health responds, single tiny haiku request returns 200 with a subscription representative-claim. The runner workflow will produce the same result once landed. 75/75 default suite green. No src/ changes.
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.
What does this PR do?
Operational hardening. The v4.2.2 walkthrough seeded the runner's CC credential at `/root/.claude/.credentials.json`. On boxes where that path is also mounted into other CC clients (docker services that mount the host's `/root/.claude/` as a credentials volume, operator SSH sessions, etc.), both clients use the same access/refresh tokens. When either refreshes, the other's bearer can be silently invalidated until its next refresh attempt. We hit one such 401 during v4.2.2 setup; the 30-min cron cadence absorbed it, but it's a real failure mode for higher-frequency setups (e.g. v4.4.0's auto-rebake firing during a cycle that happens to overlap a token refresh).
Fix
Both runner workflows now pin `HOME: /root/.claude-runner` on every step that spawns CC. Runner's credential lives at `/root/.claude-runner/.claude/.credentials.json`, isolated from `/root/.claude/` — refreshes on the two paths are now independent.
Verification
Generated a fresh OAuth credential on the production runner via `HOME=/root/.claude-runner dario login --manual`. dario writes its credentials to `
/.dario/credentials.json`; CC reads from `/.claude/.credentials.json`. Same JSON format though (top-level `claudeAiOauth` key), so setup mirrors the file. Confirmed:How to test
```bash
git fetch origin fix/v4.4.1-runner-credential-isolation
git checkout fix/v4.4.1-runner-credential-isolation
npm run build && npm test # 74/74
End-to-end: once merged, the next 30-min watcher cron tick exercises
the new HOME pinning. Manual workflow_dispatch on master also available.
```
Checklist