Files
portfolio-hub/docs/srs/Interface/req-049_user-info-daemon-scoped-broker-delivery.md
T

8.4 KiB

REQ-049: GET /v1/user_info daemon-scoped 단일 broker 전달로 확장

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

Intent

  • 기존 GET /v1/user_info가 user_id 기반으로 brokers: list[BrokerItem]을 반환한다. 이를 service token의 auth.daemon_id로 매칭된 단일 broker 인증정보를 반환하는 daemon-scoped 전달로 확장한다.
  • "1 데몬 = 1 계좌" 불변식(dcy-010 A-2 confirmed)에 따라 응답을 broker: BrokerItem | None(단일)으로 정규화하여, 같은 user의 두 데몬이 서로 다른 KIS 계좌를 각각 수신할 수 있게 한다.
  • 유일 소비자인 trex-core hub_read.whoami()는 daemon_id만 읽으며 brokers 필드를 참조하지 않으므로, 응답 형태 변경이 소비자에게 무영향임이 확인된 안전한 변경이다(dcy-010 OQ-2 Answered).

Requirement

  • GET /v1/user_info의 응답 스키마를 다음과 같이 변경한다:
    • brokers: list[BrokerItem] 필드를 제거하고 broker: BrokerItem | None 단일 필드로 대체한다.
    • broker는 service token의 auth.daemon_id에 매칭된 인증정보 1건을 복호화하여 반환한다. daemon_id에 매칭된 인증정보가 없으면 broker: null을 반환한다(graceful degrade — NFR-3).
  • service token에 daemon_id가 없는 경우(None), 엔드포인트는 HTTP 403 Forbidden을 반환한다. 기존 "daemon_id 없어도 200 반환" 동작을 broker 필드에 대해서는 적용하지 않으며, daemon_id 자체가 없으면 403으로 거부한다.
  • app/schemas/v1.py의 UserInfoResponse 모델을 broker: BrokerItem | None = None 필드로 변경하고 brokers: list[BrokerItem]를 제거한다.
  • app/api/v1_user_info.py의 엔드포인트 구현이 auth.daemon_id로 list_broker_credentials(daemon_id=auth.daemon_id) 호출 후 결과에서 단일 항목을 복호화·반환하도록 변경한다.
  • 인증정보 복호화 실패(잘못된 키, 페이로드 손상)는 기존 graceful degrade 정책을 유지한다: 경고 로깅 후 credential_payload: null을 포함한 BrokerItem을 반환한다(응답을 크래시시키지 않음).

Acceptance Criteria

  1. Given daemon_id가 바인딩된 service token으로 GET /v1/user_info 호출, 해당 daemon_id에 매칭된 broker 인증정보가 존재하면, When 호출, Then HTTP 200 + broker 필드에 단일 BrokerItem(account_ref, credential_payload, credential_version, last_rotated_at 포함) 반환.
  2. Given daemon_id가 바인딩된 service token으로 호출, 해당 daemon_id에 매칭된 인증정보가 없으면, When 호출, Then HTTP 200 + broker: null 반환 (graceful degrade, 크래시 없음).
  3. Given daemon_id가 없는(None) service token으로 GET /v1/user_info 호출, When 호출, Then HTTP 403 Forbidden 반환.
  4. Given 같은 user 소유의 daemon A, daemon B에 각각 다른 KIS account_ref가 등록된 상황, When daemon A의 service token으로 호출, Then broker.account_ref가 daemon A에 등록된 account_ref와 일치함.
  5. Given 같은 상황에서 daemon B의 service token으로 호출, When 호출, Then broker.account_ref가 daemon B에 등록된 account_ref와 일치함 (daemon A의 계좌 반환하지 않음).
  6. Given UserInfoResponse 응답 스키마, When 응답 JSON 확인, Then brokers 키가 존재하지 않고 broker 단일 키가 존재한다.
  7. Given 인증정보 복호화 실패(잘못된 key), When daemon_id에 매칭된 인증정보가 있으나 복호화 실패, Then HTTP 200 + broker.credential_payload: null 반환 (경고 로그 기록, 크래시 없음).
  8. Given service 토큰이 아닌 user 토큰(web 토큰)으로 호출, When 호출, Then HTTP 403 Forbidden 반환 (기존 service-token gate 유지).
  9. Given runtime_id, daemon_id, trading_enabled, user_id, username, permission 필드, When GET /v1/user_info 호출, Then 이 필드들은 기존과 동일하게 반환된다 (broker 변경이 나머지 필드에 영향 없음, 회귀 없음).

