Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
9.4 KiB
9.4 KiB
REQ-052: 사용자 소유 스코프 인증정보 관리 HTTP API
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: Justin Ko
Intent
- 현재 BrokerCredential 관리는 CLI(
pfhub credential)와 service-token read 경로(REQ-051/REQ-049)만 존재하며, HTTP user-token 기반 관리 표면이 없다. - trex-web dcy-009 사용자 self-service UI가 소비하는 백엔드 경로를 신설한다: 사용자가 자기 소유 데몬의 KIS 인증정보를 HTTP API로 등록·회전·삭제하고, 메타데이터(secret 미포함)를 조회할 수 있도록 한다.
- dcy-010 자산(BrokerCredential 모델, Fernet 암호화,
CREDENTIAL_ENCRYPTION_KEY, PK(daemon_id, broker))을 재사용하여 CLI와 동일 repository·암호화 경로를 공유한다.
Requirement
- 시스템은 user-token으로 인증된 사용자가 자기 소유 데몬의 broker 인증정보를 등록·회전·삭제할 수 있는 write 엔드포인트를 제공해야 한다.
- 등록/회전:
app_key+app_secret+account_ref입력을 Fernet 암호화하여BrokerCredential에 upsert. 회전 시credential_version증가,last_rotated_at갱신. - 삭제: 해당
(daemon_id, broker)행 제거.
- 등록/회전:
- 시스템은 사용자가 자기 소유 데몬의 인증정보 메타데이터를 조회할 수 있는 read 엔드포인트를 제공해야 한다. 응답에는
broker,account_ref,credential_version,last_rotated_at, 보유 여부(has_credential)만 포함하며 복호화된app_key/app_secret은 절대 포함하지 않는다. - 소유 스코프 인가를 모든 관리 경로에 강제해야 한다: 요청자
user_id가 대상 데몬의owner_user_id와 일치하지 않으면 HTTP 403 Forbidden을 반환한다. 인증 토큰이 없는 요청은 HTTP 401을 반환한다. - 인증정보 write 요청이 성공하면 응답에는 메타데이터(
broker,account_ref,credential_version,last_rotated_at)만 반환하고app_key/app_secret은 포함하지 않는다. - 엔드포인트 경로·HTTP 메서드의 구체 형태는 draft-batch-design에서 v1 컨벤션(
/v1/daemons/{daemon_id}/credential방향 권고, dcy-011 OQ-1 Deferred)에 맞춰 확정한다. - 기존 CLI(
pfhub credential)와 동일한BrokerCredentialRepository메서드 및app/core/encryption.pyFernet 자산을 재사용해야 한다.
Acceptance Criteria
- Given user-token(소유자 A)으로 자기 소유 daemon D에
app_key/app_secret/account_ref를 등록, When write 엔드포인트를 호출, Then HTTP 200/201 + 메타데이터 응답(broker,account_ref,credential_version,last_rotated_at)이 반환되고 응답 JSON에app_key/app_secret필드가 존재하지 않는다. - Given 같은 소유자 A가 동일 daemon D 인증정보를 재등록(회전), When write 엔드포인트를 호출, Then 응답의
credential_version이 이전보다 1 증가하고last_rotated_at이 갱신된다. - Given 소유자 A가 daemon D 인증정보를 등록한 뒤, When service-token
/v1/user_info(REQ-049)로 해당 daemon D의 인증정보를 fetch하면, Thenbroker.account_ref가 방금 등록한 값과 일치한다(CLI·API·service-token 경로 정합). - Given user-token(소유자 A)으로 자기 소유 daemon D 인증정보 메타데이터를 GET, When 조회 엔드포인트를 호출, Then HTTP 200 +
broker,account_ref,credential_version,last_rotated_at,has_credential반환되고app_key/app_secret필드는 응답에 없다. - Given user-token(소유자 A)으로 자기 소유 daemon D 인증정보를 삭제, When delete 엔드포인트를 호출, Then HTTP 200/204 반환 후 해당 daemon D 메타데이터 조회 시
has_credential: false(또는 인증정보 없음 응답). - Given user-token(사용자 B)으로 사용자 A 소유 daemon D의 인증정보에 대한 write/read/delete 요청, When 엔드포인트를 호출, Then HTTP 403 Forbidden 반환(소유 스코프 위반).
- Given 인증 토큰 없는 요청으로 인증정보 관리 엔드포인트 호출, When 호출, Then HTTP 401 반환.
- Given 존재하지 않는 daemon_id를 대상으로 인증정보 관리 요청, When 호출, Then HTTP 404 반환.
- Given admin 토큰으로 자기 소유 데몬이 아닌 daemon D의 인증정보 write 엔드포인트 호출, When 호출, Then HTTP 403 반환(관리 API는 소유 스코프 전용 — admin role로 타인 인증정보 조작 불가).
- Given service-token으로 인증정보 관리 엔드포인트 호출, When 호출, Then HTTP 403 반환(service-token은 read 전용
/v1/user_info경로만 허용).
Impacted Area
- Docs:
docs/interface-contract.md— 인증정보 관리 엔드포인트 경로·권한·응답 스키마(secret 미포함 정책) 신규 섹션 추가.
- Modules:
- 신규 라우터 파일(경로·파일명은 design 확정) — 인증정보 관리 write/read/delete 엔드포인트.
app/schemas/—CredentialSetRequest(app_key/app_secret/account_ref),CredentialMetaResponse(메타데이터 only, secret 미포함) 스키마 신규 정의.app/services/— 소유 스코프 인가 검사 + Fernet 암호화/upsert/삭제 서비스 메서드 신규 또는 확장.app/repositories/broker_credential_repository.py— 메타데이터 조회·write 메서드 확장(CLI와 공유).app/core/encryption.py— 재사용 (변경 없음).app/main.py또는 라우터 등록 — 신규 라우터 include.
- Tests:
- AC-1~10 커버 pytest 케이스. 특히 AC-6(소유 스코프 음성), AC-9(admin 소유 스코프 음성), AC-10(service-token 음성), AC-3(CLI·API·service-token 정합) 강제 검증.
Notes
- OQ-1(엔드포인트 경로): draft-batch-design 위임(dcy-011 Deferred). 팀장 권고 = daemon-scoped(
/v1/daemons/{daemon_id}/credential). v1 컨벤션·dcy-009 UI 흐름 정합 설계 단계 확정. - 복호화 secret 미반환 불변: 이 REQ의 어떤 응답도
app_secret/app_key평문을 포함하지 않는다. 유일 decrypt-return 경로는 service-tokenGET /v1/user_info(REQ-051/REQ-049) — 본 REQ로 변경하지 않는다. - AC-9(admin 소유 스코프): admin은 데몬 CRUD(REQ-053)를 담당하며, admin role로 타인 인증정보 write/read를 허용하지 않는다. 인증정보는 사용자 본인 소유 스코프만. 이 경계가 REQ-052(user-token, 소유 스코프)와 REQ-053(admin, 데몬 CRUD)의 책임 분리이다.
- NFR-1(보안 — secret 미반환·로그 미노출)은 REQ-054에서 독립 Non-Functional REQ로 추적한다. 이 REQ AC는 응답 schema 단의 secret 부재 확인을 포함하며, REQ-054가 전체 보안 격리를 측정한다.
- NFR-3(일관성 — CLI·API 정합): AC-3이 흡수한다. 구현 시 동일 repository 메서드 재사용 강제.
- Source: dcy-011 FR-1, FR-2, FR-3, NFR-2, NFR-3.
Change Log
CHG-20260628-01
- Date: 2026-06-28
- Author: Justin Ko
Change Summary
- 신규 생성 (Proposed) — dcy-011 FR-1/FR-2/FR-3 산출물.
Intent
- dcy-011 confirmed Discovery의 FR-1(인증정보 등록·회전·삭제), FR-2(메타데이터 조회, secret 미반환), FR-3(소유 스코프 인가 강제)를 단일 Interface REQ로 정규화한다. 세 FR이 동일 관리 표면(user-token + 소유 스코프 인증정보 관리)에 속하므로 하나의 REQ로 묶는다.
Acceptance Criteria Delta
- Added:
- AC-1 ~ AC-10 전체 (신규 초안)
- Updated: 없음
- Removed: 없음
Impacted Area Delta
- Docs:
docs/srs/Interface/req-052_user-owned-credential-management-api.md신규 생성docs/interface-contract.md갱신 예고
- Modules:
- 인증정보 관리 라우터(신규), 스키마(신규), 서비스·repository 확장
- Tests:
- 소유 스코프 음성(AC-6/9/10), 메타데이터 secret 부재(AC-1/4), CLI 정합(AC-3) 케이스 신규
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-053/REQ-054와 동일 batch 묶기 권고. OQ-1(경로)은 design 단계 해소.
Validation Plan
- pytest로 AC-1~10 각 케이스 확인. AC-6(타 사용자 소유 스코프 음성), AC-9(admin 소유 스코프 음성), AC-10(service-token 음성)은 음성 테스트로 강제 검증.
CHG-20260628-02
- Date: 2026-06-28
- Author: 팀장(Claude)
- confirm-req:
Proposed→Approved. dcy-011 FR-1/2/3 추적. 소유 스코프 음성(AC-6/9/10)·메타데이터 secret 부재(AC-1/4)·CLI·API·service-token 정합(AC-3) 적절. AC-9(admin도 타인 인증정보 write→403) = 사장님 "self-service 전용·admin 감독 없음" 결정과 정합 확인(admin은 데몬 CRUD만, 인증정보는 본인 소유 스코프). 경로(OQ-1) design 위임. blocker 없음.
CHG-20260628-03
- Date: 2026-06-28
- Author: 팀장(Claude)
- confirm-req-implemented:
Approved→Implemented. 근거: BAT-022 PR #19 mergeCommit1b78c18, QC PASS-WITH-NOTES(opus, blocker 0). AC-1~10 전건 테스트 통과(565 passed). 음성 케이스(AC-6 소유 스코프·AC-9 admin 소유 스코프·AC-10 service-token) 및 secret 미반환(AC-1/4) 검증 PASS. Major 보안 #3(owner 재할당 credential leak) 원자화 수정83e6dde— 단일 트랜잭션+선삭제+leak 방지 테스트 3종 포함하여 전체 통과. 잔여 리스크 없음.