Files
portfolio-hub/docs/srs/Interface/req-026_v1-portfolios-update.md
T

8.6 KiB

REQ-026: PATCH /v1/portfolios/{portfolio_id} 신설

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

Intent

  • v1 API에 portfolio 부분 수정 경로(PATCH /v1/portfolios/{portfolio_id})를 신설해 user/admin이 HTTP로 portfolio 속성(broker/status/name/symbol/strategy 등)을 직접 수정할 수 있도록 한다.
  • 토큰 분기 + ownership 검증을 REQ-025와 동일 패턴으로 적용해 v1 portfolio CRUD 인가 일관성을 확보한다.

Requirement

  • 신규 라우트 PATCH /v1/portfolios/{portfolio_id} (Bearer 인증 필수).
  • 토큰 분기 규칙 (REQ-025 + dcy-003 OQ-2/OQ-5 결정과 정합):
    • token_type ∈ {service, client} → HTTP 403 fail-closed.
    • 그 외(token_type=session 또는 env token):
      • permission='admin' → 모든 portfolio 수정 가능.
      • permission ∈ {read, trade-write} → 자기 소유(owner_user_id = auth.user_id) portfolio만 수정 가능, 불일치 시 HTTP 403.
  • 비존재 portfolio는 HTTP 404.
  • 수정 가능 필드는 기존 UpdatePortfolioRequest 범위: broker, status, name, symbol, strategy_name, strategy_params, asset_price, managed_by_daemon_id 등.
  • disabled portfolio 보호 (REQ-027 soft delete 정책 정합): portfolios.status == 'disabled'인 portfolio에 대해 status 전이('enabled'로 복구) 외 다른 필드 변경 시 HTTP 409 또는 422로 거부.
  • 응답: HTTP 200 + 갱신된 PortfolioItem.
  • 응답의 symbol 값은 수정 대상 portfolio가 참조하는 assets.symbol을 기준으로 server-side join 결과에서 채운다.

Acceptance Criteria

  1. Given admin token + 본인 또는 타 user portfolio, When PATCH /v1/portfolios/{id} body {"strategy_name": "..."}, Then HTTP 200 + 갱신된 portfolio 반환.
  2. Given session/env token with permission ∈ {read, trade-write} + 본인 portfolio, When PATCH /v1/portfolios/{id}, Then HTTP 200 + 갱신된 portfolio.
  3. Given session/env token with permission ∈ {read, trade-write} + 타 user portfolio, When PATCH /v1/portfolios/{id}, Then HTTP 403 (ownership 불일치).
  4. Given service token, When PATCH /v1/portfolios/{id}, Then HTTP 403 fail-closed.
  5. Given client token(폐지 전), When PATCH /v1/portfolios/{id}, Then HTTP 403 fail-closed.
  6. Given Bearer token 없음, When PATCH /v1/portfolios/{id}, Then HTTP 401.
  7. Given 비존재 portfolio_id, When PATCH /v1/portfolios/{id}, Then HTTP 404.
  8. Given status='disabled' portfolio + body {"strategy_name": "..."}(status 외 필드), When PATCH, Then HTTP 409 또는 422 (disabled write 차단).
  9. Given status='disabled' portfolio + body {"status": "enabled"} (admin), When PATCH, Then HTTP 200 + status 복구.
  10. Given portfolio가 active asset(symbol="005930")을 참조, When PATCH /v1/portfolios/{id} 성공, Then HTTP 200 응답의 PortfolioItem.symbol == "005930" 이고 값은 joined asset row와 일치한다.

Impacted Area

  • Docs:
    • docs/interface-contract.md — PATCH /v1/portfolios/{id} 명세 추가 (REQ-032)
    • docs/runtime-flows.md — portfolio update flow + ownership 검증 + disabled 보호 (REQ-032)
  • Modules:
    • app/api/v1_portfolios.py — PATCH 라우트 추가 (REQ-025의 인증 헬퍼 재사용)
    • app/schemas/v1.py — PortfolioUpdateRequest 신규 (기존 UpdatePortfolioRequest 재사용 또는 v1 전용 래핑)
    • app/services/portfolio_service.py:update_portfolio — 기존 메서드 재사용 + disabled 보호 검증 추가
  • Tests:
    • 신규/갱신 tests/test_v1_portfolios_crud.py — AC-1~9 검증

Notes

  • ownership 검증은 admin/user 분기 후 service 계층 또는 라우터에서 일관 처리. 본 REQ의 검증 위치는 REQ-025 catalog 검증 위치 결정과 함께 결정한다.
  • disabled portfolio 보호는 REQ-027(soft delete) 정책의 일부로, 본 REQ에서 PATCH 측면 검증을 명시. ledger trade/tag/comment 측면은 REQ-029/030/031에서 각각 처리.
  • 본 REQ는 dcy-003 FR-3 산출물이며 NFR-1/NFR-3/NFR-4를 검증 기준에 흡수.
  • Source: dcy-003 FR-3, OQ-2, OQ-5, NFR-1, NFR-3, NFR-4.

