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>
5.5 KiB
5.5 KiB
REQ-017: service-token rotate unique index 보강
- Status: Approved
- Type: Migration
- Priority: High
- Owner: Justin Ko
Intent
- 현행
idx_auth_tokens_service_name_uniquepartial index가WHERE token_type='service'조건만 적용해 revoked row와 새 row가 같은 name으로 unique 충돌을 일으켜pfhub service-token rotate가 실 DB에서 insert 실패하는 결함을 정상화한다(REL-006 verification 실패 기록). - index 조건에
AND revoked_at IS NULL을 추가해 active service token name만 unique 유지하도록 보강한다.
Requirement
- Alembic migration 신규 작성: 기존
idx_auth_tokens_service_name_unique를 drop하고(name)partial index를WHERE token_type='service' AND revoked_at IS NULL조건으로 재생성한다. - migration은
CREATE INDEX CONCURRENTLY적용으로 운영 lock 영향을 최소화한다(autocommit 외부 트랜잭션 필요 — Alembic op.execute로 직접 SQL 실행). app/repositories/postgres.py:161-167ensure_schema()의idx_auth_tokens_service_name_unique정의도 동일 조건으로 갱신한다.- 기존 active service token 행 데이터에는 변경 없음. 데이터 backfill 불요.
- rotate 동작은 기존 코드(
app/services/auth_service.py:rotate_service_token,app/repositories/postgres.py:1502-1549)를 변경하지 않으며, index 보강만으로 정상 작동해야 한다.
Acceptance Criteria
- Given 신규 Alembic revision 적용 후, When
pfhub service-token issue NAME --user U --no-expiry→pfhub service-token rotate NAME --force시퀀스 실행, Then 두 명령 모두 unique 위반 없이 성공한다(실 DBdocker-compose.local-test.yml환경). - Given AC-1 시퀀스 실행 후, When
SELECT name, token_type, revoked_at FROM auth_tokens WHERE name = '<NAME>', Then revoked row 1건 + active row 1건이 존재한다. - Given AC-1 rotate 결과, When 새 token의
runtime_id와daemon_id를 확인, Then runtime_id는 갱신, daemon_id는 유지(rotate invariant 보존). - Given
ensure_schema()단독 실행, When 새 partial index 조건이 적용, Then 동일 조건(WHERE token_type='service' AND revoked_at IS NULL)이 PostgreSQL에 반영된다. - Given migration이 운영 환경에서 적용, When CREATE INDEX CONCURRENTLY가 실행, Then auth_tokens write 작업이 long-running lock 없이 진행된다(staging 환경 사전 검증).
Impacted Area
- Docs:
docs/data-model.md— auth_tokens 인덱스 변경 반영 (REQ-019에서 처리)
- Modules:
migrations/versions/— 신규 Alembic revision (예:20260520_NNNN_service_token_unique_index_fix.py).op.execute("DROP INDEX IF EXISTS ...")+op.execute("CREATE UNIQUE INDEX CONCURRENTLY ... WHERE token_type='service' AND revoked_at IS NULL")패턴app/repositories/postgres.py:161-167—ensure_schema()의 idx 정의 조건 갱신
- Tests:
- 신규
tests/test_service_token_rotate_integration.py(실 DB 의존 마킹) — AC-1~3 검증 - 기존
tests/test_daemon_registry.py::test_rotate_*— 신규 index 조건에서 통과 확인
- 신규
Notes
- 이 결함은 REL-006 verification에 "rotate insert 막힘" 검증 실패로 이미 기록됨(temp/20260519_old_sdlc/releases/rel-006_20260513_daemon-model-implementation.md:74).
- CREATE INDEX CONCURRENTLY는 transactional block 밖에서 실행 필요. Alembic revision에서
autocommit_block을 사용하거나op.execute()로 직접 SQL 실행해야 한다. - 기존 운영 환경에 revoked service token이 있다면 새 partial index 생성 시점에 자동 적용되며, 별도 데이터 정리 불요.
- Source: dcy-004 FR-2, dcy-004 NFR-2/NFR-3/NFR-6, dcy-004 OQ-2 결정(partial 조건 추가).
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-2 (rotate unique index 보강) 산출물.
Intent
- rotate 실 DB 실패 결함 해소 + R-2(migration lock) 완화 적용.
Acceptance Criteria Delta
- Added:
- AC-1~5 최초 작성
Impacted Area Delta
- Docs: docs/data-model.md (REQ-019에서 처리)
- Modules: migrations/versions/, app/repositories/postgres.py — 최초 지정
- Tests: tests/test_service_token_rotate_integration.py (신규), tests/test_daemon_registry.py — 최초 지정
Delivery Trace Delta
- Batches: none (미정)
- Releases: none (미정)
Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 batch 계획 편입; staging 환경에서 CONCURRENTLY migration dry-run으로 lock 시간 측정
Validation Plan
- 실 DB(
docker-compose.local-test.yml) 환경에서 AC-1~3 시퀀스 검증; staging 환경에서 AC-5 lock 측정