# 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