Impacted Area

  • Docs:
    • docs/interface-contract.md — GET /v1/user_info 섹션: brokers: list → broker: object|null 응답 스키마 갱신, daemon_id 없음 → 403 정책 명시.
    • docs/data-model.md — BrokerCredential State Rules 갱신: 전달 경로에 daemon-scoped 언급 추가.
  • Modules:
    • app/schemas/v1.py — UserInfoResponse 모델: brokers: list[BrokerItem] → broker: BrokerItem | None = None.
    • app/api/v1_user_info.py — 엔드포인트 구현: user_id 기반 list → daemon_id 기반 단일 조회, daemon_id None → 403.
  • Tests:
    • GET /v1/user_info 단위/통합 테스트 갱신: daemon_id 있음/없음, broker 있음/없음, 2데몬 격리(AC-4/5), 복호화 실패(AC-7), 회귀(AC-9).
    • 기존 brokers 필드 참조 테스트 → broker 단일 필드로 변경.

Notes

  • 파괴적 변경(breaking change) 해당 여부: brokers: list → broker: object|null는 API 응답 스키마 변경이다. 그러나 dcy-010 OQ-2에서 유일 소비자 trex-core hub_read.whoami()가 daemon_id만 읽고 brokers 필드를 참조하지 않음이 확인되었으므로, 실질적 소비자 영향은 없다. 다만 이 REQ 구현 전 trex-core 소비자 코드 재확인을 권장한다.
  • daemon_id 없음 → 403 정책은 dcy-010 FR-2 및 universe 인가(REQ-028 managed_by_daemon_id 일치 요구)와 동일한 규율이다.
  • broker: null graceful degrade(AC-2)는 dcy-010 NFR-3(인증정보 부재가 daemon_id, trading_enabled 필수 필드를 크래시시키지 않음)을 구현한다. broker: null은 그날 거래 개시 차단 신호로 소비자(trex-core)가 해석한다. 이 해석 로직은 trex-core Discovery(별도)에서 구현한다.
  • OQ-3(부트스트랩 통합 — universe+인증정보 단일 응답): dcy-010 Deferred. 이 REQ는 인증정보 전달 형태만 확정하며, 부트스트랩 통합은 다루지 않는다.
  • Source: dcy-010 FR-2, OQ-2 Answered, A-2, NFR-3.

Change Log

CHG-20260628-01

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

Change Summary

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

Intent

  • dcy-010 FR-2(기존 GET /v1/user_info daemon-scoped 확장, 단일 broker 정규화)를 Interface REQ로 정규화한다.

Acceptance Criteria Delta

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

Impacted Area Delta

  • Docs:
    • docs/srs/Interface/req-049_user-info-daemon-scoped-broker-delivery.md 신규 생성
    • docs/interface-contract.md, docs/data-model.md 갱신 예고
  • Modules:
    • app/schemas/v1.py (UserInfoResponse 변경), app/api/v1_user_info.py (로직 변경)
  • Tests:
    • user_info 엔드포인트 테스트 전면 갱신 신규

Delivery Trace Delta

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

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no (기존 brokers 필드 구현은 이 REQ 구현 시 대체됨)
  • Status Recommendation: keep-current
  • Follow-up Action: confirm-req 후 batch 배정. REQ-046(모델), REQ-047(스키마) 선행 의존. trex-core 소비자 코드 재확인.

Validation Plan

  • pytest로 AC-1~9 각 케이스 확인. 2데몬 격리(AC-4/5) 특히 중요.

CHG-20260628-02

  • Date: 2026-06-28
  • Author: 팀장(Claude)
  • confirm-req: Proposed → Approved. dcy-010 FR-2/OQ-2/A-2/NFR-3 추적. brokers→단일 broker reshape, daemon_id 없음 403, 2데몬 격리(AC-4/5), graceful degrade(AC-2) 적절. 구현 전 trex-core 소비자 재확인 권고(Notes) 유효. blocker 없음.

CHG-20260628-03

  • Date: 2026-06-28
  • Author: 팀장(Claude)

Change Summary

  • confirm-req-implemented: Approved → Implemented. PR #17 머지(mergeCommit d4acfd4), BAT-020, QC PASS-WITH-NOTES(blocker 0), 테스트 통과.

Intent

  • BAT-020 delivery(PR #17 머지)에서 GET /v1/user_info daemon-scoped 단일 broker 전달 구현 및 AC-1~9 테스트 통과가 확인되어 Implemented로 전환한다.

Acceptance Criteria Delta

  • Added: 없음
  • Updated: 없음
  • Removed: 없음

Impacted Area Delta

  • 없음 (상태 전환만)

Delivery Trace Delta

  • Batches: BAT-020 (PR #17, mergeCommit d4acfd4)
  • Releases: 미정

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: implemented

Validation Plan

  • BAT-020 verification 문서 및 QC PASS-WITH-NOTES 결과(blocker 0)로 AC-1~9 근거 확보됨.