Phase 2 moves the dashboard off raw task-state leakage and onto stable public projections. Task status, task listings, progress websocket events, and portfolio recommendation reads now load persisted contracts when available, expose a contract-first envelope, and keep legacy fields inside a compat block instead of smearing them across top-level payloads.
Constraint: existing task-status JSON and recommendation files must continue to read successfully during migration
Rejected: return raw task_results directly from API and websocket | keeps legacy fields as the public contract and blocks cutover
Rejected: rewrite stored recommendation files in-place | adds risky migration work before rollout gates exist
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: keep public payload shaping in job/result-store projections, not in ad-hoc route logic
Tested: python -m pytest web_dashboard/backend/tests/test_executors.py web_dashboard/backend/tests/test_services_migration.py web_dashboard/backend/tests/test_api_smoke.py web_dashboard/backend/tests/test_main_api.py web_dashboard/backend/tests/test_portfolio_api.py -q
Tested: python -m pytest orchestrator/tests/test_application_service.py orchestrator/tests/test_trading_graph_config.py -q
Tested: python -m compileall orchestrator tradingagents web_dashboard/backend
Not-tested: legacy frontend rendering against new compat-wrapped task payloads
Not-tested: real websocket clients and provider-backed end-to-end analysis
* fix: add API key auth, pagination, and configurable CORS to dashboard API
Security hardening:
- API key authentication via X-API-Key header on all endpoints
(opt-in: set DASHBOARD_API_KEY or ANTHROPIC_API_KEY env var to enable)
If no key is set, endpoints remain open (backward-compatible)
- WebSocket auth via ?api_key= query parameter
- CORS now configurable via CORS_ORIGINS env var (default: allow all)
Pagination (all list endpoints):
- GET /api/reports/list — limit/offset with total count
- GET /api/portfolio/recommendations — limit/offset with total count
- DEFAULT_PAGE_SIZE=50, MAX_PAGE_SIZE=500
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add tests for critical security fixes in dashboard API
- remove_position: empty position_id must be rejected (mass deletion fix)
- get_recommendation: path traversal blocked for ticker/date inputs
- get_recommendations: pagination limit/offset works correctly
- Named constants verified: semaphore, pagination, retry values
- API key auth: logic tested for both enabled/disabled states
- _auth_error helper exists for 401 responses
15 tests covering: mass deletion, path traversal (2 vectors),
pagination, auth logic, magic number constants
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>