{"slug":"architecture/ARCHITECTURE_REFERENCE","title":"Workspace Projection Architecture","section":"architecture","sectionLabel":"Architecture","status":"unclassified","type":"document","path":"architecture/ARCHITECTURE_REFERENCE.mdx","bytes":9283,"description":null,"updated":null,"source":"integratewise/Integratewise-docs-wiki","content":"\n\n> **Tier C — Historical.** This document is a point-in-time snapshot preserved for reference. For current architecture, see [CANONICAL_PLATFORM_ARCHITECTURE.md](../architecture/CANONICAL_PLATFORM_ARCHITECTURE.md).\n\n## Overview\n\nThis document defines the architectural contract between frontend and backend for the IntegrateWise dashboard.\n\n**Core Principle:** Frontend doesn't know about backend service topology. Frontend only knows about **one DTO**.\n\n---\n\n## The Single Contract: WorkspaceDashboard\n\n```typescript\ninterface WorkspaceDashboard {\n  // Tier 1: Operational (required)\n  health_score: number\n  metrics: WorkspaceMetrics\n  tasks: DashboardTask[]\n  activity: DashboardActivity[]\n  insights: DashboardInsight[]\n  search: DashboardSearch\n\n  // Tier 2: Optional (nice to have)\n  calendar?: DashboardCalendarEvent[]\n  email?: DashboardEmail[]\n  documents?: DashboardDocument[]\n\n  // Metadata\n  last_updated: string\n  next_sync: string\n}\n```\n\n**That's it.** This is the ONLY object the frontend needs to understand.\n\n---\n\n## Frontend Architecture\n\n### How HomeView Consumes the DTO\n\n```tsx\n  const [dashboard, setDashboard] = useState<WorkspaceDashboard | null>(null)\n  const [error, setError] = useState<string | null>(null)\n  const [isLoading, setIsLoading] = useState(true)\n\n  // ONE API call\n  useEffect(() => {\n    const loadDashboard = async () => {\n      try {\n        const gateway = getGateway()\n        const data = await gateway.workspace.dashboard()\n        setDashboard(data)\n      } catch (err) {\n        setError(err.message)\n      } finally {\n        setIsLoading(false)\n      }\n    }\n    loadDashboard()\n  }, [])\n\n  // Every widget is a pure presentation component\n  return (\n    <HealthCard health={dashboard?.health_score} />\n    <KPICards metrics={dashboard?.metrics} />\n    <TasksPanel tasks={dashboard?.tasks} />\n    <ActivityFeed activity={dashboard?.activity} />\n    <InsightsPanel insights={dashboard?.insights} />\n  )\n}\n```\n\n**Key properties:**\n- ✅ Single `dashboard` state (not 10 different states)\n- ✅ Single useEffect (not multiple per widget)\n- ✅ Widgets are pure presentation (receive data as props)\n- ✅ No widget knows about API endpoints\n- ✅ No service names in frontend code\n\n### Widget Pattern\n\nEvery widget follows this pattern:\n\n```tsx\nfunction HealthCard({ health }: { health?: number }) {\n  return (\n    \n      <CardContent>\n        {health ? (\n          <div>\n            <p>Health Score</p>\n            <p className=\"text-5xl\">{health}/100</p>\n          </div>\n        ) : (\n          <Skeleton />\n        )}\n      </CardContent>\n    \n  )\n}\n```\n\n**Rules:**\n- ✅ Receives data as props\n- ✅ No API calls\n- ✅ No Supabase hooks\n- ✅ No service-specific knowledge\n- ✅ Pure presentation logic\n\n---\n\n## Backend Architecture\n\n### Projection Builder Pattern\n\nThe backend Gateway receives a dashboard request and orchestrates:\n\n```\nGET /api/v1/workspace/dashboard\n    ↓\nProjection Builder\n    ↓\nFetches from multiple services:\n  • Workspace Aggregator (entity data)\n  • Adaptive Spine (health score)\n  • Adaptive Memory (context)\n  • Intelligence Service (signals, insights)\n  • Connector Platform (data sync status)\n  • Task Service (pending tasks)\n  • Audit Log (recent activity)\n  • Search Index (search metadata)\n    ↓\nShapes data into WorkspaceDashboard DTO\n    ↓\nReturns single JSON response\n```\n\n### Service Choreography\n\nThe Projection Builder is responsible for:\n\n1. **Parallel fetches** where possible\n2. **Fallback values** if a service is down\n3. **Caching** the result\n4. **Rate limiting** the aggregation\n5. **Partial responses** if needed\n\nExample pseudocode:\n\n```typescript\nasync function buildDashboard(workspaceId: string): WorkspaceDashboard {\n  // Parallel fetches\n  const [health, tasks, activity, insights] = await Promise.allSettled([\n    adaptiveSpine.getHealth(workspaceId),\n    taskService.list(workspaceId),\n    auditLog.recent(workspaceId, 5),\n    intelligence.signals(workspaceId, { limit: 5 }),\n  ])\n\n  // Build DTO with fallbacks\n  return {\n    health_score: health.value?.score ?? 50,\n    metrics: health.value?.metrics ?? {},\n    tasks: tasks.value ?? [],\n    activity: activity.value ?? [],\n    insights: insights.value ?? [],\n    search: { query: \"\", recent_queries: [], suggestions: [] },\n    last_updated: new Date().toISOString(),\n    next_sync: new Date(Date.now() + 5 * 60000).toISOString(),\n  }\n}\n```\n\n### Why This Works\n\n- ✅ **Resilience:** One service down doesn't break the dashboard\n- ✅ **Performance:** Parallel fetches, single response\n- ✅ **Maintainability:** Frontend never changes when backend services do\n- ✅ **Scalability:** Can add services to projection without frontend code\n- ✅ **Cacheable:** Entire dashboard can be cached as one unit\n- ✅ **Real-time Ready:** Can broadcast updates via WebSocket as one DTO\n\n---\n\n## SDK Layer (Gateway SDK)\n\nThe `GatewaySDK` exposes business operations:\n\n```typescript\n// ✅ GOOD - Business operations\nsdk.workspace.dashboard()\nsdk.accounts.list()\nsdk.tasks.list()\nsdk.search.query(\"term\")\n\n// ❌ BAD - Service topology\nsdk.cognitiveSpine.getHealth()\nsdk.intelligence.signals()\nsdk.adaptiveMemory.list()\n```\n\n### Usage\n\n```typescript\nconst gateway = getGateway()\ngateway.setToken(authToken)\n\n// Single call for entire dashboard\nconst dashboard = await gateway.workspace.dashboard()\n\n// Individual operations for other pages\nconst accounts = await gateway.accounts.list()\nconst searchResults = await gateway.search.query(\"customer\")\n```\n\n---\n\n## Phase 1 Success Criteria\n\n| Item | Status |\n|------|--------|\n| Dashboard renders at `/dashboard` | ✅ |\n| No redirects | ✅ |\n| Single DTO pattern | ✅ |\n| Health metrics live | ✅ |\n| KPI cards live | ✅ |\n| Tasks live | ✅ |\n| Activity live | ✅ |\n| Zero mock data | ⏳ |\n| Backend Projection Builder | ⏳ |\n| Search live | ⏳ |\n\n---\n\n## Implementation Checklist\n\n### Backend (Next)\n\n- [ ] Create Projection Builder service\n- [ ] Implement `GET /api/v1/workspace/dashboard`\n- [ ] Fetch from Adaptive Spine (health)\n- [ ] Fetch from Task service (tasks)\n- [ ] Fetch from Audit log (activity)\n- [ ] Fetch from Intelligence (insights)\n- [ ] Add caching (5 min TTL)\n- [ ] Add fallback values\n- [ ] Test in Postman\n- [ ] Test with multiple services down\n\n### Frontend (Current)\n\n- [x] Define WorkspaceDashboard DTO\n- [x] Create GatewaySDK\n- [x] Update HomeView to use single DTO\n- [x] Make all widgets pure presentation\n- [x] Remove Supabase hooks from HomeView\n- [ ] Test on localhost\n- [ ] Remove remaining mock data\n- [ ] Add error boundaries\n- [ ] Wire search functionality\n\n---\n\n## Data Flow Diagram\n\n```\nUser at /dashboard\n        ↓\nDashboard Page\n        ↓\nHomeView Component\n        ↓\nuseEffect triggers\n        ↓\ngetGateway().workspace.dashboard()\n        ↓\nHTTP GET /api/v1/workspace/dashboard\n        ↓\nGateway Router\n        ↓\nProjection Builder Service\n        ↓\nParallel fetches to:\n  • Adaptive Spine\n  • Task Service\n  • Audit Log\n  • Intelligence Service\n        ↓\nAggregate into WorkspaceDashboard DTO\n        ↓\nReturn JSON\n        ↓\nHomeView setState(dashboard)\n        ↓\nRender all widgets from single DTO\n```\n\n---\n\n## Key Files\n\n| File | Purpose |\n|------|---------|\n| `packages/lib/src/workspace-dashboard.ts` | DTO definitions (Tier 1, 2, 3) |\n| `packages/lib/src/gateway-sdk.ts` | SDK wrapper (business operations) |\n| `apps/web/components/views/home-view.tsx` | Dashboard view (uses DTO) |\n| `apps/web/app/(app)/dashboard/page.tsx` | Route handler |\n\n---\n\n## Migration Path\n\nIf you have existing components using Supabase hooks:\n\n### Before\n```tsx\nfunction OldDashboard() {\n  const { data: health } = useWorkspaceHealth()\n  const { data: tasks } = useTasks()\n  const { data: activity } = useActivities()\n  \n  return (\n    <HealthCard health={health} />\n    <TasksPanel tasks={tasks} />\n    <ActivityFeed activity={activity} />\n  )\n}\n```\n\n### After\n```tsx\nfunction NewDashboard() {\n  const [dashboard] = useDashboard() // Single hook\n\n  return (\n    <HealthCard health={dashboard.health_score} />\n    <TasksPanel tasks={dashboard.tasks} />\n    <ActivityFeed activity={dashboard.activity} />\n  )\n}\n```\n\n---\n\n## Future Enhancements\n\nOnce this architecture is solid:\n\n1. **Real-time Updates** - WebSocket emits new `WorkspaceDashboard` DTO\n2. **Selective Refresh** - Update individual sections (tasks, activity) without full reload\n3. **Offline Support** - Cache entire DTO locally\n4. **Optimistic Updates** - Update UI before server confirms\n5. **Streaming** - Large responses via streaming protocol\n6. **GraphQL** - Replace REST with GraphQL for better caching\n7. **Per-user Permissions** - RLS at DTO level\n\n---\n\n## Principles\n\n1. **Single Responsibility** - Frontend doesn't care about backend topology\n2. **Contracts Over Implementation** - DTO is the only contract\n3. **Composition Over Coupling** - Projection Builder composes services\n4. **Resilience** - Graceful degradation if services are down\n5. **Performance** - Parallel fetches, cached responses\n6. **Maintainability** - One place to change (Projection Builder)\n\n---\n\n**Last Updated:** 2024-01-15\n**Status:** ACTIVE\n**Owner:** Architecture Team\n"}