feat(codex): add subscription auth via CODEX_AUTH_JSON credential#801
Merged
zbigniewsobiecki merged 275 commits intomainfrom Mar 14, 2026
Merged
feat(codex): add subscription auth via CODEX_AUTH_JSON credential#801zbigniewsobiecki merged 275 commits intomainfrom
zbigniewsobiecki merged 275 commits intomainfrom
Conversation
…nction-duplication-dead-code
Add per-agent-type concurrency limits to prevent multiple instances of the same agent type running simultaneously for a project. Core implementation: - New `agent_configs.max_concurrency` column with CHECK constraint - Two-layer lock in `src/router/agent-type-lock.ts`: 1. In-memory concurrency map (fast path, TTL safety net) 2. DB count of running `agent_runs` (authoritative, survives restarts) - Trigger-level dedup (60s TTL) suppresses batch webhook re-triggers - Shared `checkAgentTypeConcurrency()` consolidates logic from 3 handlers Key design decisions: - Use `Math.max(dbCount, inMemoryCount)` instead of sum to avoid double-counting during the enqueued→running transition - 5-second TTL cache on `getMaxConcurrency()` DB queries - Graceful fallback (no limit) when DB is unreachable - Periodic cleanup of dedup map when it exceeds 100 entries Dashboard & CLI: - Agent config forms expose Max Concurrency field - `cascade agents create/update --max-concurrency N` - Agent configs table shows concurrency column Container manager: - `extractAgentType()` handles both trigger-based and dashboard jobs - Worker cleanup releases agent-type locks on exit - `detachAll()` clears all agent-type locks on shutdown Tests: 24 unit tests for agent-type-lock, concurrency-blocked tests added to all 3 webhook handler test suites (3868 total tests passing). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ency-limiting feat(router): add agent-type concurrency limiting
* refactor: clean up trigger config migration — deduplicate, validate, and harden - Add `checkTriggerEnabledWithParams()` to combine enabled check + parameter fetch in a single DB call (eliminates double query in check-suite-success and pr-opened handlers) - Extract `evaluateAuthorMode()` into `src/triggers/github/utils.ts` to deduplicate ~25 lines of authorMode gating logic across two handlers, with proper validation against ['own', 'external', 'all'] and fallback - Switch pr-ready-to-merge and pr-merged from direct `isTriggerEnabled()` to shared `checkTriggerEnabled()` helper for consistent logging - Add debug log for no-@mention path in pr-comment-mention - Remove ~1900 lines of legacy trigger config schemas and tests - Add disabled-trigger + argument verification tests to all 13 handler test files for complete coverage of the DB-driven trigger config path Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: include evaluateAuthorMode in utils.ts (missed in prior commit) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: update integration tests to use DB-driven trigger config Config toggle tests were using legacy `project_integrations.triggers` JSON which is no longer consulted. Updated to: - Seed `agent_trigger_configs` rows with `enabled: false` for disable tests - Test via `handle()` (which checks DB config) instead of `matches()` - Add `seedTriggerConfig` helper and include table in truncateAll Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The backlog manager posted its selection comment after moving the card, which meant downstream automation (pm:status-changed triggers) could fire before the rationale was visible. Swap steps 5 and 6 so the comment is posted first, then the card is moved. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…OMMENT_ID env var (#638) * feat(progress): replace file-based comment ID with CASCADE_PROGRESS_COMMENT_ID env var * chore: remove .cascade-progress-comment-id state file from repo The file-based progress comment ID mechanism has been replaced with the CASCADE_PROGRESS_COMMENT_ID env var. Remove the previously tracked state file and its .gitignore entry. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(progress): use ENV_VAR_NAME constant and add injection tests - Import ENV_VAR_NAME from progressState.ts in secretBuilder.ts and env.ts instead of hardcoding 'CASCADE_PROGRESS_COMMENT_ID' string literal - Add 5 unit tests for injectProgressCommentId covering: string ackCommentId with cardId injects, numeric ackCommentId skips, missing cardId skips, undefined ackCommentId skips, empty string ackCommentId skips Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(test): update progressMonitor.test.ts for env-var-based progress state Tests from dev branch (PR #637) used old file-based signatures for writeProgressCommentId and clearProgressCommentId. Updated to match the new env-var-based API (no repoDir parameter). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ci): restore .cascade-progress-comment-id in .gitignore The file may still be created by running cascade processes (e.g. the orchestrator session itself). Keeping the gitignore entry prevents it from appearing as an uncommitted change and triggering the stop hook. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Cascade Bot <bot@cascade.dev> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Three bugs caused the review agent to silently not run on PR#425: 1. Check polling window too short — `waitForChecks` polled 5×10s = 50s max, but CI took ~60s. Increase MAX_RETRIES from 5 to 12 (120s window). 2. Orphaned ack comment — when `pollWaitForChecks` returns false the handler returned without cleaning up the "👀 Reviewing" ack comment, leaving a misleading message on the PR. Now deletes the ack comment before returning. 3. Ack posted before job enqueued — the router posted the ack comment (step 8) before calling `addJob()` (step 9). A router crash between them orphans the ack with no corresponding job. Swap the ordering: enqueue first (durable in Redis), then post ack and patch the ackCommentId onto the job via `updateData()`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lience fix(router): review agent trigger resilience and ack ordering
…tions Replace the tautological assertion in the "provides suggestions when similar content exists" test that would pass regardless of gadget behavior. The test now verifies that the error message contains both "NOT FOUND", "SIMILAR CONTENT FOUND", and the actual similar content from the file. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…-replace-tests test(gadgets): add unit tests for FileSearchAndReplace
Removes the unused `fireAndForget` and `checkCapacity` properties from `WebhookHandlerConfig` interface along with their associated JSDoc. Also simplifies the `processWebhook` JSDoc to reflect router-only (always-await) semantics. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ode-router-mode
…bhook processor Step 2 (event type filter) now returns "Event type not processable: <eventType>" instead of reusing the Step 1 (parse failure) reason string, making the two distinct decision points distinguishable in logs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ew-commented-state
…n-reason-logging
…race-condition
Replace the binary work-item lock with a two-dimensional concurrency model: up to 2 agents per work item but only 1 of the same type. This allows implementation + review to overlap on the same card while still preventing duplicate agents. Key changes: - work-item-lock: track per (projectId, workItemId, agentType) with count-based slots, in-memory short-circuits before DB queries - container-manager: separate clearWorkItemEnqueued guard (needs agentType) from failOrphanedRun guard (only needs projectId + workItemId) — fixes silent regression for jobs lacking agentType - webhook-processor: pass agentType through to lock functions, call onBlocked() when job cannot be enqueued - check-suite-success: add onBlocked callback to clear dedup entry when router blocks the job - TriggerResult: add optional onBlocked callback for trigger handlers - runsRepository: add countActiveRunsForWorkItem/AndType queries Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
#774) * feat(cancel-button): improve UX with loading spinner and success state - Add loading spinner (Loader2 with animate-spin) during mutation - Show brief success indicator with auto-dismiss after 2 seconds - Replace window.confirm() with shadcn AlertDialog - Update dialog text: 'This will terminate the worker container?' - Improve error display to show full error message - Prevent double-cancellation by disabling button during success * fix(cancel-button): remove dead code and use AlertDialogFooter - Remove dead `disabled={cancelMutation.isPending}` props from AlertDialogCancel and AlertDialogAction — Radix UI auto-closes the dialog on action click, so isPending is never true while the dialog is visible - Remove the unreachable Loader2 spinner inside AlertDialogAction for the same reason - Replace raw `<div>` footer with `AlertDialogFooter` for consistent responsive layout matching credentials-table, projects-table, and agent-configs-table Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Cascade Bot <bot@cascade.dev> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…#776) Co-authored-by: Cascade Bot <bot@cascade.dev>
…ancellation (#777) * feat(router): implement cancel listener and API integration for run cancellation - New src/router/cancel-listener.ts: subscribes to Redis cancel channel and kills workers - Fallback Docker label scanning when jobId not found in database (race condition handling) - Updated router startup in src/router/index.ts to start/stop cancel listener with lifecycle - Updated runs.ts cancel mutation to publish cancel command after cancelRunById succeeds - Fire-and-forget publish with error logging to prevent API failures - Comprehensive unit tests for cancel-listener with Docker and DB mocking - Updated runs.test.ts to verify publishCancelCommand is called with correct parameters All tests pass, lint and typecheck clean. * fix(cancel-listener): address review feedback on correctness and cleanup - Remove unsafe Docker fallback that could kill wrong container in multi-run environments; containers have no run ID label so matching is impossible — replaced with a warning log - Add unsubscribeFromCancelCommands() to queue/cancel.ts so the Redis subscriber connection is properly closed on graceful shutdown - Replace misleading type hack (cancelSubscriber = true as unknown as ...) with a clear boolean flag (cancelSubscriberActive) - Remove redundant cascadeContainers.length > 0 check that was always true after the early return guard - Update tests to cover new warning-log behavior and verify shutdown properly calls unsubscribeFromCancelCommands Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test(scm): fix pre-existing sidecar test assertion for ackCommentDeleted field The sidecar now includes ackCommentDeleted in its output; update the assertion to use toMatchObject to allow for extra fields. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Cascade Bot <bot@cascade.dev> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(opencode): hardcode agent to 'build' and remove selection * test(opencode): remove stale agent field references from schema tests Remove `agent` field from the two opencode engine settings test cases in schema.test.ts, matching the cleanup done in the rest of this PR. The tests now only assert on `webSearch`, which is the only remaining field in OpenCodeSettingsSchema. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Cascade Bot <bot@cascade.dev> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Cascade Bot <bot@cascade.dev>
…irect navigation (#780) Co-authored-by: Cascade Bot <bot@cascade.dev>
* feat(trello): add createBoardCustomField support
- Add createBoardCustomField method to trelloClient making POST to /customFields
- Method accepts boardId, name, type and returns { id, name, type }
- Add createTrelloCustomField tRPC mutation in integrationsDiscoveryRouter
- Validate boardId (alphanumeric, max 32), name (min 1, max 100), type (enum)
- Add unit tests for client method and tRPC endpoint
- Tests cover success, validation, auth, credentials, and error handling
* test(trello): move createTrelloCustomField describe inside parent block
Move the describe('createTrelloCustomField') block inside the parent
describe('integrationsDiscoveryRouter') so the beforeEach DB mock setup
runs before these tests, matching the pattern of all other endpoint suites.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Cascade Bot <bot@cascade.dev>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…oint (#782) * feat(jira): add createCustomField method to JIRA client and tRPC endpoint * fix(jira): use neutral error prefix in createCustomField error handler Replace misleading "requires admin permissions" prefix with neutral "failed (admin permissions may be required)" to avoid confusion when the root cause is a network error, duplicate name, or validation issue. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(jira): add searcherKey to createCustomField for JQL searchability Pass the exactnumber searcherKey when creating a float custom field so the field is queryable via JQL (e.g. `"Cost" > 100`). The method signature accepts an optional searcherKey param; the tRPC endpoint always passes exactnumber for the hardcoded float type. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Cascade Bot <bot@cascade.dev> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Cascade Bot <bot@cascade.dev>
…on (#784) * feat(pm-wizard): add Trello custom field creation UI with Create button - Add ADD_TRELLO_BOARD_CUSTOM_FIELD action to WizardAction type - Handle ADD_TRELLO_BOARD_CUSTOM_FIELD in wizardReducer to append custom field - Create useTrelloCustomFieldCreation hook following useTrelloLabelCreation pattern - Hook calls createTrelloCustomField tRPC endpoint and dispatches actions on success - Add Create button next to cost field in TrelloFieldMappingStep - Button shows Loader2 spinner during creation and is disabled while creating - New field auto-selects in dropdown on successful creation - Display clear 403 error about Custom Fields power-up requirement on failure - Add comprehensive test cases for ADD_TRELLO_BOARD_CUSTOM_FIELD action - All tests passing (4618 tests) Closes #309 * fix(pm-wizard): hide cost field Create button when field already selected or exists Guard the Create button with checks for an already-selected cost field (trelloCostFieldId) and an already-existing Cost number custom field in customFields, matching the label creation pattern. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Cascade Bot <bot@cascade.dev> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…785) Co-authored-by: Cascade Bot <bot@cascade.dev>
… pages (#786) * feat(dashboard): add recharts visualizations to Work Item and PR Runs pages * docs(chart-colors): correct misleading comment about dark mode support The JSDoc claimed the palette covered both light and dark themes, but only light-mode oklch approximations were defined. Update the comment to accurately state the palette is static and visible in both modes but not theme-adaptive. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Cascade Bot <bot@cascade.dev> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(wizard): add Create button for JIRA cost custom field * fix(wizard): add duplicate-field guard to JIRA cost field Create button Check whether a "Cost" field already exists in jiraProjectDetails.fields before showing the Create button, mirroring the Trello equivalent guard. This prevents creating duplicate global JIRA custom fields when a Cost field already exists but hasn't been selected yet. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Cascade Bot <bot@cascade.dev> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…nly agent configs The agent config tests were still using the old API signatures (orgId param, projectId: null, no-arg listAgentConfigs). Updated to match the new project-only schema after migration 0036. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ent-configs feat(agent-configs): remove global/org-level agent configs — project-only migration
* feat(run-links): add per-project run links in agent comments * fix(run-links): include run link in GitHub PR ack comment and deduplicate buildRunLinkFooter - Fix correctness bug where GitHub PR ack comment was posted without the run link footer. Previously the link was appended to the internal AckResult.message *after* the comment was already on GitHub, so users never saw it. Now the message is built with the run link before calling postGitHubPRAck, matching the Trello/JIRA/PM-focused paths. - Extract shared buildRunLinkFooterFromEnv(workItemId?) to src/utils/runLink.ts and replace the 4 identical copies in createPR.ts, createPRReview.ts, postPRComment.ts, and postComment.ts, preventing future drift. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Cascade Bot <bot@cascade.dev> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…ository functions (#791) Co-authored-by: Cascade Bot <bot@cascade.dev>
…to workers The Claude Code backend now surfaces a human-readable error when a run hits the maxBudgetUsd limit instead of the raw SDK subtype string `error_max_budget_usd`. The error formatting is extracted into a standalone `formatErrorMessage` function, resolving a pre-existing biome cognitive-complexity lint warning on `buildResult`. Worker containers spawned by the router now receive the `CASCADE_DASHBOARD_URL` env var so the progress monitor can include run links in Trello/JIRA comments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e-and-worker-dashboard-url fix: improve budget-exceeded error message and forward dashboard URL to workers
…s control (#792) * feat(api): add users tRPC router with CRUD operations and admin access control * fix(users): enforce superadmin privilege hierarchy for update and delete - Prevent regular admins from revoking superadmin role (update procedure) - Prevent regular admins from deleting superadmin users (delete procedure) - Add tests covering both new security guards - Replace misleading passwordHash assertion with explanatory comment Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Cascade Bot <bot@cascade.dev> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…lete) (#794) Co-authored-by: Cascade Bot <bot@cascade.dev>
Co-authored-by: Cascade Bot <bot@cascade.dev>
) * feat(dashboard): merge agent config modal into expandable sections * fix(dashboard): move Saved indicator after confirmed save and clean up timers - setSaved(true) now fires only after the mutation's onSuccess callback, preventing "Saved" text showing when the mutation fails - Save success is signalled via a per-agent saveSuccessNonce counter that increments on each confirmed onSuccess, so repeated saves always trigger the useEffect in DefinitionAgentSection - setTimeout IDs are stored in useRef and cleared in useEffect cleanup to avoid state updates on unmounted components (fixes both agent section and lifecycle triggers section) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(dashboard): fix saved indicator race condition and add delete error handling - Add `justSavedRef` to prevent the config sync effect from clearing the "Saved" indicator when `invalidateQueries` triggers a refetch after save - Set `justSavedRef.current = true` in the nonce effect before showing the indicator, cleared by the next config sync cycle - Add `onError` toast to `deleteMutation` for consistent error feedback alongside create/update mutations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Cascade Bot <bot@cascade.dev> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…dence module (#798) Introduces a continuation loop in both Claude Code and OpenCode backends so agents that fail a post-completion check (e.g. no authoritative PR sidecar written) can resume the session and retry rather than immediately failing the run. ## Core changes ### Shared completion module (`src/backends/completion.ts`) - Extract `applyCompletionEvidence()` from OpenCode's local scope to the shared `completion.ts` module so both backends share identical evidence-upgrade logic. ### Claude Code backend (`src/backends/claude-code/index.ts`) - Add `consumeStream()` helper: processes the SDK stream, returns `turnCount` and `toolCallCount` (replaces the `StreamConsumptionContext` mutable-ref pattern). - Add `countToolCalls()` helper to count `tool_use` blocks without deep nesting. - Add `decideContinuation()` helper: encapsulates the completion-failure check, max-turns guard, and continuation-warning log; keeps `execute()` complexity low. - Add `cleanupPersistedSession()`: removes `~/.claude/projects/<encoded-cwd>` after each worker run. Encodes cwd with `replaceAll(path.sep, '-')` to match the SDK's actual directory naming (fix: plain `path.join` silently produced a wrong path). - Continuation loop in `execute()`: on completion failure, re-prompt the existing session with `{ continue: true }` up to `maxContinuationTurns` times. - Fix log message: "execution completed" → "turn completed" (accurate for both initial and continuation turns). - Fix spread pattern: `...(bool && obj)` → `...(bool ? obj : {})`. - Log `toolCallCount` in the continuation warning (parity with OpenCode). ### OpenCode backend (`src/backends/opencode/index.ts`) - Remove local `applyCompletionEvidence()` in favour of the shared import. - Fix `maxContinuationTurns` fallback: `1` → `0` (match Claude Code; if `completionRequirements` is absent there is nothing to check). ### Adapter (`src/backends/adapter.ts`) - Bump `maxContinuationTurns` from 1 → 2. ## Tests - `tests/unit/backends/completion.test.ts` (new): covers `applyCompletionEvidence` for all cases (no sidecar, sidecar upgrades text evidence, adds missing prUrl, default command fallback). - `tests/unit/backends/claude-code.test.ts`: five new continuation-loop scenarios (success after retry, exhausted turns, non-success stops immediately, cost accumulation, no-op when completionRequirements absent). Adds `beforeEach` reset and renames inner helper to `queueStream` to avoid shadowing the outer `mockStream`. - `tests/unit/backends/adapter.test.ts`: update `maxContinuationTurns` expectation. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Bumps [undici](https://github.com/nodejs/undici) from 7.22.0 to 7.24.1. - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](nodejs/undici@v7.22.0...v7.24.1) --- updated-dependencies: - dependency-name: undici dependency-version: 7.24.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…lls, not describe them (#799) Gemini Flash (and similar models) sometimes output bash commands inside markdown code blocks instead of actually invoking them as tool calls, then stop with reason:stop — causing silent no-ops (card never moved). Adds an engine-agnostic CRITICAL rule to the Rules section of the backlog-manager prompt instructing the model to always invoke tool calls rather than narrate them as text. Also adds a regression test asserting the rule appears in the rendered system prompt. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Cascade Bot <bot@cascade.dev>
Enables ChatGPT Plus/Pro users to run the Codex engine without an API key by storing the `~/.codex/auth.json` OAuth token pair as an org-scoped credential. - `writeCodexAuthFile`: validates and writes `auth.json` (mode 0600) before each run; returns the original content for change detection - `captureRefreshedToken`: reads `auth.json` after the run; if the Codex CLI refreshed the access token, updates the DB credential so it stays current in ephemeral worker environments - Strips `CODEX_AUTH_JSON` from the subprocess env so the JSON blob never leaks into the spawned `codex` process - `findCredentialIdByEnvVarKey` added to `credentialsRepository` with `isDefault = true` filter to target the right credential row - Module-level path constants (`CODEX_AUTH_DIR`, `CODEX_AUTH_FILE`) shared by both helpers; JSON validated before writing - 5 new unit tests covering auth write, env stripping, token refresh capture, no-op on unchanged file, and WARN on missing credential - CLAUDE.md: Codex Backend section documenting subscription auth setup and automatic token refresh behaviour Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
CODEX_AUTH_JSONcredential instead of an API keywriteCodexAuthFile()validates and writes~/.codex/auth.json(mode 0600); after the run,captureRefreshedToken()detects any token refresh the Codex CLI performed and updates the DB credential automatically — keeping it current in ephemeral worker environmentsCODEX_AUTH_JSONis stripped from the subprocess environment so the JSON blob never leaks into the spawnedcodexprocessfindCredentialIdByEnvVarKey()tocredentialsRepositorywithisDefault = truefilter to correctly target the default credentialTest plan
npm run typecheck— cleannpm run lint— cleannpm test— 4683 tests, 270 files, all passCODEX_AUTH_JSONabsent from subprocess env, DB credential updated on token refresh, no-op when file unchanged, WARN logged when credential row not found🤖 Generated with Claude Code