BAT-006 (REQ-016/017/018): - client token 발급 경로 제거 (issue_client_token, POST /auth/tokens, 관련 스키마/테스트) - service-token rotate unique index revoked_at IS NULL 조건 추가 (Alembic CONCURRENTLY 마이그레이션) - POST /auth/service-tokens body daemon_id forward 누락 보정 (1-line fix) BAT-007 (REQ-022/023): - daemon deactivate 시 바인딩 service token 자동 revoke (CLI --force 옵션 + revoke_tokens_by_daemon_id) - NULL daemon_id legacy token 진단 CLI (migrate-null-daemon --dry-run) 거버넌스 문서: dcy-003/004 Discovery, REQ-016~023/025~032 신규, BAT-006/007 전체 산출물 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3.8 KiB
3.8 KiB
BAT-007 Design
- Status: confirmed
- Batch: BAT-007
Architecture Summary
- REQ-022: daemon CLI의
--deactivate분기에 신규 service 메서드(revoke_tokens_for_daemon) 호출을 추가한다. 해당 메서드는 repository의revoke_tokens_by_daemon_id를 통해UPDATE auth_tokens SET revoked_at=NOW() WHERE daemon_id=? AND revoked_at IS NULL을 실행한다. - REQ-023: service_tokens CLI에
migrate_null_daemon서브커맨드를 추가한다.--dry-run만 허용하며 실제 변경 없이 inventory + 매핑 후보를 출력한다. - 두 변경 모두 신규 repository 메서드 → service 헬퍼 → CLI 연결 패턴으로 일관된다.
Changed Areas
- Docs:
- 없음 (baseline 문서 갱신은 REQ-019~021/024 별도 배치)
- Modules:
app/repositories/portfolio_repository.py—revoke_tokens_by_daemon_id(daemon_id: str) -> int추상 메서드 (REQ-022);list_service_tokens_with_null_daemon() -> list[AuthToken]추상 메서드 (REQ-023)app/repositories/postgres.py— 두 메서드 구현app/services/auth_service.py—revoke_tokens_for_daemon(daemon_id: str) -> int(REQ-022);list_null_daemon_service_tokens() -> list[AuthToken],find_candidate_daemons_for_user(user_id: str) -> list[Daemon](REQ-023)app/cli/commands/daemon.py—update_daemon--deactivate 분기에 revoke 호출 추가 (REQ-022)app/cli/commands/service_tokens.py—migrate_null_daemon서브커맨드 추가 (REQ-023)
- Tests:
tests/test_daemon_registry.py— REQ-022 AC-1~4 회귀 추가 (_DaemonRepo에revoke_tokens_by_daemon_id추가)tests/test_null_daemon_migration.py— 신규, FakeRepo 기반 REQ-023 AC-1~5
Key Decisions
- REQ-022 CLI 호출 패턴: daemon.py
_with_service는 callback에(repository, app_context)를 전달한다.repo.update_daemon(...)후repo.revoke_tokens_by_daemon_id(daemon_id)를 순차 호출하여 deactivate + revoke를 처리.AuthService.revoke_tokens_for_daemon은 서비스 계층 테스트 목적으로 추가. - REQ-022 --force 옵션 추가:
update_daemon명령에force: bool = typer.Option(False, "--force")추가.--deactivate와 함께 사용 시--force없으면 확인 프롬프트 표시. 자동 revoke는--force여부와 무관하게 항상 실행. - REQ-022 회피 옵션 없음:
--keep-tokens옵션 미노출 (dcy-004 OQ-3 결정 — 정책 일관성). deactivation이면 항상 revoke. - REQ-022 재활성화 시 자동 복구 없음:
--activate분기에서는revoke_tokens_by_daemon_id호출 없음. 이미 revoke된 token은 운영자가 신규 발급해야 함. - REQ-023 dry-run 전용 설계:
--dry-run없이 실행 시typer.Exit(code=1)+ 수동 rebind/revoke 안내 메시지. 자동 변경 코드 없음. - REQ-023 매핑 후보 조회: service_tokens.py
_with_service는 callback에(service, app_context)전달.service.list_null_daemon_service_tokens()와service.find_candidate_daemons_for_user(user_id)를 사용해 출력 구성. - revoke_tokens_by_daemon_id 반환값: revoke된 token 수(
int) 반환 — AC-3(no-op, 0 반환) 검증에 사용.
Edge Cases
- REQ-022: daemon에 바인딩된 token이 0건인 경우 →
revoke_tokens_by_daemon_id0 반환, 정상 종료 (AC-3) - REQ-022:
--activate재활성화 시 token revoke 호출 안 함 (분기 조건:deactivate=True일 때만) - REQ-023: NULL daemon active token이 0건인 경우 → "no NULL daemon tokens" 메시지 + exit 0 (AC-2)
- REQ-023: 매핑 후보 daemon이 0건인 token → dry-run 출력에 별도 경고 표시
Architecture Impact
- none (runtime-flows, project-structure 변경 없음 — REQ-019 배치에서 docs 반영)
Reference Doc Update Plan
- project-structure.md: none (이 배치에서 변경 없음)
- runtime-flows.md: none (이 배치에서 변경 없음)