feat(REQ-005): implement TrEx Basic V1 API contract with auth, assets, ledger, and user endpoints
- Add V1 API routes for assets, ledger, and user info with complete CRUD operations - Implement authentication scopes and request validation via auth_routes.py - Extend schemas with V1-specific models for accounts, holdings, and positions - Add database queries and aggregations for P&L, performance, and account data - Include comprehensive test coverage for all V1 endpoints and integration flows - Update batch and release documentation with implementation and verification evidence - Sync project structure and runtime flows per V1 API contract requirements Closes implementation phase of BAT-001 (TrEx Basic V1 API Contract)
This commit is contained in:
+49
-9
@@ -4,8 +4,8 @@
|
||||
- Baseline Seed: .stagepilot/bootstrap/baseline.yaml
|
||||
- Status: confirmed
|
||||
- Owner: repository-maintainers
|
||||
- Last Updated (KST): 2026-04-30 22:13
|
||||
- Source Discovery / Batch: bootstrap-baseline
|
||||
- Last Updated (KST): 2026-05-01 00:00
|
||||
- Source Discovery / Batch: bootstrap-baseline, bat-001
|
||||
- Primary Runtime: mixed
|
||||
|
||||
## Project Summary
|
||||
@@ -57,18 +57,58 @@
|
||||
- Request validation and auth resolution should happen before persistence mutation or response rendering.
|
||||
- The health endpoint remains unauthenticated so infrastructure can probe readiness without a token.
|
||||
|
||||
## Flow: `v1 API — Service-Token Authentication`
|
||||
|
||||
1. v1 endpoint receives Bearer token from Authorization header.
|
||||
2. `require_read` resolves the token: checks env tokens first, then DB lookup via `get_token_principal()`.
|
||||
3. If DB token: validates `token_source == "db"` and `token_type == "service"`, else returns HTTP 403.
|
||||
4. `AuthContext` is populated with `user_id`, `token_type`, `permission`, and `runtime_id`.
|
||||
|
||||
## Flow: `v1 API — GET /v1/assets`
|
||||
|
||||
1. Service-token auth required (see above).
|
||||
2. `list_portfolios_with_strategies()` fetches all portfolios from DB.
|
||||
3. Optional `?status=<value>` query param filters portfolios by status field.
|
||||
4. For portfolios with `active_strategy_id`, `get_strategy_set()` fetches config and JSON-parses `strategy_params`; failures fall back to `{}`.
|
||||
5. Returns `AssetsResponse` with `total` and `assets[]` using new field names: `cash`, `quantity`, `broker_type`, `strategy_params`.
|
||||
|
||||
## Flow: `v1 API — GET /v1/user_info`
|
||||
|
||||
1. Service-token auth required. HTTP 404 if `runtime_id` is None.
|
||||
2. `get_user()` fetches user record by `user_id`.
|
||||
3. `list_broker_credentials()` fetches all broker credential rows for the user.
|
||||
4. For each credential, Fernet-decrypts `encrypted_payload` using `CREDENTIAL_ENCRYPTION_KEY`; decryption failures log a warning and return `credential_payload: null`.
|
||||
5. Returns `UserInfoResponse` with `trading_enabled` (from `is_active`), `disabled_reason`, and `brokers[]`.
|
||||
|
||||
## Flow: `v1 API — POST /v1/assets/{asset_id}/ledger/trades`
|
||||
|
||||
1. Service-token auth required with `trade-write` permission.
|
||||
2. Validates asset existence via `repo.get(asset_id)`; HTTP 404 if missing.
|
||||
3. Calls `insert_ledger_trade()` with idempotency key `(asset_id, order_id, execution_id)`.
|
||||
4. If new record: returns HTTP 201 with `status="new"`.
|
||||
5. If duplicate key with identical payload: returns HTTP 200 with `status="duplicate"`.
|
||||
6. If duplicate key with different payload: returns HTTP 409 with conflict detail.
|
||||
|
||||
## Flow: `v1 API — POST /auth/service-tokens`
|
||||
|
||||
1. Admin token auth required (`require_admin` dependency).
|
||||
2. Validates request body: `name`, `username`, `permission`, `expires_in_days` / `no_expiry`.
|
||||
3. Calls `AuthService.issue_service_token()` which creates a new DB token with `runtime_id`.
|
||||
4. Returns HTTP 201 with `token` (raw value), `runtime_id`, and `auth_token` metadata.
|
||||
|
||||
## Flow: `Application Startup Validation`
|
||||
|
||||
1. `lifespan` startup hook runs `_bootstrap_initial_user()` if DB enabled and bootstrap credentials configured.
|
||||
2. If `db_enabled=True`, calls `settings.require_credential_encryption_key()`.
|
||||
3. If `CREDENTIAL_ENCRYPTION_KEY` is not configured, raises `RuntimeError` and aborts startup.
|
||||
|
||||
## Current Gaps / Planned Changes
|
||||
|
||||
- End-to-end validation against a real PostgreSQL or TimescaleDB deployment is still pending.
|
||||
- Redis and Loki are configured as supporting infrastructure but are not yet represented as explicit runtime flows.
|
||||
- Ownership-scoped authorization remains an open evolution area after bootstrap.
|
||||
|
||||
## Update Triggers
|
||||
|
||||
- Update this document when a command entry point changes.
|
||||
- Update this document when a runtime orchestration path changes.
|
||||
- Update this document when a batch changes the approved flow baseline.
|
||||
- Broker credential write path (upsert) is available only via CLI; no HTTP API endpoint for credential registration exists yet.
|
||||
|
||||
## Change Log
|
||||
|
||||
- 2026-05-01 KST: bat-001 — Added v1 API flows (service-token auth, GET /v1/assets, GET /v1/user_info, POST ledger/trades, POST /auth/service-tokens), startup validation flow.
|
||||
- 2026-04-30 KST: Bootstrap baseline created from repository observation for initial StagePilot adoption.
|
||||
Reference in New Issue
Block a user