feat: v1 portfolio mutation, sub-resources, ledger path migration (BAT-008~011)
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>
This commit is contained in:
@@ -4,8 +4,8 @@
|
||||
- Baseline Seed: .stagepilot/bootstrap/baseline.yaml
|
||||
- Status: confirmed
|
||||
- Owner: repository-maintainers
|
||||
- Last Updated (KST): 2026-05-20 00:00
|
||||
- Source Discovery / Batch: bootstrap-baseline, bat-001, bat-002, bat-006, bat-007, bat-003, bat-004, bat-005
|
||||
- Last Updated (KST): 2026-05-21 00:00
|
||||
- Source Discovery / Batch: bootstrap-baseline, bat-001, bat-002, bat-006, bat-007, bat-003, bat-004, bat-005, BAT-006(dcy-004), BAT-007(dcy-004), BAT-008(dcy-004)
|
||||
|
||||
## Project Summary
|
||||
- PortfolioHub exposes portfolio management and trading ledger workflows through a FastAPI service and a companion CLI.
|
||||
@@ -83,12 +83,15 @@
|
||||
- Hosts StagePilot skills, document templates, and helper scripts such as stagepilot-doctor and stagepilot-bootstrap-seed.
|
||||
- app/api/
|
||||
- Defines FastAPI route surfaces for health, authentication, users, strategy sets, portfolios, and tags.
|
||||
- v1 route surfaces: `v1_assets.py` (GET /v1/assets token-branched, POST /v1/assets admin catalog, PATCH /v1/assets/{id}, PATCH /v1/assets/{id}/deactivate, POST/DELETE /v1/assets/{id}/tags), `v1_tags.py` (POST/GET /v1/tags, PATCH /v1/tags/{id}/deactivate), `v1_portfolios.py` (POST/DELETE /v1/portfolios/{id}/tags), `v1_user_info.py` (GET /v1/user_info), `v1_ledger.py` (POST /v1/assets/{asset_id}/ledger/trades).
|
||||
- v1 route surfaces: `v1_assets.py` (GET /v1/assets token-branched, POST /v1/assets admin catalog, PATCH /v1/assets/{id}, PATCH /v1/assets/{id}/deactivate, POST/DELETE /v1/assets/{id}/tags), `v1_tags.py` (POST/GET /v1/tags, PATCH /v1/tags/{id}/deactivate), `v1_portfolios.py` (POST/PATCH/DELETE/GET /v1/portfolios; GET/POST/DELETE /v1/portfolios/{id}/tags; POST/GET/PATCH/DELETE /v1/portfolios/{id}/comments; POST /v1/portfolios/{id}/ledger/trades), `v1_user_info.py` (GET /v1/user_info).
|
||||
- `v1_ledger.py` 제거됨 (BAT-011/REQ-029): 구 path `POST /v1/assets/{asset_id}/ledger/trades` 삭제, 신 path는 `v1_portfolios.py`로 통합.
|
||||
- GET /v1/assets supports service/user/admin token branching; admin catalog CRUD requires admin token; tag endpoints added by BAT-004.
|
||||
- app/cli/
|
||||
- Defines the Typer entrypoint, command groups, output helpers, and operator-facing command flows.
|
||||
- Command groups: `asset` (catalog CRUD via admin), `portfolio`, `strategy`, `tag` (tag master CRUD and apply/remove; BAT-005), `user`, `service-token`, `credential` (broker credential management), and health commands (`health-check`, `init-db`, `migrate-db`).
|
||||
- Command groups: `asset` (catalog CRUD via admin), `portfolio`, `strategy`, `tag` (tag master CRUD and apply/remove; BAT-005), `user`, `service-token`, `daemon`, `credential` (broker credential management), and health commands (`health-check`, `init-db`, `migrate-db`).
|
||||
- `app/cli/commands/tag.py` (BAT-005): `pfhub tag create/list/deactivate/apply asset|portfolio/remove asset|portfolio`; direct repo method calls following existing AppContext pattern. `pfhub portfolio tag add/list/remove` removed (breaking change, BAT-005).
|
||||
- `app/cli/commands/service_tokens.py` (BAT-006/BAT-007): `issue`, `rotate`, `rebind` (daemon_id 변경, runtime_id 불변), `revoke`, `list`, `migrate-null-daemon --dry-run` (NULL daemon_id active token 진단 CLI).
|
||||
- `app/cli/commands/daemon.py` (BAT-007): `create`, `list`, `update` (`--deactivate --force` 시 바인딩 service token 즉시 revoke).
|
||||
- app/core/
|
||||
- Owns configuration loading, auth guards, security helpers, and shared error handling.
|
||||
- `encryption.py`: Fernet-based credential payload encrypt/decrypt helpers. Reads `CREDENTIAL_ENCRYPTION_KEY` env var via `Settings.require_credential_encryption_key()`.
|
||||
@@ -97,9 +100,10 @@
|
||||
- app/repositories/
|
||||
- Provides the repository protocol, repository factory, and concrete Postgres persistence implementation.
|
||||
- Key methods added in bat-006: `get_portfolio_by_name_and_user(owner_user_id, name) -> Portfolio | None` for (owner_user_id, name) → portfolio_id (UUID) resolution used by CLI commands.
|
||||
- Key methods added in BAT-007: `revoke_tokens_by_daemon_id(daemon_id) -> int` (UPDATE auth_tokens WHERE daemon_id=X AND revoked_at IS NULL); `list_service_tokens_with_null_daemon() -> list[AuthToken]` (NULL daemon_id active service token 조회); abstract methods added to `portfolio_repository.py`.
|
||||
- app/schemas/
|
||||
- Defines request and response schemas for HTTP contracts.
|
||||
- `v1.py`: Contract schemas for v1 API (AssetItem, AssetsResponse, UserInfoResponse, BrokerItem, LedgerTradeRequest/Response, AssetCatalogCreateRequest, AssetCatalogUpdateRequest, AssetCatalogResponse, TagItem, TagCreateRequest, TagListResponse, TagApplyRequest, TagApplyResponse; tag schemas added by BAT-004).
|
||||
- `v1.py`: Contract schemas for v1 API — TagItem, TagCreateRequest, TagListResponse, TagApplyRequest, TagApplyResponse (BAT-004); AssetItem, AssetsResponse, UserInfoResponse, BrokerItem, LedgerTradeRequest/Response (BAT-001/002); AssetCatalogCreateRequest, AssetCatalogUpdateRequest, AssetCatalogResponse (BAT-002); PortfolioCreateRequest, PortfolioUpdateRequest, PortfolioItem, PortfolioListResponse (BAT-009); PortfolioTagListResponse, PortfolioCommentItem, PortfolioCommentRequest, PortfolioCommentUpdateRequest, PortfolioCommentListResponse (BAT-010).
|
||||
- app/services/
|
||||
- Implements business logic for auth, portfolios, strategy sets, and users.
|
||||
- migrations/
|
||||
@@ -132,7 +136,7 @@
|
||||
|
||||
| 소유 경로 | 관리 객체 | 비고 |
|
||||
|-----------|-----------|------|
|
||||
| ensure_schema() 전용 | `idx_auth_tokens_service_name_unique` (partial index) | Alembic revision에 없음 |
|
||||
| ensure_schema() 전용 | `idx_auth_tokens_service_name_unique` (partial index, BAT-006/REQ-017: `AND revoked_at IS NULL` 조건 추가) | Alembic revision 20260520_0022에도 CONCURRENTLY 버전 존재 |
|
||||
| Alembic 전용 | `portfolios.market`, `auth_tokens.runtime_id`, `idx_auth_tokens_runtime_id_unique`, `broker_credentials`, `ledger_trades` | ensure_schema()에 없음 — v1 API 전제 조건 |
|
||||
| 양쪽 공유 (IF NOT EXISTS 보호) | users, auth_tokens, strategy_sets, portfolios, portfolio_ledger, portfolio_comments, portfolio_tags + 대부분의 인덱스 | ensure_schema() 우선 실행 후 Alembic 실행 시 충돌 없음 |
|
||||
|
||||
@@ -162,6 +166,9 @@
|
||||
|
||||
## Change Log
|
||||
|
||||
- 2026-05-21 KST: BAT-011 (REQ-029) — ledger path migration: `v1_ledger.py` 제거; `v1_portfolios.py`에 `POST /{id}/ledger/trades` 흡수; `app/main.py` include 정리. Source Discovery/Batch 헤더 갱신.
|
||||
- 2026-05-21 KST: BAT-010 (REQ-032) — v1 portfolio surface 반영: v1_portfolios.py 책임 갱신 (POST/PATCH/DELETE/GET /v1/portfolios + 태그/댓글 서브 라우트); v1.py schema 목록 갱신 (BAT-009/010 schema 5종 추가); Source Discovery/Batch 헤더 갱신.
|
||||
- 2026-05-21 KST: BAT-008 (REQ-019) — 패키지 구조 갱신: service-token rebind/migrate-null-daemon CLI 서브커맨드 추가 반영; daemon command group 및 --deactivate auto-revoke 동작 반영; repositories에 revoke_tokens_by_daemon_id / list_service_tokens_with_null_daemon 메서드 추가 반영; Schema Ownership 표의 idx_auth_tokens_service_name_unique 조건 갱신(AND revoked_at IS NULL).
|
||||
- 2026-05-20 KST: bat-005 — REQ-008 AC-3: added app/cli/commands/tag.py (pfhub tag command group); updated app/api/ to reflect v1_tags.py, v1_portfolios.py, v1_assets.py tag endpoints; updated app/schemas/v1.py tag schemas; updated pfhub entry point (tags); noted pfhub portfolio tag removal.
|
||||
- 2026-05-11 KST: bat-007 — Added "Schema Ownership Boundary" section documenting ensure_schema() vs Alembic ownership zones, allowed/forbidden execution sequences, and legacy scope exclusion.
|
||||
- 2026-05-11 KST: bat-006 — Added get_portfolio_by_name_and_user() to repositories section; noted that portfolio_id is now a server-generated UUID.
|
||||
|
||||
Reference in New Issue
Block a user