diff --git a/docs/discovery/dcy-012_20260714_manual-ledger-write-api-owner-scoped.md b/docs/discovery/dcy-012_20260714_manual-ledger-write-api-owner-scoped.md index a0159fc..7d498c2 100644 --- a/docs/discovery/dcy-012_20260714_manual-ledger-write-api-owner-scoped.md +++ b/docs/discovery/dcy-012_20260714_manual-ledger-write-api-owner-scoped.md @@ -26,6 +26,7 @@ - 해석: - portfolio-hub에는 수동 장부에 필요한 도메인 서비스/CLI 흐름이 상당 부분 존재하지만, trex-web이 사용할 **HTTP v1 user-token owner-scoped API 계약**은 아직 정식 제품 계약으로 정리되어 있지 않다. - 현재 v1 service-token endpoint(`POST /v1/portfolios/{portfolio_id}/ledger/trades`)는 daemon/trade-write 체결 보고용이다. 사용자 수동 장부 입력은 owner-scoped user/session token 기반으로 분리해야 한다. + - **사용자 결정(2026-07-14)**: 기존 `POST /v1/portfolios/{portfolio_id}/ledger/trades`는 trex-core/daemon/service-token broker trade write 전용으로 유지한다. trex-web manual BUY/SELL은 이 endpoint를 재사용하지 않고 신규 manual endpoint를 사용한다. 단, 내부 ledger append + snapshot update 회계 helper는 가능한 한 공유한다. # 2. 요구사항 판정 결과 - 판정: 신규 @@ -73,6 +74,7 @@ - 변경 3 — **ledger history/read API 계약**: trex-web이 최근 장부 이력을 표시할 수 있는 response shape, pagination/limit, action filter 필요 여부를 정의한다. - 변경 4 — **권한/운영 안전 정책**: owner-scoped authorization, disabled portfolio, daemon-managed portfolio warning/confirmation metadata, negative input policy, reversal policy를 정의한다. - 변경 5 — **기존 domain/CLI와 v1 API 정합화**: 현행 `apply_invest`, `apply_transfer`, `apply_buy`, `apply_sell` 흐름을 재사용/분리할지 결정하고, broker/service-token endpoint와 충돌하지 않도록 source를 분리한다. +- 변경 6 — **기존 broker trade endpoint 보존**: `POST /v1/portfolios/{portfolio_id}/ledger/trades`는 기존 trex-core/daemon 체결 보고 계약으로 유지하고, manual endpoint와 auth/source/idempotency 의미를 분리한다. ## 영향 범위 - 코드 영향: @@ -94,6 +96,8 @@ # 5. 요구사항 목록 ## 기능 요구사항 - FR-1: user/session token 사용자는 자기 소유 portfolio에 manual ledger entry를 append할 수 있어야 한다. 타 사용자 portfolio는 HTTP 403 또는 동등한 fail-closed 응답이어야 한다. +- FR-1a: 기존 `POST /v1/portfolios/{portfolio_id}/ledger/trades`는 daemon/service-token broker trade write 전용으로 유지한다. manual user write를 이 endpoint에 추가 허용하지 않는다. +- FR-1b: 신규 manual endpoint를 추가한다. 기본 방향은 `POST /v1/portfolios/{portfolio_id}/ledger/manual` 단일 action-dispatch endpoint이며, request body에 `action` enum을 포함한다. - FR-2: `INVEST` action은 외부자금에서 `profit_buffer`로 유입된 것으로 기록한다. 효과: `profit_buffer += amount`, `cash_balance`/`asset_quantity` 변화 없음. - FR-3: `BUFFER_OUT` action은 `profit_buffer -> cash_balance` 이동을 기록한다. 효과: `profit_buffer -= amount`, `cash_balance += amount`. - FR-4: `BUFFER_IN` action은 `cash_balance -> profit_buffer` 이동을 기록한다. 효과: `cash_balance -= amount`, `profit_buffer += amount`. @@ -112,6 +116,7 @@ - NFR-2: 같은 portfolio에 대한 동시 manual ledger write는 lost update가 없어야 한다(row lock 또는 동등한 concurrency control). - NFR-3: action/effect 계산은 기존 portfolio-hub domain/CLI 흐름과 일관되어야 한다. - NFR-4: manual user-token write와 daemon/service-token broker write는 source/permission/path 의미가 분리되어야 한다. +- NFR-4a: HTTP endpoint는 분리하되, ledger append + snapshot update의 action/effect 계산은 shared domain helper 또는 동일 test vectors로 중복/divergence를 방지해야 한다. - NFR-5: 모든 write request는 audit 가능한 note/source/requester 정보를 남길 수 있어야 한다. - NFR-6: 기존 `GET /v1/portfolios`, daemon ledger trade write, CLI portfolio flows에 회귀가 없어야 한다. @@ -131,6 +136,7 @@ - 복잡한 세금/회계 모델 - `QUANTITY_ADJUSTMENT` 1차 구현 - 기존 daemon/service-token broker ledger endpoint의 의미 변경 + - 기존 `POST /v1/portfolios/{portfolio_id}/ledger/trades`에 user/session-token manual write 권한을 추가하는 것 # 6. 리스크/가정 목록 ## 리스크 @@ -156,10 +162,10 @@ ## 오픈 질문 - OQ-1: 신규 manual write endpoint shape은 action-dispatch 단일 endpoint인가, action별 endpoint인가? - - 후보 A: `POST /v1/portfolios/{portfolio_id}/ledger/manual` with `action` enum - - 후보 B: `POST /v1/portfolios/{portfolio_id}/ledger/invest|transfer|buy|sell|withdraw|reversal` - - 상태: Open - - 종료 조건: REQ draft 전 API path/shape 확정 + - 상태: Answered + - 결정: 기존 `POST /v1/portfolios/{portfolio_id}/ledger/trades`는 유지하고, 신규 manual endpoint를 추가한다. 기본 shape은 `POST /v1/portfolios/{portfolio_id}/ledger/manual` + `action` enum 단일 action-dispatch endpoint로 한다. + - 근거: `/ledger/trades`는 trex-core/daemon/service-token broker 체결 보고이며, manual write는 user/session-token owner-scoped operation이다. auth/source/idempotency/audit 의미가 달라 HTTP endpoint는 분리한다. 단, 내부 회계 helper는 공유한다. + - 종료 조건: 완료 - OQ-2: `REVERSAL`은 target ledger entry id를 필수로 둘 것인가? - 상태: Open - 종료 조건: audit/reference policy 확정 @@ -196,7 +202,7 @@ - baseline doc diff: interface-contract/runtime-flows/data-model updates # 8. REQ로 넘기기 전 확인 체크 -- [ ] API endpoint shape 확정(OQ-1) +- [x] API endpoint shape 확정(OQ-1) — 기존 `/ledger/trades` 유지 + 신규 `POST /v1/portfolios/{portfolio_id}/ledger/manual` 추가 - [ ] REVERSAL target/reference policy 확정(OQ-2) - [ ] 부족 잔고/수량 validation policy 확정(OQ-3) - [ ] daemon-managed confirmation contract 확정(OQ-4) @@ -219,7 +225,7 @@ # 10. 사용자 결정 필요 항목 요약 ## DECIDE -- API shape: 단일 action-dispatch endpoint vs action별 endpoint +- ~~API shape: 단일 action-dispatch endpoint vs action별 endpoint~~ → 기존 `/ledger/trades` 유지, 신규 `POST /v1/portfolios/{portfolio_id}/ledger/manual` + `action` enum 추가 - REVERSAL target ledger id/reference 필수 여부 - 부족 cash/quantity 시 validation 거부 vs 결과 음수 허용 - daemon-managed portfolio warning/confirmation을 API-level로 강제할지 UI-level로 둘지 @@ -237,7 +243,7 @@ # 11. Discovery Freeze - Handoff Decision: 보류(draft) -- Handoff Rationale: trex-web dcy-011의 backend-first 후속 Discovery로 생성했다. 현행 portfolio-hub 구조와 action/effect는 확인했으나 API shape, reversal reference, validation, daemon-managed confirmation contract 결정이 필요하다. +- Handoff Rationale: trex-web dcy-011의 backend-first 후속 Discovery로 생성했다. 현행 portfolio-hub 구조와 action/effect는 확인했고, 기존 `/ledger/trades` 유지 + 신규 `/ledger/manual` 추가 방향은 확정했다. 남은 결정은 reversal reference, validation, daemon-managed confirmation contract, history fields, legacy PROFIT mapping이다. - Ready for REQ Drafting: false - Confirmed By: 미정 - Confirmed At (KST): 미정