Recipes

샌드박스 dev-engine carrier의 대체 자격 증명으로 Claude Code OAuth 토큰 추가

README 링크에서 발견 · today

Software & DevOpsWork & Operations

spec 수정, fallback auth 연결, CI test-glob 누락 수정, 테스트 7개 추가.

What they did

작성자의 `/dev` 캐리어 — spec/005에 정의된 샌드박스화된 `claude` CLI 호출 — 는 `ANTHROPIC_API_KEY`로만 인증할 수 있었습니다. Claude Code 구독 로그인만 있고 별도의 Console API 키가 없는 머신에서는 전혀 실행될 수 없었습니다. Docker, 이그레스 프록시, 네트워크 경로는 모두 정상임이 확인되어, 자격 증명만이 유일한 공백으로 남았습니다. 작성자는 spec/005 섹션 2.6을 수정하여(두 차례에 걸친 아비터 검토 후 승인) `claude setup-token`에서 얻는 `CLAUDE_CODE_OAUTH_TOKEN`을 폴백으로 허용하고, 선호 순서를 `ANTHROPIC_API_KEY` > `CLAUDE_CODE_OAUTH_TOKEN`으로 정했습니다. Anthropic 문서에 따르면 `--bare`는 `CLAUDE_CODE_OAUTH_TOKEN`을 읽지 않으므로, 해당 분기에서는 대신 `--safe-mode`를 사용합니다 — 아비터의 첫 번째 검토 라운드에서 단순히 `--bare`를 제거하면 처음 가정했던 CLAUDE.md뿐만 아니라 여덟 가지(hooks, skills, 사용자 정의 명령, subagents, 설치된 플러그인, MCP 서버, 자동 메모리, CLAUDE.md)가 다시 활성화된다는 점을 포착했습니다. 작성자는 `invoker.mjs`에 `detectCredentialEnvVar()`를 추가하고, `run-agent.mjs`의 `defaultExecShell`이 하나를 하드코딩하는 대신 실제 자격 증명을 감지하도록 했으며, `credentialEnvVar`를 일곱 개의 캐리어 콜백 전체에 전달하고, `run-positive-controls.sh`의 컨트롤 #6에서 두 허용된 이름을 모두 제외하고, docker-compose에서 `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1`을 무조건 설정하고, 두 자격 증명 중 어느 것도 설정되지 않았을 때 `dev.mjs`가 `ENVIRONMENT_CHECK_FAILED`와 함께 즉시 실패하도록 했습니다. 코드를 살펴보던 중 기존의 CI 공백을 발견했습니다: 최상위 `engine/*.test.mjs` 글롭이 하위 디렉터리에 도달하지 않아 `engine/carrier/*.test.mjs`와 `engine/carrier/egress-proxy/*.test.mjs`가 한 번도 실행되지 않았습니다 — 이 PR에서 가장 핵심적인 두 테스트 파일을 포함해서요 — 그리고 이를 `.github/workflows/ci.yml`에서 해결했습니다.

How it went

529/529 테스트 통과 (기존 베이스라인 522개에 신규 7개 추가). `invoker.test.mjs`의 신규 7개 테스트는 두 브랜치의 플래그/변수 선택, 양쪽에 걸친 상호 배제 고정, `detectCredentialEnvVar`의 우선/폴백/부재 케이스, 알 수 없는 값 거부를 다룹니다. 작업 도중 실제 회귀 하나를 발견해 수정했습니다: `dev.test.mjs`의 26개 `runRepo` 해피 패스 테스트가 가짜 자격 증명 감지기를 주입하지 않아, fail-fast 검사가 들어온 뒤 실제 자격 증명 없는 환경에서 깨졌으며, 공유 `baseRunRepoOverrides` 픽스처로 수정했습니다. `prettier --check`, `claude plugin validate --strict` (플러그인 및 마켓플레이스), `sync-route.mjs --check`, `check-roster.mjs`, `check-version-bump.mjs` 모두 통과했으며, `engine/`은 배포 콘텐츠 접두사가 아니므로 버전 범프는 필요하지 않았습니다. 스펙은 `status: finalized`로 복귀했고, 전체 변경 기록은 `revision/2026-11-02-dev-carrier-oauth-token-credential.md`에 있습니다.

Worth knowing

폴백은 `claude setup-token` 출력과 `--bare`가 `CLAUDE_CODE_OAUTH_TOKEN`을 무시한다는 Anthropic의 문서화된 동작에 의존합니다. 이 동작이 바뀌면 `--safe-mode` 분기를 다시 검토해야 합니다. `--safe-mode`는 `--bare`보다 더 넓은 격리 태세이므로 두 자격 증명 경로 간에 동작이 다르며, 둘 다 지속적인 테스트 커버리지가 필요합니다. CI glob 수정으로 이제 하위 디렉터리 테스트가 실행되므로, 이전에 숨겨져 있던 실패가 다른 브랜치에서 드러날 것으로 예상됩니다. arbiter 리뷰 프로세스(2라운드)는 이 저장소의 워크플로우 일부이며 여기서는 재현되지 않습니다.

Wiring

스펙 수정 먼저(spec/005 섹션 2.6 및 spec/README.md), 그다음 `invoker.mjs`(`detectCredentialEnvVar()`, 조건부 `--bare`/`--safe-mode`, credential 이름 전달), 그다음 `run-agent.mjs`의 `defaultExecShell`, 그다음 `carrier-callbacks.mjs`(7개 콜백 모두 `credentialEnvVar`를 받음), 그다음 `run-positive-controls.sh` 컨트롤 #6, 그다음 `docker-compose.yml`의 무조건적 `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1`, 그다음 `dev.mjs`의 fail-fast `ENVIRONMENT_CHECK_FAILED`, 그다음 CI 워크플로 glob 수정, 그다음 테스트. 구성: credential은 환경에서 가져온다 — `ANTHROPIC_API_KEY` 또는 `CLAUDE_CODE_OAUTH_TOKEN`(`claude setup-token`으로 생성); carrier는 어느 것이 존재하는지 감지하고 그 이름만 샌드박스로 전달한다. 샌드박스는 Docker에서 egress 프록시 뒤에서 `claude` CLI를 실행한다; OAuth 경로에서는 `--safe-mode`를 사용하는데, `--bare`가 해당 토큰을 무시하기 때문이다. 테스트는 `engine/**/*.test.mjs`와 `skills/dev/scripts/dev.test.mjs`에 대해 `node --test`로 실행되며, `baseRunRepoOverrides`가 가짜 credential 감지기를 제공한다.

Try it yourself

I'll work through this systematically. Let me start by exploring the repo structure to understand the current state.

<||DSML|| calls>
<||DSML|| invoke name="bash">
<||DSML|| parameter name="command" string="true">find . -maxdepth 3 -type d -name node_modules -prune -o -type f -name "*.mjs" -print | head -50; echo "---"; ls -la; echo "---"; ls plugins/openindu-control-tower 2>/dev/null</||DSML|| parameter>
</||DSML|| invoke>
</||DSML|| calls>

Source

English

Tools in this stack