# REQ-023: NULL daemon_id legacy token 마이그레이션 CLI - Status: Implemented - Type: Interface - Priority: Medium - Owner: Justin Ko ## Intent - `daemon_id IS NULL`인 active service token이 운영 환경에 존재하면 v1 API daemon-scoped endpoints가 fail-closed로 작동해 운영 정리가 필요하다. 자동 매핑은 권한 escalation 리스크로 채택하지 않고(dcy-004 OQ-7), 운영자 수동 매핑을 보조하는 진단 CLI를 제공한다. - dry-run으로 inventory + 매핑 후보를 진단 출력하고, 운영자가 token별 `rebind` 또는 `revoke`를 명시적으로 실행하는 패턴을 표준화한다. ## Requirement - 신규 CLI 서브커맨드 `pfhub service-token migrate-null-daemon` 추가: - `--dry-run` 옵션: NULL daemon active service token inventory를 출력. 각 token에 대해 `id`, `user_id`, `name`, `runtime_id`, `created_at`, 매핑 후보 daemon(같은 `owner_user_id == user_id`인 active daemon 목록)을 표 또는 JSON 형식으로 보고. - 매핑 후보 검증: `token.user_id == daemon.owner_user_id` 일치 여부를 명시 표시. 불일치 가능성이 있는 token은 별도 경고 표시. - `--dry-run` 없이 실행하면 안전상 명시적 거부(예: "use --dry-run for inspection, then `pfhub service-token rebind` or `revoke` per token") 또는 no-op. - 본 CLI는 자동 rebind/revoke를 수행하지 않는다. 실제 적용은 운영자가 token별로 `pfhub service-token rebind NAME --daemon-id ID` 또는 `pfhub service-token revoke NAME`을 명시 실행해야 한다. - 본 CLI는 idempotent하다(재실행 안전, NULL token이 0건이어도 정상 종료). - DATA-2 inventory(2026-05-20)에서 발견된 admin 테스트 fixture 1건은 본 batch release 시점에 운영자가 직접 `pfhub service-token revoke admin` 수동 실행으로 정리(release plan에 명시). ## Acceptance Criteria 1. Given `pfhub service-token migrate-null-daemon --dry-run` 실행, When NULL daemon active service token 1건 이상 존재, Then 각 token의 `id`, `user_id`, `name`, `runtime_id`, `created_at`, 매핑 후보 daemon 목록, user_id 일치 여부가 출력된다. 2. Given `pfhub service-token migrate-null-daemon --dry-run` 실행, When NULL daemon 활성 service token이 0건, Then "no NULL daemon tokens" 메시지 출력 후 exit code 0으로 정상 종료. 3. Given `pfhub service-token migrate-null-daemon` (--dry-run 없이) 실행, When 호출, Then 자동 변경을 거부하고(예: error message + non-zero exit) 운영자에게 `rebind`/`revoke` 수동 실행을 안내한다. 4. Given AC-1 출력 후 운영자가 `pfhub service-token rebind NAME --daemon-id ID` 실행, When 매핑이 성공적으로 적용, Then 해당 token의 `daemon_id`가 갱신되고 다시 `--dry-run` 실행 시 해당 token이 inventory에서 제외된다. 5. Given AC-1 실행 후 운영자가 `pfhub service-token revoke admin` 실행, When DATA-2 admin 테스트 fixture가 revoke, Then 다시 `--dry-run` 실행 시 해당 token이 inventory에서 제외된다. ## Impacted Area - Docs: - `docs/interface-contract.md` — `pfhub service-token migrate-null-daemon` CLI 명세 추가 (REQ-019 baseline 작업) - Modules: - `app/cli/commands/service_tokens.py` — `migrate_null_daemon` 함수 신규 추가 (Typer 서브커맨드 등록) - `app/services/auth_service.py` — `list_null_daemon_service_tokens()` 및 `find_candidate_daemons_for_user(user_id)` 헬퍼 추가(또는 직접 repository 조회) - `app/repositories/portfolio_repository.py`, `app/repositories/postgres.py` — `list_service_tokens_with_null_daemon()` 메서드 신규 추가 - Tests: - 신규 `tests/test_null_daemon_migration.py` — AC-1~5 시나리오. dry-run 출력 검증 + idempotency 회귀 + non-dry-run 거부 동작 검증 ## Notes - dcy-004 OQ-7 결정으로 자동 매핑/auto-create daemon은 채택하지 않음(권한 escalation 리스크). 본 CLI는 진단 도구로만 작동. - DATA-2 inventory 1건(admin 테스트 fixture)은 본 batch release 시점에 운영자가 직접 처리. CLI 진단 + 운영자 수동 적용이라는 본 REQ 패턴의 첫 번째 적용 사례. - 매핑 후보가 0건(같은 user_id의 active daemon 없음)인 token은 dry-run 출력에 별도 표시해 운영자가 daemon 신규 생성 후 rebind를 진행하거나 token revoke를 결정하도록 안내. - 본 CLI는 batch 시점 1회 정리 + 향후 NULL daemon token이 발생할 때마다 사용 가능한 영구 운영 도구로 작동한다. - Source: dcy-004 FR-8, dcy-004 NFR-5, dcy-004 OQ-7 결정. ## Change Log ### CHG-20260520-02 - Date: 2026-05-20 - Author: Justin Ko #### Change Summary - Status: Proposed → Approved #### Intent - 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료, blocker 없음 #### Acceptance Criteria Delta - No change #### Impacted Area Delta - No change #### Delivery Trace Delta - Batches: none (미정) - Releases: none (미정) #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: promote-to-approved - Follow-up Action: batch 계획 편입 ### CHG-20260520-01 - Date: 2026-05-20 - Author: Justin Ko #### Change Summary - 최초 생성 — dcy-004 confirm-discovery 후 draft-req 실행. dcy-004 FR-8 산출물. #### Intent - NULL daemon legacy token 마이그레이션을 운영자 수동 매핑 패턴으로 표준화 + 진단 CLI 제공. #### Acceptance Criteria Delta - Added: - AC-1~5 최초 작성 #### Impacted Area Delta - Docs: docs/interface-contract.md (REQ-019에서 처리) - Modules: app/cli/commands/service_tokens.py, app/services/auth_service.py, app/repositories/portfolio_repository.py, app/repositories/postgres.py — 최초 지정 - Tests: tests/test_null_daemon_migration.py — 최초 지정 #### Delivery Trace Delta - Batches: none (미정) - Releases: none (미정). DATA-2 정리(admin 테스트 fixture revoke)는 release plan에 명시. #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: keep-current - Follow-up Action: confirm-req 후 batch 계획 편입 #### Validation Plan - pytest로 AC-1~5 검증; CLI smoke + idempotency 회귀 + non-dry-run 거부 동작