# VS-08: Risk Dashboard — Vertical Slice Specification **Domain:** Comprehensive Risk Monitoring **Capability:** Real-time aggregation of portfolio, risk metrics, stress scenarios, and alerts **User Goal:** "I need a unified view of my entire portfolio risk profile in one dashboard" --- ## Non-Goals - Custom dashboard builder (fixed layout) - Real-time market tick updates (EOD refresh acceptable) - Mobile-optimized view (desktop focus) --- ## Requirements ### Functional | Req ID | Description | RBAC | SLA | Evidence | |--------|-------------|------|-----|----------| | **DASH-001** | GET /api/dashboard/risk | DataReader | <500ms | Aggregated JSON | | **DASH-002** | Render portfolio composition (VS-04) | System | <100ms FE | Visual table | | **DASH-003** | Display risk metrics (VS-05) | System | <100ms FE | Metric cards | | **DASH-004** | Show stress scenarios (VS-06) | System | <100ms FE | Scenario grid | | **DASH-005** | List active alerts (VS-07) | System | <100ms FE | Alert badges | | **DASH-006** | Real-time updates via SignalR | System | <5s latency | WebSocket push | ### Non-Functional - **Availability:** 99.5% - **Latency:** <500ms aggregation, <100ms FE render - **Caching:** Cache dashboard for <1hr (refresh on alert escalation) - **Audit:** All data sourced from authoritative VS-04~07 tables --- ## State Transitions ``` Portfolio Snapshot (VS-04) Risk Metrics (VS-05) Stress Results (VS-06) Risk Alerts (VS-07) ↓ (All aggregated) Dashboard Data (VS-08) ↓ (Publish event) DashboardUpdated event → SignalR push ``` **Frequency:** On-demand + event-driven updates **Real-time:** SignalR WebSocket (no polling) --- ## Data & API Contracts ### GET /api/dashboard/risk **Response (200 OK):** ```json { "portfolioId": "550e8400-e29b-41d4-a716-446655440001", "snapshotDate": "2026-08-05", "portfolio": { "totalValue": 42700.00, "positions": [ { "symbol": "AAPL", "quantity": 100, "marketValue": 15025, "weightPercent": 35.3 } ] }, "riskMetrics": { "var95": 15250, "sharpe": 1.85, "sortino": 2.45, "volatility": 0.185, "concentration": { "topFivePercent": 52.3, "maxPosition": 40.0 } }, "stressResults": [ { "scenario": "bull", "portfolioLoss": 12500, "lossPercent": 4.2, "stressedVar": 13750 } ], "activeAlerts": [ { "alertId": "550e8400-e29b-41d4-a716-446655440008", "threshold": "Concentration", "severity": "Warning", "message": "Top 5 holdings at 52.3%" } ], "lastUpdate": "2026-08-05T10:00:00Z" } ``` ### SignalR Message **DashboardUpdated:** ```json { "eventType": "DashboardUpdated", "portfolioId": "550e8400-e29b-41d4-a716-446655440001", "changedComponents": ["riskMetrics", "activeAlerts"], "updatedAt": "2026-08-05T10:05:00Z" } ``` --- ## RBAC & Authorization | Operation | Role | Condition | |-----------|------|-----------| | VIEW dashboard | DataReader | Own portfolio only | | TRIGGER refresh | DataAnalyst | Manual override | --- ## Testing Strategy 1. **Unit:** Data aggregation logic (5 tests) 2. **Integration:** DB → aggregation → API (4 tests) 3. **E2E:** Full dashboard load + SignalR push (2 tests) 4. **Golden:** Known portfolio → expected snapshot --- ## Assumptions - All VS-04~07 data is fresh (<1hr old) - SignalR hub is available (separate deployment) - Portfolio ID is authenticated via RBAC --- ## Vertical Slice Boundary ✅ **In Scope:** Aggregation logic + API endpoint + real-time updates ❌ **Out of Scope:** Custom drill-down reports, export functionality **Rationale:** Minimal, read-only aggregation; all mutations in VS-04~07