feat(V1-API): implement TREX-Basic consumer API contract with encryption and persistence

- Add V1 API endpoints: assets, ledger, user-info
- Implement Fernet-based credential payload encryption (req-010)
- Extend health response schema with runtime info (req-004)
- Add service token runtime ID issuance (req-005)
- Implement database schema migration for V1 API (req-009)
- Add comprehensive test coverage for V1 endpoints
- Update SRS with 10 new requirements (REQ-004 through REQ-011)
- Create batch planning, design, and verification for BAT-001
- Integrate review-discovery StagePilot skill
- Update documentation indices and baseline specs
This commit is contained in:
2026-05-02 09:06:15 +00:00
parent 24096a1e58
commit ce63c75c9c
37 changed files with 2851 additions and 21 deletions
+82
View File
@@ -0,0 +1,82 @@
"""Schemas for v1 (Consumer-Driven Contract) API endpoints."""
from __future__ import annotations
from datetime import datetime
from decimal import Decimal
from typing import Literal
from pydantic import BaseModel, Field
# ---------------------------------------------------------------------------
# GET /v1/assets
# ---------------------------------------------------------------------------
class AssetItem(BaseModel):
asset_id: str
broker: str
market: str | None = None
symbol: str
name: str
status: str
cash_balance: float
asset_quantity: float
price: float
profit_buffer: float
active_strategy_id: str | None = None
available_strategies: list[str] | None = None
tags: list[str] | None = None
owner_user_id: str | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
last_trade_at: datetime | None = None
class AssetsResponse(BaseModel):
assets: list[AssetItem]
total: int
# ---------------------------------------------------------------------------
# GET /v1/user_info
# ---------------------------------------------------------------------------
class UserInfoResponse(BaseModel):
user_id: str
username: str
email: str | None = None
permission: str
is_active: bool
disabled_reason: str | None = None
runtime_id: str
# ---------------------------------------------------------------------------
# POST /v1/assets/{asset_id}/ledger/trades
# ---------------------------------------------------------------------------
class LedgerTradeRequest(BaseModel):
order_id: str = Field(..., min_length=1)
execution_id: str = Field(..., min_length=1)
side: Literal["buy", "sell"]
quantity: Decimal = Field(..., gt=0)
price: Decimal = Field(..., gt=0)
fee_amount: Decimal = Field(default=Decimal("0"), ge=0)
tax_amount: Decimal = Field(default=Decimal("0"), ge=0)
executed_at: datetime
class LedgerTradeResponse(BaseModel):
ledger_entry_id: int
asset_id: str
order_id: str
execution_id: str
side: str
quantity: float
price: float
fee_amount: float
tax_amount: float
executed_at: datetime
recorded_at: datetime | None = None
created: bool