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>
6.9 KiB
6.9 KiB
REQ-027: DELETE /v1/portfolios/{portfolio_id} 신설 (soft delete)
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: Justin Ko
Intent
- v1 API에 portfolio 종료 경로(
DELETE /v1/portfolios/{portfolio_id})를 신설해 user/admin이 HTTP로 portfolio를 종료할 수 있도록 한다. - dcy-003 OQ-1 결정에 따라 soft delete(
status='disabled')로 구현해 데이터 보존성과 운영 복구 가능성을 확보한다. hard delete 경로는 v1에 노출하지 않는다.
Requirement
- 신규 라우트
DELETE /v1/portfolios/{portfolio_id}(Bearer 인증 필수). - 토큰 분기 규칙 (REQ-025/026과 동일 패턴):
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.
- soft delete 동작:
portfolios.status = 'disabled'로 전환managed_by_daemon_id는NULL로 자동 해제updated_at갱신- 의존 데이터(
portfolio_ledger,ledger_trades,portfolio_comments,portfolios.tag_ids) 모두 보존
- disabled 상태 write 차단 (REQ-026/029/030/031에서도 검증되는 정책):
PATCH(status 전이 외 필드 변경) → HTTP 409 또는 422POST /ledger/trades→ 차단(REQ-029에서 처리)- tag/comment 추가·수정·삭제 → 차단(REQ-030/031에서 처리)
- 복구 경로: admin이
PATCH /v1/portfolios/{portfolio_id}body{"status": "enabled"}(또는 이전 status)로 전환(REQ-026 AC-9). daemon 재배정은 별도 호출. - 비존재
portfolio_id는 HTTP 404. ownership 불일치는 HTTP 403. - 이미
disabled상태인 portfolio에 재호출 시 HTTP 200 + 멱등 응답(또는 HTTP 409 — 본 REQ 구현 시 확정). - 응답: HTTP 200 또는 204 + (HTTP 200 시) disabled 상태 portfolio 또는 확정 응답.
Acceptance Criteria
- Given session token + 본인 active portfolio, When
DELETE /v1/portfolios/{id}, Then HTTP 200/204 +portfolios.status='disabled'+managed_by_daemon_id IS NULL사후 상태. - Given AC-1 실행 후, When
portfolio_ledger/ledger_trades/portfolio_comments/portfolios.tag_ids조회, Then 의존 데이터가 모두 보존되어 있다. - Given admin token + 타 user active portfolio, When
DELETE /v1/portfolios/{id}, Then HTTP 200/204 + 동일 사후 상태. - Given session token + 타 user portfolio, When
DELETE /v1/portfolios/{id}, Then HTTP 403 (ownership 불일치). - Given service token, When
DELETE /v1/portfolios/{id}, Then HTTP 403 fail-closed. - Given client token(폐지 전), When
DELETE /v1/portfolios/{id}, Then HTTP 403 fail-closed. - Given Bearer token 없음, When
DELETE /v1/portfolios/{id}, Then HTTP 401. - Given 비존재
portfolio_id, WhenDELETE /v1/portfolios/{id}, Then HTTP 404. - Given disabled portfolio + admin
PATCH status='enabled', WhenPATCH, Then HTTP 200 + 복구. (REQ-026 AC-9와 연계) - Given AC-1 실행 후 disabled portfolio에 ledger trade/tag/comment write 시도, When 시도, Then 모두 차단(HTTP 409 또는 422). (REQ-029/030/031과 연계 검증)
Impacted Area
- Docs:
docs/interface-contract.md— DELETE /v1/portfolios/{id} 명세 (REQ-032)docs/runtime-flows.md— soft delete flow + disabled write 차단 + 복구 (REQ-032)docs/data-model.md— Portfolio.status='disabled' 의미 + 의존 데이터 보존 정책 (REQ-032)
- Modules:
app/api/v1_portfolios.py— DELETE 라우트app/services/portfolio_service.py:delete— 기존 메서드 재사용 시 soft delete로 변경 또는 신규soft_delete_portfolio헬퍼app/repositories/portfolio_repository.py,app/repositories/postgres.py—set_portfolio_status(portfolio_id, status, clear_daemon=True)메서드 신규 또는 기존update_portfolio활용
- Tests:
- 신규/갱신
tests/test_v1_portfolios_crud.py— AC-1~10 검증
- 신규/갱신
Notes
- dcy-003 R-2(disabled 누적 가시성·write 차단 일관성)는 본 REQ + REQ-028
?include_disabledopt-in 정책 + REQ-026/029/030/031의 차단 검증으로 함께 완화. - 누적 disabled 정리(아카이브, 영구 삭제 운영 SOP)는 본 Discovery 범위 밖. 별도 운영 Discovery로 위임.
- 본 REQ는 hard delete 경로를 v1에 노출하지 않으므로 hard 삭제 운영은 DB 직접 접근 또는 별도 운영 도구로만 가능.
- Source: dcy-003 FR-4, OQ-1, OQ-2, OQ-5, NFR-1, NFR-3, NFR-4.
Change Log
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~10 전 케이스 pytest 통과 (2026-05-21, 298 PASSED). soft_delete_portfolio: status='disabled', managed_by_daemon_id=NULL, 의존 데이터 보존.
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-4 산출물.
Intent
- v1 portfolio 종료 경로 + soft delete 정책 명시.
Acceptance Criteria Delta
- Added:
- AC-1~10 최초 작성
Impacted Area Delta
- Docs: docs/interface-contract.md, docs/runtime-flows.md, docs/data-model.md (REQ-032)
- Modules: app/api/v1_portfolios.py, app/services/portfolio_service.py, app/repositories/* — 최초 지정
- 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/026과 동일 batch 권장
Validation Plan
- pytest TestClient로 AC-1~10 검증; soft delete 사후 상태 + 의존 데이터 보존 + 복구 경로 + write 차단 일관성