Add ProofLine criteria documentation and Strategy Catalog v1 implementation

- Add acceptance criteria documentation (AC-0013 through AC-0023)
- Add Line-0003 discovery documentation
- Implement Strategy Catalog v1 with new database migration
- Update portfolio API endpoints and schemas
- Refactor strategy and portfolio services
- Add strategy management CLI commands
- Update domain models with strategy catalog support
- Add comprehensive tests for v1 strategies
- Update design documentation (data model, interfaces, runtime flows)
This commit is contained in:
2026-08-15 11:18:31 +09:00
parent 5fc389dea8
commit 6e02d92282
48 changed files with 2114 additions and 393 deletions
+12 -1
View File
@@ -121,13 +121,24 @@
- Any valid token; `_require_write_token` blocks service/client (`token_type ∈ {service, client}` → HTTP 403).
- admin with `body.user_id` → creates portfolio for target user; otherwise uses `auth.user_id`.
- `repo.get_asset_by_id(asset_id)` → None or inactive → HTTP 422.
- `repo.get_or_create_strategy_set(strategy_name, strategy_params_json)` → resolves strategy.
- Required `strategy_id` is resolved with `repo.get_strategy_set(strategy_id)`; unknown → HTTP 404, inactive → HTTP 409. Portfolio mutation never creates a strategy implicitly.
- `repo.create_portfolio(...)` with `status="enabled"` → HTTP 201 `PortfolioItem`.
2. **PATCH /v1/portfolios/{portfolio_id}** (update):
- `_require_write_token` blocks service/client → HTTP 403.
- `_get_portfolio_or_404(auth, portfolio_id, repo)` → checks ownership; non-owner non-admin → HTTP 403.
- If `portfolio.status == "disabled"`: non-status fields present → HTTP 409 (only status restoration allowed).
- Optional `strategy_id` is resolved before `repo.update_portfolio(...)`; unknown → HTTP 404, inactive → HTTP 409. The stable catalog ID becomes `active_strategy_id`.
- `repo.update_portfolio(portfolio_id, **fields)` → HTTP 200 `PortfolioItem`.
## Flow: `v1 Strategy Catalog`
1. Read callers list active entries at `GET /v1/strategies`; admin reads include inactive entries under `/v1/admin/strategies`.
2. Admin create canonicalizes the JSON config. A new row stores the requested status at revision 1; a matching existing name/config reuses its stable ID and applies an actual status change through the normal update path.
3. Admin PATCH requires at least one field. The row is locked `FOR UPDATE`; effective no-ops keep the current revision, while concurrent real changes serialize, preserve ID, recompute the derived nick from the latest committed name/config, increment revision once, and update `updated_at`.
4. Inactive entries are retained for existing portfolio references but rejected for new assignments.
5. Portfolio selection locks an active strategy `FOR SHARE` in the same transaction as portfolio INSERT/UPDATE. Admin PATCH/DELETE lock it `FOR UPDATE`; DELETE checks both `active_strategy_id` and `avabile_strategies` and deletes in one transaction. Any reference returns HTTP 409, otherwise deletion returns HTTP 204 without an orphan or inactive-selection race.
6. Legacy unversioned `/strategy-sets` routes are not registered.
7. BUY/SELL persistence updates balances, price, buffer, timestamps, and ledger atomically but never writes `active_strategy_id` or `avabile_strategies`; a stale trade snapshot therefore cannot restore an old or deleted catalog assignment after a concurrent strategy change.
3. **DELETE /v1/portfolios/{portfolio_id}** (soft delete):
- `_require_write_token` blocks service/client → HTTP 403.
- `_get_portfolio_or_404` → ownership check.