Files
portfolio-hub/docs/batches/bat-022_20260628_daemon-crud-self-service-credential-api/implementation.md
T

3.4 KiB

BAT-022 Implementation

  • Status: completed
  • Commit: 6a0e14d

변경 파일 목록

신규 파일

파일 역할
app/api/v1_admin_daemons.py REQ-053 admin daemon CRUD 라우터 (/v1/admin/daemons)
app/api/v1_daemon_credential.py REQ-052 소유 스코프 credential 관리 라우터 (/v1/daemons/{id}/credential)
tests/test_bat022_req052_credential_api.py REQ-052 AC-1~10 테스트 (17 케이스)
tests/test_bat022_req053_admin_daemon_crud.py REQ-053 AC-1~12 테스트 (15 케이스)
tests/test_bat022_req054_security.py REQ-054 AC-1~7 + REQ-051 회귀 (12 케이스)

변경 파일

파일 변경 내용
app/schemas/v1.py CredentialSetRequest, CredentialMetaResponse, DaemonCreateRequest, DaemonUpdateRequest, DaemonAdminResponse 추가
app/repositories/postgres.py get_broker_credential_by_daemon, delete_credentials_by_daemon_id, update_daemon_owner 추가
app/repositories/portfolio_repository.py Protocol에 신규 3개 메서드 추가
app/main.py v1_admin_daemons_router, v1_daemon_credential_router include

REQ별 구현 요약

REQ-052 (소유 스코프 인증정보 관리 API)

  • GET /v1/daemons/{daemon_id}/credential — 소유 스코프 검증 후 BrokerCredential 메타데이터 반환 (has_credential, version, last_rotated_at). secret 없음.
  • PUT /v1/daemons/{daemon_id}/credential — app_key/app_secret Fernet 암호화 후 upsert_broker_credential(daemon_id=...) 호출. 응답 메타데이터만.
  • DELETE /v1/daemons/{daemon_id}/credential — delete_broker_credential(daemon_id=...) 호출, 204 반환(멱등).
  • 소유 스코프 게이트: daemon.owner_user_id != auth.user_id → 403. admin role도 동일 검사(AC-9).
  • service-token 거부: token_source == "db" and token_type == "service" → 403(AC-10).
  • 기존 upsert_broker_credential, delete_broker_credential(dcy-010 자산) 재사용. CLI와 동일 repo 메서드.

REQ-053 (admin 데몬 CRUD API)

  • POST /v1/admin/daemons → 기존 create_daemon() 재사용, 201.
  • PATCH /v1/admin/daemons/{id} → owner 변경 시 update_daemon_owner()(새 메서드), display_name만 변경 시 기존 update_daemon().
  • POST .../deactivate → update_daemon(is_active=False) + revoke_tokens_by_daemon_id()(REQ-022 재사용).
  • POST .../activate → update_daemon(is_active=True).
  • DELETE .../ → 명시적 405 핸들러 등록.
  • require_admin dependency 사용 (기존 app/core/auth.py).

REQ-054 (보안 격리)

  • 응답 스키마: CredentialMetaResponse/DaemonAdminResponse 모두 secret 필드 부재.
  • 로그: PUT credential 처리 시 broker/daemon_id만 기록 (app_key/app_secret 값 미포함).
  • Fernet at-rest: encrypt_payload() 호출 후 upsert_broker_credential() — 평문 미저장(AC-5).
  • REQ-051 decrypt 경로 불변: /v1/user_info 코드 무변경, 회귀 4개 테스트 PASS(AC-7).

설계 결정 트레이스 (design.md 참조)

  • OQ-1 해소: /v1/daemons/{daemon_id}/credential — daemon-scoped, REST 정합.
  • OQ-2 해소: /v1/admin/daemons — admin 전용 prefix, 기존 GET /v1/daemons(caller-scoped)와 분리.
  • service-token 403: token_source == "db" and token_type == "service" 조건. env-token은 token_type=None이므로 해당 없음.
  • admin + 소유 스코프: admin role도 ownership 검사 통과 → 403(REQ-052 AC-9).