# REQ-023: Daemon Registry 관리 경로 - Status: Approved - Type: Interface - Priority: High - Owner: repository-maintainers ## Intent - service-token issue/rotate가 기존 daemon에만 binding할 수 있으려면, daemon을 사전에 생성·수정할 수 있는 별도 관리 경로(daemon registry CRUD)가 필요하다. - daemon provisioning은 service-token issuance와 분리된 경로에서 수행되어야 하며, REQ-005(issuance binding)와 REQ-012(rotate daemon_id 유지)의 전제 조건이 된다. ## Requirement - 시스템은 daemon을 생성·수정할 수 있는 별도 관리 경로를 제공해야 한다. - daemon은 owner user 내에서 unique한 `daemon_slug`(lowercase kebab-case)와 `daemon_display_name`(non-empty human-readable label)을 가진다. - 동일 owner user 내에서 중복 `daemon_slug`로 생성 시 명시적으로 거부한다. - daemon list 조회는 owner user 범위로 제한된다. ## Acceptance Criteria 1. Given admin context에서 유효한 `daemon_slug`와 `daemon_display_name`으로 daemon create를 호출할 때, Then 새 daemon entry가 registry에 생성되고 `daemon_id`가 반환된다. 2. Given 기존 daemon에 대해 `daemon_display_name` 수정을 요청할 때, Then daemon entry가 갱신된다. 3. Given 동일 owner user 내에 이미 존재하는 `daemon_slug`로 daemon create를 요청할 때, Then 명시적 오류로 거부되고 중복 entry가 생성되지 않는다. 4. Given daemon list 조회를 요청할 때, Then 인증된 user 소유의 daemon만 반환된다. 5. Given `pfhub portfolio update --user --daemon-id `를 실행할 때, Then 해당 portfolio의 `managed_by_daemon_id`가 지정한 daemon_id로 갱신된다. 6. Given `pfhub portfolio list --user `을 실행할 때, Then `managed_by_daemon_id`가 설정된 portfolio에는 해당 daemon_id가 출력에 포함되고, 미설정 portfolio에는 해당 항목이 출력되지 않는다. ## Impacted Area - Docs: `docs/interface-contract.md`, `docs/runtime-flows.md` - Modules: `app/domain/models.py`, `app/repositories/postgres.py`, `app/api/auth_routes.py` 또는 별도 daemon management route, `app/cli/commands/` (daemon subcommand 신규) - Modules (AC-5~6 추가): `app/cli/commands/portfolio.py` (`update` 명령 `--daemon-id` 옵션), `app/schemas/portfolio.py` (`UpdatePortfolioRequest.managed_by_daemon_id`, `PortfolioSummary.managed_by_daemon_id`), `app/services/portfolio_service.py` (`_to_portfolio_summary` 필드 전달), `app/cli/core/utils.py` (`print_portfolio_list` daemon 표시) - Tests: 신규 `tests/test_daemon_registry.py` ## Notes - service-token issuance의 unknown daemon 거부(REQ-005 AC-6), rotate daemon_id 유지 불변식(REQ-012 CHG-20260513-01)은 이 REQ의 daemon registry가 사전 구축된 상태를 전제한다. - daemon registry CRUD의 구체적인 transport 형태(HTTP endpoint vs CLI subcommand)는 구현 시 결정한다. - canonical 운영 표기: `/` ## Change Log ### CHG-20260518-01 - Date: 2026-05-18 - Author: repository-maintainers #### Change Summary - AC-5(`portfolio update --daemon-id`), AC-6(`portfolio list` daemon-id 표시) 추가 및 Impacted Area 보강. 구현 완료. Status Approved 유지. #### Intent - daemon provisioning runbook에서 "asset → daemon 배정" 단계가 CLI로 수행 가능해야 한다. 기존 AC-1~4는 daemon registry CRUD만 다루며 portfolio-daemon 배정 경로가 누락되어 있었다. 운영팀 요청(2026-05-18)에 따라 `portfolio update --daemon-id` CLI 옵션과 `portfolio list` 결과의 daemon-id 표시를 REQ 범위에 추가한다. #### Acceptance Criteria Delta - Added: - AC-5: `pfhub portfolio update --user --daemon-id `로 `managed_by_daemon_id` 갱신 - AC-6: `pfhub portfolio list --user ` 결과에 `managed_by_daemon_id` 조건부 표시 - Updated: 없음 - Removed: 없음 #### Impacted Area Delta - Modules: - `app/cli/commands/portfolio.py`: `update` 명령에 `--daemon-id` 옵션 추가 - `app/schemas/portfolio.py`: `UpdatePortfolioRequest.managed_by_daemon_id`, `PortfolioSummary.managed_by_daemon_id` 필드 추가 - `app/services/portfolio_service.py`: `_to_portfolio_summary`에 `managed_by_daemon_id` 전달 추가 - `app/repositories/postgres.py`: `update_portfolio` allowed dict에 `managed_by_daemon_id` 추가 - `app/cli/core/utils.py`: `print_portfolio_list`에 daemon 줄 조건부 출력 추가 #### Delivery Trace Delta - Batches: BAT-010 (release-candidate) — AC-5~6 구현이 BAT-010 delivery scope에 포함 - Releases: REL-006 (draft) #### Revalidation Impact - Reverification Needed: yes (AC-5~6 신규이므로 검증 증거 추가 필요) - Existing Implementation Invalidated: no (AC-1~4 기존 구현 유효) - Status Recommendation: keep-current (Approved) - Follow-up Action: BAT-010 verification.md에 AC-5~6 검증 증거 추가 후 Implemented 전환 가능 #### Validation Plan - `pfhub portfolio update --user --daemon-id --force` 실행 후 DB `portfolios.managed_by_daemon_id` 값 확인 - `pfhub portfolio list --user ` 출력에서 daemon-id 유무 항목별 표시 확인 ### CHG-20260513-02 - Date: 2026-05-13 - Author: repository-maintainers #### Change Summary - Status: Proposed → Approved (confirm-req 게이트 통과) #### Intent - 필수 필드, AC, blocker 없음 확인 후 승인 전환 #### Acceptance Criteria Delta - Added: 없음 - Updated: 없음 - Removed: 없음 #### Impacted Area Delta - Docs: 없음 - Modules: 없음 - Tests: 없음 #### Delivery Trace Delta - Batches: 미정 - Releases: 미정 #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: keep-current - Follow-up Action: 없음 #### Validation Plan - 없음 (상태 전환만) ### CHG-20260513-01 - Date: 2026-05-13 - Author: repository-maintainers #### Change Summary - dcy-006 FR-1의 daemon provisioning 관리 경로 부분만 추출해 신규 생성 (issuance binding·rotate invariant·fail-closed는 REQ-005/012/006/008에 이미 반영) #### Intent - service-token issuance(REQ-005)와 rotate(REQ-012)의 전제가 되는 daemon registry CRUD 경로를 별도 REQ로 정의 #### Acceptance Criteria Delta - Added: - AC-1~4 전체 신규 추가 - Updated: 없음 - Removed: 없음 #### Impacted Area Delta - Docs: `docs/interface-contract.md`, `docs/runtime-flows.md` - Modules: daemon registry route, CLI subcommand - Tests: `tests/test_daemon_registry.py` #### Delivery Trace Delta - Batches: 미정 - Releases: 미정 #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: keep-current - Follow-up Action: 없음 (신규 REQ) #### Validation Plan - pytest로 daemon create/duplicate reject/update/list 시나리오 통과 확인