# DASH-001: Dashboard Real Data Integration **Status:** In Review **Created:** 2026-01-08 **Tags:** dashboard, api, discord-client, database, real-time ## 1. Context & User Story * **As a:** Bot Administrator * **I want to:** See real data on the dashboard instead of mock/hardcoded values * **So that:** I can monitor actual bot metrics, user activity, and system health in real-time ## 2. Technical Requirements ### Data Model Changes - [ ] No new tables required - [ ] SQL migration required? **No** – existing schema already has `users`, `transactions`, `moderationCases`, and other relevant tables ### API / Interface #### New Dashboard Stats Service Create a new service at `shared/modules/dashboard/dashboard.service.ts`: ```typescript interface DashboardStats { guilds: { count: number; changeFromLastMonth?: number; }; users: { active: number; changePercentFromLastMonth?: number; }; commands: { total: number; changePercentFromLastMonth?: number; }; ping: { avg: number; changeFromLastHour?: number; }; recentEvents: RecentEvent[]; activityOverview: ActivityDataPoint[]; } interface RecentEvent { type: 'success' | 'error' | 'info'; message: string; timestamp: Date; } ``` #### API Endpoints | Method | Path | Description | |--------|------|-------------| | `GET` | `/api/stats` | Returns `DashboardStats` object | | `GET` | `/api/stats/realtime` | WebSocket/SSE for live updates | ### Discord Client Data The `AuroraClient` (exported from `bot/lib/BotClient.ts`) provides access to: | Property | Data Source | Dashboard Metric | |----------|-------------|------------------| | `client.guilds.cache.size` | Discord.js | Total Servers | | `client.users.cache.size` | Discord.js | Active Users (approximate) | | `client.ws.ping` | Discord.js | Avg Ping | | `client.commands.size` | Bot commands | Commands Registered | | `client.lastCommandTimestamp` | Custom property | Last command run time | ### Database Data Query from existing tables: | Metric | Query | |--------|-------| | User count (registered) | `SELECT COUNT(*) FROM users WHERE is_active = true` | | Commands executed (today) | `SELECT COUNT(*) FROM transactions WHERE type = 'COMMAND_RUN' AND created_at >= NOW() - INTERVAL '1 day'` | | Recent moderation events | `SELECT * FROM moderation_cases ORDER BY created_at DESC LIMIT 10` | | Recent transactions | `SELECT * FROM transactions ORDER BY created_at DESC LIMIT 10` | > [!IMPORTANT] > The Discord client instance (`AuroraClient`) is in the `bot` package, while the web server is in the `web` package. Need to establish cross-package communication: > - **Option A**: Export client reference from `bot` and import in `web` (same process, simple) > - **Option B**: IPC via shared memory or message queue (separate processes) > - **Option C**: Internal HTTP/WebSocket between bot and web (microservice pattern) ## 3. Constraints & Validations (CRITICAL) - **Input Validation:** - API endpoints must not accept arbitrary query parameters - Rate limiting on `/api/stats` to prevent abuse (max 60 requests/minute per IP) - **System Constraints:** - Discord API rate limits apply when fetching guild/user data - Cache Discord data and refresh at most every 30 seconds - Database queries should be optimized with existing indices - API response timeout: 5 seconds maximum - **Business Logic Guardrails:** - Do not expose sensitive user data (only aggregates) - Do not expose Discord tokens or internal IDs in API responses - Activity history limited to last 24 hours to prevent performance issues - User counts should count only registered users, not all Discord users ## 4. Acceptance Criteria 1. [ ] **Given** the dashboard is loaded, **When** the API `/api/stats` is called, **Then** it returns real guild count from Discord client 2. [ ] **Given** the bot is connected to Discord, **When** viewing the dashboard, **Then** the "Total Servers" shows actual `guilds.cache.size` 3. [ ] **Given** users are registered in the database, **When** viewing the dashboard, **Then** "Active Users" shows count from `users` table where `is_active = true` 4. [ ] **Given** the bot is running, **When** viewing the dashboard, **Then** "Avg Ping" shows actual `client.ws.ping` value 5. [ ] **Given** recent bot activity occurred, **When** viewing "Recent Events", **Then** events from `transactions` and `moderation_cases` tables are displayed 6. [ ] **Given** mock data exists in components, **When** the feature is complete, **Then** all hardcoded values in `Dashboard.tsx` are replaced with API data ## 5. Implementation Plan ### Phase 1: Data Layer & Services - [ ] Create `shared/modules/dashboard/dashboard.service.ts` with statistics aggregation functions - [ ] Add helper to query active user count from database - [ ] Add helper to query recent transactions (as events) - [ ] Add helper to query moderation cases (as events) --- ### Phase 2: Discord Client Exposure - [ ] Create a client stats provider that exposes Discord metrics - [ ] Implement caching layer to avoid rate limiting (30-second TTL) - [ ] Export stats getter from `bot` package for `web` package consumption --- ### Phase 3: API Implementation - [ ] Add `/api/stats` endpoint in `web/src/server.ts` - [ ] Wire up `dashboard.service.ts` functions to API - [ ] Add error handling and response formatting - [ ] Consider adding rate limiting middleware --- ### Phase 4: Frontend Integration - [ ] Create custom React hook `useDashboardStats()` for data fetching - [ ] Replace hardcoded values in `Dashboard.tsx` with hook data - [ ] Add loading states and error handling - [ ] Implement auto-refresh (poll every 30 seconds or use SSE/WebSocket) --- ### Phase 5: Activity Overview Chart - [ ] Query hourly command/transaction counts for last 24 hours - [ ] Integrate charting library (e.g., Recharts, Chart.js) - [ ] Replace "Chart Placeholder" with actual chart component --- ## Architecture Decision Required > [!WARNING] > **Key Decision: How should the web server access Discord client data?** > > The bot and web server currently run in the same process. Recommend: > - **Short term**: Direct import of `AuroraClient` singleton in API handlers > - **Long term**: Consider event bus or shared state manager if splitting to microservices ## Out of Scope - User authentication/authorization for API endpoints - Historical data beyond 24 hours - Command execution tracking (would require new database table) - Guild-specific analytics (separate feature) --- ## Implementation Notes **Status:** In Review **Implemented:** 2026-01-08 **Branch:** `feat/dashboard-real-data-integration` **Commit:** `17cb70e` ### Files Changed #### New Files Created (7) 1. `shared/modules/dashboard/dashboard.types.ts` - TypeScript interfaces 2. `shared/modules/dashboard/dashboard.service.ts` - Database query service 3. `shared/modules/dashboard/dashboard.service.test.ts` - Service unit tests 4. `bot/lib/clientStats.ts` - Discord client stats provider with caching 5. `bot/lib/clientStats.test.ts` - Client stats unit tests 6. `web/src/hooks/use-dashboard-stats.ts` - React hook for data fetching 7. `tickets/2026-01-08-dashboard-real-data-integration.md` - This ticket #### Modified Files (3) 1. `web/src/server.ts` - Added `/api/stats` endpoint 2. `web/src/pages/Dashboard.tsx` - Integrated real data with loading/error states 3. `.gitignore` - Removed `tickets/` to track tickets in version control ### Test Results ``` ✓ 11 tests passing ✓ TypeScript check clean (bun x tsc --noEmit) ``` ### Architecture Decision Used **Option A** (direct import) for accessing `AuroraClient` from web server, as both run in the same process. This is the simplest approach and avoids unnecessary complexity.