Files
portfolio-hub/docs/srs/Interface/req-053_admin-daemon-crud-api.md
T
genichinandClaude Opus 4.8 9fe6f3b511 docs(req-053): GET /v1/admin/daemons 목록 엔드포인트 핫픽스 거버넌스 백필
핫픽스 2dcbafb(목록 조회 405 갭 해소)를 REQ-053에 change-req로 기록.
스코프 갭(GET-list AC 누락) 정정 + AC-13/14 추가, 라이브 통합검증 근거 기재.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
2026-06-28 19:16:20 +09:00

12 KiB

REQ-053: admin 데몬 CRUD HTTP API

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

Intent

  • 현재 Daemon 엔티티는 GET /v1/daemons(read 전용, REQ-045)만 HTTP로 노출되며, 생성·변경·(비)활성화 HTTP API가 없다. 관리자(admin)가 HTTP API로 데몬을 provisioning하고 owner를 할당·변경·(비)활성화할 수 있어야 한다.
  • trex-web dcy-009 admin UI가 소비하는 백엔드 경로를 신설한다.
  • 데몬은 운영 런타임 식별자(service-token daemon_id 바인딩, KIS 계좌 연결)로 하드 삭제는 제공하지 않으며 비활성화로 대체한다(dcy-011 FR-4 결정). owner 재할당은 허용하되 owner 변경 시 해당 데몬의 기존 인증정보를 자동 무효화한다(이전 owner의 KIS 계좌 이관 금지, dcy-011 OQ-3 결정).

Requirement

  • 시스템은 admin role로 인증된 요청자가 데몬을 생성하고 owner_user_id를 할당할 수 있는 POST 엔드포인트를 제공해야 한다.
    • 입력: daemon_slug(고유 식별자), display_name(선택), owner_user_id.
    • 성공 시 생성된 Daemon의 id, daemon_slug, display_name, owner_user_id, is_active 반환.
  • 시스템은 admin이 기존 데몬의 display_name 또는 owner_user_id를 변경할 수 있는 PATCH 엔드포인트를 제공해야 한다.
    • owner 변경 시 해당 데몬의 기존 BrokerCredential 전체를 자동 삭제(무효화) 해야 한다 — 이전 owner의 KIS 계좌 정보가 새 owner에게 이관되는 것을 방지한다.
  • 시스템은 admin이 데몬을 비활성화(is_active=false) 및 재활성화(is_active=true)할 수 있는 엔드포인트를 제공해야 한다.
    • 비활성화 시 해당 데몬에 바인딩된 service token을 자동 revoke해야 한다(기존 REQ-022 정책 재사용).
  • 하드 삭제(DELETE) 엔드포인트는 제공하지 않는다. 비활성화가 유일한 종료 경로이다.
  • admin role이 아닌 요청(user-token, service-token 포함)은 HTTP 403 Forbidden을 반환해야 한다.
  • 엔드포인트 경로·HTTP 메서드의 구체 형태는 draft-batch-design에서 v1 admin 컨벤션(dcy-011 OQ-2 Deferred, dcy-006 admin 경로 참고)에 맞춰 확정한다.

Acceptance Criteria

  1. Given admin 토큰으로 daemon_slug, display_name, owner_user_id를 포함한 생성 요청, When POST 엔드포인트를 호출, Then HTTP 201 + 생성된 Daemon(id, daemon_slug, display_name, owner_user_id, is_active=true) 반환.
  2. Given admin 토큰으로 중복 daemon_slug로 생성 요청, When POST 엔드포인트를 호출, Then HTTP 409(또는 422) Conflict 반환(중복 슬러그 거부).
  3. Given admin 토큰으로 존재하는 daemon D의 display_name 변경 요청(owner 변경 없음), When PATCH 엔드포인트를 호출, Then HTTP 200 + 갱신된 Daemon 반환. 기존 BrokerCredential은 유지된다.
  4. Given admin 토큰으로 daemon D의 owner_user_id를 사용자 B로 재할당 요청(원래 소유자 A), When PATCH 엔드포인트를 호출, Then HTTP 200 + 갱신된 Daemon 반환 + 해당 daemon D의 BrokerCredential이 모두 삭제(무효화)된다.
  5. Given daemon D의 owner가 변경된 직후, When 변경 전 소유자 A의 service-token으로 /v1/user_info를 호출, Then broker: null 반환(이전 owner 인증정보 이관 차단).
  6. Given admin 토큰으로 활성 daemon D 비활성화 요청, When 비활성화 엔드포인트를 호출, Then HTTP 200 + is_active: false 반환 + daemon D에 바인딩된 service token 자동 revoke(REQ-022 정책).
  7. Given admin 토큰으로 비활성 daemon D 재활성화 요청, When 재활성화 엔드포인트를 호출, Then HTTP 200 + is_active: true 반환.
  8. Given admin 토큰으로 daemon D에 DELETE 요청(하드 삭제), When 호출, Then HTTP 405 Method Not Allowed(또는 404) 반환 — 하드 삭제 엔드포인트 미제공.
  9. Given user-token(admin role 없음)으로 데몬 생성·변경·비활성화 엔드포인트 호출, When 호출, Then HTTP 403 Forbidden 반환.
  10. Given service-token으로 데몬 CRUD 엔드포인트 호출, When 호출, Then HTTP 403 Forbidden 반환.
  11. Given 인증 토큰 없는 요청으로 데몬 CRUD 엔드포인트 호출, When 호출, Then HTTP 401 반환.
  12. Given admin 토큰으로 존재하지 않는 daemon_id에 PATCH/비활성화 요청, When 호출, Then HTTP 404 반환.

