fix: stop hardcoding CLAUDE_CODE_OAUTH_TOKEN in required_env (#1028)

The provisioner was unconditionally writing CLAUDE_CODE_OAUTH_TOKEN into
config.yaml's required_env for all claude-code workspaces.  When the
baked token expired, preflight rejected every workspace — even those
with a valid token injected via the secrets API at runtime.

Changes:
- workspace_provision.go: remove hardcoded required_env for claude-code
  and codex runtimes; tokens are injected at container start via secrets
- workspace_provision_test.go: flip assertion to reject hardcoded token

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
rabbitblood 2026-04-19 21:56:21 -07:00
parent 19cae2986c
commit 639b4dbb9f
2 changed files with 9 additions and 10 deletions

View File

@ -439,12 +439,12 @@ func (h *WorkspaceHandler) ensureDefaultConfig(workspaceID string, payload model
// Model always at top level — config.py reads raw["model"] for all runtimes.
configYAML += fmt.Sprintf("model: %s\n", quoteModel)
// Add required_env based on runtime — preflight checks these are set via secrets API.
// Add runtime_config. required_env is intentionally omitted — the
// platform injects secrets at container-start time via the secrets API,
// and preflight already validates that the env vars are present before
// the agent loop starts. Hardcoding token names here caused #1028
// (expired CLAUDE_CODE_OAUTH_TOKEN baked into config.yaml).
switch runtime {
case "claude-code":
configYAML += "runtime_config:\n required_env:\n - CLAUDE_CODE_OAUTH_TOKEN\n timeout: 0\n"
case "codex":
configYAML += "runtime_config:\n required_env:\n - OPENAI_API_KEY\n timeout: 0\n"
case "langgraph", "deepagents":
// These runtimes read API keys from env directly, no runtime_config needed.
default:

View File

@ -247,11 +247,10 @@ func TestEnsureDefaultConfig_ClaudeCode(t *testing.T) {
if !contains(content, "runtime_config:") {
t.Errorf("config.yaml should have runtime_config section for claude-code, got:\n%s", content)
}
if !contains(content, "required_env:") {
t.Errorf("config.yaml should have required_env for claude-code, got:\n%s", content)
}
if !contains(content, "CLAUDE_CODE_OAUTH_TOKEN") {
t.Errorf("config.yaml should require CLAUDE_CODE_OAUTH_TOKEN, got:\n%s", content)
// required_env is no longer hardcoded — tokens are injected at runtime
// via the secrets API (#1028).
if contains(content, "CLAUDE_CODE_OAUTH_TOKEN") {
t.Errorf("config.yaml should NOT hardcode CLAUDE_CODE_OAUTH_TOKEN (fix #1028), got:\n%s", content)
}
// Should NOT have .auth-token file
if _, ok := files[".auth-token"]; ok {