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
4.0 KiB
4.0 KiB
BAT-010 Design
- Status: confirmed
- Batch: BAT-010
Architecture Summary
daemon identity 모델을 도입해 service-token과 asset에 stable daemon_id를 부여하고, /v1/assets와 /v1/assets/{asset_id}/ledger/trades의 authorization 축을 user-scope에서 daemon-scope로 전환한다. 기존 service-token bearer auth와 permission 모델은 유지하고, daemon assignment는 그 위에 추가되는 두 번째 authorization 축이다. 전환 구간에서는 NULL backfill을 허용하고 fail-closed로 처리한다.
Changed Areas
- Docs:
docs/interface-contract.md— daemon binding, daemon-scoped contract, 403 mismatch policydocs/data-model.md— daemons 테이블, auth_tokens.daemon_id, portfolios.managed_by_daemon_iddocs/runtime-flows.md— daemon registry binding 흐름, rotate invariant, daemon-scoped v1 API 흐름README.md— daemon provisioning runbook, enforcement enablement gate
- Modules:
migrations/versions/— daemons, auth_tokens.daemon_id, portfolios.managed_by_daemon_id migrationapp/domain/models.py— Daemon entity 추가app/repositories/postgres.py— daemon CRUD methodsapp/repositories/portfolio_repository.py— daemon-scoped asset queryapp/services/auth_service.py— daemon binding at issue/rotateapp/api/auth_routes.py(또는 신규 daemon route) — daemon registry management endpointapp/api/v1_assets.py— daemon-scoped GET, daemon assignment auth for ledger writeapp/api/v1_user_info.py— daemon_id 필드 노출app/schemas/v1.py— daemon_id 필드 추가app/cli/commands/service_tokens.py— daemon_id binding at issue, daemon_id invariant at rotate, daemon_id in output
- Interfaces:
- Daemon registry management: HTTP endpoint(
POST /daemons,GET /daemons,PATCH /daemons/{daemon_id}) 또는 CLI subcommand(pfhub daemon create/list/update) — 아래 Key Decisions 참조 POST /auth/service-tokensrequest body:daemon_id필드 추가GET /v1/assetsresponse: daemon-scoped 필터GET /v1/user_inforesponse:daemon_id필드 추가POST /v1/assets/{asset_id}/ledger/trades: daemon assignment 검증 추가
- Daemon registry management: HTTP endpoint(
Key Decisions
- Daemon registry 관리 경로 형태: CLI subcommand(
pfhub daemon create/list/update)를 1차 관리 경로로 채택. 운영자 중심 도구이고, HTTP endpoint로 노출 시 별도 admin-only auth guard 설계가 필요하다. HTTP endpoint는 향후 필요 시 추가한다. - daemon_slug uniqueness: owner user 내에서 unique. DB unique constraint(
daemons.owner_user_id + daemons.daemon_slugcomposite unique)로 강제. - enforcement enablement gate: migration level에서 별도 flag 없이 진행. NULL backfill token/asset에 대한 fail-closed는 코드 레벨에서 처리. production cutover는 inventory + dry-run + release approver 승인 후 수동으로 진행.
- NULL backfill fail-closed boundary:
daemon_id = NULL인 token이 daemon-scoped endpoint(GET /v1/assets,POST /v1/assets/{asset_id}/ledger/trades)를 호출하면 403 Forbidden.GET /v1/user_info는 NULL이어도 200 OK +daemon_id: null진단 노출.
Edge Cases
- 동일 user 아래 daemon이 없는 상태에서 service-token 발급 시: daemon registry에 daemon이 없으면 발급 불가. 운영자가 먼저 daemon create를 수행해야 한다.
- rotate 중 daemon이 삭제된 경우: daemon FK 참조 무결성 위반으로 rotate 거부. 소프트 삭제(is_active flag) 방식으로 daemon을 비활성화하는 것이 안전하다.
- managed_by_daemon_id가 설정된 asset을 다른 daemon으로 재배정: 명시적 reassignment API/CLI 또는 migration-level 절차로만 허용. 자동 재배정 없음.
Architecture Impact
- runtime-flows
Reference Doc Update Plan
- project-structure.md: none (파일 구조 변경 없음)
- runtime-flows.md: 갱신 필요 — daemon registry binding 흐름, daemon-scoped v1 API 처리 흐름, rotate
runtime_id/daemon_id역할 차이 반영 (REQ-011 범위)