Core Implementation (BAT-010):
- Add daemon registry schema and CRUD operations (req-023)
- Implement single-daemon asset assignment constraint (one asset per daemon)
- Add daemon_id field to service_token for daemon identification
- Add daemon.py CLI module for daemon management commands
- Add 20260513_0016_daemon_model.py migration for daemon tables
API Changes:
- GET /v1/assets: include daemon_id in AssetResponse
- POST /v1/assets/{asset_id}/ledger/trades: require daemon token binding
- GET /v1/user_info: include daemon metadata
- Enhanced service-token rotate to preserve daemon bindings
CLI Commands:
- pfhub daemon register --name <name> --runtime-id <runtime-id>
- pfhub daemon list
- pfhub daemon get <daemon-id>
- pfhub daemon revoke <daemon-id>
Requirements (REQ-023, REQ-028):
- REQ-023: Daemon Registry and Service Token Daemon Binding (Interface, Approved)
* AC-1: daemon CRUD operations
* AC-2: service token daemon binding for POST /v1/assets/{asset_id}/ledger/trades
* AC-3: single daemon per asset (exact-one assignment model)
- REQ-028: README.md Daemon Provisioning Runbook update (Documentation, Approved)
Documentation:
- Add dcy-006 Discovery for daemon-id and single-daemon asset assignment
- Update README.md with Daemon Provisioning Runbook section
- Add BAT-010 batch documentation with planning, implementation, verification
- Update rel-006 release document (daemon model implementation)
- Update data-model.md with daemon and daemon_asset_assignment tables
- Update interface-contract.md with daemon registry APIs
- Update runtime-flows.md with daemon lifecycle flows
Breaking Changes:
- REQ-005~009, REQ-011~012 status reverted to Approved due to revised contract
* daemon_id field addition and exact-one asset assignment requirement
* Existing Implemented evidence invalidated by contract revision
* BAT-001/002/008 re-verification required
Testing:
- Add test_daemon_registry.py for daemon CRUD operations
- Add test_daemon_assignment.py for single-asset assignment constraints
- Update test_auth.py, test_cli.py, test_v1.py for daemon support
- Verify daemon token binding in trade endpoint authorization
Impact:
- Database: 2 new tables (daemons, daemon_asset_assignments)
- Migration: 20260513_0016 creates daemon model schema
- CLI: 4 new daemon subcommands
- API: daemon_id propagation through v1 endpoints
- Verification: BAT-001/002/008 re-verification gates next release
10 KiB
10 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만 교체하고daemon_id를 포함한 나머지 메타데이터를 유지하여, 동일한 token 이름과 daemon binding을 유지한 채 새 token 원문만 배포할 수 있게 한다. 단,runtime_id를 소비하는 시스템은 rotate 후 새 토큰 기준으로 runtime_id를 재조회해야 한다.
Requirement
pfhub service-token rotate <name> [--force]CLI 명령을 구현한다.- rotate는 기존 auth_token 행의
token_hash,token_prefix,runtime_id를 새 값으로 UPDATE하고,daemon_id는 유지해야 한다. id,user_id,name,permission,token_type,expires_at,created_at,daemon_id는 변경하지 않는다.- rotate 대상 token이 존재하지 않으면 오류를 반환한다.
- rotate 대상 token이 이미 revoked 상태이면 오류를 반환한다.
- rotate 대상 token의
expires_at이 NULL이 아닌 경우(만료일이 설정된 토큰) 오류를 반환한다. rotate는--no-expiry로 발급된 영구 토큰에만 허용된다. --force없이 실행하면 확인 프롬프트를 표시한다.- rotate 성공 시 새 token 원문을 1회 출력하고, 이후 list/조회에서는 token_prefix만 표시된다. rotate 출력 메타데이터에는
daemon_id가 포함되어야 한다.
Acceptance Criteria
- Given
expires_at IS NULL인 유효한 service-token 이름, Whenpfhub service-token rotate <name> --force를 실행, Then DB 행의token_hash,token_prefix,runtime_id가 새 값으로 변경되고id,permission,expires_at(NULL),daemon_id는 기존과 동일하다. - Given rotate 성공, When CLI 출력, Then 새 token 원문이 화면에 1회 출력되고 "이 토큰은 지금 1회만 표시" 안내 메시지와 함께
daemon_id메타데이터가 표시되어야 한다. - Given 존재하지 않는 token 이름, When
rotate, Then 오류 메시지를 출력하고 종료 코드 1을 반환한다. - Given revoked 상태의 token, When
rotate, Then 오류 메시지를 출력하고 종료 코드 1을 반환한다. - Given
expires_at이 NULL이 아닌(만료일이 설정된) token, Whenrotate, Then "만료일이 설정된 토큰은 rotate할 수 없습니다" 오류를 출력하고 종료 코드 1을 반환한다. - Given
--force없이 실행, When CLI, Then 확인 프롬프트를 표시하고 거절 시 변경 없이 종료한다.
Impacted Area
- Docs: docs/project-structure.md (변경 없음), docs/runtime-flows.md (변경 없음)
- Modules:
app/repositories/portfolio_repository.py—rotate_service_tokenProtocol stub 추가app/repositories/postgres.py—rotate_service_tokenUPDATE 구현 추가app/services/auth_service.py—rotate_service_token(name)서비스 메서드 추가app/cli/commands/service_tokens.py—rotate명령 및daemon_id출력 추가tests/test_cli.py— stub repo에rotate_service_token추가 및 테스트 케이스 추가
- Tests:
tests/test_cli.py: rotate 성공, 없는 이름, revoked 상태,daemon_id유지/출력 케이스
Notes
expires_at은 rotate 시 변경하지 않는다. 만료일 변경이 필요하면 revoke + re-issue를 사용한다.- rotate는
--no-expiry로 발급된 영구 토큰(expires_at IS NULL)에만 허용된다. 만료일이 설정된 토큰은 rotate 대상이 아니다. 해당 토큰은 만료 후 re-issue하는 것이 권장 패턴이다. - rotate는
runtime_id도 새 값으로 갱신하지만daemon_id는 유지한다. trex-basic 등runtime_id를 소비하는 시스템은 rotate 후 새 토큰으로 다시 인증하고GET /v1/user_info를 재호출해 새runtime_id를 재인식해야 한다. - 기존
runtime_id를 캐싱한 상태로 계속 사용하면 consumer 식별 불일치가 발생할 수 있다. rotate는 "토큰 원문 교체 시 token name과 메타데이터를 유지한다"는 의미이지,runtime_id까지 불변이라는 뜻은 아니다. - rotate는 daemon provisioning 경로가 아니며, unknown daemon 자동 생성/업서트를 수행하면 안 된다.
- DB 스키마 변경(migration)은 없다. 기존
auth_tokens테이블의 기존 컬럼만 UPDATE한다. - 구조/인터페이스/런타임 흐름 변경 없음 → minor-change fast path 적용.
Change Log
CHG-20260513-01
- Date: 2026-05-13
- Author: repository-maintainers
Change Summary
- rotate REQ에
daemon_id불변식과 CLI diagnostic 출력 요구를 추가하고, 기존 Implemented 상태를 Approved로 되돌림
Intent
- dcy-006은 rotate 이후에도
daemon_id가 stable identity로 유지되어야 하고, 운영자는 rotate 출력과 provenance 절차에서daemon_id를 확인할 수 있어야 한다. BAT-002/REL-002 구현은 runtime_id lifecycle만 다루므로 revised REQ를 충족하지 못한다.
Acceptance Criteria Delta
- Added:
- none
- Updated:
- AC-1:
daemon_id유지 불변식 추가 - AC-2: CLI output에
daemon_idmetadata 추가
- AC-1:
- Removed:
- none
Impacted Area Delta
- Docs:
README.md, token provenance 문서,docs/runtime-flows.md
- Modules:
app/cli/commands/service_tokens.py,app/services/auth_service.py,app/repositories/postgres.py
- Tests:
tests/test_cli.py, 필요한 경우 auth/v1 provenance 회귀 테스트
Delivery Trace Delta
- Batches:
- BAT-002 (release-candidate; REL-002 released input) — rotate verification evidence는
daemon_id유지/출력 기준으로 재검증 필요
- BAT-002 (release-candidate; REL-002 released input) — rotate verification evidence는
- Releases:
- REL-002 (released) — rotate 운영 메모는 runtime_id 재조회만 다루며 daemon-aware provenance는 미반영
Revalidation Impact
- Reverification Needed: yes
- Existing Implementation Invalidated: yes
- Status Recommendation: rollback-to-approved
- Follow-up Action: dcy-006 후속 batch에서 rotate response metadata와 daemon binding invariants를 구현하고, REL-002 후속 tooling release evidence를 갱신한다.
Validation Plan
- current CLI/service/repository 구현이
daemon_id를 보존·출력하지 않는지 코드 리뷰로 확인한다. - 구현 후 rotate 전후
daemon_id불변,runtime_id갱신, CLI output metadata를 targeted CLI 테스트로 검증한다.
CHG-20260511-02
- Date: 2026-05-11
- Author: repository-maintainers
Change Summary
- Implemented 전환 — BAT-002 verification passed, confirm-req-implemented 게이트 통과
Intent
- BAT-002 verification.md에서 REQ-012 AC-1~6이 모두 PASS이고 blocking issue가 없음을 근거로 Implemented로 승격한다.
Acceptance Criteria Delta
- Added: none
- Updated: none
- Removed: none
Impacted Area Delta
- Docs: none
- Modules: none
- Tests: none
Delivery Trace Delta
- Batches:
- BAT-002 (release-candidate)
- Releases:
- none
Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: implemented
- Follow-up Action: tooling release에 포함 시 rotate 후 runtime_id 재조회 운영 메모 반영
Validation Plan
- BAT-002 verification.md의 REQ-012 AC-1~6 evidence와 Ready for Release: true 확인
CHG-20260511-01
- Date: 2026-05-11
- Author: repository-maintainers
Change Summary
- rotate 후
runtime_idlifecycle 명시 추가 — downstream consumer는 새 토큰 배포 후runtime_id를 재조회해야 함
Intent
- CONFLICT-3 분석 결과를 반영해
runtime_id가 rotate 시 변경된다는 사실과, trex-basic 같은 consumer가 이를 어떻게 재인식해야 하는지 REQ-012 문서에 명시한다.
Acceptance Criteria Delta
- Added:
- none
- Updated:
- none
- Removed:
- none
Impacted Area Delta
- Docs:
docs/srs/Interface/req-012_service-token-rotate-cli.md: Intent/Notes에 rotate 후runtime_id재조회 lifecycle 추가
- Modules:
- none
- Tests:
- none
Delivery Trace Delta
- Batches:
- BAT-002 (release-candidate) — verification evidence는 유지 가능하나, rotate 후 consumer 재인식 절차를 운영 메모로 함께 검토해야 한다.
- Releases:
- none
Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: trex-basic 연동 runbook 또는 후속 REQ에서 rotate 후
runtime_id재조회 절차를 운영 문서에 반영 검토
Validation Plan
- REQ-005, REQ-007, REQ-012 문구를 대조해 rotate 시
runtime_id변경과GET /v1/user_info재조회 필요성이 일관되게 설명되는지 코드 리뷰로 확인
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 테스트 회귀 없음으로 완료 판단