Change Log

CHG-20260524-02

  • Date: 2026-05-24
  • Author: Hermes Agent

Change Summary

  • Status: Approved → Implemented

Intent

  • BAT-014 verification 완료. PATCH 성공 응답의 PortfolioItem.symbol 계약이 코드/테스트/문서에 반영되어 REQ-026 acceptance criteria 전부가 다시 충족되었다.

Acceptance Criteria Delta

  • No change

Impacted Area Delta

  • No change

Delivery Trace Delta

  • Batches: BAT-014 (release-candidate); BAT-009 response-contract evidence superseded by BAT-014
  • Releases: pending

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: promote-to-implemented
  • Follow-up Action: release 단계에서 smoke 확인

CHG-20260524-01

  • Date: 2026-05-24
  • Author: Hermes Agent

Change Summary

  • PortfolioItem.symbol 응답 계약 추가에 따라 REQ-026 수정 응답 contract를 보강하고 상태를 Implemented → Approved로 되돌림.

Intent

  • trex-orbit 팀이 portfolio mutation 후에도 추가 catalog lookup 없이 즉시 symbol을 사용해야 하는 요구를 제기했다. PATCH 응답이 기존 portfolio state만 되돌리고 joined asset 식별자(symbol)를 생략하면 CRUD 응답 contract가 비대칭이므로, 수정 응답에도 동일 필드를 포함하도록 정의를 확장한다.

Acceptance Criteria Delta

  • Added:
    • AC-10: PATCH 성공 응답의 PortfolioItem.symbol 이 joined assets.symbol 과 일치해야 함

Impacted Area Delta

  • Docs: docs/interface-contract.md 의 PATCH /v1/portfolios/{id} 응답 예시에 symbol 추가 필요 (REQ-032 후속)
  • Modules: app/schemas/v1.py, app/api/v1_portfolios.py (_portfolio_to_item)
  • Tests: tests/test_v1_portfolios_crud.py 에 PATCH 응답 symbol 검증 추가 필요

Delivery Trace Delta

  • Batches: BAT-009 evidence partially superseded; follow-up BAT-014 예정
  • Releases: REL-001 response-contract evidence 일부 재검토 필요

Revalidation Impact

  • Reverification Needed: yes
  • Existing Implementation Invalidated: yes (response schema evidence partial)
  • Status Recommendation: revert-to-approved
  • Follow-up Action: BAT-014에서 PATCH 응답 contract 회귀 검증 추가

Validation Plan

  • tests/test_v1_portfolios_crud.py 에서 PATCH 200 응답 body의 symbol 존재 및 joined asset symbol 일치 여부를 검증한다.

CHG-20260521-01

  • Date: 2026-05-21
  • Author: Justin Ko

Change Summary

  • Status: Approved → Implemented

Intent

  • BAT-009 confirm-batch-verification 완료. tests/test_v1_portfolios_crud.py AC-1~9 전 케이스 pytest 통과 (2026-05-21, 298 PASSED).

Acceptance Criteria Delta

  • No change

Impacted Area Delta

  • No change

Delivery Trace Delta

  • Batches: BAT-009 (release-candidate)
  • Releases: TBD

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: promote-to-implemented
  • Follow-up Action: 없음

CHG-20260520-02

  • Date: 2026-05-20
  • Author: Justin Ko

Change Summary

  • Status: Proposed → Approved

Intent

  • 승인 게이트 통과: 필수 필드(Status/Type/Priority/Owner/Intent/Requirement/AC/Impacted Area/Change Log) 모두 충족, AC 구체성 확인 완료, blocker 없음

Acceptance Criteria Delta

  • No change

Impacted Area Delta

  • No change

Delivery Trace Delta

  • Batches: none (미정)
  • Releases: none (미정)

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: promote-to-approved
  • Follow-up Action: batch 계획 편입

CHG-20260520-01

  • Date: 2026-05-20
  • Author: Justin Ko

Change Summary

  • 최초 생성 — dcy-003 confirm-discovery 후 draft-req 실행. dcy-003 FR-3 산출물.

Intent

  • v1 portfolio mutation의 부분 수정 진입점 + ownership 검증 + disabled 보호.

Acceptance Criteria Delta

  • Added:
    • AC-1~9 최초 작성

Impacted Area Delta

  • Docs: docs/interface-contract.md, docs/runtime-flows.md (REQ-032)
  • Modules: app/api/v1_portfolios.py, app/schemas/v1.py, app/services/portfolio_service.py — 최초 지정
  • Tests: tests/test_v1_portfolios_crud.py — 최초 지정

Delivery Trace Delta

  • Batches: none (미정)
  • Releases: none (미정)

Revalidation Impact

  • Reverification Needed: no
  • Existing Implementation Invalidated: no
  • Status Recommendation: keep-current
  • Follow-up Action: confirm-req 후 batch 계획 편입; REQ-025와 동일 batch 권장

Validation Plan

  • pytest TestClient로 AC-1~9 검증; ownership·token type·disabled 보호 시나리오