Impacted Area

  • Docs:
    • docs/interface-contract.md — admin 데몬 CRUD 엔드포인트 경로·권한·owner 재할당 시 인증정보 무효화 정책 신규 섹션 추가.
  • Modules:
    • 신규 또는 확장 admin 데몬 라우터(경로·파일명은 design 확정).
    • app/schemas/ — DaemonCreateRequest, DaemonUpdateRequest, DaemonAdminResponse 스키마 신규 정의.
    • app/services/ — 데몬 생성·변경·비활성화 서비스 메서드 신규. owner 재할당 시 BrokerCredential 무효화 로직 포함.
    • app/repositories/ — DaemonRepository create/update/deactivate/reactivate 메서드 신규.
    • app/repositories/broker_credential_repository.py — owner 재할당 시 credential 삭제 메서드(신규 또는 확장).
    • REQ-022(daemon deactivation service token auto-revoke) 서비스 로직 재사용 — 비활성화 경로에서 호출.
  • Tests:
    • AC-1~12 커버 pytest 케이스. AC-4/5(owner 재할당 + 인증정보 무효화), AC-8(DELETE 405 음성), AC-9/10/11(권한 음성) 강제 검증.

Notes

  • OQ-2(엔드포인트 경로): draft-batch-design 위임(dcy-011 Deferred). /v1/admin/daemons vs /v1/daemons(admin 분기) — dcy-006 admin 경로 컨벤션 참고.
  • owner 재할당 + 인증정보 자동 무효화(AC-4/5): dcy-011 OQ-3 Answered(2026-06-28 결정). 새 owner는 자기 KIS 인증정보를 REQ-052 API로 재등록해야 한다. 이 정책은 이전 owner의 KIS 계좌 정보가 데몬에 잔류하는 보안 위험을 제거한다.
  • 하드 삭제 미제공(AC-8): 데몬은 운영 런타임 식별자(service-token daemon_id 바인딩)이므로 참조 무결성 보호를 위해 비활성화가 유일 종료 경로. dcy-011 FR-4 결정.
  • 비활성화 → service token revoke(AC-6): 기존 REQ-022 정책(daemon deactivation auto-revoke)을 이 경로에서도 호출. REQ-022 구현 재사용.
  • NFR-2(권한 — admin role 강제): AC-9/10/11로 흡수한다.
  • daemon_slug 중복 처리(AC-2): HTTP 409 vs 422는 design 단계에서 v1 컨벤션에 맞춰 확정.
  • Source: dcy-011 FR-4, NFR-2, OQ-3 Answered.

Change Log

CHG-20260628-01

  • Date: 2026-06-28
  • Author: Justin Ko

Change Summary

  • 신규 생성 (Proposed) — dcy-011 FR-4 산출물.

Intent

  • dcy-011 confirmed Discovery의 FR-4(admin 데몬 생성·owner 할당·변경·(비)활성화, 삭제 제외) 및 OQ-3 결정(owner 재할당 허용 + 인증정보 자동 무효화)을 Interface REQ로 정규화한다.

Acceptance Criteria Delta

  • Added:
    • AC-1 ~ AC-12 전체 (신규 초안)
  • Updated: 없음
  • Removed: 없음

Impacted Area Delta

  • Docs:
    • docs/srs/Interface/req-053_admin-daemon-crud-api.md 신규 생성
    • docs/interface-contract.md 갱신 예고
  • Modules:
    • admin 데몬 라우터(신규), DaemonCreate/UpdateRequest/AdminResponse 스키마(신규), 서비스·repository 신규
  • Tests:
    • owner 재할당+인증정보 무효화(AC-4/5), DELETE 음성(AC-8), 권한 음성(AC-9~11) 케이스 신규

Delivery Trace Delta

  • Batches: 미정 (suggest-batch-reqs 대기)
  • Releases: 미정

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: keep-current
  • Follow-up Action: confirm-req 후 suggest-batch-reqs. REQ-052/REQ-054와 동일 batch 묶기 권고. OQ-2(경로)은 design 단계 해소.

