Files
portfolio-hub/docs/srs/Migration/req-017_service-token-rotate-unique-index-fix.md
T
genichinandClaude Sonnet 4.6 6add0ade29 feat: REQ-001~018 Implemented 전환, REQ-010 GET /v1/assets admin catalog 재정의, REL-001 draft
- confirm-req-implemented: REQ-001~018 (17건, REQ-013 제외) Approved → Implemented
  - BAT-001(REQ-009/011/014), BAT-002(REQ-010/012/015), BAT-003(REQ-001/002/003/006)
  - BAT-004(REQ-004/005), BAT-005(REQ-007/008), BAT-006(REQ-016/017/018)
  - CHG-20260521-01 entry 각 REQ에 추가; SRS index Recent Change Log 갱신

- REQ-010 CHG-20260521-02: GET /v1/assets admin catalog 전용 재정의
  - 기존 token_type 분기 portfolio 조회 코드 제거, admin permission + list_assets() 호출로 대체
  - AssetCatalogListResponse 스키마 추가 (items/total)
  - REQ-010 Status: Implemented → Approved (재검증 필요)
  - 테스트 343건 전체 통과: service/user token 403, admin token 200 + catalog schema 검증

- migration 보강: portfolios_asset_migration market 컬럼 부재 fallback,
  portfolio_tags 빈 테이블 early-return, service_token index fix autocommit_block 정리

- docs/releases/rel-001: REL-001 draft 추가 (BAT-001~011 포함)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 10:17:39 +00:00

6.3 KiB

REQ-017: service-token rotate unique index 보강

  • Status: Implemented
  • Type: Migration
  • Priority: High
  • Owner: Justin Ko

Intent

  • 현행 idx_auth_tokens_service_name_unique partial 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-167 ensure_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

  1. Given 신규 Alembic revision 적용 후, When pfhub service-token issue NAME --user U --no-expiry → pfhub service-token rotate NAME --force 시퀀스 실행, Then 두 명령 모두 unique 위반 없이 성공한다(실 DB docker-compose.local-test.yml 환경).
  2. Given AC-1 시퀀스 실행 후, When SELECT name, token_type, revoked_at FROM auth_tokens WHERE name = '<NAME>', Then revoked row 1건 + active row 1건이 존재한다.
  3. Given AC-1 rotate 결과, When 새 token의 runtime_id와 daemon_id를 확인, Then runtime_id는 갱신, daemon_id는 유지(rotate invariant 보존).
  4. Given ensure_schema() 단독 실행, When 새 partial index 조건이 적용, Then 동일 조건(WHERE token_type='service' AND revoked_at IS NULL)이 PostgreSQL에 반영된다.
  5. 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-20260521-01

  • Date: 2026-05-21
  • Author: Justin Ko

Change Summary

  • Status: Approved → Implemented

Intent

  • BAT-006 confirm-batch-verification 완료. idx_auth_tokens_service_name_unique partial index 조건 AND revoked_at IS NULL 보강 Alembic revision + ensure_schema() 갱신 구현. AC-1~3/5(실 DB issue/rotate 시퀀스 및 staging lock 검증)는 실 DB 의존 — release 배포 시 최종 확인 예정.

Acceptance Criteria Delta

  • No change

Impacted Area Delta

  • No change

Delivery Trace Delta

  • Batches:
    • BAT-006
  • Releases:
    • REL-001

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: implemented
  • Follow-up Action: REL-001 배포 시 실 DB에서 issue → rotate 시퀀스로 AC-1~3 최종 확인

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 측정