Files
portfolio-hub/docs/runtime-flows.md
T
genichin 3509606c7e 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)
2026-05-02 11:37:42 +00:00

6.6 KiB

Portfolio Hub Runtime Flows

  • Baseline Mode: observed
  • Baseline Seed: .stagepilot/bootstrap/baseline.yaml
  • Status: confirmed
  • Owner: repository-maintainers
  • Last Updated (KST): 2026-05-01 00:00
  • Source Discovery / Batch: bootstrap-baseline, bat-001
  • Primary Runtime: mixed

Project Summary

  • PortfolioHub exposes portfolio management and trading ledger workflows through a FastAPI service and a companion CLI.

Purpose

  • This document is the current approved execution-flow baseline for the project.
  • It is a cross-cutting reference document for Discovery, REQ, Batch Design, Batch Verification, and implementation updates.

Scope

  • Covers representative command and runtime flows.
  • Does not duplicate full acceptance criteria or low-level implementation details.

Covered Entry Points

  • uvicorn app.main:app :: serve the authenticated HTTP API, OpenAPI docs, and startup bootstrap hooks
  • pfhub :: run operational CLI commands for health, users, portfolios, strategies, and service tokens
  • alembic upgrade head :: apply ordered database schema migrations for persistent environments

Shared Components

  • app/core/config.py Settings loading and environment normalization
  • app/core/auth.py permission guards and auth context resolution
  • app/services/* business logic for auth, users, portfolios, and strategy sets
  • app/repositories/factory.py repository selection and Postgres config construction
  • app/repositories/postgres.py Postgres persistence, schema bootstrap, and query execution

Flow: HTTP API Request Handling

  1. Uvicorn loads app.main:app, which creates the FastAPI application from create_app().
  2. create_app() loads Settings, registers middleware and routers, and wires exception handlers.
  3. During lifespan startup, the app optionally bootstraps an initial admin user when DB mode and bootstrap credentials are configured.
  4. Incoming requests pass through auth and permission dependencies before services mutate state or query persistence.
  5. Services call the repository factory, which returns PostgresPortfolioRepository only when PORTFOLIOHUB_DB_ENABLED=true.
  6. Routes serialize domain results into app/schemas response models or return HTTP 204 for deletion flows.

Flow: CLI Operational Command Execution

  1. The pfhub entrypoint builds a Typer application and injects Settings, console output, and a repository factory into AppContext.
  2. Command groups parse arguments, confirmations, and output format selection before invoking the relevant service or repository methods.
  3. Database setup commands use the shared settings layer to target the configured PostgreSQL or TimescaleDB instance.
  4. Read commands print table or JSON output, while write commands require explicit confirmation unless --force is supplied.
  5. Command failures surface as validation errors, feature-not-ready errors, or persistence and auth exceptions.

Flow Constraints

  • Persistence-dependent HTTP and CLI flows require PORTFOLIOHUB_DB_ENABLED=true plus valid TimescaleDB connection settings.
  • Permission levels read, trade-write, and admin must map consistently across API guards, issued tokens, and CLI mutations.
  • 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.
  • 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.