dcy-003/004 기반 v1 API surface 완성 및 BAT-008~011 구현·검증 완료:
- BAT-008 (REQ-019~021,024): 토큰 surface baseline 문서 갱신
- BAT-009 (REQ-025~028): POST/PATCH/DELETE/GET /v1/portfolios CRUD 신설
- _require_write_token, _get_portfolio_or_404, soft delete, daemon-scoped list
- BAT-010 (REQ-030~032): portfolio tag/comment 서브 라우트 신설 + baseline 갱신
- GET/POST/DELETE /v1/portfolios/{id}/tags
- POST/GET/PATCH/DELETE /v1/portfolios/{id}/comments
- BAT-011 (REQ-029): ledger path migration
- POST /v1/assets/{asset_id}/ledger/trades → /v1/portfolios/{portfolio_id}/ledger/trades
- v1_ledger.py 제거, disabled 차단(409) 추가
- test_v1.py / test_daemon_assignment.py 구 path 갱신
- 신규 tests: test_v1_portfolios_crud.py, test_v1_portfolios_list.py,
test_v1_portfolios_tags_comments.py, test_v1_portfolios_ledger.py
- 전체 suite: 340 passed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7.6 KiB
7.6 KiB
REQ-029: POST /v1/portfolios/{portfolio_id}/ledger/trades 이전
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: Justin Ko
Intent
- 기존
POST /v1/assets/{asset_id}/ledger/trades(app/api/v1_ledger.py)의 path param 이름이asset_id이나 실제 값은portfolios.portfolio_id(UUID)로 의미 혼용되는 결함을 해소한다. - dcy-003 옵션 B(path 명명 분리)에 따라 신 path
POST /v1/portfolios/{portfolio_id}/ledger/trades로 이전하고 구 path는 동일 release에서 제거한다. 동작·인가·idempotency는 그대로 보존.
Requirement
- 신규 라우트
POST /v1/portfolios/{portfolio_id}/ledger/trades(Bearer 인증 필수). - 동작은 기존
POST /v1/assets/{asset_id}/ledger/trades와 동일하게 보존:- daemon assignment 3단계 fail-closed 인가: (1) token
daemon_id IS NULL→ HTTP 403, (2) portfoliomanaged_by_daemon_id IS NULL(미배정 asset) → HTTP 403, (3)portfolio.managed_by_daemon_id != auth.daemon_id(불일치) → HTTP 403. - idempotency:
(portfolio_id, order_id, execution_id)unique constraint (기존uq_ledger_trades_idempotency재사용). - duplicate/conflict 응답: 동일 키 + 동일 payload → HTTP 200 +
status="duplicate". 동일 키 + 다른 payload → HTTP 409. - 새 ledger row → HTTP 201 +
status="new".
- daemon assignment 3단계 fail-closed 인가: (1) token
- disabled portfolio 차단 (REQ-027 정합):
portfolios.status='disabled'인 portfolio에 대해서는 HTTP 409 또는 422로 차단. - 구 path
POST /v1/assets/{asset_id}/ledger/trades제거: 동일 batch release에서 라우트 삭제. 호출 시 HTTP 404. - trex-basic 동시 배포 필수 (dcy-003 OQ-3 + NFR-2): 신 path 단일 서빙. 한시적 별칭/redirect 없음. release plan에 배포 순서 잠금(trex-basic 클라이언트 사전 빌드 → portfolio-hub 배포 → trex-basic 배포) + rollback 시 trex-basic 동반 rollback 전제 명시.
Acceptance Criteria
- Given service token + 본인 daemon에 배정된 active portfolio + 신규 trade payload, When
POST /v1/portfolios/{portfolio_id}/ledger/trades, Then HTTP 201 +status="new"+ 생성된 ledger row. - Given AC-1 실행 후 동일 key + 동일 payload 재호출, When 호출, Then HTTP 200 +
status="duplicate"+ 단일 ledger row 유지. - Given AC-1 실행 후 동일 key + 다른 payload 호출, When 호출, Then HTTP 409 + ledger row 변경 없음.
- Given service token
daemon_id IS NULL, WhenPOST /v1/portfolios/{portfolio_id}/ledger/trades, Then HTTP 403 fail-closed. - Given service token +
portfolio.managed_by_daemon_id IS NULL(미배정 asset), When 호출, Then HTTP 403 fail-closed. - Given service token +
portfolio.managed_by_daemon_id != auth.daemon_id(불일치), When 호출, Then HTTP 403 fail-closed. - Given service token +
status='disabled'portfolio, When 호출, Then HTTP 409 또는 422 (disabled write 차단). - Given 비존재
portfolio_id, When 호출, Then HTTP 404. - Given 구 path
POST /v1/assets/{asset_id}/ledger/trades호출, When 본 REQ 구현 후 동일 batch release, Then HTTP 404. - Given Bearer token 없음, When 호출, Then HTTP 401.
Impacted Area
- Docs:
docs/interface-contract.md— POST /v1/portfolios/{id}/ledger/trades 명세 + 구 path 제거 (REQ-032)docs/runtime-flows.md— daemon assignment 3단계 인가 + idempotency + path 이전 흐름 (REQ-032)
- Modules:
app/api/v1_portfolios.py—POST /v1/portfolios/{portfolio_id}/ledger/trades라우트 추가 (또는 별도v1_ledger.py를 신 path로 이전)app/api/v1_ledger.py— 구 path 제거 또는 신 path로 라우트 prefix 이전app/main.py— 라우터 include 갱신 (구 ledger 라우터 제거)app/services/portfolio_service.py또는app/services/ledger_service.py— 기존 ledger trade 로직 재사용 + disabled 차단 검증 추가
- Tests:
- 갱신
tests/test_v1.py— 구 path 케이스를 신 path로 갱신, 구 path 호출 시 HTTP 404 확인 - 신규
tests/test_v1_portfolios_ledger.py— AC-1~10 검증
- 갱신
Notes
- 본 REQ는 기능 추가가 아닌 path 이전이라 기존 동작·테스트 시나리오를 그대로 재사용한다. 다만 disabled portfolio 차단(AC-7)은 REQ-027 soft delete 정책 정합 검증으로 신규.
- dcy-003 NFR-2(trex-basic 동시 배포)는 본 REQ의 가장 큰 운영 리스크(R-1)이며, release plan에 배포 순서 잠금·rollback 전제를 명시해야 함. release plan은 batch design/release 단계 작업.
- ledger_trades 테이블의
asset_id컬럼명은 본 REQ에서 변경하지 않는다(dcy-001assets.asset_id와 의미 혼용이 잔존하나, ledger_trades 컬럼은 portfolio_id를 가리킨다는 점이 path 이름 정합화로 충분히 명확해짐). 컬럼명 변경은 별도 migration REQ로 분리 가능. - Source: dcy-003 FR-6, OQ-3, NFR-1, NFR-2, R-1 완화.
Change Log
CHG-20260521-01
- Date: 2026-05-21
- Author: Justin Ko
Change Summary
- Status: Approved → Implemented
Intent
- BAT-011 구현 완료:
app/api/v1_portfolios.py에POST /{portfolio_id}/ledger/trades신설 (daemon 인가 3단계 + disabled 409 + idempotency 보존);app/api/v1_ledger.py삭제;app/main.pyinclude 정리;tests/test_v1_portfolios_ledger.pyAC-1~10 신규;tests/test_v1.py+tests/test_daemon_assignment.py구 path 갱신
Acceptance Criteria Delta
- No change
Impacted Area Delta
- No change
Delivery Trace Delta
- Batches: BAT-011 (release-candidate)
- Releases: pending
Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: implemented
- Follow-up Action: BAT-011 release candidate → draft-release; trex-basic 동시 배포 순서 잠금 필수
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: BAT-011 (in-delivery)
- Releases: none (미정)
Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: promote-to-approved
- Follow-up Action: BAT-011 draft-batch-planning 완료 → draft-batch-design 진행
CHG-20260520-01
- Date: 2026-05-20
- Author: Justin Ko
Change Summary
- 최초 생성 — dcy-003 confirm-discovery 후 draft-req 실행. dcy-003 FR-6 산출물.
Intent
- ledger trade path 명명 정합화 + 동시 배포 정책 명시 + disabled 차단 추가.
Acceptance Criteria Delta
- Added:
- AC-1~10 최초 작성
Impacted Area Delta
- Docs: docs/interface-contract.md, docs/runtime-flows.md (REQ-032)
- Modules: app/api/v1_portfolios.py, app/api/v1_ledger.py(제거 또는 이전), app/main.py, app/services/* — 최초 지정
- Tests: tests/test_v1.py(갱신), tests/test_v1_portfolios_ledger.py(신규) — 최초 지정
Delivery Trace Delta
- Batches: none (미정)
- Releases: none (미정). trex-basic 동시 배포 release plan은 batch design 단계에서 작성.
Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 batch 계획 편입; trex-basic 측 release readiness(DATA_TREX_BASIC_RELEASE_WINDOW) 외부 확인 필요
Validation Plan
- pytest TestClient로 AC-1~10 검증; 신·구 path 회귀 + daemon 인가 3단계 + idempotency·conflict + disabled 차단