Files
portfolio-hub/docs/srs/Interface/req-012_service-token-rotate-cli.md
T
genichin b4d964253b feat(REQ-012): implement service token rotation CLI
- Add service token rotation CLI command with force flag support
- Implement token rotation in auth service with expiration handling
- Add portfolio repository helper for transaction/batch operations
- Add cascade delete support in postgres repository
- Add comprehensive CLI tests for service token operations
- Add REQ-012 specification for service token rotation
- Create BAT-002 delivery batch for token rotation implementation
- Update SRS and batch indexes
2026-05-02 12:43:43 +00:00

4.8 KiB

req-012: service-token rotate CLI 명령 구현

  • Status: Approved
  • Type: Interface
  • Priority: Medium
  • Owner: repository-maintainers

Intent

  • 발급된 service-token의 원문이 노출되었거나 주기적 교체가 필요한 경우, token을 revoke 없이 in-place로 갱신할 수 있는 CLI 명령이 필요하다.
  • 기존 revoke → re-issue 방식은 token_id, user_id, permission, expires_at, created_at 등 메타데이터가 변경되므로, 운영 시스템에서 동일한 이름으로 참조하는 통합 구성을 다시 설정해야 하는 불편이 있다.
  • rotate는 token_hash, token_prefix, runtime_id만 교체하고 나머지 메타데이터를 유지하여, 통합 구성 변경 없이 새 token 원문만 배포할 수 있게 한다.

Requirement

  • pfhub service-token rotate <name> [--force] CLI 명령을 구현한다.
  • rotate는 기존 auth_token 행의 token_hash, token_prefix, runtime_id를 새 값으로 UPDATE한다.
  • id, user_id, name, permission, token_type, expires_at, created_at은 변경하지 않는다.
  • rotate 대상 token이 존재하지 않으면 오류를 반환한다.
  • rotate 대상 token이 이미 revoked 상태이면 오류를 반환한다.
  • rotate 대상 token의 expires_at이 NULL이 아닌 경우(만료일이 설정된 토큰) 오류를 반환한다. rotate는 --no-expiry로 발급된 영구 토큰에만 허용된다.
  • --force 없이 실행하면 확인 프롬프트를 표시한다.
  • rotate 성공 시 새 token 원문을 1회 출력하고, 이후 list/조회에서는 token_prefix만 표시된다.

Acceptance Criteria

  1. Given expires_at IS NULL인 유효한 service-token 이름, When pfhub service-token rotate <name> --force를 실행, Then DB 행의 token_hash, token_prefix, runtime_id가 새 값으로 변경되고 id, permission, expires_at(NULL)은 기존과 동일하다.
  2. Given rotate 성공, When CLI 출력, Then 새 token 원문이 화면에 1회 출력되고 "이 토큰은 지금 1회만 표시" 안내 메시지가 함께 표시된다.
  3. Given 존재하지 않는 token 이름, When rotate, Then 오류 메시지를 출력하고 종료 코드 1을 반환한다.
  4. Given revoked 상태의 token, When rotate, Then 오류 메시지를 출력하고 종료 코드 1을 반환한다.
  5. Given expires_at이 NULL이 아닌(만료일이 설정된) token, When rotate, Then "만료일이 설정된 토큰은 rotate할 수 없습니다" 오류를 출력하고 종료 코드 1을 반환한다.
  6. Given --force 없이 실행, When CLI, Then 확인 프롬프트를 표시하고 거절 시 변경 없이 종료한다.

Impacted Area

  • Docs: docs/project-structure.md (변경 없음), docs/runtime-flows.md (변경 없음)
  • Modules:
    • app/repositories/portfolio_repository.py — rotate_service_token Protocol stub 추가
    • app/repositories/postgres.py — rotate_service_token UPDATE 구현 추가
    • app/services/auth_service.py — rotate_service_token(name) 서비스 메서드 추가
    • app/cli/commands/service_tokens.py — rotate 명령 추가
    • tests/test_cli.py — stub repo에 rotate_service_token 추가 및 테스트 케이스 추가
  • Tests:
    • tests/test_cli.py: rotate 성공, 없는 이름, revoked 상태 3개 케이스

Notes

  • expires_at은 rotate 시 변경하지 않는다. 만료일 변경이 필요하면 revoke + re-issue를 사용한다.
  • rotate는 --no-expiry로 발급된 영구 토큰(expires_at IS NULL)에만 허용된다. 만료일이 설정된 토큰은 rotate 대상이 아니다. 해당 토큰은 만료 후 re-issue하는 것이 권장 패턴이다.
  • DB 스키마 변경(migration)은 없다. 기존 auth_tokens 테이블의 기존 컬럼만 UPDATE한다.
  • 구조/인터페이스/런타임 흐름 변경 없음 → minor-change fast path 적용.

Change Log

CHG-20260502-01

  • Date: 2026-05-02
  • Author: repository-maintainers

Change Summary

  • REQ-012 신규 작성 (minor-change fast path, Approved 직행)
  • rotate 허용 대상을 expires_at IS NULL(no-expiry) 토큰으로 제한

Intent

  • service-token rotate CLI 명령 필요성 확인 후 즉시 구현 진행

Acceptance Criteria Delta

  • Added:
    • 6개 기준 신규 정의 (AC-5: expires_at 설정 토큰 rotate 거부 추가)

Impacted Area Delta

  • Modules:
    • postgres.py, auth_service.py, service_tokens.py, test_cli.py 추가
  • Tests:
    • test_cli.py 3개 케이스 신규

Delivery Trace Delta

  • Batches:
    • BAT-002 (batch-lite)
  • Releases:
    • none (미정)

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: keep-current
  • Follow-up Action: BAT-002 planning → implementation → verification 진행

Validation Plan

  • test_cli.py 3개 케이스 통과 + 기존 service-token 테스트 회귀 없음으로 완료 판단