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
212 lines
10 KiB
Markdown
212 lines
10 KiB
Markdown
# 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
|
|
|
|
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), `daemon_id`는 기존과 동일하다.
|
|
2. Given rotate 성공, When CLI 출력, Then 새 token 원문이 화면에 1회 출력되고 "이 토큰은 지금 1회만 표시" 안내 메시지와 함께 `daemon_id` 메타데이터가 표시되어야 한다.
|
|
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` 명령 및 `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_id` metadata 추가
|
|
- 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` 유지/출력 기준으로 재검증 필요
|
|
- 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_id` lifecycle 명시 추가 — 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 테스트 회귀 없음으로 완료 판단
|