Shell:
- One shared NexusLayout for ALL routes (dashboard + pages): compact 68px
icon rail with hover-expand overlay, replaces both old sidebars + topbars
- Single flat nav source (railNav) — same menu everywhere incl. Settings
- Removed dead shell components (AppSidebar, AppHeader, Topbar, NavGroup,
NavItem, ModuleView) and dead nav routes; App.vue is now just RouterView
Live updates:
- Fix SSE loop in DashboardController: PeriodicTimer.WaitForNextTickAsync and
ChannelReader.ReadAsync were re-invoked while pending — every published
update threw InvalidOperationException and killed ALL live streams
- liveSync store: treat graceful stream close as disconnect (was stuck
connected=true with polling stopped -> page frozen until manual reload),
fast first retry, heartbeat watchdog (65s), reconnect on online/visibility
- One app-wide SSE connection owned by the layout instead of per-view
connect/disconnect churn; removed duplicate live-sync.ts store
Performance:
- Board endpoint: drop nested childTasks duplication (counts stay) — payload
104KB -> 65KB; SSE snapshots shrink equally
- nginx: gzip for JSON/JS/CSS (board 18KB, bundle 95KB over the wire);
text/event-stream excluded to keep SSE unbuffered
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Root cause: /api/bridge/health and /api/dashboard/live returned 404 live because
the source files existed on disk but were never committed to git. The CD pipeline
deploys from committed main, so the deployed containers lacked these endpoints.
Changes:
- Add GatewayBridgeController with /api/bridge/health endpoint
- Add DashboardController Live() SSE endpoint for /api/dashboard/live
- Add LiveUpdateService (in-memory pub/sub for SSE updates)
- Add TaskBridgeService (structured agent-to-backend bridge)
- Add nginx routing blocks for /api/bridge/ and /api/dashboard/live
- Add host-level nginx-nexus.conf blocks for bridge + live pass-through
- Update ServiceCollectionExtensions with DI registrations
- Update Dashboard.cs model with SSE-related DTOs
Verification after deploy:
curl https://nexus.noveria.net/api/bridge/health → 200 JSON
curl https://nexus.noveria.net/api/dashboard/live → 200 SSE stream
- Remove duplicate @keyframes pulse-* from 3 component files (already in nexus-tokens.css)
- Rename AgentDetail → AgentDetailData in dashboard types to avoid collision with types/agent.ts
- Extract shared formatNumber/initials/formatTime to utils/format.ts
- Simplify FlowBoard: use agentStore modal/selection getters instead of duplicating local state
- Add error banner + empty state to IrisChat; add loading skeleton + error/empty states to TaskStrip
- Remove 105-line unused mockAgents array from useFlowLayout
- Reduce operations store fallbacks from hardcoded preview data to minimal safe defaults
- Update operations store tests to match lean fallback structure
- Net: -73 lines, cleaner imports, fewer magic strings