Validation Plan

  • pytest로 AC-1~12 각 케이스 확인. AC-4/5(owner 재할당 + 인증정보 무효화) 통합 시나리오, AC-8(DELETE 음성), AC-9(admin role 강제 음성) 강제 검증.

CHG-20260628-02

  • Date: 2026-06-28
  • Author: 팀장(Claude)
  • confirm-req: Proposed → Approved. dcy-011 FR-4/OQ-3 추적. 데몬 생성·할당·(비)활성화, owner 재할당 시 인증정보 자동 무효화(AC-4/5) 보안정합, 하드 삭제 미제공(AC-8)·비활성화→service token revoke(REQ-022 재사용, AC-6)·admin role 강제(AC-9/10/11) 적절. 경로(OQ-2)·409/422·405/404 design 위임. blocker 없음.

CHG-20260628-03

  • Date: 2026-06-28
  • Author: 팀장(Claude)
  • confirm-req-implemented: Approved → Implemented. 근거: BAT-022 PR #19 mergeCommit 1b78c18, QC PASS-WITH-NOTES(opus, blocker 0). AC-1~12 전건 테스트 통과(565 passed). owner 재할당 원자화 수정(83e6dde) — 단일 트랜잭션+선삭제 방식으로 기존 BrokerCredential 삭제 후 owner 변경을 원자적으로 처리, leak 방지 테스트 3종 PASS. AC-4/5(owner 재할당+인증정보 무효화), AC-8(DELETE 405 음성), AC-9/10/11(권한 음성) 전건 통과. 잔여 리스크 없음.

CHG-20260628-04

  • Date: 2026-06-28
  • Author: 팀장(Claude) — change-req (핫픽스 백필 / 스코프 갭 정정)

Change Summary

  • GET /v1/admin/daemons(전체 데몬 목록) 엔드포인트 누락 갭을 정정한다. Status Implemented 유지(이번 변경으로 스코프 완결).

Intent / 증상·영향·근본원인 (핫픽스 예외 경로)

  • 증상: trex-web admin "데몬 관리" 화면이 adminListDaemons(REQ-035)로 GET /v1/admin/daemons 호출 시 405 Method Not Allowed → "데몬 목록을 불러오지 못했습니다" 에러.
  • 영향: admin 데몬 목록 열람 불가(생성·변경 자체는 가능하나 목록 미표시). 라이브 통합테스트 전까지 미발견.
  • 근본원인: REQ-053 최초 스코프가 POST/PATCH/activate/deactivate(+DELETE 405 음성)만 AC로 잡고 목록 조회(GET-list)를 AC로 누락. 목록 수요는 trex-web REQ-035(admin API 클라/훅)에서 발생했으나 백엔드 계약(REQ-053)에 반영되지 않음. mock 기반 UI 단위테스트는 실제 405를 포착하지 못함(실연동 갭).

Acceptance Criteria Delta

  • Added:
    • AC-13: Given admin 인증, When GET /v1/admin/daemons, Then 전체 데몬 목록({daemons:[{id,daemon_slug,display_name,is_active,owner_user_id}], total})을 200으로 반환한다.
    • AC-14: Given 비admin 인증, When GET /v1/admin/daemons, Then 403으로 차단된다(admin role 강제 회귀).
  • Updated: 없음
  • Removed: 없음

Impacted Area Delta

  • Modules: app/api/v1_admin_daemons.py(GET 핸들러 list_all_daemons), app/schemas/v1.py(DaemonDetail, DaemonDetailListResponse), app/repositories/postgres.py(list_daemons_all())
  • Tests: tests/test_bat022_req053_admin_daemon_crud.py(GET 목록 케이스 추가)

Delivery Trace Delta

  • 핫픽스 커밋 2dcbafb(로컬 main 직접 커밋 — worktree/PR/QC 정식 게이트 대신 핫픽스 fast-path). 정식 QC 게이트는 생략했고, 대신 **라이브 통합검증(실행 중 portfolio-hub :8000 상대 API E2E 18항목 PASS, GET 목록에 신규 데몬 포함 확인)**으로 검증을 대체했다.

Revalidation Impact

  • Reverification Needed: no (라이브 E2E로 검증 완료)
  • Existing Implementation Invalidated: no (순수 추가, 기존 핸들러 무변경)
  • Status Recommendation: implemented
  • Rollback: git revert 2dcbafb(순수 추가라 안전). 롤백 시 목록 화면만 405로 회귀, 생성/변경 영향 없음.
  • Follow-up Action: 후속 batch에서 GET 목록 케이스를 정식 회귀 테스트 스위트에 편입. 동종 갭 예방 위해 UI API 클라(REQ-035)와 백엔드 계약(REQ-053) 간 엔드포인트 교차대조 체크리스트화.