Phase 2a: Projection Facade Layer - COMPLETE
Tier C — Historical. This document is a point-in-time snapshot preserved for reference. For current architecture, see CANONICAL_PLATFORM_ARCHITECTURE.md.
Overview
Frozen the backend architecture to support all frontends.
The Projection Facade Layer is the missing business assembler between the Gateway and the Capability Engine. It implements the architectural principle: "The backend is capable of everything. Every frontend should consume only what it needs."
What Was Built
1. Projection Context Types (services/projection-engine/src/types.ts)
Defines the contract for every frontend request:
ProjectionContext {
tenant_id, workspace_id, user_id // Identity
role, permissions // Access
device, user_agent // Environment
features, tier // Capabilities
projection_type, request_id, timestamp // Request info
}
Every request carries full context about who, what, when, and where. The backend uses this to assemble only what's needed.
2. Workspace Facade (services/projection-engine/src/facades/workspace-facade.ts)
First concrete example of a Projection Facade:
WorkspaceProjection {
overview: {
health_score: 87
metrics: { total_revenue, active_customers, pending_tasks }
kpis: KPICard[]
}
execution: {
tasks: Task[]
workflows: Workflow[]
}
intelligence: {
signals: Signal[]
insights: Insight[]
recommendations: Recommendation[]
}
collaboration: {
activity: ActivityItem[]
}
search: {
enabled: boolean
placeholder: string
}
}
Key principle: Semantic sections, not widgets.
The Workspace projection is organized by what the user does, not how it's displayed:
overview- See the big pictureexecution- Get things doneintelligence- Understand what matterscollaboration- Know what changedsearch- Find anything
3. Facade Registry (services/projection-engine/src/facades/facade-registry.ts)
Central routing for all projection types:
FacadeRegistry {
facades: Map<string, IProjectionFacade>
loadProjection(context) → T
getAvailableProjections() → string[]
hasProjection(type) → boolean
registerFacade(type, facade)
unregisterFacade(type)
}
The registry is the routing layer that maps:
workspace→ WorkspaceFacadecustomer-success→ CustomerSuccessFacade (TODO)executive→ ExecutiveFacade (TODO)developer→ DeveloperFacade (TODO)brainstorm→ BrainstormFacade (TODO)twin→ TwinFacade (TODO)
4. Projection Endpoint (services/gateway/src/router.ts)
New unified frontend entry point:
POST /api/v1/projection
{
projection_type: 'workspace' | 'customer-success' | 'executive' | ...
tenant_id, workspace_id, user_id
role, permissions, device, features
}
Returns:
{
request_id, timestamp
projection: WorkspaceProjection (or other type)
metadata: {
cached, cache_key, ttl_seconds
capabilities_available, user_permissions
rate_limit: { limit, remaining, reset_at }
}
}
Architecture Flow
Frontend Gateway Facade Layer
│ │ │
├─→ POST /api/v1/ │ │
│ projection { │ │
│ projection_type, │ │
│ tenant_id, │ │
│ user_id, │ │
│ role, device... │ │
│ } │ │
│ ├─→ FacadeRegistry │
│ │ .loadProjection() │
│ │ ├─→ WorkspaceFacade
│ │ │ .buildProjection()
│ │ │
│ │ ├─→ Compose capabilities
│ │ │ (TODO: Adaptive Spine,
│ │ │ Tasks, Intelligence,
│ │ │ Audit Log, Search)
│ │ │
│ │ ← WorkspaceProjection │
│ ← ProjectionResponse │ { overview, execution...}
│ { │
│ projection: {...}, │
│ metadata: {...} │
│ } │
Key Principles Implemented
1. Backend Decides, Not Frontend
Old Way (Widget Coupling):
- Frontend calls 5+ endpoints
- Frontend composes response
- Frontend knows service names
- Frontend is tightly coupled to backend topology
New Way (Projection Facades):
- Frontend makes 1 request: "give me workspace"
- Backend assembles response
- Backend hides service topology
- Frontend is loosely coupled
2. Context-Aware Assembly
The backend knows:
if (context.device === 'mobile') {
// Return smaller payloads
// Limit data sets
}
if (context.role === 'viewer') {
// Hide sensitive metrics
// Remove edit capabilities
}
if (context.tier === 'free') {
// Remove recommendations
// Limit search results
}
3. Semantic Sections Over Widgets
Not organized by component, but by user intent:
// WRONG - Widget Names
{
health_score_card: {...}
kpi_card: {...}
task_list: {...}
activity_feed: {...}
}
// RIGHT - Semantic Sections
{
overview: { health, metrics, kpis }
execution: { tasks, workflows }
intelligence: { signals, insights }
collaboration: { activity }
search: { ... }
}
4. Tier Structure
Tier 1 (Required)
├── overview (health, metrics)
├── execution (tasks, workflows)
├── intelligence (signals, insights)
├── collaboration (activity)
└── search
Tier 2 (Optional)
├── calendar (events)
├── email (messages)
└── documents
Tier 3 (Future)
├── webhooks
├── integrations
└── notifications
Frontend can depend on Tier 1. Tier 2 and 3 are nice-to-have.
How It Enables Multiple Products
// Workspace Projection - Operational Hub
sdk.projection.load({ projection_type: 'workspace' })
→ WorkspaceProjection { overview, execution, intelligence, collaboration }
// Customer Success Projection - Account Management
sdk.projection.load({ projection_type: 'customer-success' })
→ CustomerSuccessProjection { accounts, health, renewals, signals, timeline }
// Executive Projection - Business Intelligence
sdk.projection.load({ projection_type: 'executive' })
→ ExecutiveProjection { metrics, goals, insights, forecast, approvals }
// Developer Projection - Integration & Automation
sdk.projection.load({ projection_type: 'developer' })
→ DeveloperProjection { mcp, adk, workflows, registry, logs, schema }
// Brainstorm Projection - Creative Collaboration
sdk.projection.load({ projection_type: 'brainstorm' })
→ BrainstormProjection { ideas, memory, chat, tasks, search }
// Twin Projection - Full Platform Access
sdk.projection.load({ projection_type: 'twin' })
→ TwinProjection { all capabilities, full control }
Each product is just another projection. Same backend, different assembly.
Files Created
| File | Lines | Purpose |
|---|---|---|
services/projection-engine/src/types.ts | 117 | Context, request, response types |
services/projection-engine/src/facades/workspace-facade.ts | 417 | Workspace projection assembly |
services/projection-engine/src/facades/facade-registry.ts | 98 | Projection routing registry |
| Total New | 632 | Architectural foundation |
Files Updated
| File | Changes |
|---|---|
services/gateway/src/router.ts | Added POST /api/v1/projection endpoint |
| Kept legacy GET /api/v1/workspace/dashboard for backward compatibility |
Status: Phase 2a Complete
| Item | Status |
|---|---|
| Projection Context defined | ✅ |
| Facade pattern implemented | ✅ |
| Workspace Facade created | ✅ |
| Facade Registry created | ✅ |
| Unified endpoint created | ✅ |
| Backward compatibility maintained | ✅ |
| Ready for service integration | ✅ |
Ready for Phase 2b: Service Integration
The architecture is now ready to integrate real capabilities:
// Phase 2b Tasks
WorkspaceFacade.buildProjection():
1. Call Adaptive Spine → health_score, metrics
2. Call Workspace Service → tasks, workflows
3. Call Intelligence → signals, insights, recommendations
4. Call Audit Log → activity timeline
5. Call Search Index → search capabilities
6. Compose into WorkspaceProjection
7. Return to frontend
Then create additional facades:
8. CustomerSuccessFacade
9. ExecutiveFacade
10. DeveloperFacade
11. BrainstormFacade
12. TwinFacade
Why This Matters
Before Phase 2a:
Frontend was tightly coupled to services:
HomeView → GET /spine (health)
→ GET /signals (insights)
→ GET /tasks (tasks)
→ GET /audit (activity)
→ 4+ network requests
→ Widget-level orchestration
After Phase 2a:
Frontend is loosely coupled to backend:
HomeView → POST /projection { type: 'workspace' }
→ 1 request
→ Backend orchestrates
→ Receives complete DTO
→ Pure presentation
Impact:
- Network: 4+ requests → 1 request (75% reduction)
- Coupling: Tight → Loose (service topology hidden)
- Products: Single codebase, many projections
- Maintenance: Changes to services don't affect frontend
Git Commit
3da5c53 - feat: Implement Projection Facade Layer (Phase 2a)
Next Steps
Immediate (Phase 2b):
- Integrate Adaptive Spine into WorkspaceFacade
- Integrate Workspace Service into WorkspaceFacade
- Integrate Intelligence into WorkspaceFacade
- Integrate Audit Log into WorkspaceFacade
- Test complete data flow
Short-term (Phase 2c-2e):
- Create additional facades (CustomerSuccess, Executive, Developer)
- Add Projection Context pattern to all facades
- Implement caching at facade layer
- Add real-time WebSocket support
Medium-term (Phase 3+):
- Implement all Tier 2 sections (calendar, email, documents)
- Create Tier 3 sections (webhooks, integrations, notifications)
- Implement search capabilities
- Add analytics and monitoring
Architecture Freeze Summary
✅ Backend frozen. Ready to support all frontends.
The system now has:
- Clear layers (Gateway → Facade → Capability)
- Service topology hidden from frontend
- Semantic organization (sections, not widgets)
- Context-aware assembly (device, role, tier)
- Multiple projections from one backend
- One SDK for all frontends
Every backend capability is now discoverable and composable into any frontend product.