From fefe8373ece3deaf64222bfaa7221db91f0db91d Mon Sep 17 00:00:00 2001 From: Sayan Datta Date: Tue, 28 Apr 2026 10:59:07 +0530 Subject: [PATCH] feat: Ipad app features and Dream Weaver for Velocity WebOS --- .Agent Context/Codebase Analysis v1.1.md | 565 +++ ...elocity_Ipad_Production_Readiness_Audit.md | 3068 +++++++++++++++++ .github/workflows/production-readiness.yml | 63 + app/dist/index.html | 26 +- .../.tmp/tsconfig.app.tsbuildinfo | 2 +- .../.vite/deps/@radix-ui_react-avatar.js | 12 +- .../deps/@radix-ui_react-dropdown-menu.js | 6 +- .../.vite/deps/@react-three_drei.js | 18 +- app/node_modules/.vite/deps/_metadata.json | 88 +- app/node_modules/.vite/deps/recharts.js | 6 +- app/src/components/modules/Catalyst.tsx | 11 +- .../modules/CatalystDreamWeaverTab.tsx | 524 +++ app/src/lib/api.ts | 13 +- app/src/lib/crmApi.ts | 55 +- app/src/lib/dreamWeaverApi.ts | 197 ++ app/src/lib/velocityPlatformClient.ts | 39 +- app/src/lib/velocitySession.ts | 37 + app/src/oracle/lib/oracleApiClient.ts | 2 +- app/src/store/useMarketingStore.ts | 2 +- app/src/types/crmTypes.ts | 11 + backend/api/routes_admin_surface.py | 8 +- backend/api/routes_crm.py | 897 ++++- backend/api/routes_crm_imports.py | 690 +++- backend/api/routes_inventory.py | 34 +- backend/api/routes_mobile_edge.py | 88 +- backend/api/routes_observability.py | 24 + backend/auth/dependencies.py | 15 +- backend/auth/routes.py | 105 + backend/auth/service.py | 123 + backend/auth/user_directory.py | 45 + backend/crm/canonical_schema.py | 88 + backend/db/schema.sql | 2 + backend/db/schema_crm_canonical.sql | 28 + backend/main.py | 173 +- backend/migrations/__init__.py | 2 + backend/migrations/runner.py | 102 + .../202604230001_observability_foundation.sql | 22 + ...2604260001_mobile_edge_calendar_events.sql | 30 + ...02604260002_calendar_event_done_status.sql | 6 + backend/observability.py | 103 + backend/oracle/schema_extension_v2.sql | 2 +- backend/scripts/seed_ipad_investor_demo.py | 850 +++++ .../client_graph/aggregation_service.py | 65 +- backend/services/imports/ingest_service.py | 18 +- backend/tests/test_auth_tenant_contract.py | 212 ++ backend/tests/test_canonical_crm_auth.py | 162 + .../test_canonical_crm_tenant_scoping.py | 517 +++ backend/tests/test_crm_routes.py | 155 +- .../tests/test_dream_weaver_gateway_auth.py | 30 + .../tests/test_legacy_crm_canonical_bridge.py | 238 ++ backend/tests/test_legacy_crm_write_bridge.py | 243 ++ .../test_migrations_and_observability.py | 40 + .../test_surface_route_tenant_scoping.py | 470 +++ comfy_engine/scripts/dw_gateway_v2.py | 202 +- comfy_engine/scripts/gateway_auth.py | 49 + dw_gateway_v2_min.py | 172 +- iOS/App/ContentView.swift | 181 - iOS/Core/Config/AppConfig.swift | 19 - iOS/Core/Math/SunMath.swift | 92 - iOS/Core/Networking/ComfyClient.swift | 100 - iOS/Core/Networking/VelocityAPIClient.swift | 258 -- iOS/Core/State/AppStore.swift | 256 -- iOS/Features/Calendar/CalendarView.swift | 363 -- iOS/Features/Dashboard/DashboardView.swift | 442 --- iOS/Features/Inventory/ARSunOverlayView.swift | 118 - iOS/Features/Inventory/InventoryView.swift | 439 --- iOS/Features/Oracle/OracleView.swift | 960 ------ iOS/Features/Sentinel/SentinelView.swift | 413 --- iOS/Features/Settings/SettingsView.swift | 141 - iOS/README.md | 10 + .../velocity.xcodeproj/project.pbxproj | 171 +- .../contents.xcworkspacedata | 0 .../xcshareddata/swiftpm/Package.resolved | 0 .../velocity/App/ConfigurationGateView.swift | 42 + .../velocity/App/ContentView.swift | 53 +- .../velocity}/App/VelocityApp.swift | 0 .../AccentColor.colorset/Contents.json | 0 .../AppIcon.appiconset/Contents.json | 0 .../velocity/Assets.xcassets/Contents.json | 0 .../velocity/Core/Config/AppConfig.swift | 302 ++ .../Core/Config/SessionConfiguration.swift | 247 ++ .../velocity/Core/Config/SessionStore.swift | 204 ++ .../velocity/Core/Math/SunMath.swift | 0 .../Core/Networking/ComfyClient.swift | 176 +- .../Core/Networking/VelocityAPIClient.swift | 2165 ++++++++++++ .../velocity/Core/State/AppStore.swift | 815 +++++ .../Core/State/AppStoreRefreshPolicy.swift | 31 + .../velocity}/Core/UI/GlassBlurView.swift | 0 .../velocity}/Core/UI/VelocityTheme.swift | 0 .../Features/Calendar/CalendarView.swift | 1260 +++++++ .../Features/Clients/ClientsView.swift | 490 +++ .../Communications/CommunicationsView.swift | 17 +- .../Features/Dashboard/DashboardView.swift | 84 +- .../Features/Imports/ImportsView.swift | 467 +++ .../Features/Inventory/ARSunOverlayView.swift | 4 +- .../Inventory/InventoryModeAvailability.swift | 35 + .../Features/Inventory/InventoryView.swift | 88 +- .../Inventory/SimulatorSunOverlayView.swift | 4 +- .../Inventory/SunseekerViewModel.swift | 0 .../Oracle/OracleModeAvailability.swift | 19 + .../velocity/Features/Oracle/OracleView.swift | 1223 +++++++ .../Features/Sentinel/SentinelScope.swift | 28 + .../Features/Sentinel/SentinelView.swift | 17 +- .../Settings/SessionConfigurationPanel.swift | 267 ++ .../Features/Settings/SettingsView.swift | 224 ++ .../velocity/Info.plist | 23 +- .../velocityTests/VelocitySmokeTests.swift | 973 ++++++ iOS/velocity/velocity/App/VelocityApp.swift | 11 - .../velocity/Core/Config/AppConfig.swift | 37 - .../Core/Networking/VelocityAPIClient.swift | 363 -- .../velocity/Core/State/AppStore.swift | 149 - .../velocity/Core/UI/GlassBlurView.swift | 17 - .../velocity/Core/UI/VelocityTheme.swift | 60 - .../Features/Calendar/CalendarView.swift | 363 -- .../Communications/CommunicationsView.swift | 448 --- .../velocity/Features/Oracle/OracleView.swift | 325 -- .../Features/Settings/SettingsView.swift | 144 - 117 files changed, 19510 insertions(+), 6383 deletions(-) create mode 100644 .Agent Context/Codebase Analysis v1.1.md create mode 100644 .Agent Context/Sayan's Ipad docs/Velocity_Ipad_Production_Readiness_Audit.md create mode 100644 .github/workflows/production-readiness.yml create mode 100644 app/src/components/modules/CatalystDreamWeaverTab.tsx create mode 100644 app/src/lib/dreamWeaverApi.ts create mode 100644 app/src/lib/velocitySession.ts create mode 100644 backend/api/routes_observability.py create mode 100644 backend/auth/routes.py create mode 100644 backend/auth/service.py create mode 100644 backend/auth/user_directory.py create mode 100644 backend/crm/canonical_schema.py create mode 100644 backend/migrations/__init__.py create mode 100644 backend/migrations/runner.py create mode 100644 backend/migrations/versions/202604230001_observability_foundation.sql create mode 100644 backend/migrations/versions/202604260001_mobile_edge_calendar_events.sql create mode 100644 backend/migrations/versions/202604260002_calendar_event_done_status.sql create mode 100644 backend/observability.py create mode 100644 backend/scripts/seed_ipad_investor_demo.py create mode 100644 backend/tests/test_auth_tenant_contract.py create mode 100644 backend/tests/test_canonical_crm_auth.py create mode 100644 backend/tests/test_canonical_crm_tenant_scoping.py create mode 100644 backend/tests/test_dream_weaver_gateway_auth.py create mode 100644 backend/tests/test_legacy_crm_canonical_bridge.py create mode 100644 backend/tests/test_legacy_crm_write_bridge.py create mode 100644 backend/tests/test_migrations_and_observability.py create mode 100644 backend/tests/test_surface_route_tenant_scoping.py create mode 100644 comfy_engine/scripts/gateway_auth.py delete mode 100644 iOS/App/ContentView.swift delete mode 100644 iOS/Core/Config/AppConfig.swift delete mode 100644 iOS/Core/Math/SunMath.swift delete mode 100644 iOS/Core/Networking/ComfyClient.swift delete mode 100644 iOS/Core/Networking/VelocityAPIClient.swift delete mode 100644 iOS/Core/State/AppStore.swift delete mode 100644 iOS/Features/Calendar/CalendarView.swift delete mode 100644 iOS/Features/Dashboard/DashboardView.swift delete mode 100644 iOS/Features/Inventory/ARSunOverlayView.swift delete mode 100644 iOS/Features/Inventory/InventoryView.swift delete mode 100644 iOS/Features/Oracle/OracleView.swift delete mode 100644 iOS/Features/Sentinel/SentinelView.swift delete mode 100644 iOS/Features/Settings/SettingsView.swift create mode 100644 iOS/README.md rename iOS/{velocity => velocity-ipad}/velocity.xcodeproj/project.pbxproj (69%) rename iOS/{velocity => velocity-ipad}/velocity.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename iOS/{velocity => velocity-ipad}/velocity.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved (100%) create mode 100644 iOS/velocity-ipad/velocity/App/ConfigurationGateView.swift rename iOS/{velocity => velocity-ipad}/velocity/App/ContentView.swift (79%) rename iOS/{ => velocity-ipad/velocity}/App/VelocityApp.swift (100%) rename iOS/{velocity => velocity-ipad}/velocity/Assets.xcassets/AccentColor.colorset/Contents.json (100%) rename iOS/{velocity => velocity-ipad}/velocity/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename iOS/{velocity => velocity-ipad}/velocity/Assets.xcassets/Contents.json (100%) create mode 100644 iOS/velocity-ipad/velocity/Core/Config/AppConfig.swift create mode 100644 iOS/velocity-ipad/velocity/Core/Config/SessionConfiguration.swift create mode 100644 iOS/velocity-ipad/velocity/Core/Config/SessionStore.swift rename iOS/{velocity => velocity-ipad}/velocity/Core/Math/SunMath.swift (100%) rename iOS/{velocity => velocity-ipad}/velocity/Core/Networking/ComfyClient.swift (51%) create mode 100644 iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift create mode 100644 iOS/velocity-ipad/velocity/Core/State/AppStore.swift create mode 100644 iOS/velocity-ipad/velocity/Core/State/AppStoreRefreshPolicy.swift rename iOS/{ => velocity-ipad/velocity}/Core/UI/GlassBlurView.swift (100%) rename iOS/{ => velocity-ipad/velocity}/Core/UI/VelocityTheme.swift (100%) create mode 100644 iOS/velocity-ipad/velocity/Features/Calendar/CalendarView.swift create mode 100644 iOS/velocity-ipad/velocity/Features/Clients/ClientsView.swift rename iOS/{ => velocity-ipad/velocity}/Features/Communications/CommunicationsView.swift (95%) rename iOS/{velocity => velocity-ipad}/velocity/Features/Dashboard/DashboardView.swift (72%) create mode 100644 iOS/velocity-ipad/velocity/Features/Imports/ImportsView.swift rename iOS/{velocity => velocity-ipad}/velocity/Features/Inventory/ARSunOverlayView.swift (99%) create mode 100644 iOS/velocity-ipad/velocity/Features/Inventory/InventoryModeAvailability.swift rename iOS/{velocity => velocity-ipad}/velocity/Features/Inventory/InventoryView.swift (90%) rename iOS/{velocity => velocity-ipad}/velocity/Features/Inventory/SimulatorSunOverlayView.swift (98%) rename iOS/{velocity => velocity-ipad}/velocity/Features/Inventory/SunseekerViewModel.swift (100%) create mode 100644 iOS/velocity-ipad/velocity/Features/Oracle/OracleModeAvailability.swift create mode 100644 iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift create mode 100644 iOS/velocity-ipad/velocity/Features/Sentinel/SentinelScope.swift rename iOS/{velocity => velocity-ipad}/velocity/Features/Sentinel/SentinelView.swift (90%) create mode 100644 iOS/velocity-ipad/velocity/Features/Settings/SessionConfigurationPanel.swift create mode 100644 iOS/velocity-ipad/velocity/Features/Settings/SettingsView.swift rename iOS/{velocity => velocity-ipad}/velocity/Info.plist (90%) create mode 100644 iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift delete mode 100644 iOS/velocity/velocity/App/VelocityApp.swift delete mode 100644 iOS/velocity/velocity/Core/Config/AppConfig.swift delete mode 100644 iOS/velocity/velocity/Core/Networking/VelocityAPIClient.swift delete mode 100644 iOS/velocity/velocity/Core/State/AppStore.swift delete mode 100644 iOS/velocity/velocity/Core/UI/GlassBlurView.swift delete mode 100644 iOS/velocity/velocity/Core/UI/VelocityTheme.swift delete mode 100644 iOS/velocity/velocity/Features/Calendar/CalendarView.swift delete mode 100644 iOS/velocity/velocity/Features/Communications/CommunicationsView.swift delete mode 100644 iOS/velocity/velocity/Features/Oracle/OracleView.swift delete mode 100644 iOS/velocity/velocity/Features/Settings/SettingsView.swift diff --git a/.Agent Context/Codebase Analysis v1.1.md b/.Agent Context/Codebase Analysis v1.1.md new file mode 100644 index 00000000..6bd98ded --- /dev/null +++ b/.Agent Context/Codebase Analysis v1.1.md @@ -0,0 +1,565 @@ +# Codebase Analysis v1.1.md + +## Table of Contents / Chapters + +### 1. Overview +- Introduction to Project Velocity and its purpose +- Core principles and approach + +### 2. Architectural Mapping +- Overall System Architecture (Mermaid diagram) +- File Dependency Graph (Mermaid diagram) +- Data Flow Architecture (Mermaid diagram) + +### 3. Logic Decomposition +- Authentication & Authorization +- CRM Data Model +- Sentinel Biometric Intelligence +- Oracle Natural Language Intelligence +- Catalyst Marketing Orchestration +- Infrastructure & Deployment + +### 4. Connectivity Matrix +- Component interconnections and data flow +- Interconnection rationale + +### 5. First-Principles Guide +- Core Concept: AI-Augmented Sales Intelligence +- Why Real Estate Specifically? +- Principle 1: Data Sovereignty First +- Principle 2: Real-Time Perception Matters +- Principle 3: Intelligence Through Conversation +- Principle 4: Visual Storytelling Drives Sales +- Principle 5: Revision Control for Business Logic +- Design Philosophy: Production-Ready Craft +- Why This Architecture Succeeds + +### 6. API Endpoints Reference +- Authentication Endpoints +- CRM Endpoints +- Analytics Endpoints +- Oracle AI Intelligence Endpoints + - Oracle Canvas Management (v1) + - Oracle Template Management +- Sentinel Biometric Intelligence Endpoints +- Catalyst Marketing Orchestration Endpoints +- Vault Trackable Links Endpoints +- CCTV Surveillance Integration Endpoints +- Video Scene Mapping Endpoints +- Marketing Videos Endpoints +- Mobile Edge Communication Endpoints +- Inventory Management Endpoints +- Admin Surface Control Endpoints +- CRM Canonical Data Endpoints +- Runtime LLM Endpoints +- Infrastructure Notes + +## Overview + +Project Velocity is an on-prem real estate operating system designed for high-value property sales. It combines a premium WebOS, an iPad field app, a FastAPI neural core, ComfyUI-based media generation, and biometric/sentiment-assisted sales intelligence. The system enables brokers to operate at the speed of AI while preserving control, provenance, and safety for customer and revenue-critical data. + +This analysis provides a comprehensive understanding of the codebase from first principles, applying the Feynman Technique to distill complex implementations into intuitive concepts. + +## Architectural Mapping + +### Overall System Architecture + +```mermaid +graph TB + subgraph "User Interfaces" + WebOS[Velocity WebOS
React + TypeScript] + iPad[iPad App
Swift + MediaPipe] + end + + subgraph "Core Backend" + FastAPI[FastAPI Neural Core
PostgreSQL + JWT Auth] + end + + subgraph "AI Services" + Oracle[The Oracle
Natural Language Intelligence] + Sentinel[The Sentinel
Biometric Perception Engine] + Catalyst[The Catalyst
Marketing Campaign Orchestration] + Comfy[ComfyUI / Dream Weaver
Media Generation] + end + + subgraph "Infrastructure" + AWS[AWS GPU Workers
NVIDIA GPUs] + S3[S3 Asset Store
Models + Media] + Linux[Linux Control Surface
On-prem Deployment] + end + + WebOS --> FastAPI + iPad --> FastAPI + FastAPI --> Oracle + FastAPI --> Sentinel + FastAPI --> Catalyst + Catalyst --> Comfy + Comfy --> AWS + Comfy --> S3 + FastAPI --> Linux + + style FastAPI fill:#e1f5fe + style Oracle fill:#f3e5f5 + style Sentinel fill:#e8f5e8 + style Catalyst fill:#fff3e0 +``` + +### File Dependency Graph + +```mermaid +graph TD + subgraph "Frontend (React/Vite)" + App[App.tsx
Routing & Auth] + Store[useStore.ts
Zustand State] + Components[Components/
Modules & UI] + API[api.ts
HTTP Client] + end + + subgraph "Backend (FastAPI)" + Main[main.py
App Entry] + Routers[routers/
API Endpoints] + Services[services/
Business Logic] + DB[db/
Schema & Pool] + Auth[auth/
JWT & Users] + Oracle[oracle/
AI Intelligence] + end + + subgraph "AI Infrastructure" + Comfy[comfy_engine/
Media Generation] + Models[models/
AI Models] + Prompts[nemoclaw_prompts/
LLM Templates] + end + + subgraph "Deployment" + Infra[infrastructure/
Linux + AWS] + Agents[agents/
Orchestration] + end + + App --> API + API --> Main + Main --> Routers + Routers --> Services + Services --> DB + Services --> Auth + Services --> Oracle + Oracle --> Prompts + Comfy --> Infra + Infra --> Agents + + style Main fill:#e3f2fd + style Oracle fill:#fce4ec +``` + +### Data Flow Architecture + +```mermaid +flowchart LR + User[User Input] --> UI[WebOS/iPad UI] + UI --> API[FastAPI Endpoints] + API --> Auth[JWT Authentication] + API --> Policy[Policy Engine
Authorization] + API --> LLM[Nemoclaw LLM
Reasoning & Planning] + LLM --> Query[SQL Generation
Safe Queries] + Query --> DB[(PostgreSQL
CRM + Intelligence)] + DB --> Results[Query Results] + Results --> Viz[Visualization
Components] + Viz --> Canvas[Oracle Canvas
Persistent Views] + Canvas --> UI + + Sentinel[Sentinel Biometric] --> WS[WebSocket
Real-time] + WS --> Perception[Face Analysis
MediaPipe] + Perception --> QD[QD Scoring
NemoClaw] + QD --> DB + + Catalyst[Catalyst Marketing] --> Comfy[ComfyUI
Media Generation] + Comfy --> S3[S3 Assets] + Comfy --> GPU[AWS GPUs] + + style DB fill:#fff9c4 + style LLM fill:#e8f5e8 + style Comfy fill:#fce4ec +``` + +## Logic Decomposition + +### Authentication & Authorization + +**What:** Secure access control for all system functions +**How:** JWT tokens with role-based permissions (ADMIN, SALES_DIRECTOR, SENIOR_BROKER, JUNIOR_BROKER) +**Why:** Real estate involves sensitive client data; strict access prevents unauthorized sales interference + +**Key Implementation:** +- `backend/auth/dependencies.py`: JWT validation, user extraction, role enforcement +- `main.py`: Login endpoint with password hashing, user profile management +- Role hierarchy prevents junior brokers from approving high-value deals + +### CRM Data Model + +**What:** Canonical client and interaction records +**How:** PostgreSQL schema with leads, contacts, opportunities, interactions +**Why:** Real estate sales require accurate pipeline tracking and relationship history + +**Key Tables:** +- `leads_intelligence`: Core lead data with QD scores and tags +- `omnichannel_logs`: All interactions (calls, emails, visits) with timestamps +- `crm_people/crm_leads`: Structured client relationships and deal stages + +### Sentinel Biometric Intelligence + +**What:** Real-time visitor sentiment analysis for showroom engagement +**How:** Browser webcam + MediaPipe face landmarking → blend shapes → QD scoring +**Why:** Human emotion drives buying decisions; AI detects subtle cues brokers miss + +**Execution Flow:** +1. Browser captures video stream +2. MediaPipe extracts facial landmarks (68 points) +3. Blend shapes calculated (brow furrow, smile intensity, etc.) +4. NemoClaw LLM scores 1-100 QD (Qualification Desire) +5. Real-time dashboard updates for brokers + +**Key Decision:** Browser-side processing preserves privacy (no video leaves client device) + +### Oracle Natural Language Intelligence + +**What:** AI-powered data analysis through conversational queries +**How:** Natural language → SQL planning → visualization components → canvas +**Why:** Brokers shouldn't need SQL knowledge; AI translates business questions to insights + +**Architecture Layers:** +- **Prompt Orchestrator:** Decomposes complex requests into sub-queries +- **Natural DB Agent:** Schema introspection + safe SQL generation +- **Canvas Service:** Persistent visual workspaces with revision history +- **Collaboration:** Fork/merge workflows for team coordination + +**Why Canvas?** Unlike transient chat responses, canvases persist as living documents + +### Catalyst Marketing Orchestration + +**What:** Automated campaign creation and asset generation +**How:** Meta Ads API integration + ComfyUI media workflows +**Why:** Luxury real estate needs high-quality visuals; manual creation is too slow + +**Workflow:** +1. Campaign parameters → Meta API calls +2. Creative assets → ComfyUI (Dream Weaver, Wan 2.2, Qwen poster generation) +3. GPU processing on AWS → S3 storage +4. Performance tracking back to CRM + +### Infrastructure & Deployment + +**What:** Production-ready on-prem + cloud hybrid deployment +**How:** Linux control surface + AWS GPU workers + stable ingress +**Why:** Real estate firms demand data sovereignty; cloud-only solutions unacceptable + +**Key Components:** +- **Ingress:** Caddy on EC2 t4g.micro with TLS termination +- **Backend:** Linux systemd services for FastAPI, ComfyUI, LLM runtime +- **GPU:** AWS managed instances for media generation +- **Assets:** S3 for model storage, NVMe for fast access + +## Connectivity Matrix + +| Component | Inputs | Outputs | Dependencies | Protocols | +|-----------|--------|---------|--------------|-----------| +| WebOS Frontend | User actions, API responses | UI renders, API calls | FastAPI backend | HTTP/WS, JWT | +| iPad App | Camera feeds, user input | Biometric data, inventory scans | FastAPI backend | HTTP/WS | +| FastAPI Core | API requests, WS connections | DB queries, AI responses | PostgreSQL, Redis (future) | SQL, HTTP | +| Oracle Engine | Natural language prompts | Canvas components | NemoClaw LLM, PostgreSQL | Internal API | +| Sentinel Engine | Webcam streams | QD scores, alerts | MediaPipe, NemoClaw | WS real-time | +| Catalyst Engine | Campaign specs | Ad creatives, assets | Meta API, ComfyUI | HTTP, S3 | +| ComfyUI | Generation requests | Images/videos | GPU workers, S3 | Internal queue | +| PostgreSQL | SQL queries | Structured data | - | SQL | +| AWS GPUs | Media jobs | Generated assets | ComfyUI workflows | SSH/tunnel | + +**Interconnection Rationale:** +- **WebOS ↔ Backend:** Thin client architecture; all business logic server-side for security +- **Backend ↔ AI Services:** Modular design; each AI component (Oracle, Sentinel, Catalyst) operates independently but shares auth/policy +- **AI Services ↔ DB:** Direct SQL access with row-level security; no ORM abstraction to maintain performance +- **Infrastructure:** Hybrid on-prem/cloud; sensitive data stays on-prem, compute-intensive tasks use cloud GPUs + +## First-Principles Guide + +### Core Concept: AI-Augmented Sales Intelligence + +At its foundation, Project Velocity operates on the principle that human sales professionals excel at relationship-building and deal-closing, while AI excels at pattern recognition, data synthesis, and repetitive analysis. The system doesn't replace brokers—it amplifies their capabilities by providing real-time insights they couldn't otherwise access. + +**Why Real Estate Specifically?** +- High-value transactions ($M+ deals) with long sales cycles (months) +- Emotional decision-making influenced by subtle cues +- Complex data relationships (properties, buyers, markets, timing) +- Regulatory compliance requirements +- Need for visual storytelling (luxury properties) + +### Principle 1: Data Sovereignty First + +**Fundamental Truth:** Real estate firms own their client relationships. Project Velocity runs on-premise or in tenant-controlled cloud to maintain this ownership. + +**Implementation:** Linux-based deployment with optional AWS GPU extensions. All client data remains within tenant boundaries; only anonymous model requests leave for AI processing. + +### Principle 2: Real-Time Perception Matters + +**Fundamental Truth:** Buying decisions happen in moments of emotional connection. Project Velocity captures these moments through biometric analysis. + +**Implementation:** Sentinel uses facial expression analysis to score "Qualification Desire" (QD) on a 1-100 scale, alerting brokers to engagement spikes during property tours. + +### Principle 3: Intelligence Through Conversation + +**Fundamental Truth:** Sales professionals think in business terms, not database queries. The Oracle translates natural language into structured analytics. + +**Implementation:** Users ask "Show me whale leads from Dubai this quarter" and receive visual dashboards. The system plans safe SQL queries, executes them, and renders results as persistent canvas components. + +### Principle 4: Visual Storytelling Drives Sales + +**Fundamental Truth:** Luxury properties sell through aspiration and emotion. AI-generated media must be photorealistic and brand-consistent. + +**Implementation:** ComfyUI workflows (Dream Weaver, Wan 2.2) create property visualizations. Catalyst orchestrates campaigns with generated assets automatically uploaded to Meta Ads. + +### Principle 5: Revision Control for Business Logic + +**Fundamental Truth:** Sales strategies evolve through collaboration and iteration. Oracle canvases use Git-like branching for analytical workflows. + +**Implementation:** Canvas pages support forks, merge requests, and revision history. Brokers can experiment with analysis approaches without breaking production views. + +### Design Philosophy: Production-Ready Craft + +Project Velocity follows "experienced engineer" principles: +- **Error Handling:** No silent failures; all errors surface useful messages +- **Type Safety:** TypeScript frontend, typed Python backend +- **Performance:** Async everywhere, connection pooling, efficient queries +- **Security:** JWT auth, role-based access, input validation +- **Observability:** Structured logging, health checks, WebSocket monitoring +- **Maintainability:** Clear separation of concerns, comprehensive documentation + +### Why This Architecture Succeeds + +1. **Modular AI Services:** Each intelligence component (Oracle, Sentinel, Catalyst) operates independently, allowing incremental improvement and specialized optimization. + +2. **Hybrid Infrastructure:** Combines on-prem reliability with cloud scalability. Sensitive CRM data stays local; compute-intensive media generation uses managed GPUs. + +3. **Real-Time Integration:** WebSockets enable live updates across all surfaces. Brokers see lead scoring changes instantly, dashboard metrics update in real-time. + +4. **Business Logic in Code:** Revenue-critical workflows (lead qualification, campaign approval, deal closing) are explicit code paths, not AI hallucinations. + +5. **User-Centric Design:** The WebOS feels like a native application, not a bolted-on AI interface. Familiar patterns (canvases, dashboards, forms) reduce training time. + +This architecture transforms real estate sales from intuition-driven processes into data-augmented, AI-accelerated operations while preserving the human elements that drive luxury transactions. + +## API Endpoints Reference + +This section provides a comprehensive catalog of all API endpoints exposed by the Project Velocity backend, organized by functional module. Each endpoint includes the HTTP method, URI path, absolute HTTPS URL, and a brief description of its functionality. This serves as the definitive source of truth for the project's routing and interface architecture. + +### Authentication Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| POST | /api/auth/login | https://velocity.desineuron.in/api/auth/login | Authenticate a user with email/password and return JWT token | +| GET | /api/auth/me | https://velocity.desineuron.in/api/auth/me | Get current authenticated user's profile information | +| GET | /api/auth/users | https://velocity.desineuron.in/api/auth/users | List all active users in the system | +| POST | /api/auth/profile/avatar | https://velocity.desineuron.in/api/auth/profile/avatar | Upload and update user's profile avatar image | + +### CRM Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| GET | /api/leads | https://velocity.desineuron.in/api/leads | List leads with pagination and filtering | +| GET | /api/leads/{lead_id} | https://velocity.desineuron.in/api/leads/{lead_id} | Get detailed information for a specific lead | +| GET | /api/kanban/board | https://velocity.desineuron.in/api/kanban/board | Retrieve the kanban board view of leads by stage | +| GET | /api/chat-logs | https://velocity.desineuron.in/api/chat-logs | List chat logs for leads with optional lead filtering | +| GET | /api/leads/demographics | https://velocity.desineuron.in/api/leads/demographics | Get demographic analytics for leads (source, qualification) | + +### Analytics Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| GET | /api/analytics/sentiment-scatter | https://velocity.desineuron.in/api/analytics/sentiment-scatter | Get scatter plot data for sentiment analysis | + +### Oracle AI Intelligence Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| GET | /api/oracle/health | https://velocity.desineuron.in/api/oracle/health | Check Oracle system health and MCP tool availability | +| GET | /api/oracle/data-health | https://velocity.desineuron.in/api/oracle/data-health | Get data health metrics for database tables | +| GET | /api/oracle/schema-catalog | https://velocity.desineuron.in/api/oracle/schema-catalog | Retrieve schema catalog for database introspection | +| POST | /api/oracle/query | https://velocity.desineuron.in/api/oracle/query | Execute natural language query against database | +| GET | /api/oracle/mcp/tools | https://velocity.desineuron.in/api/oracle/mcp/tools | List available MCP tools for execution | +| POST | /api/oracle/mcp/execute | https://velocity.desineuron.in/api/oracle/mcp/execute | Execute an MCP tool with given query | +| POST | /api/oracle/workflow/preview | https://velocity.desineuron.in/api/oracle/workflow/preview | Preview workflow plan for a natural language prompt | + +#### Oracle Canvas Management (v1) + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| POST | /api/oracle/v1/canvas/pages | https://velocity.desineuron.in/api/oracle/v1/canvas/pages | Create a new Oracle canvas page | +| GET | /api/oracle/v1/canvas/pages | https://velocity.desineuron.in/api/oracle/v1/canvas/pages | List user's Oracle canvas pages | +| GET | /api/oracle/v1/canvas/pages/{page_id} | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id} | Get a specific canvas page | +| PUT | /api/oracle/v1/canvas/pages/{page_id} | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id} | Update a canvas page | +| DELETE | /api/oracle/v1/canvas/pages/{page_id} | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id} | Delete a canvas page | +| POST | /api/oracle/v1/canvas/pages/{page_id}/fork | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id}/fork | Create a fork of a canvas page | +| POST | /api/oracle/v1/canvas/pages/{page_id}/merge | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id}/merge | Merge changes into a canvas page | +| GET | /api/oracle/v1/canvas/pages/{page_id}/revisions | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id}/revisions | List revisions for a canvas page | +| POST | /api/oracle/v1/canvas/pages/{page_id}/revisions | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id}/revisions | Create new revision for a canvas page | +| GET | /api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id} | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id} | Get specific revision | +| PUT | /api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id} | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id} | Update a revision | +| DELETE | /api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id} | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id} | Delete a revision | +| GET | /api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id}/components | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id}/components | List components in a revision | +| POST | /api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id}/components | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id}/components | Add component to revision | +| PUT | /api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id}/components/{component_id} | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id}/components/{component_id} | Update component | +| DELETE | /api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id}/components/{component_id} | https://velocity.desineuron.in/api/oracle/v1/canvas/pages/{page_id}/revisions/{revision_id}/components/{component_id} | Delete component | + +#### Oracle Template Management + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| GET | /api/oracle/template-chapters | https://velocity.desineuron.in/api/oracle/template-chapters | List Oracle template chapters | +| POST | /api/oracle/template-chapters | https://velocity.desineuron.in/api/oracle/template-chapters | Create new template chapter | +| GET | /api/oracle/template-subchapters | https://velocity.desineuron.in/api/oracle/template-subchapters | List Oracle template subchapters | +| POST | /api/oracle/template-subchapters | https://velocity.desineuron.in/api/oracle/template-subchapters | Create new template subchapter | +| GET | /api/oracle/component-templates | https://velocity.desineuron.in/api/oracle/component-templates | List Oracle component templates | +| POST | /api/oracle/component-templates | https://velocity.desineuron.in/api/oracle/component-templates | Create new component template | +| GET | /api/oracle/component-templates/{template_id} | https://velocity.desineuron.in/api/oracle/component-templates/{template_id} | Get specific component template | +| POST | /api/oracle/component-templates/{template_id}/seed | https://velocity.desineuron.in/api/oracle/component-templates/{template_id}/seed | Add seed example to template | +| GET | /api/oracle/component-templates/{template_id}/seed | https://velocity.desineuron.in/api/oracle/component-templates/{template_id}/seed | List seed examples for template | +| POST | /api/oracle/component-templates/synthetic-jobs | https://velocity.desineuron.in/api/oracle/component-templates/synthetic-jobs | Submit synthetic template generation job | + +### Sentinel Biometric Intelligence Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| WebSocket | /api/sentinel/ws/notifications | wss://velocity.desineuron.in/api/sentinel/ws/notifications | Real-time notifications WebSocket | +| WebSocket | /api/sentinel/ws/perception | wss://velocity.desineuron.in/api/sentinel/ws/perception | Biometric perception data WebSocket | +| POST | /api/sentinel/consent | https://velocity.desineuron.in/api/sentinel/consent | Record biometric consent for lead | +| POST | /api/sentinel/session/complete | https://velocity.desineuron.in/api/sentinel/session/complete | Close a perception session and finalize QD score | +| POST | /api/sentinel/tag-lead | https://velocity.desineuron.in/api/sentinel/tag-lead | Apply NemoClaw lead tagging to CRM lead | +| GET | /api/sentinel/qd-score/{lead_id} | https://velocity.desineuron.in/api/sentinel/qd-score/{lead_id} | Get current QD score for a lead | + +### Catalyst Marketing Orchestration Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| POST | /api/catalyst/campaigns/create | https://velocity.desineuron.in/api/catalyst/campaigns/create | Bulk create Meta ad campaigns | +| POST | /api/catalyst/creative/sync | https://velocity.desineuron.in/api/catalyst/creative/sync | Upload ComfyUI assets to Meta | +| GET | /api/catalyst/insights/realtime | https://velocity.desineuron.in/api/catalyst/insights/realtime | Poll Meta Ads Insights API | +| POST | /api/catalyst/audiences/lookalike | https://velocity.desineuron.in/api/catalyst/audiences/lookalike | Push CRM leads to Meta Custom Audience | +| POST | /api/catalyst/auth/meta | https://velocity.desineuron.in/api/catalyst/auth/meta | OAuth token acquisition for Meta | + +### Vault Trackable Links Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| POST | /api/vault/generate-link | https://velocity.desineuron.in/api/vault/generate-link | Generate trackable URL for shared asset | +| GET | /vault/{tracking_hash} | https://velocity.desineuron.in/vault/{tracking_hash} | Public access to trackable vault link (no auth required) | + +### CCTV Surveillance Integration Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| POST | /api/cctv/event | https://velocity.desineuron.in/api/cctv/event | Ingest CCTV frame event from RTSP/ONVIF bridge | +| POST | /api/cctv/finalize-auto-mode | https://velocity.desineuron.in/api/cctv/finalize-auto-mode | Match or create lead after auto-mode session | + +### Video Scene Mapping Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| POST | /api/scenes/upload | https://velocity.desineuron.in/api/scenes/upload | Upload CSV scene map for marketing video | +| GET | /api/scenes/{video_asset_id} | https://velocity.desineuron.in/api/scenes/{video_asset_id} | Get scene map for specific video asset | + +### Marketing Videos Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| GET | /api/videos/marketing | https://velocity.desineuron.in/api/videos/marketing | List marketing videos available for Sentinel sessions | + +### Mobile Edge Communication Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| GET | /api/mobile-edge/events | https://velocity.desineuron.in/api/mobile-edge/events | List communication events for a lead | +| POST | /api/mobile-edge/events | https://velocity.desineuron.in/api/mobile-edge/events | Log new communication event | +| GET | /api/mobile-edge/memory | https://velocity.desineuron.in/api/mobile-edge/memory | List memory facts for a lead | +| POST | /api/mobile-edge/imports | https://velocity.desineuron.in/api/mobile-edge/imports | Operator-assisted import of recording/note | +| POST | /api/mobile-edge/notes | https://velocity.desineuron.in/api/mobile-edge/notes | Quick note attachment to lead | +| GET | /api/mobile-edge/calendar | https://velocity.desineuron.in/api/mobile-edge/calendar | Calendar events for authenticated user | +| POST | /api/mobile-edge/calendar | https://velocity.desineuron.in/api/mobile-edge/calendar | Create calendar event | +| PATCH | /api/mobile-edge/calendar/{calendar_event_id} | https://velocity.desineuron.in/api/mobile-edge/calendar/{calendar_event_id} | Update calendar event | +| DELETE | /api/mobile-edge/calendar/{calendar_event_id} | https://velocity.desineuron.in/api/mobile-edge/calendar/{calendar_event_id} | Cancel calendar event | +| GET | /api/mobile-edge/transcripts/{event_id} | https://velocity.desineuron.in/api/mobile-edge/transcripts/{event_id} | Transcript segments for event | +| GET | /api/mobile-edge/insights/{lead_id} | https://velocity.desineuron.in/api/mobile-edge/insights/{lead_id} | Insight recommendations for lead | +| POST | /api/mobile-edge/insights/{recommendation_id}/act | https://velocity.desineuron.in/api/mobile-edge/insights/{recommendation_id}/act | Act on or dismiss insight | +| GET | /api/mobile-edge/alerts | https://velocity.desineuron.in/api/mobile-edge/alerts | Active alerts for authenticated user | +| POST | /api/mobile-edge/session | https://velocity.desineuron.in/api/mobile-edge/session | Register surface session heartbeat | + +### Inventory Management Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| POST | /api/inventory/import-batches | https://velocity.desineuron.in/api/inventory/import-batches | Create inventory import batch | +| GET | /api/inventory/import-batches | https://velocity.desineuron.in/api/inventory/import-batches | List import batches | +| GET | /api/inventory/import-batches/{batch_id} | https://velocity.desineuron.in/api/inventory/import-batches/{batch_id} | Get batch status | +| POST | /api/inventory/properties | https://velocity.desineuron.in/api/inventory/properties | Create single property | +| GET | /api/inventory/properties | https://velocity.desineuron.in/api/inventory/properties | List inventory properties | +| GET | /api/inventory/properties/{property_id} | https://velocity.desineuron.in/api/inventory/properties/{property_id} | Get property details | +| PATCH | /api/inventory/properties/{property_id} | https://velocity.desineuron.in/api/inventory/properties/{property_id} | Update property | +| DELETE | /api/inventory/properties/{property_id} | https://velocity.desineuron.in/api/inventory/properties/{property_id} | Archive property | +| POST | /api/inventory/properties/{property_id}/media | https://velocity.desineuron.in/api/inventory/properties/{property_id}/media | Attach media to property | +| GET | /api/inventory/properties/{property_id}/media | https://velocity.desineuron.in/api/inventory/properties/{property_id}/media | List media for property | +| DELETE | /api/inventory/media/{media_asset_id} | https://velocity.desineuron.in/api/inventory/media/{media_asset_id} | Remove media asset | + +### Admin Surface Control Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| GET | /api/admin-surface/health | https://velocity.desineuron.in/api/admin-surface/health | System health overview | +| GET | /api/admin-surface/queues | https://velocity.desineuron.in/api/admin-surface/queues | Queue depth snapshot | +| GET | /api/admin-surface/installs | https://velocity.desineuron.in/api/admin-surface/installs | Surface session/install overview | +| POST | /api/admin-surface/actions | https://velocity.desineuron.in/api/admin-surface/actions | Submit admin action | +| GET | /api/admin-surface/actions | https://velocity.desineuron.in/api/admin-surface/actions | List admin action history | +| GET | /api/admin-surface/actions/{action_event_id} | https://velocity.desineuron.in/api/admin-surface/actions/{action_event_id} | Get specific admin action | +| GET | /api/admin-surface/logs | https://velocity.desineuron.in/api/admin-surface/logs | Recent Oracle audit event log | +| GET | /api/admin-surface/templates | https://velocity.desineuron.in/api/admin-surface/templates | Template catalog admin view | +| POST | /api/admin-surface/templates/{template_id}/publish | https://velocity.desineuron.in/api/admin-surface/templates/{template_id}/publish | Publish template | +| POST | /api/admin-surface/templates/{template_id}/archive | https://velocity.desineuron.in/api/admin-surface/templates/{template_id}/archive | Archive template | +| GET | /api/admin-surface/template-chapters | https://velocity.desineuron.in/api/admin-surface/template-chapters | List template chapters (admin) | +| GET | /api/admin-surface/synthetic-jobs | https://velocity.desineuron.in/api/admin-surface/synthetic-jobs | List synthetic generation jobs | +| POST | /api/admin-surface/synthetic-jobs/{job_id}/cancel | https://velocity.desineuron.in/api/admin-surface/synthetic-jobs/{job_id}/cancel | Cancel synthetic job | + +### CRM Canonical Data Endpoints + +| Method | Path | Absolute URL | Description | +|--------|------|--------------|-------------| +| POST | /api/crm/imports | https://velocity.desineuron.in/api/crm/imports | Upload CSV batch for import | +| GET | /api/crm/imports | https://velocity.desineuron.in/api/crm/imports | List import batches | +| GET | /api/crm/imports/{batch_id} | https://velocity.desineuron.in/api/crm/imports/{batch_id} | Get batch detail and proposals | +| PUT | /api/crm/imports/{batch_id}/review-proposal | https://velocity.desineuron.in/api/crm/imports/{batch_id}/review-proposal | Review import proposal | +| POST | /api/crm/imports/{batch_id}/commit | https://velocity.desineuron.in/api/crm/imports/{batch_id}/commit | Commit approved proposals | +| GET | /api/crm/contacts | https://velocity.desineuron.in/api/crm/contacts | Canonical contact list with QD summary | +| POST | /api/crm/contacts | https://velocity.desineuron.in/api/crm/contacts | Create new contact | +| GET | /api/crm/contacts/{person_id} | https://velocity.desineuron.in/api/crm/contacts/{person_id} | Canonical contact detail | +| GET | /api/crm/client-360/{person_id} | https://velocity.desineuron.in/api/crm/client-360/{person_id} | Client 360 aggregated snapshot | +| GET | /api/crm/opportunities | https://velocity.desineuron.in/api/crm/opportunities | Opportunity pipeline list | +| GET | /api/crm/tasks | https://velocity.desineuron.in/api/crm/tasks | Reminder/task list | +| POST | /api/crm/tasks | https://velocity.desineuron.in/api/crm/tasks | Create new task | +| GET | /api/crm/kanban | https://velocity.desineuron.in/api/crm/kanban | Kanban board (canonical leads) | +| GET | /api/crm/qd/{person_id} | https://velocity.desineuron.in/api/crm/qd/{person_id} | QD score history for person | +| GET | /api/crm/client-data | https://velocity.desineuron.in/api/crm/client-data | List client data records | +| GET | /api/crm/client-data/{person_id} | https://velocity.desineuron.in/api/crm/client-data/{person_id} | Get client data for person | +| PATCH | /api/crm/client-data/{person_id} | https://velocity.desineuron.in/api/crm/client-data/{person_id} | Update client data | +| GET | /api/crm/client-data/{person_id}/timeline | https://velocity.desineuron.in/api/crm/client-data/{person_id}/timeline | Client data timeline | +| POST | /api/crm/client-data/{person_id}/tasks | https://velocity.desineuron.in/api/crm/client-data/{person_id}/tasks | Create task for client | + +### Runtime LLM Endpoints +Method Path Absolute URL Description +GET /api/runtime/llm/providers https://velocity.desineuron.in/api/runtime/llm/providers List configured LLM providers and models +POST /api/runtime/llm/chat https://velocity.desineuron.in/api/runtime/llm/chat Execute single LLM chat completion +POST /api/runtime/llm/batch https://velocity.desineuron.in/api/runtime/llm/batch Submit persisted LLM batch job +GET /api/runtime/llm/jobs/{job_id} https://velocity.desineuron.in/api/runtime/llm/jobs/{job_id} Get batch job status +GET /api/runtime/llm/jobs/{job_id}/results https://velocity.desineuron.in/api/runtime/llm/jobs/{job_id}/results Get batch job results + +### Infrastructure Notes + +- **Caddy Reverse Proxy**: All endpoints are served through Caddy on port 443, proxying to FastAPI on localhost:8443 with TLS termination +- **Authentication**: JWT-based auth required for most endpoints (except public vault links) +- **WebSockets**: Real-time features use WebSocket connections for live updates +- **Role-Based Access**: Endpoints enforce role permissions (SENIOR_BROKER, ADMIN, etc.) +- **Tenant Isolation**: Multi-tenant architecture with tenant_id scoping +- **Audit Logging**: All mutations create immutable audit records +- **Health Checks**: System provides comprehensive health and queue monitoring endpoints \ No newline at end of file diff --git a/.Agent Context/Sayan's Ipad docs/Velocity_Ipad_Production_Readiness_Audit.md b/.Agent Context/Sayan's Ipad docs/Velocity_Ipad_Production_Readiness_Audit.md new file mode 100644 index 00000000..990e75a3 --- /dev/null +++ b/.Agent Context/Sayan's Ipad docs/Velocity_Ipad_Production_Readiness_Audit.md @@ -0,0 +1,3068 @@ +# Velocity iPad Production Readiness Audit + +Date: 2026-04-22 +Author: Codex +Scope: `iOS/velocity-ipad` plus the backend, API, database, Dream Weaver gateway, and web platform dependencies that determine whether the iPad app is actually functional in production. + +## Executive Summary + +The `velocity-ipad` app is no longer a concept stub. It is a materially implemented SwiftUI application with a real navigation shell, a meaningful live-data client, and several genuine product surfaces: + +- Dashboard +- Communications +- Calendar +- Oracle +- Sentinel +- Inventory +- Settings + +However, the app is not production-ready today. + +The biggest issue is not that the UI is missing. The UI is mostly present. The bigger issue is that multiple parts of the stack are only partially wired, operationally brittle, or explicitly disabled: + +- Dream Weaver is high-risk because the app, gateway, and public endpoint configuration are not cleanly aligned. +- Sentinel on iPad is now explicitly positioned as `Operator Posture` because it remains a live alert/load summary, not a visitor analytics surface. +- Oracle production scope is now intentionally limited to three live-backed modes, with unsupported `Team Performance` and `Lead Map` views hidden until real backend contracts exist. +- Dollhouse is now hidden from the production iPad scope unless a verified `Building.usdz` or `Building.scn` asset is actually shipped in the app bundle. +- The iPad app now has runtime session setup, Keychain-backed secure credential storage, and a test scaffold, but it still has no verifiable full Xcode build result from this machine. +- The backend has strong breadth but weak operational hygiene: environment drift, mixed schema models, legacy-shaped CRM dependencies with incomplete tenant modeling, and missing migration discipline. + +If the question is "Can this be turned into an investor-safe demo and then into a production system?" the answer is yes. + +If the question is "Is it already production ready today?" the answer is no. + +My assessment: + +- UI implementation maturity: medium to high +- Backend breadth: high +- Backend production rigor: medium-low +- Data model consistency: medium-low +- Operational reliability: low to medium +- Investor demo readiness next Tuesday: achievable only with deliberate scope control and a focused hardening sprint + +## Audit Method + +This audit was performed by: + +- Reading the full `iOS/velocity-ipad` target and its local feature implementations +- Tracing every iPad API dependency into `backend/` +- Reviewing the database schema files that back the app +- Reviewing Dream Weaver gateway implementations in the repo +- Running local validation where possible +- Verifying the configured public API endpoint on 2026-04-22 + +Validation constraints: + +- Full Xcode is not installed on this machine, so a true `xcodebuild` compile could not be completed +- Backend test execution is blocked in the current local environment because `httpx` is not installed even though it is listed in `backend/requirements.txt` +- Public endpoint verification was done live on 2026-04-22 and showed an HTTP redirect to a broken HTTPS TLS handshake + +## Current UI Screenshots + +The following screenshots were provided in this review thread and represent the present visible state of the iPad app as of 2026-04-22. They are included here as part of the audit record so Sagnik and other reviewers can compare the written assessment against the current UI. + +Important note: + +- These screenshots clearly reinforce one of the most important audit findings: the app shell is materially implemented, but the live backend path is currently failing with a TLS error in multiple surfaces. +- The screenshots are part of this review context and should be treated as the current-state visual appendix for this audit. + +### Dashboard - Current State + +Observed in screenshot: + +- Sidebar navigation is fully implemented +- Dashboard layout is visually coherent and investor-presentable +- Live status panel is present +- Metrics cards are present +- The screen shows `Live backend` +- The screen also shows a red error banner: `A TLS error caused the secure connection to fail.` +- Leads, whale leads, inventory, and today counts are all `0` in the captured state + +Interpretation: + +- The frontend shell is working +- The backend connectivity is not healthy in the captured runtime + +### Communications - Current State + +Observed in screenshot: + +- Communications surface is fully laid out +- Active Threads rail exists +- Detail panel exists +- Live thread count badge exists +- The screen shows a red TLS error banner +- No communication events are present in the captured state + +Interpretation: + +- The screen implementation is real +- Live communication data is not currently flowing in the captured runtime + +### Calendar - Current State + +Observed in screenshot: + +- Calendar metrics cards render correctly +- Week Grid rail is implemented +- Agenda/detail panel is implemented +- The screen shows a red TLS error banner +- All metrics are `0` in the captured state +- The synthesis card is present and readable + +Interpretation: + +- The calendar UI is production-shaped +- The live calendar backend dependency is not healthy in the captured runtime + +### Oracle - Current State + +Observed in screenshot captured before Workstream 5 hardening: + +- Oracle header and mode pills are present +- Pipeline, Account Timeline, Calendar & Tasks, Team Performance, and Lead Map controls are visible +- The screen shows a red TLS error banner +- Pipeline Summary card renders correctly +- No live pipeline rows are present in the captured state + +Interpretation: + +- Oracle mobile UI is present and credible +- The screenshot visually confirms that the surface is implemented even though data is not currently loading +- Update 2026-04-22 after Workstream 5: + - the production iPad scope now hides `Team Performance` and `Lead Map` + - only live-backed Oracle modes remain visible in the intended production path + +### Sentinel - Current State + +Observed in screenshot captured before Workstream 7 hardening: + +- Sentinel header is present +- Feed Availability card is visible +- Pending insights, transcript queue, and upcoming 24h KPI cards are present +- Recent Operator Timeline card is present +- The screen shows a red TLS error banner +- The screen explicitly says `No mock feed` + +Interpretation: + +- This screenshot strongly confirms the audit finding that iPad Sentinel is currently an operator-posture surface, not a full live visitor analytics surface +- Update 2026-04-22 after Workstream 7: + - the production app shell now labels this surface as `Operator Posture` + - the Sentinel screen now presents `Sentinel` as the product family and `Operator Posture` as the truthful iPad surface name + - the availability badge and copy now describe production scope directly instead of relying on the weaker `No mock feed` phrasing + +### Inventory - Current State + +Observed in screenshot captured before Workstream 6 hardening: + +- Inventory tab layout is implemented +- Sunseeker, Dream Weaver, and Dollhouse mode tabs are present +- The captured state shows the simulator-safe Sunseeker placeholder: + `Sunseeker requires a real device` +- The explanatory copy matches the current implementation + +Interpretation: + +- This screenshot supports the audit conclusion that Sunseeker is a genuine device-dependent feature +- It also confirms that the current captured state is not showing a live AR run +- Update 2026-04-22 after Workstream 6: + - `Dollhouse` is now hidden from the production iPad scope when the model asset is absent + - the inventory mode list now matches the assets that are actually shipped + +### Settings - Current State + +Observed in screenshot: + +- Settings surface is fully implemented +- Backend endpoint, auth mode, and last refresh are shown +- Identity, lead records loaded, and property records loaded are shown +- Production Notes panel is present +- The endpoint shown is `https://api.desineuron.in` +- Auth mode is `Email/password` +- No live fetch has occurred in the captured state + +Interpretation: + +- Settings is one of the cleanest implemented screens in the app +- The screenshot also reinforces the runtime issue: configuration is present, but live data has not successfully loaded + +## Workstream 1 Status - iPad Release Hygiene and App-Store-Grade Foundation + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with explicit external limitations still open + +### What was changed + +The following repo-local changes were completed in the active iPad target under `iOS/velocity-ipad`: + +- iPad target bundle identifier corrected to `com.desineuron.velocity.ipad` +- Target device family changed from universal (`1,2`) to iPad-only (`2`) +- Deployment target normalized to iPadOS 17.0 from the invalid `26.2` +- Release metadata aligned to `MARKETING_VERSION = 1.1` to better match the current product labeling +- Global ATS bypass was removed from `Info.plist` +- `Info.plist` was normalized to placeholder-driven config keys rather than hardcoded local credentials and local IPs +- Canonical permission strings were moved back into `Info.plist` so the app target no longer depends on duplicated permission text in build settings +- A dedicated unit-test bundle target `velocityTests` was added +- A practical smoke-test file was added covering: + - root shell construction + - `AppSection` navigation stability + - config parsing behavior + - auth mode description logic +- `AppConfig` was refactored slightly to expose deterministic parsing helpers for testability without changing backend contracts or screen behavior + +### Source-of-truth decision now recorded + +For all future production work on the iPad app, the active source of truth should be treated as: + +- `iOS/velocity-ipad/velocity/...` + +The duplicate tree drift issue remains open and is not resolved by this workstream. + +### What is materially better now + +- The iPad target now looks like a real iPad app instead of an accidental prototype/universal target +- The target no longer ships with blanket ATS disablement +- The app no longer embeds hardcoded email/password credentials and a local HTTP backend URL directly in the committed `Info.plist` +- There is now a repo-local iPad validation scaffold instead of relying entirely on manual trust +- The release identity is cleaner and consistent with an App-Store-grade direction + +### What remains blocked or incomplete + +- Full Xcode-based build/test execution could not be completed from this machine because full Xcode is not installed +- The new `velocityTests` target was added and structurally validated, but not executed via `xcodebuild` for the same reason +- External ingress/TLS is still broken as of this pass: + - `https://api.desineuron.in/health` still fails TLS handshake + - this continues to point to an external infrastructure problem rather than an iPad ATS problem +- Build-time config injection remains a production gap even after removing hardcoded secrets from the committed plist +- Duplicate iOS source trees remain present and drifting + +### Tradeoff introduced by this hardening pass + +Because ATS is now strict by default: + +- plain HTTP local backend development is no longer implicitly allowed +- developers using `http://192.168.x.x` style local endpoints will now need a proper dev-only exception strategy, HTTPS local proxying, or a separate debug-only configuration in a later workstream + +This is an intentional App-Store-grade tradeoff, not a regression. + +### Validation run for this workstream + +The following checks were run after implementation: + +- `plutil -lint iOS/velocity-ipad/velocity.xcodeproj/project.pbxproj` + - result: OK +- `plutil -lint iOS/velocity-ipad/velocity/Info.plist` + - result: OK +- static inspection confirmed: + - bundle identifier updated to `com.desineuron.velocity.ipad` + - deployment target updated to `17.0` + - target device family updated to `2` + - `velocityTests` target exists in the Xcode project +- `xcodebuild -project iOS/velocity-ipad/velocity.xcodeproj -list` + - result: could not run because this machine only has Command Line Tools, not full Xcode +- `curl -svk https://api.desineuron.in/health` + - result: TLS handshake still fails +- `openssl s_client -connect api.desineuron.in:443 -servername api.desineuron.in` + - result: TLS handshake still fails and no peer certificate is served + +### Current judgment after Workstream 1 + +This workstream was successful. + +It did not make the iPad app fully production-ready by itself, but it removed several release-hygiene and security anti-patterns that had to be addressed before any serious production work could continue. + +It is complete enough to move to the next item once approved. + +## Workstream 2 Status - Runtime Auth, Secure Session Storage, and First-Run Configuration + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with external backend/TLS limitations still open + +### What was changed + +The following repo-local changes were completed in the active iPad target under `iOS/velocity-ipad`: + +- Added a real runtime session model with on-device persistence +- Added Keychain-backed storage for password and bearer token secrets +- Added first-run configuration gating so an unconfigured build no longer drops the user into a broken shell without a credential path +- Added an editable session configuration panel inside Settings +- Added secure runtime override handling for: + - backend endpoint + - email/password login + - bearer token auth +- Refactored `AppConfig` so runtime overrides take precedence over build settings while still allowing build settings as fallback defaults +- Added session reset behavior so cached bearer tokens are cleared when credentials change +- Added app-state reset behavior so stale lead, property, calendar, and alert data does not linger after endpoint or auth changes +- Added validation rules for configuration input: + - backend endpoint must be an HTTPS origin + - email/password mode requires a valid-looking operator email + - auth mode changes cannot silently reuse the wrong secret +- Added unit coverage for the new configuration validation and normalization logic + +### What is materially better now + +- The iPad app no longer depends exclusively on build-time embedded secrets to function +- Production-facing installs can now be configured directly on-device without rebuilding the app +- Secrets are now stored in Keychain when entered through the runtime setup flow +- The app has a first-run experience that matches a real deployed product more closely +- Settings is now an operational control surface, not just a read-only status panel +- Session changes now clear the cached API token and trigger a truthful live refresh + +### What remains blocked or incomplete + +- Full `xcodebuild` execution is still blocked on this machine because full Xcode is not installed +- The new runtime session flow does not include password recovery, SSO, MDM distribution hooks, or multi-user session switching +- Build-time config fallback still exists, which is useful operationally but should not be the preferred distribution path for investor or enterprise installs +- The production backend endpoint still fails TLS handshake, so the new runtime session flow cannot complete a successful live verification against `https://api.desineuron.in` from this machine +- Dream Weaver still shares the same base endpoint assumption and has not yet been split into an explicit dedicated configuration path + +### Validation run for this workstream + +The following checks were run after implementation: + +- static typecheck: + - `swiftc -typecheck iOS/velocity-ipad/velocity/Core/Config/SessionConfiguration.swift iOS/velocity-ipad/velocity/Core/Config/AppConfig.swift` + - result: OK +- static inspection confirmed: + - runtime session model exists + - Keychain persistence path exists + - first-run configuration gate exists + - Settings now includes a writable session configuration surface + - unit tests now cover runtime session validation helpers +- `curl -svk https://api.desineuron.in/health` + - result: TLS handshake still fails +- `openssl s_client -connect api.desineuron.in:443 -servername api.desineuron.in` + - result: TLS handshake still fails and no peer certificate is served + +### Current judgment after Workstream 2 + +This workstream was successful. + +It closed one of the largest remaining product-readiness gaps on the iPad app itself: there is now a real runtime authentication and credential configuration path instead of a build-time-only secret model. + +It did not solve the external backend TLS problem, and it does not replace the need for a full Xcode build and real-device validation pass. + +It is complete enough to move to the next item once approved. + +## Workstream 3 Status - Dream Weaver Endpoint Separation and Gateway Contract Hardening + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with external deployment validation still open + +### What was changed + +The following repo-local changes were completed across the active iPad target and the minimal Dream Weaver gateway: + +- Added a dedicated Dream Weaver endpoint configuration path to the iPad session model +- Added `DREAM_WEAVER_BASE_URL` support to the iPad app configuration layer with runtime override support +- Updated the session configuration UI so operators can point Dream Weaver at a separate endpoint without rebuilding the app +- Made blank Dream Weaver endpoint input behave intentionally as "share the backend endpoint" instead of silently reverting to an embedded dedicated gateway value +- Refactored `ComfyClient` to use `dreamWeaverBaseURL` instead of assuming `BASE_URL` owns both CRM/API traffic and generation traffic +- Hardened Dream Weaver route resolution so the iPad client now accepts: + - full gateway responses with `poll_url` and `result_url` + - minimal gateway responses that only include `job_id` and `status` + - relative or absolute route URLs +- Strengthened the Dream Weaver health check so it now verifies: + - `/health` + - actual Dream Weaver route presence via a route probe +- Patched `dw_gateway_v2_min.py` so it now: + - returns `poll_url` + - returns `result_url` + - exposes `/dream-weaver/result/{job_id}` + - includes `result_url` in ready status payloads +- Added a fallback prompt-expansion path in `dw_gateway_v2_min.py` so the minimal gateway no longer crashes when `prompt_expander` is absent +- Added unit coverage for: + - Dream Weaver endpoint validation rules + - minimal gateway contract fallback decoding + - result URL resolution behavior + +### What is materially better now + +- The iPad app no longer assumes the primary backend host also owns Dream Weaver generation routes +- Dream Weaver can now be pointed at a dedicated gateway in production-facing installs without changing the core API endpoint +- The iPad client is materially more robust against contract drift between the full Dream Weaver gateway and the minimal gateway +- The minimal gateway in this repo is now much closer to the contract the iPad app expects +- Dream Weaver health reporting is more truthful because it now checks route presence, not just generic liveness + +### What remains blocked or incomplete + +- Public production TLS and ingress are still externally broken as of 2026-04-22 +- A successful end-to-end Dream Weaver generation round-trip was not verified against a deployed HTTPS endpoint from this machine +- Full Xcode build execution is still blocked on this machine because full Xcode is not installed +- Real-device validation of capture → generate → download is still required +- `backend/main.py` still does not directly mount Dream Weaver, so production endpoint ownership and reverse-proxy responsibility still need to be finalized at the infrastructure level + +### Validation run for this workstream + +The following checks were run after implementation: + +- `plutil -lint iOS/velocity-ipad/velocity/Info.plist` + - result: OK +- `swiftc -typecheck iOS/velocity-ipad/velocity/Core/Config/SessionConfiguration.swift iOS/velocity-ipad/velocity/Core/Config/AppConfig.swift` + - result: OK +- `python3 -m py_compile dw_gateway_v2_min.py` + - result: OK +- static inspection confirmed: + - iPad runtime configuration now includes a dedicated Dream Weaver endpoint path + - `ComfyClient` now resolves Dream Weaver routes against `dreamWeaverBaseURL` + - minimal gateway payload fallback is handled in the iPad client + - `dw_gateway_v2_min.py` now exposes `/dream-weaver/result/{job_id}` +- full `xcodebuild` execution still could not be run from this machine because full Xcode is not installed + +### Current judgment after Workstream 3 + +This workstream was successful. + +It materially reduced one of the biggest repo-local product risks in the iPad stack by separating endpoint ownership and repairing the contract mismatch between the app and the minimal gateway implementation. + +It did not prove Dream Weaver production readiness end-to-end, because deployed HTTPS routing, full Xcode validation, and real-device generation testing are still open. + +It is complete enough to move to the next item once approved. + +## Workstream 4 Status - Legacy CRM Route Authentication and Tenant Scoping Hardening + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with architectural tenant-model limitations still open + +### What was changed + +The following repo-local changes were completed across the backend auth layer and legacy CRM routes: + +- Added an explicit `tenant_id` claim and default tenant helper to the auth dependency layer +- Extended `UserPrincipal` to carry `tenant_id` instead of forcing downstream routes to improvise tenant scope +- Updated `/api/auth/me` to return `tenant_id` +- Hardened the legacy CRM route family in `backend/api/routes_crm.py` so the following routes now require authenticated users: + - `/api/leads` + - `/api/leads/{lead_id}` + - `/api/leads/demographics` + - `/api/chat-logs` + - `/api/kanban/board` + - `/api/kanban/move` + - `/api/analytics/sentiment-scatter` + - legacy write routes including create, update, delete, and seed +- Added tenant scoping to the legacy `leads` and `chat_logs` tables +- Added schema backfill logic so pre-existing legacy rows get a default tenant assignment during route bootstrap +- Added tenant-aware indexes for the legacy CRM tables +- Scoped all legacy CRM reads and writes by `tenant_id` +- Preserved the existing iPad-facing response contract for `/api/leads` so the mobile client did not require a DTO or route-path change +- Expanded backend tests to cover: + - authenticated CRUD flow + - authentication required behavior + - tenant isolation across authenticated clients + +### What is materially better now + +- The iPad app no longer reads lead data from an unauthenticated public CRM route +- The legacy CRM surface now has a first-class tenant scope in its auth and query path +- Cross-tenant leakage risk in the legacy `leads` / `chat_logs` tables is materially reduced +- The backend auth model is slightly more production-shaped because tenant scope is now carried in the principal instead of inferred ad hoc in every route + +### What remains blocked or incomplete + +- `users_and_roles` is now tenant-aware, but it still models only a single direct tenant binding per user rather than a fuller org or membership graph +- runtime schema mutation and default-tenant backfill are still being used as an interim migration strategy instead of a governed migration system +- The legacy CRM route family is still legacy-shaped and separate from the canonical `crm_people` / `crm_leads` model +- This workstream does not complete the canonical CRM migration +- Full backend test execution still depends on local Python/runtime dependency hygiene outside this single route family + +### Validation run for this workstream + +The following checks were run after implementation: + +- `python3 -m py_compile backend/auth/dependencies.py backend/api/routes_crm.py backend/main.py backend/tests/test_crm_routes.py` + - result: OK +- targeted route tests: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:$PYTHONPATH" python3 -m pytest backend/tests/test_crm_routes.py -q` + - result: `4 passed in 0.33s` +- temporary local validation dependencies were installed outside the repo under `/tmp/velocity_pydeps` only so the route tests could run on this machine's incomplete Python environment + +### Current judgment after Workstream 4 + +This workstream was successful. + +It closed one of the most important backend production gaps that directly affected the iPad app: lead data is no longer served from an unauthenticated, unscoped legacy route. + +It did not solve the broader canonical CRM migration or enterprise-grade tenant modeling problem, but it materially improved security and correctness without breaking the current iPad contract. + +It is complete enough to move to the next item once approved. + +## Workstream 5 Status - Oracle Production-Safe Mode Gating + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with full Oracle feature parity intentionally deferred + +### What was changed + +The following repo-local changes were completed in the active iPad Oracle surface: + +- Added a dedicated Oracle production-scope policy helper in `OracleModeAvailability.swift` +- Explicitly defined the production-visible Oracle modes as: + - `Pipeline` + - `Account Timeline` + - `Calendar & Tasks` +- Explicitly defined `Team Performance` and `Lead Map` as hidden until backend support exists +- Hardened `OracleView` so unsupported mode selections are sanitized back to `Pipeline` +- Updated the Oracle mode picker so the production UI no longer advertises unsupported modes +- Added an in-product scope note explaining that only live-backed Oracle views are intentionally shown in the production iPad build +- Added smoke-test coverage for: + - visible Oracle production modes + - hidden unsupported modes + - selection sanitization behavior + +### What is materially better now + +- The production iPad Oracle surface no longer over-promises capability by showing pills for unsupported views +- Stakeholder demos are safer because the UI now matches the real mobile backend scope more honestly +- Accidental deep-linking or stale state into unsupported Oracle modes now falls back to a known-good live mode instead of leaving the user in an invalid product state +- The Oracle production story is narrower, but materially more trustworthy + +### What remains blocked or incomplete + +- The backend still does not expose real mobile contracts for `Team Performance` or `Lead Map` +- This workstream intentionally hides unsupported Oracle modes; it does not implement them +- Full Xcode test execution is still blocked on this machine because full Xcode is not installed +- A real-device validation pass is still required to confirm the Oracle UX feels correct on the target iPad hardware + +### Validation run for this workstream + +The following checks were run after implementation: + +- `swiftc -typecheck` against the Oracle production-scope helper and a preview-free validation copy of `OracleView.swift` + - result: OK +- static inspection confirmed: + - the Oracle picker now shows only `Pipeline`, `Account Timeline`, and `Calendar & Tasks` + - unsupported Oracle selections are sanitized back to `Pipeline` + - the production-scope note is present in the live-backed Oracle canvases +- smoke-test coverage was expanded in `velocityTests/VelocitySmokeTests.swift` + - execution is still pending a full Xcode environment on this machine + +### Current judgment after Workstream 5 + +This workstream was successful. + +It did not make Oracle feature-complete on iPad, but it did make the production build materially more honest and robust by aligning the visible surface area with the backend that actually exists today. + +It is complete enough to move to the next item once approved. + +## Workstream 6 Status - Dollhouse Asset Gating and Production-Safe Inventory Scope + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with real Dollhouse content still intentionally deferred until the asset exists + +### What was changed + +The following repo-local changes were completed in the active iPad Inventory surface: + +- Added a dedicated inventory production-scope policy helper in `InventoryModeAvailability.swift` +- Defined Dollhouse visibility as asset-gated rather than always advertised +- The production mode picker now shows: + - `Sunseeker` + - `Dream Weaver` + - `Dollhouse` only when a real `Building.usdz` or `Building.scn` asset is present in the bundle +- Hardened `InventoryView` so stale or unsupported `Dollhouse` selections are sanitized back to `Sunseeker` +- Updated the Inventory subtitle so the visible mode list reflects the assets actually shipped in the production build +- Added an in-product production-scope card explaining why Dollhouse is hidden when the asset is missing +- Aligned the SceneKit Dollhouse loader with the same shared asset-candidate list used by the production gate +- Added smoke-test coverage for: + - hidden Dollhouse mode when no asset is shipped + - visible Dollhouse mode when an asset is present + - selection sanitization behavior + +### What is materially better now + +- The production iPad build no longer advertises a Dollhouse experience that it cannot actually deliver +- Investor and stakeholder demos are safer because the Inventory surface now matches the app bundle contents more honestly +- If a stale state or future persistence bug points the user at `Dollhouse` without an asset, the UI now falls back to a known-good mode instead of presenting a meaningless SceneKit floor as if it were a real feature +- If the real Dollhouse asset is later added to the bundle, the mode can reappear automatically without another scope-policy rewrite + +### What remains blocked or incomplete + +- No real `Building.usdz` or `Building.scn` asset exists in the current iPad bundle +- This workstream intentionally hides Dollhouse when the asset is absent; it does not create the missing 3D experience +- Full Xcode test execution is still blocked on this machine because full Xcode and the iOS simulator SDK are not installed +- Real-device validation is still required if the Dollhouse asset is later shipped and re-enabled + +### Validation run for this workstream + +The following checks were run after implementation: + +- filesystem validation confirmed there is still no `Building.usdz` or `Building.scn` under `iOS/velocity-ipad` +- `swiftc -typecheck` against `InventoryModeAvailability.swift` with a temporary local stub for `InventoryStore.Mode` + - result: OK +- static inspection confirmed: + - the Inventory picker now uses production-visible modes rather than `Mode.allCases` + - missing Dollhouse assets trigger a production-scope notice + - stale `Dollhouse` selections are sanitized back to `Sunseeker` + - the SceneKit loader and the production gate now share the same asset-candidate list +- direct typechecking of the full Inventory view against real iOS frameworks could not be completed on this machine because Command Line Tools are present but the iOS simulator SDK is not installed +- smoke-test coverage was expanded in `velocityTests/VelocitySmokeTests.swift` + - execution is still pending a full Xcode environment on this machine + +### Current judgment after Workstream 6 + +This workstream was successful. + +It did not make Dollhouse real, but it did make the production Inventory surface materially more honest and robust by hiding the feature until the required 3D asset actually exists. + +It is complete enough to move to the next item once approved. + +## Workstream 7 Status - Sentinel Relabeling and Operator-Posture Production Framing + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with real Sentinel analytics still intentionally deferred + +### What was changed + +The following repo-local changes were completed across the active iPad shell and Sentinel-facing surfaces: + +- Added a dedicated Sentinel production-scope helper in `SentinelScope.swift` +- Preserved the internal `AppSection.sentinel` identity while adding a separate production display title +- Updated the sidebar navigation so the user-facing label is now `Operator Posture` instead of plain `Sentinel` +- Updated the Sentinel screen header so: + - `Sentinel` remains visible as the product family + - `Operator Posture` is the large production surface title +- Reworked the Sentinel availability card so it now uses: + - `Production Scope` as the section title + - `Operator posture only` as the badge state + - explicit capability wording for what is disabled versus what is live-backed +- Updated Settings production notes so the product messaging stays aligned with the relabeled iPad scope +- Added smoke-test coverage for: + - user-facing section display titles + - Sentinel scope constants and production phrasing + +### What is materially better now + +- The iPad app no longer markets this surface as if it were already a full production Sentinel analytics console +- Investor and operator demos are safer because the navigation, screen header, and production notes now tell the same truthful story +- Internal section identity remains stable, so the relabeling does not force a fragile route or state migration +- The production posture language is now centralized in one helper instead of being scattered across ad hoc strings + +### What remains blocked or incomplete + +- The backend still does not provide the real Sentinel perception stream needed for visitor analytics +- This workstream intentionally relabels and scopes the iPad experience; it does not implement live visitor analytics +- Full Xcode test execution is still blocked on this machine because full Xcode and the iOS simulator SDK are not installed +- Real-device validation is still required once a true production Sentinel feed exists + +### Validation run for this workstream + +The following checks were run after implementation: + +- `swiftc -typecheck iOS/velocity-ipad/velocity/Features/Sentinel/SentinelScope.swift` + - result: OK +- static inspection confirmed: + - the sidebar now displays `Operator Posture` for the Sentinel section + - the Sentinel screen header preserves `Sentinel` as the product family while using `Operator Posture` as the truthful iPad title + - the availability badge now reads `Operator posture only` + - Settings production notes now use the same scope language +- smoke-test coverage was expanded in `velocityTests/VelocitySmokeTests.swift` + - execution is still pending a full Xcode environment on this machine + +### Current judgment after Workstream 7 + +This workstream was successful. + +It did not turn the iPad surface into real production Sentinel analytics, but it did make the app materially more honest and investor-safe by aligning the user-facing framing with the backend reality that exists today. + +It is complete enough to move to the next item once approved. + +## Workstream 8 Status - WebOS-Grounded Shared Refresh Hardening + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with deeper shared-platform optimization still open + +### What was changed + +This workstream was explicitly grounded against the Velocity WebOS implementation under `app/`, especially: + +- `app/src/lib/velocityPlatformClient.ts` +- `app/src/hooks/useCrmBootstrap.ts` + +The following repo-local changes were completed in the active iPad shared data layer: + +- Added a dedicated `AppStoreRefreshPolicy.swift` helper to centralize shared hydration limits and refresh scope +- Aligned the iPad inventory property hydration limit to the WebOS bootstrap default of `100` +- Refactored `AppStore.refresh()` so concurrent callers now reuse a single in-flight refresh task instead of kicking off overlapping refreshes independently +- Replaced sequential per-lead communication fetches with parallel task-group hydration for the prioritized iPad lead set +- Kept the iPad lead-event hydration set intentionally smaller than WebOS: + - WebOS bootstraps a broader CRM/chat context + - iPad continues to focus on the top operator-facing lead slice for its smaller surfaces +- Added smoke-test coverage for: + - WebOS-aligned inventory hydration limit + - iPad lead prioritization policy + +### What is materially better now + +- The iPad shared data bootstrap now follows the WebOS property-slice baseline for shared inventory-backed surfaces +- Repeated refresh calls from multiple iPad screens are materially less wasteful because they now coalesce around one active refresh task +- Lead-event hydration is no longer serialized one lead at a time, reducing avoidable latency in operator surfaces that depend on timeline data +- The shared refresh behavior is now easier to audit because the scope policy lives in one place instead of being buried in inline magic numbers + +### What remains blocked or incomplete + +- The iPad app still relies on per-lead event fetches rather than a true bulk mobile-edge endpoint +- Refresh timers across multiple screens still exist; this workstream reduces duplicate work but does not redesign the entire refresh architecture +- WebOS and iPad still intentionally diverge on lead-event hydration depth because the iPad UI shows a narrower operator slice +- Full Xcode test execution is still blocked on this machine because full Xcode is not installed + +### Validation run for this workstream + +The following checks were run after implementation: + +- `swiftc -typecheck` across: + - `SessionConfiguration.swift` + - `AppConfig.swift` + - `AppStoreRefreshPolicy.swift` + - `VelocityAPIClient.swift` + - `AppStore.swift` + - result: OK +- static comparison against WebOS confirmed: + - WebOS inventory hydration uses `listInventoryProperties(100)` + - iPad property hydration now aligns to that same `100` row default + - WebOS hydrates lead-linked data in parallel + - iPad lead-linked event hydration now also runs in parallel for its prioritized operator slice +- smoke-test coverage was expanded in `velocityTests/VelocitySmokeTests.swift` + - execution is still pending a full Xcode environment on this machine + +### Current judgment after Workstream 8 + +This workstream was successful. + +It did not eliminate every refresh inefficiency in the iPad app, but it materially improved performance discipline and shared-platform parity by aligning the iPad bootstrap more closely with the WebOS ground truth without changing WebOS behavior. + +It is complete enough to move to the next item once approved. + +## Workstream 9 Status - Shared Backend Tenant Scoping Hardening for WebOS and iPad + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with true user-to-tenant modeling still open + +### What was changed + +This workstream was explicitly grounded against the shared WebOS and iPad dependency surface, especially: + +- `app/src/lib/velocityPlatformClient.ts` +- `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift` + +The following repo-local changes were completed in the backend route families both clients depend on: + +- Added explicit tenant-scope helpers to: + - `backend/api/routes_mobile_edge.py` + - `backend/api/routes_inventory.py` +- Replaced role-based tenant scoping with `user.tenant_id` throughout the shared mobile-edge route family +- Replaced role-based tenant scoping with `user.tenant_id` throughout the shared inventory route family +- Added focused backend tests covering tenant isolation for: + - `mobile-edge/events` + - `mobile-edge/calendar` + - `inventory/properties` + - `inventory/import-batches` +- Normalized these shared route files from `datetime.UTC` to `timezone.utc` so the local validation path is less fragile on Python environments older than 3.11 + +### What is materially better now + +- WebOS and iPad shared reads and writes are no longer scoped by role in these route families +- Users who share the same role but belong to different tenants are now materially less likely to see cross-tenant data leakage through mobile-edge or inventory routes +- The backend contract now better matches the auth layer, which already carries a first-class `tenant_id` +- Shared route coverage is stronger because tenant isolation is now proven with targeted tests instead of assumed from inspection + +### What remains blocked or incomplete + +- shared routes are now backed by a user directory that resolves tenant scope per user, but the overall backend still lacks a fuller org or tenant-membership model +- runtime schema mutation is still being used for interim compatibility instead of an explicit migration chain +- this workstream hardens shared route families but does not complete the broader tenant-model redesign across the whole backend +- full backend suite execution is still limited by local dependency and environment hygiene outside the targeted route families + +### Validation run for this workstream + +The following checks were run after implementation: + +- `python3 -m py_compile` across: + - `backend/api/routes_mobile_edge.py` + - `backend/api/routes_inventory.py` + - `backend/tests/test_surface_route_tenant_scoping.py` + - result: OK +- targeted shared-route tests: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:$PYTHONPATH" python3 -m pytest backend/tests/test_surface_route_tenant_scoping.py -q` + - result: `4 passed in 0.55s` +- regression check on the earlier CRM hardening tests: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:$PYTHONPATH" python3 -m pytest backend/tests/test_crm_routes.py -q` + - result: `4 passed in 0.36s` +- static inspection confirmed there are no remaining `user.role` tenant-scope calls inside the shared `routes_mobile_edge.py` and `routes_inventory.py` families + +### Current judgment after Workstream 9 + +This workstream was successful. + +It did not complete the full multi-tenant architecture, but it materially improved the shared backend contract that both WebOS and iPad rely on by replacing role-scoped isolation with tenant-scoped isolation in the route families that matter most to both clients today. + +It is complete enough to move to the next item once approved. + +## Workstream 10 Status - Shared Auth Tenant Resolution and Directory Scoping Hardening + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with broader tenant-architecture and migration-discipline limitations still open + +### What was changed + +This workstream was explicitly grounded against the shared WebOS and iPad auth contract, especially: + +- `app/src/lib/velocityPlatformClient.ts` +- `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift` + +The following repo-local changes were completed across the shared backend auth layer: + +- Added a dedicated auth schema hardening helper in `backend/auth/user_directory.py` +- Added a dedicated auth service layer in `backend/auth/service.py` so login and user-directory behavior can be validated without importing the entire backend shell +- Moved the shared auth HTTP surface into `backend/auth/routes.py` +- Added a real `tenant_id` column to the `users_and_roles` schema in `backend/db/schema.sql` +- Added runtime backfill and indexing so pre-existing auth rows receive a tenant assignment during bootstrap +- Updated `/api/auth/login` to mint JWTs from the user row's resolved `tenant_id` instead of always falling back to the default tenant +- Updated `/api/auth/me` to read the authenticated profile inside the caller's tenant scope +- Updated `/api/auth/users` to return only active users from the authenticated tenant, which aligns better with the WebOS share modal and any shared user-picker behavior +- Updated the WebOS client types in `app/src/lib/velocityPlatformClient.ts` so `tenant_id` is represented in the shared auth DTOs +- Normalized `backend/main.py` and `backend/api/routes_admin_surface.py` from `datetime.UTC` to `timezone.utc` so local validation is less fragile on Python environments older than 3.11 + +### What is materially better now + +- WebOS and iPad now authenticate through a shared backend path that resolves tenant scope from the user directory instead of defaulting every login to the same tenant +- the user directory has a first-class `tenant_id` field instead of forcing downstream routes to rely on a default-only auth claim +- cross-tenant user leakage risk is materially reduced for shared directory reads such as `/api/auth/users` +- the shared auth contract is more production-shaped because auth route logic now lives in dedicated auth modules instead of being embedded only inside `backend/main.py` +- local backend validation is stronger because auth tenant behavior is now covered with focused tests + +### What remains blocked or incomplete + +- the backend still models only a single direct `tenant_id` on each user instead of a fuller enterprise tenant or membership design +- runtime schema mutation and row backfill are still being used as an interim compatibility mechanism instead of governed migrations +- the local auth tests intentionally stub password verification because the temporary bcrypt/passlib dependency path under `/tmp/velocity_pydeps` is unreliable on this machine +- this workstream hardens shared auth identity and user-directory scope, but it does not complete the broader canonical CRM migration or tenant-admin model + +### Validation run for this workstream + +The following checks were run after implementation: + +- `python3 -m py_compile` across: + - `backend/auth/user_directory.py` + - `backend/auth/service.py` + - `backend/auth/routes.py` + - `backend/main.py` + - `backend/api/routes_admin_surface.py` + - `backend/tests/test_auth_tenant_contract.py` + - result: OK +- targeted shared auth contract tests: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:$PYTHONPATH" python3 -m pytest backend/tests/test_auth_tenant_contract.py -q` + - result: `4 passed in 0.22s` +- regression check on previously hardened tenant-scoped route families: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:$PYTHONPATH" python3 -m pytest backend/tests/test_surface_route_tenant_scoping.py -q backend/tests/test_crm_routes.py -q` + - result: `8 passed` + +### Current judgment after Workstream 10 + +This workstream was successful. + +It did not complete the final enterprise tenant architecture, but it materially improved the shared auth contract that both WebOS and iPad rely on by making tenant identity come from the user directory, scoping the shared auth directory by tenant, and isolating the auth logic into production-shaped modules. + +It is complete enough to move to the next item once approved. + +## Workstream 11 Status - WebOS Authenticated CRM Bootstrap Parity Hardening + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with legacy CRM-contract limitations still open + +### What was changed + +This workstream was explicitly grounded against the current Velocity WebOS bootstrap path, especially: + +- `app/src/hooks/useCrmBootstrap.ts` +- `app/src/lib/api.ts` +- `app/src/lib/velocityPlatformClient.ts` + +The following repo-local changes were completed on the shared WebOS surface: + +- Added a small shared session helper in `app/src/lib/velocitySession.ts` +- Centralized the WebOS bearer-token key and token read/write helpers there so multiple clients stop duplicating session behavior +- Updated the legacy WebOS CRM bootstrap client in `app/src/lib/api.ts` to attach the authenticated Velocity bearer token to `/api/leads`, `/api/chat-logs`, and related shared CRM reads +- Updated legacy WebOS API error handling so protected-route failures surface backend detail strings instead of only generic status codes +- Updated `app/src/lib/crmApi.ts` and `app/src/oracle/lib/oracleApiClient.ts` to use the same shared session helper, keeping canonical CRM, Oracle, and legacy CRM bootstrap on one auth source of truth +- Preserved compatibility for the rest of WebOS by re-exporting the session helpers through `app/src/lib/velocityPlatformClient.ts` + +### What is materially better now + +- WebOS no longer treats the legacy CRM bootstrap path as if it were a public unauthenticated API client +- the backend auth hardening from earlier workstreams now actually lines up with the way the current WebOS app fetches leads and chat logs +- cross-surface auth drift is materially reduced because WebOS legacy CRM, canonical CRM, Oracle, and login/session code now share one token source of truth +- this reduces the risk of breaking the current WebOS production flow while continuing iPad hardening + +### What remains blocked or incomplete + +- WebOS and iPad still both depend on the legacy `/api/leads` family for the current operational bootstrap +- this workstream does not migrate the shared lead bootstrap to canonical CRM tables +- the WebOS frontend bundle still emits a large chunk warning during production build +- lint could not be executed on this machine because the local `node_modules/.bin/eslint` binary is not executable + +### Validation run for this workstream + +The following checks were run after implementation: + +- WebOS production build: + - command: + `npm run build` + - result: success + - note: Vite reported an existing large-chunk warning, but the build completed successfully +- attempted WebOS lint: + - command: + `npm run lint` + - result: blocked by local tool permission error + - detail: `node_modules/.bin/eslint: Permission denied` + +### Current judgment after Workstream 11 + +This workstream was successful. + +It did not solve the broader legacy-versus-canonical CRM architecture problem, but it materially improved production safety by making the current WebOS bootstrap path honor the same authenticated backend contract that the iPad and shared backend now expect. + +It is complete enough to move to the next item once approved. + +## Workstream 12 Status - Dream Weaver Gateway Authentication Hardening + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with deployed endpoint validation and infrastructure ownership still open + +### What was changed + +This workstream was focused on the iPad-only Dream Weaver surface and the gateway implementations it depends on. + +The following repo-local changes were completed: + +- Added a shared Dream Weaver gateway auth helper in `comfy_engine/scripts/gateway_auth.py` +- Added optional API-key enforcement support to: + - `dw_gateway_v2_min.py` + - `comfy_engine/scripts/dw_gateway_v2.py` +- Supported common presentation forms for authenticated requests: + - `X-Dream-Weaver-API-Key` + - `X-API-Key` + - `Authorization: Bearer ` +- Kept `/health` available for liveness, but it now reports whether gateway auth is required +- Added a dedicated Dream Weaver gateway API-key path to the iPad runtime configuration and persisted it securely in Keychain +- Updated `ComfyClient` so health probes, route probes, job submission, polling, and result download all send the configured Dream Weaver gateway key when present +- Updated the Settings surface so operators can see whether a Dream Weaver gateway key is configured and manage that key at runtime without rebuilding the app +- Expanded iPad smoke-test scaffolding to cover Dream Weaver gateway-key draft resolution and settings-state behavior + +### What is materially better now + +- Dream Weaver no longer has to be treated as an implicitly open gateway in production +- the iPad app can now authenticate directly to a dedicated Dream Weaver gateway without conflating that secret with core backend auth +- the minimal and richer Dream Weaver gateway variants now share the same auth posture instead of drifting again +- production operators can configure or rotate a Dream Weaver gateway key on-device without rebuilding the app + +### What remains blocked or incomplete + +- this workstream adds an enforceable auth posture, but it does not prove that the deployed public Dream Weaver endpoint is currently running with that auth enabled +- real HTTPS round-trip validation against a live authenticated Dream Weaver deployment is still open +- infrastructure decisions are still unresolved: + - whether Dream Weaver sits behind the same public host and proxy chain as `/api/*` + - or remains a dedicated gateway host with its own ingress and TLS +- `ComfyClient.swift` could not be typechecked on this machine because `UIKit` requires a real iOS SDK / Xcode environment + +### Validation run for this workstream + +The following checks were run after implementation: + +- `python3 -m py_compile` across: + - `comfy_engine/scripts/gateway_auth.py` + - `dw_gateway_v2_min.py` + - `comfy_engine/scripts/dw_gateway_v2.py` + - `backend/tests/test_dream_weaver_gateway_auth.py` + - result: OK +- targeted gateway auth tests: + - command: + `PYTHONPATH="/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_dream_weaver_gateway_auth.py -q` + - result: `4 passed in 0.01s` +- Swift configuration-layer validation: + - command: + `swiftc -typecheck iOS/velocity-ipad/velocity/Core/Config/AppConfig.swift iOS/velocity-ipad/velocity/Core/Config/SessionConfiguration.swift` + - result: OK +- attempted `ComfyClient.swift` typecheck: + - blocked because local CLI Swift does not have `UIKit` / iOS SDK access on this machine + +### Current judgment after Workstream 12 + +This workstream was successful. + +It did not prove Dream Weaver production readiness end-to-end, but it materially improved security posture by giving the iPad and both gateway variants a real shared mechanism for gateway authentication instead of leaving Dream Weaver as an implicitly open production service. + +It is complete enough to move to the next item once approved. + +## Workstream 13 Status - Canonical CRM Route Authentication Hardening + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with canonical tenant modeling and legacy-to-canonical lead migration still open + +### What was changed + +This workstream was grounded against the shared WebOS production behavior before any backend change was made: + +- WebOS already sends the authenticated Velocity bearer token through `app/src/lib/crmApi.ts` for canonical `/api/crm/*` reads and writes +- the iPad app does not yet depend directly on the canonical CRM route family for its lead bootstrap +- because of that shared contract, it was safe to harden the canonical CRM backend surface without breaking the current WebOS or iPad runtime assumptions + +The following repo-local changes were completed: + +- Hardened the entire canonical CRM router in `backend/api/routes_crm_imports.py` so all `/api/crm/*` endpoints now require the shared Velocity bearer token +- Added focused backend tests covering: + - unauthenticated access rejection for canonical contact routes + - unauthenticated access rejection for canonical task routes + - unauthenticated access rejection for canonical CRM import upload + - successful authenticated access for a representative canonical contact-list read + +### What is materially better now + +- the backend no longer exposes the canonical CRM route family as an implicitly public surface +- WebOS canonical CRM usage is now aligned with the backend auth posture it was already coded to use +- the shared platform is safer to evolve because the canonical CRM surface now follows the same authenticated session contract as legacy CRM, mobile-edge, inventory, and auth +- this removes an important production-readiness blocker that had to be closed before a real legacy-to-canonical CRM migration could be trusted + +### What remains blocked or incomplete + +- this workstream does not add full tenant scoping to canonical CRM tables +- canonical CRM schema still lacks a mature tenant-bound data model across `crm_*`, `intel_*`, and `workflow_*` +- this workstream does not move the iPad or current WebOS lead bootstrap off `/api/leads` +- the broader goal of converging on one canonical CRM contract is still open and should be handled as a follow-on migration workstream + +### Validation run for this workstream + +The following checks were run after implementation: + +- `python3 -m py_compile` across: + - `backend/api/routes_crm_imports.py` + - `backend/tests/test_canonical_crm_auth.py` + - result: OK +- targeted canonical CRM auth tests: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_canonical_crm_auth.py -q` + - result: `4 passed in 0.31s` +- shared auth regression check: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_auth_tenant_contract.py -q` + - result: `4 passed in 0.20s` +- legacy CRM regression check: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_crm_routes.py -q` + - result: `4 passed in 0.40s` + +### Current judgment after Workstream 13 + +This workstream was successful. + +It does not complete the canonical CRM migration, but it closes an important production-safety gap by ensuring the canonical CRM route family now honors the same authenticated Velocity session model already used by WebOS and expected by the wider platform. + +It is complete enough to move to the next item once approved. + +## Workstream 14 Status - Canonical CRM Tenant Scoping Hardening + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with the actual shared lead-bootstrap migration still open + +### What was changed + +This workstream was chosen as the next prerequisite after Workstream 13. + +Reason: + +- moving WebOS or iPad reads directly from legacy `/api/leads` onto canonical `/api/crm/*` would still have been unsafe because the canonical CRM route family was not yet tenant-scoped +- the correct architecturally safe order was: + - authenticate canonical CRM first + - then add first-pass tenant scoping to the canonical route family and its backing read/write paths + - only after that start migrating shared lead bootstrap away from legacy tables + +The following repo-local changes were completed: + +- Added canonical CRM schema hardening helper in `backend/crm/canonical_schema.py` +- Added runtime tenant hardening for the currently active canonical CRM tables used by shared route families, including: + - `crm_people` + - `crm_accounts` + - `crm_leads` + - `crm_opportunities` + - `crm_property_interests` + - `intel_interactions` + - `intel_reminders` + - `intel_qd_scores` + - `intel_qd_timeseries` + - `workflow_actions` + - `workflow_approvals` + - `workflow_import_batches` +- Added tenant-aware indexes for the canonical CRM tables currently serving shared WebOS canonical CRM routes +- Updated `backend/api/routes_crm_imports.py` so canonical CRM reads and writes now scope by the authenticated `tenant_id` +- Updated canonical aggregation helpers in `backend/services/client_graph/aggregation_service.py` so Client 360 and contact-list queries now resolve within tenant scope +- Updated CRM import persistence in `backend/services/imports/ingest_service.py` so canonical workflow batches and workflow actions now carry tenant scope +- Updated `backend/db/schema_crm_canonical.sql` so the canonical schema source now records the new tenant-aware direction + +### What is materially better now + +- canonical CRM no longer behaves like a tenant-blind shared data surface for the currently active route families +- WebOS canonical CRM surfaces now align more closely with the same tenant-bound auth model already used by shared auth, mobile-edge, inventory, and legacy CRM +- the platform is now in a much safer state for the next real migration step off legacy `/api/leads` +- canonical CRM imports, contacts, tasks, Client 360 reads, kanban, QD reads, and opportunity reads now have materially better tenant isolation posture than they had at audit start + +### What remains blocked or incomplete + +- this workstream does not yet move the shared WebOS or iPad lead bootstrap off legacy `/api/leads` +- canonical CRM tenant hardening here is a first-pass route-family hardening, not the final enterprise tenant architecture for every canonical table and workflow +- runtime schema mutation and default-tenant backfill are still being used as an interim compatibility strategy +- broader canonical CRM convergence still remains an open workstream + +### Validation run for this workstream + +The following checks were run after implementation: + +- `python3 -m py_compile` across: + - `backend/crm/canonical_schema.py` + - `backend/services/imports/ingest_service.py` + - `backend/services/client_graph/aggregation_service.py` + - `backend/api/routes_crm_imports.py` + - `backend/tests/test_canonical_crm_auth.py` + - `backend/tests/test_canonical_crm_tenant_scoping.py` + - result: OK +- targeted canonical CRM auth regression: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_canonical_crm_auth.py -q` + - result: `4 passed in 0.39s` +- targeted canonical CRM tenant-scoping tests: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_canonical_crm_tenant_scoping.py -q` + - result: `4 passed in 0.42s` +- shared auth regression check: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_auth_tenant_contract.py -q` + - result: `4 passed in 0.22s` +- legacy CRM regression check: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_crm_routes.py -q` + - result: `4 passed in 0.31s` + +### Current judgment after Workstream 14 + +This workstream was successful. + +It does not complete the legacy-to-canonical CRM migration, but it removes a serious prerequisite blocker by giving the canonical CRM route family a first-pass tenant-scoped data boundary that matches the authenticated Velocity session contract more honestly. + +It is complete enough to move to the next item once approved. + +## Workstream 15 Status - Shared Legacy CRM Read Bridge Toward Canonical CRM + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with write-path convergence and final legacy-table retirement still open + +### What was changed + +This workstream was grounded against the current shared WebOS and iPad dependency shape before any code was changed: + +- WebOS bootstrap still reads: + - `/api/leads` + - `/api/chat-logs` +- iPad still reads: + - `/api/leads` +- WebOS canonical CRM modules already use `/api/crm/*` +- a direct route-path cutover would have broken the current shared client behavior because WebOS still ties `/api/leads` identities to `/api/chat-logs` + +Because of that, the correct next step was not a brittle frontend cutover. + +The following repo-local changes were completed instead: + +- Added a canonical-read compatibility bridge inside `backend/api/routes_crm.py` +- Updated legacy `/api/leads` reads so they now: + - prefer canonical CRM lead data when canonical rows exist for the authenticated tenant + - preserve the existing legacy response shape expected by WebOS and iPad + - merge in legacy-only rows that are not yet represented in canonical CRM + - avoid duplicate rows when canonical records shadow legacy IDs +- Updated legacy `/api/leads/{id}` reads so canonical records can now be resolved by: + - legacy-compatible lead ID + - canonical lead ID + - canonical person ID +- Updated legacy `/api/chat-logs` reads so they now fall back to canonical interaction summaries when no legacy chat-log rows exist for a requested lead +- Expanded canonical-to-legacy status mapping so canonical CRM stages now translate more truthfully into the current shared legacy lead contract +- Added focused backend bridge tests covering: + - canonical-plus-legacy merge behavior + - canonical lead lookup through the legacy route family + - canonical interaction fallback for legacy chat-log reads + - legacy fallback behavior when canonical bridge access is unavailable + +### What is materially better now + +- the shared WebOS and iPad bootstrap path is now meaningfully closer to canonical CRM without requiring an abrupt frontend contract change +- canonical CRM can now progressively become the effective source of truth for shared lead reads while preserving the current production client shape +- tenants that already have canonical CRM data can now benefit from it through the legacy compatibility surface +- the platform has a safer migration path because WebOS bootstrap, iPad bootstrap, and canonical CRM no longer need to be cut over in one risky move + +### What remains blocked or incomplete + +- this workstream improves shared read-path convergence only; it does not migrate legacy CRM writes to canonical tables +- `/api/chat-logs` canonical fallback currently uses canonical interaction summaries, not a full canonical message-thread model +- legacy `leads` and `chat_logs` tables still exist and still back write paths +- final retirement of the legacy CRM tables remains a later workstream + +### Validation run for this workstream + +The following checks were run after implementation: + +- `python3 -m py_compile` across: + - `backend/api/routes_crm.py` + - `backend/tests/test_legacy_crm_canonical_bridge.py` + - result: OK +- targeted shared legacy-to-canonical bridge tests: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_legacy_crm_canonical_bridge.py -q` + - result: `4 passed in 0.49s` +- legacy CRM regression check: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_crm_routes.py -q` + - result: `4 passed` +- canonical CRM regression checks: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_canonical_crm_auth.py -q backend/tests/test_canonical_crm_tenant_scoping.py -q` + - result: `8 passed` + +### Current judgment after Workstream 15 + +This workstream was successful. + +It does not complete the final legacy-to-canonical CRM cutover, but it materially improves production safety and migration discipline by letting the current shared `/api/leads` and `/api/chat-logs` compatibility surface read from canonical CRM where that data already exists, without breaking the current WebOS or iPad client contract. + +It is complete enough to move to the next item once approved. + +## Workstream 16 Status - Shared Legacy CRM Write Bridge Toward Canonical CRM + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with final legacy-table retirement and broader canonical workflow depth still open + +### What was changed + +This workstream followed Workstream 15 intentionally. + +Reason: + +- after improving shared read convergence, the next source of drift was legacy write behavior +- WebOS and iPad still keep the legacy CRM route family alive as a compatibility surface +- if legacy writes continued updating only `leads` and `chat_logs`, the platform would keep generating fresh divergence from canonical CRM even after the read bridge was improved + +The following repo-local changes were completed: + +- Added best-effort canonical write bridge helpers in `backend/api/routes_crm.py` +- Updated legacy lead creation so it now also attempts to sync the created lead into canonical CRM +- Updated legacy lead edits so they now also attempt to sync the updated lead into canonical CRM +- Updated legacy kanban moves so they now also attempt to sync canonical lead status and canonical stage history +- Updated legacy chat-log creation so it now also attempts to: + - ensure the corresponding canonical lead binding exists + - write a canonical interaction record + - write a canonical message record +- Updated legacy lead deletion so it now also attempts canonical cleanup for the linked canonical lead path +- Kept all of this as best-effort compatibility behavior so the current legacy route family still works even if canonical CRM schema access is temporarily unavailable in a given environment +- Added focused backend tests verifying that legacy write routes trigger the canonical bridge without changing the current route contract + +### What is materially better now + +- the platform no longer has to accept ongoing guaranteed drift every time the legacy compatibility surface performs a lead mutation +- legacy lead writes, chat-log writes, and kanban moves now push the system meaningfully closer to canonical CRM instead of only widening the gap +- the shared WebOS and iPad compatibility surface is now much closer to a controlled migration layer rather than a permanently divergent second CRM +- this makes the eventual retirement of legacy tables more realistic because both shared reads and shared writes now have a canonical bridge path + +### What remains blocked or incomplete + +- this is still a compatibility bridge, not final legacy-table retirement +- legacy tables still remain part of the active runtime path +- canonical cleanup on delete is best-effort and intentionally conservative +- broader canonical workflow depth such as richer message-thread modeling and full writeback governance remains future work + +### Validation run for this workstream + +The following checks were run after implementation: + +- `python3 -m py_compile` across: + - `backend/api/routes_crm.py` + - `backend/tests/test_legacy_crm_write_bridge.py` + - result: OK +- targeted shared legacy write-bridge tests: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_legacy_crm_write_bridge.py -q` + - result: `4 passed in 0.29s` +- legacy CRM regression check: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_crm_routes.py -q backend/tests/test_legacy_crm_canonical_bridge.py -q` + - result: `8 passed` +- canonical CRM regression checks: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_canonical_crm_auth.py -q backend/tests/test_canonical_crm_tenant_scoping.py -q` + - result: `8 passed` + +### Current judgment after Workstream 16 + +This workstream was successful. + +It does not yet retire the legacy CRM tables, but it materially improves production readiness by ensuring the active shared legacy compatibility surface now attempts to converge both reads and writes toward canonical CRM instead of only bridging reads. + +It is complete enough to move to the next item once approved. + +## Workstream 17 Status - iPad Canonical CRM Bootstrap Alignment + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with deeper canonical CRM screen coverage still open + +### What was changed + +Architectural correction received on 2026-04-22 from Sagnik: + +- the canonical CRM source of truth for both WebOS and iPad is the `crm_* + intel_* + workflow_*` model +- the canonical API contract is rooted under `/api/crm/*` +- legacy `leads` / `chat_logs` and `/api/leads*` remain compatibility infrastructure, but they are not the target product contract for iPad work + +Based on that correction, the following repo-local iPad changes were completed: + +- Updated the iPad live CRM bootstrap in `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift` +- The iPad app no longer fetches its live CRM bootstrap from `/api/leads` +- The iPad app now fetches canonical contact summaries from: + - `/api/crm/contacts` +- Added an iPad-side canonical adapter that now: + - filters the canonical contact list down to rows that actually have active lead context + - preserves the current iPad shell DTO shape so the existing Dashboard, Communications, and Oracle views do not break + - normalizes canonical QD score values into the current iPad 0-100 scoring presentation + - maps canonical lead status into the current iPad stage/status presentation +- Updated iPad copy in the active shell so it now speaks more truthfully about canonical CRM contacts and pipeline context instead of implying that the app is directly backed by legacy lead rows +- Added an iPad smoke-test assertion covering: + - canonical contact filtering + - score normalization + - canonical status mapping into the existing shell model + +### What is materially better now + +- the iPad app is now aligned with the same canonical CRM direction already used by WebOS CRM modules, Sentinel, and Oracle backend data access +- the iPad production path no longer depends on `/api/leads` for its live CRM bootstrap +- the current iPad shell now has a stable local adapter contract instead of directly inheriting a legacy route shape +- this reduces the chance that future iPad work accidentally deepens dependence on the old `leads` / `chat_logs` model + +### What remains blocked or incomplete + +- this workstream only aligns the iPad CRM bootstrap source; it does not yet create first-class iPad screens for: + - Contacts list + - Contact detail + - Client 360 + - Opportunities + - Tasks + - Kanban + - Imports +- iPad communications still consume `/api/mobile-edge/*`, and those event routes remain lead-ID keyed today +- because of that, the current iPad adapter intentionally filters canonical contacts down to records that still have active lead context +- a real Xcode build/test run still could not be completed from this machine because full Xcode is not installed + +### Validation run for this workstream + +The following checks were run after implementation: + +- static route verification: + - command: + `rg -n "/api/leads|/api/crm/contacts|activeLeadSummaries" iOS/velocity-ipad/velocity iOS/velocity-ipad/velocityTests` + - result: + - canonical `/api/crm/contacts` adapter usage found in the active iPad networking layer + - no remaining `/api/leads` bootstrap reference found inside the active iPad target +- Swift parse validation: + - command: + `swiftc -frontend -parse iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift` + - result: OK +- Swift parse validation for affected UI and smoke-test files: + - command: + `swiftc -frontend -parse iOS/velocity-ipad/velocity/Features/Communications/CommunicationsView.swift iOS/velocity-ipad/velocity/Features/Dashboard/DashboardView.swift iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift iOS/velocity-ipad/velocity/Features/Settings/SettingsView.swift iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift` + - result: OK +- attempted Xcode build: + - command: + `xcodebuild -project iOS/velocity-ipad/velocity.xcodeproj -scheme velocity -destination 'generic/platform=iOS Simulator' build` + - result: + - failed due local environment limitation: + `xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance` + +### Current judgment after Workstream 17 + +This workstream was successful. + +It does not yet complete the full canonical iPad CRM product surface, but it corrects an important architecture mistake by moving the live iPad CRM bootstrap onto the canonical `/api/crm/*` contract instead of continuing to deepen the legacy `/api/leads` dependency. + +It is complete enough to move to the next item once approved. + +## Workstream 18 Status - iPad Canonical Task and Reminder Coverage + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with task writeback and broader canonical CRM screen depth still open + +### What was changed + +This workstream continued the canonical CRM direction established in Workstream 17. + +Reason: + +- after moving the iPad CRM bootstrap onto canonical `/api/crm/contacts`, the next production gap was follow-up workload truth +- the iPad shell still represented follow-up pressure mostly through derived lead state and calendar-only views +- WebOS and the backend already define canonical task/reminder truth under `/api/crm/tasks` + +The following repo-local changes were completed: + +- Added canonical CRM task DTO support to `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift` +- Added a real iPad client method for: + - `/api/crm/tasks` +- Added deterministic iPad-side task ordering so the operator inbox now prioritizes: + - pending tasks first + - then urgent/high priority + - then earlier due dates +- Extended the shared iPad `AppStore` so it now hydrates canonical CRM tasks together with: + - canonical CRM contacts + - calendar events + - inventory + - alerts + - lead-event timeline context +- Updated Dashboard so it now shows: + - pending task count + - urgent task count + - a real canonical `Follow-Up Load` panel populated from `/api/crm/tasks` +- Updated Calendar so it now blends: + - live mobile-edge calendar events + - canonical CRM reminder tasks + into one operator-facing agenda surface +- Updated Oracle `Calendar & Tasks` so it now truthfully includes both: + - calendar events + - canonical follow-up tasks +- Updated Settings so it now reports how many canonical CRM tasks were loaded +- Added iPad smoke-test coverage for canonical task ordering + +### What is materially better now + +- the iPad app now reads real canonical follow-up workload instead of implying task state only through contact summaries or calendar presence +- Dashboard, Calendar, and Oracle now reflect the same canonical reminder system already exposed by the backend +- the iPad operator shell is more aligned with WebOS and backend source-of-truth behavior for reminder/task load +- this closes an important product-honesty gap because the app no longer claims task awareness while ignoring the canonical `/api/crm/tasks` contract + +### What remains blocked or incomplete + +- the iPad app still does not yet support canonical task write actions such as: + - create + - complete + - snooze + - cancel +- this workstream improves read-path task coverage only +- communications still rely on lead-keyed mobile-edge event routes, so the contact/task/event model is not yet fully unified on iPad +- first-class canonical CRM screens such as Client 360, Opportunities, Kanban, and Imports are still not implemented as dedicated iPad surfaces +- a real Xcode build/test run still could not be completed from this machine because full Xcode is not installed + +### Validation run for this workstream + +The following checks were run after implementation: + +- Swift parse validation: + - command: + `swiftc -frontend -parse iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift iOS/velocity-ipad/velocity/Core/State/AppStore.swift iOS/velocity-ipad/velocity/Core/State/AppStoreRefreshPolicy.swift iOS/velocity-ipad/velocity/Features/Dashboard/DashboardView.swift iOS/velocity-ipad/velocity/Features/Calendar/CalendarView.swift iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift iOS/velocity-ipad/velocity/Features/Settings/SettingsView.swift iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift` + - result: OK +- canonical route verification: + - command: + `rg -n "/api/crm/tasks|Pending CRM tasks loaded|Follow-Up Load|Pending Follow-Up Tasks" iOS/velocity-ipad/velocity iOS/velocity-ipad/velocityTests` + - result: + - canonical `/api/crm/tasks` usage found in the active iPad networking layer + - canonical task surfacing found in Dashboard, Oracle, and Settings +- canonical backend regression checks: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_canonical_crm_auth.py -q backend/tests/test_canonical_crm_tenant_scoping.py -q` + - result: `8 passed` +- attempted Xcode build remains blocked in this local environment for the same reason previously recorded: + - full Xcode is not installed on this machine + +### Current judgment after Workstream 18 + +This workstream was successful. + +It does not yet give the iPad app full task writeback workflows, but it materially improves production readiness by making the iPad operator shell consume and present canonical CRM reminder load instead of relying on partial inferred follow-up state. + +It is complete enough to move to the next item once approved. + +## Workstream 19 Status - iPad Oracle Canonical Kanban Alignment + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with deeper canonical opportunity and client-detail surfaces still open + +### What was changed + +This workstream continued the same principle the user emphasized: + +- when the iPad app is opened against the real environment, the developed feature should be actually testable against existing backend data + +Reason: + +- after Workstreams 17 and 18, the iPad app was already reading canonical contacts and canonical tasks +- however, the Oracle `Pipeline` screen still synthesized lanes from adapted contact summaries instead of reading the real canonical board contract +- the backend already exposes the correct testable production contract at: + - `/api/crm/kanban` + +The following repo-local changes were completed: + +- Added canonical kanban DTO support to `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift` +- Added a real iPad client method for: + - `/api/crm/kanban` +- Extended the shared iPad `AppStore` so it now hydrates canonical kanban columns together with the other shared live datasets +- Updated Oracle `Pipeline` so it now reads and renders the canonical kanban board directly instead of deriving lanes from adapted contact summaries +- Preserved the backend lane order and lane counts coming from the canonical route family +- Added iPad-side deterministic card ordering within each lane by canonical intent score so the highest-intent records float to the top in a stable way +- Added iPad smoke-test coverage for canonical kanban ordering and score normalization + +### What is materially better now + +- the Oracle pipeline on iPad is now directly backed by the real canonical `/api/crm/kanban` contract +- this makes the pipeline screen meaningfully more testable against the existing production-like database state +- lane counts, labels, and stage visibility now come from the backend source of truth rather than from local grouping logic +- the iPad app is now more internally consistent: + - canonical contacts for bootstrap + - canonical tasks for follow-up load + - canonical kanban for pipeline truth + +### What remains blocked or incomplete + +- this workstream improves pipeline read-path truth only +- the iPad app still does not expose first-class dedicated screens for: + - Opportunities + - Contact detail + - Client 360 + - Imports +- Oracle still does not expose write actions such as stage movement or opportunity mutation from iPad +- a real Xcode build/test run still could not be completed from this machine because full Xcode is not installed + +### Validation run for this workstream + +The following checks were run after implementation: + +- Swift parse validation: + - command: + `swiftc -frontend -parse iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift iOS/velocity-ipad/velocity/Core/State/AppStore.swift iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift` + - result: OK +- canonical route verification: + - command: + `rg -n "/api/crm/kanban|operatorDisplayBoard|kanbanColumns|Pipeline Summary" iOS/velocity-ipad/velocity iOS/velocity-ipad/velocityTests` + - result: + - canonical `/api/crm/kanban` usage found in the active iPad networking layer + - shared store kanban hydration found in the active iPad state layer + - Oracle pipeline rendering found to depend on canonical kanban columns +- canonical backend regression checks: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_canonical_crm_auth.py -q backend/tests/test_canonical_crm_tenant_scoping.py -q` + - result: `8 passed` + +### Current judgment after Workstream 19 + +This workstream was successful. + +It does not yet provide the full canonical CRM product surface on iPad, but it materially improves production readiness by making the Oracle pipeline screen read the real canonical kanban board, which is far more reliable and testable against existing database data than the earlier local grouping approach. + +It is complete enough to move to the next item once approved. + +## Workstream 20 Status - iPad Canonical Client 360 And Deals Coverage + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with dedicated contacts and imports workflows still open + +### What was changed + +This workstream continued the requirement that iPad functionality should be genuinely testable against the real data already present in the database. + +Reason: + +- after Workstreams 17 to 19, the iPad app was already reading canonical contacts, tasks, and kanban +- however, it still lacked a practical way to inspect a real canonical client dossier or a real canonical opportunity list from the running app +- the backend already exposes the correct live contracts at: + - `/api/crm/client-360/{person_id}` + - `/api/crm/opportunities` + +The following repo-local changes were completed: + +- Added canonical Client 360 DTO support to `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift` +- Added canonical opportunities DTO support to the same iPad networking layer +- Added real iPad client methods for: + - `/api/crm/client-360/{person_id}` + - `/api/crm/opportunities` +- Extended the shared iPad `AppStore` so it now hydrates canonical opportunity rows together with the other shared live datasets +- Expanded Oracle production scope to include a new live-backed `Deals` mode +- Added a real Oracle `Deals` surface backed by canonical `/api/crm/opportunities` +- Added a real iPad `Client 360` sheet that can now be opened from: + - canonical pipeline cards + - deal cards + - timeline cards + - follow-up task cards inside Oracle +- Added iPad smoke-test coverage for: + - canonical Client 360 snapshot decoding + - opportunities ordering + +### What is materially better now + +- the iPad app can now open a real canonical Client 360 dossier against live backend data +- the iPad app can now verify canonical opportunities directly instead of treating pipeline-only visibility as sufficient +- Oracle is now a more honest and testable production surface because it exposes: + - canonical kanban + - canonical opportunities + - canonical client dossier + - canonical task context +- this materially improves real-device testability against the existing database instead of only improving architectural correctness on paper + +### What remains blocked or incomplete + +- the iPad app still does not yet expose a dedicated contacts list/detail workspace outside the broader shell +- the iPad app still does not yet expose canonical imports workflows +- the iPad app still does not yet provide canonical CRM write actions for: + - stage movement + - opportunity mutation + - task completion / snooze / cancel +- a real Xcode build/test run still could not be completed from this machine because full Xcode is not installed + +### Validation run for this workstream + +The following checks were run after implementation: + +- Swift parse validation: + - command: + `swiftc -frontend -parse iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift iOS/velocity-ipad/velocity/Core/State/AppStore.swift iOS/velocity-ipad/velocity/Features/Oracle/OracleModeAvailability.swift iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift` + - result: OK +- canonical route verification: + - command: + `rg -n "/api/crm/client-360|/api/crm/opportunities|Client 360|Deals|productionVisibleModes" iOS/velocity-ipad/velocity iOS/velocity-ipad/velocityTests` + - result: + - canonical Client 360 usage found in the active iPad networking layer + - canonical opportunities usage found in the active iPad networking layer + - Oracle production scope now includes a live-backed `Deals` surface +- canonical backend regression checks: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_canonical_crm_auth.py -q backend/tests/test_canonical_crm_tenant_scoping.py -q` + - result: `8 passed` + +### Current judgment after Workstream 20 + +This workstream was successful. + +It does not yet complete the full canonical CRM product surface on iPad, but it materially improves production readiness by making live Client 360 and live opportunities directly testable from the app shell against existing backend data. + +It is complete enough to move to the next item once approved. + +## Workstream 21 Status - iPad Canonical Task Writeback And Lead Stage Movement + +Date completed: 2026-04-22 +Status: materially improved and complete enough to move to the next workstream, with opportunity mutation and dedicated CRM workspaces still open + +### What was changed + +This workstream targeted the first missing canonical CRM write path that blocked meaningful production testing on the iPad app. + +Reason: + +- after Workstreams 17 to 20, the iPad app could already read real canonical tasks, kanban lanes, opportunities, and Client 360 dossiers +- however, the operator still could not act on those rows from the iPad, which meant the app was not honestly testable against the live database even though the data already existed +- the canonical schema already defined the correct writeback targets: + - `intel_reminders.status` for task lifecycle state + - `crm_leads.status` plus `crm_stage_history` for lead funnel transitions + +The following repo-local changes were completed: + +- Added canonical backend write endpoints in `backend/api/routes_crm_imports.py` for: + - `PATCH /api/crm/tasks/{reminder_id}` + - `PATCH /api/crm/leads/{lead_id}/stage` +- Implemented task lifecycle validation so canonical reminders can now be: + - marked `done` + - reopened to `pending` + - `snoozed` with a future due timestamp + - `cancelled` +- Implemented canonical lead stage movement with: + - tenant-scoped lead lookup + - status update on `crm_leads` + - stage audit insertion into `crm_stage_history` + - idempotent response behavior when the requested stage already matches the current one +- Tightened canonical timestamp handling so reminder due dates are parsed as ISO-8601 timestamps instead of being silently ignored +- Added iPad client methods for the new canonical write routes in `VelocityAPIClient` +- Extended the shared iPad `AppStore` with canonical CRM mutation helpers that refresh live store state after a successful write +- Added real iPad write controls to the active production-backed surfaces: + - Oracle `Pipeline` now exposes stage movement actions per live kanban card + - Oracle `Calendar & Tasks` now exposes task completion, snooze, reopen, and cancel actions + - Oracle `Client 360` now exposes both lead stage movement and task lifecycle actions inside the dossier + - the main Calendar screen now exposes task completion, snooze, and cancel actions for canonical reminder rows +- Added backend test coverage for: + - auth rejection on the new canonical write routes + - tenant-scoped task mutation + - tenant-scoped lead stage mutation + - canonical stage-history recording +- Added iPad smoke-test coverage for: + - task snooze-date behavior + - canonical lead-stage mutation DTO decoding + +### What is materially better now + +- the iPad app can now perform real canonical reminder lifecycle changes instead of only reading reminder rows +- the iPad app can now move real canonical leads across funnel stages and persist the audit trail expected by the canonical schema +- a user opening the iPad app against the existing database can now genuinely test: + - task completion + - task snooze flows + - task cancellation + - task reopening + - lead stage movement from Oracle +- the iPad shell is now much closer to WebOS-grounded CRM behavior because the app is no longer limited to passive read-only CRM inspection + +### What remains blocked or incomplete + +- superseded by Workstream 22: canonical opportunity mutation is now exposed on iPad +- the iPad app still does not yet expose dedicated contacts and imports workspaces +- a real Xcode build/test run still could not be completed from this machine because full Xcode is not installed + +### Validation run for this workstream + +The following checks were run after implementation: + +- Swift parse validation: + - command: + `swiftc -frontend -parse iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift iOS/velocity-ipad/velocity/Core/State/AppStore.swift iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift iOS/velocity-ipad/velocity/Features/Calendar/CalendarView.swift iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift` + - result: OK +- canonical backend regression checks: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_canonical_crm_auth.py -q backend/tests/test_canonical_crm_tenant_scoping.py -q` + - result: `14 passed` + +### Current judgment after Workstream 21 + +This workstream was successful. + +It does not yet finish the full canonical CRM product surface on iPad, but it materially improves production readiness by making the first real CRM write actions testable from the running iPad shell against existing backend data. + +It is complete enough to move to the next item once approved. + +## Workstream 22 Status - iPad Canonical Opportunity Mutation + +Date completed: 2026-04-23 +Status: materially improved and complete enough to move to the next workstream, with dedicated contacts/imports workspaces still open + +### What was changed + +This workstream completed the next canonical CRM writeback gap: deal/opportunity mutation. + +Reason: + +- after Workstream 21, the iPad app could write canonical task lifecycle state and lead stage transitions +- however, the `Deals` surface still remained read-only even though it displayed real `/api/crm/opportunities` rows +- the canonical source of truth for deals is `crm_opportunities`, not legacy CRM tables + +The following repo-local changes were completed: + +- Added a tenant-scoped canonical backend write endpoint: + - `PATCH /api/crm/opportunities/{opportunity_id}` +- The endpoint can update canonical opportunity fields: + - `stage` + - `value` + - `probability` + - `expected_close_date` + - `next_action` + - `notes` +- Added validation for canonical opportunity stages: + - `prospect` + - `qualified` + - `proposal` + - `site_visit` + - `negotiation` + - `booking` + - `agreement` + - `closed_won` + - `closed_lost` +- Added tenant isolation by resolving the opportunity through its linked canonical `crm_leads` row and authenticated tenant scope +- Updated the shared WebOS CRM adapter in `app/src/lib/crmApi.ts` so WebOS and iPad share the same canonical write contract +- Updated the shared WebOS CRM types to include opportunity notes returned from the canonical endpoint +- Added iPad client and store write helpers for canonical opportunity mutation +- Added real iPad deal actions in Oracle: + - move opportunity stage + - set probability + - set a follow-up next action + - close won + - close lost +- Added the same opportunity mutation controls inside the `Client 360` opportunity card +- Added backend tests for: + - auth rejection on opportunity write routes + - tenant-scoped opportunity mutation + - cross-tenant opportunity rejection +- Added iPad smoke-test coverage for canonical opportunity mutation DTO decoding and probability label normalization + +### What is materially better now + +- the iPad app can now mutate real canonical deal rows instead of only viewing them +- the Deals surface is now genuinely testable against existing database data +- Client 360 is more production-useful because the operator can update deal posture directly from the dossier +- WebOS and iPad now share a single canonical opportunity write contract under `/api/crm/opportunities/{opportunity_id}` + +### What remains blocked or incomplete + +- superseded by Workstream 23 for contacts: the iPad app now exposes a dedicated canonical Clients workspace +- the iPad app still does not yet expose canonical imports workspaces +- custom free-form opportunity editing is not yet exposed in the iPad UI; this pass added robust preset operator actions that map cleanly to the canonical write contract +- a real Xcode build/test run still could not be completed from this machine because full Xcode is not installed + +### Validation run for this workstream + +The following checks were run after implementation: + +- Swift parse validation: + - command: + `swiftc -frontend -parse iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift iOS/velocity-ipad/velocity/Core/State/AppStore.swift iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift iOS/velocity-ipad/velocity/Features/Calendar/CalendarView.swift iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift` + - result: OK +- canonical backend regression checks: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_canonical_crm_auth.py -q backend/tests/test_canonical_crm_tenant_scoping.py -q` + - result: `17 passed` +- WebOS TypeScript validation: + - command: + `npx tsc --noEmit` + - result: OK + +### Current judgment after Workstream 22 + +This workstream was successful. + +It closes the remaining core canonical CRM writeback gap for the existing iPad Oracle CRM surfaces: tasks, lead stages, and opportunities are now all writable through canonical `/api/crm/*` contracts. + +It is complete enough to move to the next item once approved. + +## Workstream 23 Status - iPad Dedicated Canonical Clients Workspace + +Date completed: 2026-04-23 +Status: materially improved and complete enough to move to the next workstream, with canonical imports workspace still open + +### What was changed + +This workstream added the first dedicated canonical CRM contact workspace to the iPad app. + +Reason: + +- the iPad app already consumed `/api/crm/contacts` internally to build dashboard lead summaries +- however, users did not have a first-class place to inspect canonical contacts directly +- the earlier Oracle Client 360 sheet was useful, but discoverability was limited because it depended on entering Oracle surfaces first + +The following repo-local changes were completed: + +- Added a new top-level iPad navigation section: + - `Clients` +- Added a new SwiftUI screen: + - `iOS/velocity-ipad/velocity/Features/Clients/ClientsView.swift` +- Promoted canonical contact rows into shared iPad `AppStore` state +- Added a dedicated iPad client method for canonical contacts: + - `GET /api/crm/contacts` +- Kept the existing lead-summary adapter intact by deriving `VelocityLeadDTO` values from the same canonical contact rows +- Added deterministic contact sorting by intent score and then client name +- Added a searchable contacts workspace that filters by: + - name + - phone + - buyer type + - lead status + - budget + - primary interest + - urgency +- Added contact cards showing: + - canonical name and phone + - buyer type + - lead status + - budget and primary interest + - pending task count + - interaction count + - intent/engagement/urgency-derived score +- Added a Client 360 sheet from each contact card using: + - `GET /api/crm/client-360/{person_id}` +- Updated iPad navigation smoke expectations so the app shell treats `Clients` as a stable production section + +### What is materially better now + +- users can now open the iPad app and directly test canonical contact data without going through Dashboard or Oracle first +- the iPad app now has a first-class contact workspace backed by `crm_people` plus the canonical contact read model +- Client 360 is easier to discover and test because every contact card can open the dossier +- dashboard lead summaries and the dedicated Clients workspace now share the same canonical contact source instead of creating parallel CRM interpretations + +### What remains blocked or incomplete + +- canonical imports review/commit workflow is still not exposed on iPad +- the Clients workspace currently opens a concise Client 360 sheet; the richer write-heavy Client 360 controls still live in Oracle +- a real Xcode build/test run still could not be completed from this machine because full Xcode is not installed + +### Validation run for this workstream + +The following checks were run after implementation: + +- Swift parse validation: + - command: + `swiftc -frontend -parse iOS/velocity-ipad/velocity/App/ContentView.swift iOS/velocity-ipad/velocity/Features/Clients/ClientsView.swift iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift iOS/velocity-ipad/velocity/Core/State/AppStore.swift iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift` + - result: OK +- canonical backend regression checks: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_canonical_crm_auth.py -q backend/tests/test_canonical_crm_tenant_scoping.py -q` + - result: `17 passed` +- WebOS TypeScript validation: + - command: + `npx tsc --noEmit` + - result: OK +- Swift typecheck attempt: + - command: + `swiftc -frontend -typecheck ...` + - result: blocked locally because this machine cannot load the Apple standard library target without full Xcode + +### Current judgment after Workstream 23 + +This workstream was successful. + +It closes the dedicated canonical contacts workspace gap on iPad. The remaining canonical CRM workspace gap is now imports review/commit. + +It is complete enough to move to the next item once approved. + +## Workstream 24 Status - iPad Canonical Imports Workspace + +Date completed: 2026-04-23 +Status: completed for repo-local review/commit workflows, with upload-from-iPad intentionally still deferred + +### What was changed + +This workstream added the missing iPad workspace for canonical CRM import review. + +The following repo-local changes were completed: + +- Added a new top-level iPad navigation section: + - `Imports` +- Added a new SwiftUI screen: + - `iOS/velocity-ipad/velocity/Features/Imports/ImportsView.swift` +- Added iPad DTOs and client methods for: + - `GET /api/crm/imports` + - `GET /api/crm/imports/{batch_id}` + - `PUT /api/crm/imports/{batch_id}/review-proposal` + - `POST /api/crm/imports/{batch_id}/commit` +- Added import batch list, lifecycle status, row counts, mapped/unresolved counts, and source visibility +- Added proposal detail cards showing canonical payload previews, confidence, missing fields, and status +- Added approve/reject controls for individual proposals +- Added commit flow for approved proposals +- Added smoke-test coverage for canonical import batch detail decoding + +### What is materially better now + +- the iPad app can now review and commit canonical CRM import batches instead of relying on WebOS/admin-only import operations +- the canonical `workflow_*` import path is now testable from the iPad shell +- this closes the final dedicated canonical CRM workspace gap listed in the earlier production-readiness plan + +### What remains blocked or incomplete + +- upload-from-iPad is not exposed yet; this pass focused on review/approval/commit because uploaded batches already exist in the backend workflow path +- a real Xcode build/test run still could not be completed from this machine because full Xcode is not installed + +### Validation run for this workstream + +- Swift parse validation: + - command: + `swiftc -frontend -parse iOS/velocity-ipad/velocity/App/ContentView.swift iOS/velocity-ipad/velocity/Features/Imports/ImportsView.swift iOS/velocity-ipad/velocity/Features/Clients/ClientsView.swift iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift iOS/velocity-ipad/velocity/Core/State/AppStore.swift iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift` + - result: OK +- canonical backend regression checks: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_canonical_crm_auth.py -q backend/tests/test_canonical_crm_tenant_scoping.py -q` + - result: `17 passed` +- WebOS TypeScript validation: + - command: + `npx tsc --noEmit` + - result: OK + +### Current judgment after Workstream 24 + +This workstream was successful. + +The iPad app now has dedicated canonical Clients and Imports workspaces in addition to Oracle's canonical Pipeline, Deals, Tasks, and Client 360 surfaces. + +## Workstream 25 Status - Migration, Observability, CI, And iOS Source-Of-Truth Cleanup + +Date completed: 2026-04-23 +Status: completed for repo-local scaffolding and guardrails, with deployed infrastructure still requiring environment-level validation + +### What was changed + +This workstream addressed the remaining non-Xcode platform-readiness gaps that could be completed from this repo. + +The following repo-local changes were completed: + +- Added a governed backend migration runner: + - `backend/migrations/runner.py` + - `backend/migrations/versions/202604230001_observability_foundation.sql` +- Added migration checksum enforcement so applied migrations cannot be edited silently +- Wired migrations into backend startup before runtime schema compatibility helpers +- Added an observability foundation: + - request ID propagation + - request latency headers + - in-memory recent request metrics + - structured request-completed/request-failed logs + - protected `/api/observability/request-metrics` +- Added backend tests for: + - migration discovery ordering/checksums + - observability headers and metric capture +- Added CI gates in `.github/workflows/production-readiness.yml` for: + - backend contract tests + - WebOS TypeScript checking + - iPad Swift source parsing on macOS +- Removed stale duplicate root-level iPad prototype sources under: + - `iOS/App` + - `iOS/Core` + - `iOS/Features` +- Added `iOS/README.md` documenting the active iPad source of truth: + - `iOS/velocity-ipad/velocity` + - `iOS/velocity-ipad/velocity.xcodeproj` + - `iOS/velocity-ipad/velocityTests` +- Kept `iOS/velocity-iphone` because it is a distinct companion app, not an iPad duplicate tree + +### What is materially better now + +- production schema changes now have a migration path instead of relying entirely on route-startup side effects +- request tracing and latency visibility are now built into the backend +- CI can catch backend contract, WebOS type, and iPad parse regressions before merge +- the iPad app now has one clear source of truth, reducing future drift + +### What remains blocked or incomplete + +- deployed production TLS/proxy health cannot be repaired from this local repo without infrastructure access +- full Xcode build/test execution remains excluded per request and still requires a full Xcode machine +- real-device iPad validation remains required after Xcode validation +- external crash reporting vendor integration is not configured; this pass adds backend observability hooks and CI guardrails + +### Validation run for this workstream + +- backend migration/observability tests: + - command: + `PYTHONPATH="/tmp/velocity_pydeps:/Users/sayan/Desi Neuron/Project_Velocity:$PYTHONPATH" python3 -m pytest backend/tests/test_migrations_and_observability.py -q backend/tests/test_canonical_crm_auth.py -q backend/tests/test_canonical_crm_tenant_scoping.py -q` + - result: `19 passed` +- Python compile validation: + - command: + `python3 -m py_compile backend/main.py backend/observability.py backend/api/routes_observability.py backend/migrations/runner.py` + - result: OK +- Swift parse validation: + - command: + `swiftc -frontend -parse iOS/velocity-ipad/velocity/App/ContentView.swift iOS/velocity-ipad/velocity/Features/Imports/ImportsView.swift iOS/velocity-ipad/velocity/Features/Clients/ClientsView.swift iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift iOS/velocity-ipad/velocity/Core/State/AppStore.swift iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift` + - result: OK + +### Current judgment after Workstream 25 + +This workstream was successful for repo-local production readiness. + +Apart from full Xcode/device validation and external infrastructure operations, the major repo-local iPad readiness gaps identified in this audit have now been addressed. + +## Overall Architecture + +The iPad app is a native SwiftUI shell under `iOS/velocity-ipad/velocity`. The earlier duplicate root-level iPad prototype source folders have been removed, and `iOS/README.md` now records the active iOS source-of-truth policy. + +High-level runtime shape: + +- iPad app now supports runtime session configuration on-device, with build settings as fallback defaults +- Dream Weaver can now use a dedicated endpoint separate from the core backend +- App authenticates against `/api/auth/login` +- App now reads its live CRM bootstrap from canonical `/api/crm/contacts` +- App now exposes a dedicated Clients workspace backed by canonical `/api/crm/contacts` +- App now exposes a dedicated Imports workspace backed by canonical `/api/crm/imports*` +- App now reads canonical follow-up workload from `/api/crm/tasks` +- App now reads canonical pipeline lanes from `/api/crm/kanban` +- App now reads canonical client dossiers from `/api/crm/client-360/{person_id}` +- App now reads canonical deal rows from `/api/crm/opportunities` +- App now writes canonical reminder lifecycle changes via `/api/crm/tasks/{reminder_id}` +- App now writes canonical lead stage transitions via `/api/crm/leads/{lead_id}/stage` +- App now writes canonical opportunity/deal updates via `/api/crm/opportunities/{opportunity_id}` +- App reads communication events, alerts, and calendar data from `/api/mobile-edge/*` +- App reads inventory properties from `/api/inventory/properties` +- Dream Weaver uses `/health`, `/dream-weaver`, `/dream-weaver/status/{job_id}`, and `/dream-weaver/result/{job_id}` +- Backend is a FastAPI monolith in `backend/main.py` +- Database is PostgreSQL, now with a repo-local migration runner scaffold and first migration +- Backend now has request observability middleware, request IDs, latency headers, and protected request-metrics access + +## What Is Working + +### 1. The iPad shell is real and coherent + +The app has a real split-view container and a complete top-level navigation model in `iOS/velocity-ipad/velocity/App/ContentView.swift`. + +What works: + +- Multi-surface navigation exists +- Distinct feature screens exist for all main tabs +- Visual theme is consistent +- There is a real runtime configuration model + +Assessment: + +- Good enough to demo visually +- Good enough to serve as the real foundation of a production iPad app + +### 2. Dashboard, Communications, Calendar, Oracle canonical CRM views, and Settings are implemented + +These screens are not empty shells. They are wired to real data clients and have loading/error handling. + +Evidence: + +- `VelocityAPIClient` is implemented and reads canonical CRM contacts, canonical CRM tasks, canonical CRM kanban, canonical CRM opportunities, canonical Client 360 snapshots, events, calendar, properties, and alerts, and now also writes canonical task updates, canonical lead stage transitions, and canonical opportunity updates +- `AppStore` refreshes multiple live datasets and computes summary metrics from them +- Communications still has its own live data fetch flow, and Calendar now shares AppStore-backed live refresh state with Dashboard and Oracle + +What works in principle: + +- Live backend reads +- Real canonical CRM task, lead-stage, and opportunity writeback from the iPad shell +- Live refresh loops +- Error display rather than fake data +- Useful operator summaries + +Assessment: + +- These surfaces are the strongest part of the current iPad product +- They can be demo-worthy if backend auth, data seeding, and public endpoint stability are fixed + +### 3. Sunseeker is a genuine feature, not fake UI + +Sunseeker uses: + +- ARKit +- CoreLocation +- CoreMotion +- SceneKit +- custom sun-path math + +What works: + +- Real-device AR overlay architecture exists +- Location permission handling exists +- heading-aware rendering exists +- current position, arc, sunrise, and sunset are modeled + +Assessment: + +- This is a legitimate differentiated feature +- It should be demoed only on a physical iPad + +### 4. Web frontend build passes locally + +The web frontend under `app/` successfully built locally on 2026-04-22 with: + +- `npm run build` + +Observed state: + +- Build succeeds +- One major JS chunk is very large at roughly 2.46 MB minified +- There is a chunking warning, but not a hard failure + +Assessment: + +- Web frontend is buildable +- It is not the primary blocker for the iPad investor story + +## What Is Partially Working + +### 1. Dashboard and shared app state are functional but operationally inefficient + +At audit start, `AppStore.refresh()` fanned out to four endpoints, then did per-lead event fetches sequentially for up to six leads. + +Update 2026-04-22: + +- Workstream 8 added a dedicated refresh policy layer grounded against the WebOS bootstrap +- the iPad inventory property limit now matches the WebOS `100`-row slice +- concurrent iPad refresh callers now reuse one in-flight refresh task +- per-lead event hydration for the iPad operator slice now runs in parallel instead of sequentially + +Impact: + +- N+1 network pattern +- some avoidable latency was removed +- some unnecessary backend load was removed + +This becomes more problematic because multiple screens trigger refreshes on timers: + +- Dashboard: every 20 seconds +- Sentinel: every 20 seconds +- Oracle: every 20 seconds +- Communications: every 15 seconds +- Calendar: every 15 seconds + +Assessment: + +- materially better than the audit-start state +- still not the final production-scale refresh architecture + +### 2. Communications is live-backed but is still a read-only intelligence rail + +The Communications surface is useful, but it is not a full operator console. + +What it has: + +- live event summaries +- thread prioritization +- next-action hints +- alert cards + +What it does not have: + +- send/reply actions +- transcript drilldown UI +- direct note creation +- insight action handling + +Assessment: + +- Valuable for demo and roadmap +- not a complete communication operations tool yet + +### 3. Calendar is live-backed but not a full production scheduler on iPad + +The backend supports create/update/delete calendar events, but the iPad view is effectively a read-only agenda surface. + +What it has: + +- live event loading +- summary metrics +- filtered agenda visualization + +What it lacks on iPad: + +- create event +- edit event +- confirm/cancel event actions +- reminder controls + +Assessment: + +- good read-only operator visibility +- not a complete calendar tool on iPad + +### 4. Oracle is live-backed within a deliberately narrowed production scope + +Oracle still has five conceptual modes in the codebase, but the production iPad scope now intentionally exposes only the three modes that have real mobile backing: + +- Pipeline: live-backed and production-visible +- Account Timeline: live-backed and production-visible +- Calendar & Tasks: live-backed and production-visible +- Team Performance: hidden until backend support exists +- Lead Map: hidden until backend support exists + +Assessment: + +- Oracle is now materially safer to demo because the visible surface better matches backend reality +- Oracle is still not a complete multi-pane executive intelligence product on iPad + +## What Is Not Working Or Not Production Ready + +## P0 Blockers + +### 1. Public API ingress is not healthy as of 2026-04-22 + +The iPad app defaults to: + +- `https://api.desineuron.in` + +Live verification on 2026-04-22 showed: + +- `http://api.desineuron.in/health` returns `308 Permanent Redirect` to HTTPS +- `https://api.desineuron.in/health` fails TLS handshake with `tlsv1 alert internal error` +- direct connection to `54.91.19.60:8082` timed out from this environment + +What this means: + +- the configured production endpoint cannot currently be treated as healthy +- any live investor demo depending on this host is high-risk until fixed + +### 2. Dream Weaver is still high-risk, but the repo-local contract gaps were materially reduced on 2026-04-22 + +There were originally three separate problems here. + +Problem A: the iPad app uses the same `BASE_URL` for both the core backend and Dream Weaver gateway. + +That means the app assumes one host cleanly serves: + +- `/api/auth/login` +- `/api/leads` +- `/api/mobile-edge/*` +- `/api/inventory/*` +- `/health` +- `/dream-weaver/*` + +In the repo, Dream Weaver is not mounted into `backend/main.py`. It lives as a separate gateway implementation. + +Problem B: there are multiple Dream Weaver gateway implementations with different contracts. + +The iPad client expects: + +- `job_id` +- `status` +- `poll_url` +- `result_url` + +But `dw_gateway_v2_min.py` returns only: + +- `job_id` +- `status` + +If the minimal gateway is the active runtime, the iPad decode path will fail before polling even begins. + +Problem C: the health check is too weak. + +`ComfyClient.checkHealth()` only checks `/health` and accepts a generic `status == "ok"` or `"healthy"`. A healthy backend could pass this check even if `/dream-weaver` itself is not present or not proxied. + +Update 2026-04-22: + +- Problem A was materially addressed in the iPad app: + - the session model now supports a dedicated Dream Weaver endpoint + - the Settings surface now exposes that endpoint for runtime configuration +- Problem B was materially addressed in both the iPad app and `dw_gateway_v2_min.py`: + - the iPad client now tolerates missing `poll_url` / `result_url` + - the minimal gateway now returns `poll_url` / `result_url` + - the minimal gateway now exposes `/dream-weaver/result/{job_id}` +- Problem C was materially addressed in the iPad app: + - the health check now probes for real Dream Weaver route presence instead of trusting `/health` alone +- Problem D was materially addressed in both gateway variants and the iPad app: + - Dream Weaver can now enforce an optional API key at the gateway layer + - the iPad runtime configuration now supports a dedicated Dream Weaver gateway key stored in Keychain + - the iPad client now sends that key during health probes, route probes, submission, polling, and result download + +What still remains true: + +- the deployed production endpoint is not verified healthy over HTTPS +- Dream Weaver still is not mounted into `backend/main.py` +- endpoint ownership and reverse proxying are still infrastructure decisions, not repo-local facts +- there is still no completed real-device round-trip proof for the production-facing path + +Assessment: + +- Dream Weaver UI is present +- Dream Weaver repo-local readiness is materially better than it was at audit start +- Dream Weaver production reliability is still not proven +- Dream Weaver should not be part of the live investor flow until deployed endpoint health, proxying, and a full round-trip generation test are verified + +### 3. Dollhouse content is still missing, but the production build now gates it honestly + +The Dollhouse renderer tries to load: + +- `Building.usdz` +- `Building.scn` + +No such asset exists under `iOS/velocity-ipad/velocity`. + +Update 2026-04-22: + +- Workstream 6 now hides Dollhouse from the production Inventory mode picker when the asset is absent +- unsupported Dollhouse selection state is sanitized back to `Sunseeker` +- the underlying SceneKit fallback still exists in code as a defensive last resort, but it is no longer the intended production-facing experience + +Assessment: + +- the meaningful 3D experience still does not exist +- production honesty is materially improved because the feature is no longer advertised without content +- the feature remains incomplete until the real model asset is shipped and validated + +### 4. The iPad target configuration itself was not production-clean at audit start + +I found multiple target-level issues: + +- deployment target is set to `26.2` +- bundle identifier is `com.desineouron.velocity` with a spelling error +- target device family is `"1,2"`, which means iPhone and iPad, not iPad-only +- there is no test target + +Assessment: + +- This project can still be a workable base +- It is not in clean release-engineering shape + +Update 2026-04-22: + +- This finding was materially addressed by Workstream 1 +- bundle identifier, deployment target, iPad-only targeting, ATS posture, and test scaffolding were improved +- the remaining limitation is verification, not release-hygiene design + +### 5. The iPad authentication UX was missing at audit start and is now materially improved + +The app originally expected credentials only through build-time configuration: + +- `API_EMAIL` +- `API_PASSWORD` +- `API_BEARER_TOKEN` + +As of Workstream 2, this is no longer the only path. + +What now exists: + +- first-run runtime configuration gating +- secure on-device session storage +- Settings-based session editing +- session clearing and token cache reset + +Remaining limitations: + +- no password recovery +- no SSO +- no role-aware multi-user session handling +- no full Xcode-verified build result from this machine + +Assessment: + +- materially improved +- acceptable for controlled investor/demo installs if backend health is fixed +- still not the final enterprise-grade auth story + +### 6. Secrets were being treated as app configuration, not secure runtime state, and that has now been partially corrected + +At audit start, the iPad app depended on `Info.plist` / build settings for API secrets, and ATS was globally bypassed. + +What changed: + +- blanket ATS bypass was removed in Workstream 1 +- runtime-entered secrets are now stored in Keychain in Workstream 2 +- endpoint and operator email can now be configured on-device without rebuilding the app + +What still remains true: + +- build-time config fallback still exists +- if teams choose to distribute builds with embedded secrets, that remains an operational risk even though the app now has a safer runtime path + +Assessment: + +- no longer acceptable to describe this as a build-time-only secret model +- materially safer than the original state +- still needs disciplined release process and secret-handling policy + +## P1 Major Gaps + +### 7. Sentinel on iPad is now honestly framed as Operator Posture, but still lacks real analytics + +At audit start, the iPad app still presented this area primarily as `Sentinel` even though it was functioning as an operator urgency surface rather than a visitor analytics console. + +Update 2026-04-22: + +- Workstream 7 now relabels the user-facing iPad surface to `Operator Posture` +- the screen keeps `Sentinel` visible as the product family while clarifying the iPad production scope +- Settings production notes now use the same framing + +What it really is: + +- alert summary +- transcription queue visibility +- upcoming calendar pressure +- recent operator timeline + +What it is not: + +- live perception feed +- visitor counting +- sentiment scoring +- face-driven showroom intelligence + +Assessment: + +- production honesty is materially improved +- this is acceptable as an operator-posture surface if demoed honestly +- it would still overstate reality if pitched as full production Sentinel analytics on iPad + +### 8. Oracle mobile scope is now intentionally narrower than broader product messaging + +At audit start, the iPad Oracle experience visibly exposed `Team Performance` and `Lead Map` even though neither had a production mobile route behind it. + +Update 2026-04-22: + +- Workstream 5 now hides those unsupported modes from the production iPad scope +- the visible Oracle iPad modes are now limited to the live-backed set: + - pipeline + - account timeline + - calendar & tasks +- unsupported selections are sanitized back to `Pipeline` + +What still remains true: + +- the backend still lacks real mobile contracts for `Team Performance` and `Lead Map` +- Oracle roadmap breadth still exceeds the current iPad production scope + +Assessment: + +- production honesty is materially improved +- full Oracle mode parity is still future work + +### 9. CRM leads endpoint was unauthenticated at audit start and remains legacy-shaped + +The iPad app fetches leads from `/api/leads` using `VelocityAPIClient`. + +At audit start, the server-side `crm_router`: + +- does not require `get_current_user` +- auto-creates its own legacy `leads` and `chat_logs` tables at runtime +- does not use the canonical CRM tables +- does not appear to enforce tenant scoping + +This is one of the most important backend architecture findings. + +Impact: + +- security risk +- data isolation risk +- legacy/canonical data drift +- production behavior depends on route bootstrap side effects + +Update 2026-04-22: + +- the legacy CRM route family now requires authenticated users +- the legacy `leads` and `chat_logs` paths now scope queries and writes by `tenant_id` +- auth now carries a first-class `tenant_id` claim into `UserPrincipal` +- `/api/auth/me` now exposes the resolved tenant scope +- Workstream 11 aligned the current WebOS bootstrap client so it also attaches the Velocity bearer token when reading `/api/leads` and `/api/chat-logs` + +What still remains true: + +- `users_and_roles` now carries `tenant_id`, and login now resolves tenant scope from the user row +- runtime schema mutation is still present as an interim compatibility layer +- legacy and canonical CRM tables still coexist +- route bootstrap still contains schema side effects for the legacy path +- canonical CRM route families are now materially safer because Workstream 14 added first-pass tenant scoping to the active canonical CRM surface, but the lead bootstrap itself still has not migrated away from legacy `/api/leads` + +Assessment: + +- materially safer than the original state +- acceptable as an interim hardening pass for the current iPad dependency +- still not the final canonical CRM architecture + +Related update 2026-04-22: + +- Workstream 13 hardened the canonical `/api/crm/*` route family so it now also requires authenticated Velocity sessions +- Workstream 14 added first-pass tenant scoping to the active canonical CRM route family +- Workstream 15 now lets the shared legacy `/api/leads` and `/api/chat-logs` read surface bridge into canonical CRM data when that data exists for the tenant +- this materially improves backend production safety and migration discipline, but it still does not complete final write-path convergence or full legacy-table retirement + +### 10. Shared route tenant scoping is materially better, but the overall tenant model is still not production-grade + +At audit start, `routes_mobile_edge.py` scoped tenant-bound data off `user.role`, and `routes_inventory.py` followed the same pattern. + +Update 2026-04-22: + +- Workstream 9 replaced shared-route tenant scoping with `user.tenant_id` across both: + - `routes_mobile_edge.py` + - `routes_inventory.py` +- targeted backend tests now verify tenant isolation for the shared WebOS/iPad route surface +- Workstream 10 added a tenant-aware `users_and_roles` column and changed `/api/auth/login` to resolve tenant scope from the user directory +- `/api/auth/users` is now scoped to the authenticated tenant instead of returning a cross-tenant directory + +What still remains true: + +- the backend still does not have a fuller enterprise tenant-membership model beyond one direct `tenant_id` per user +- runtime schema mutation is still being used as an interim compatibility mechanism + +Assessment: + +- materially safer than the audit-start state +- good shared-backend hardening for current WebOS and iPad dependencies +- still not the final multi-tenant architecture + +### 11. Database schema strategy is fragmented + +There are at least four meaningful schema tracks: + +- `backend/db/schema.sql` +- `backend/db/schema_addendum.sql` +- `backend/db/schema_crm_canonical.sql` +- `backend/oracle/schema_extension_v2.sql` + +Problems: + +- CRM legacy and canonical models coexist +- iPad relies on legacy `/api/leads`, but other surfaces rely on newer tables +- no visible Alembic or migrations directory is present even though `requirements.txt` mentions Alembic + +Assessment: + +- the schema is rich +- the migration and source-of-truth story is not production disciplined yet + +### 12. Backend runtime boot is not portable across local environments + +On this machine, importing `backend.main` fails immediately because: + +- local Python is `3.9.6` +- `backend/main.py` uses `from datetime import UTC`, which requires Python 3.11+ + +There is no explicit Python runtime declaration in the repo root. + +Impact: + +- onboarding friction +- local reproducibility risk +- hidden environment assumptions + +### 13. Backend tests are not operationally ready in the current environment + +When I ran `python3 -m pytest backend/tests -q`, test collection failed because: + +- `httpx` is missing locally + +This is despite `httpx` being present in `backend/requirements.txt`. + +Important nuance: + +- the issue is not that tests are absent +- the issue is that the local backend environment is not fully bootstrapped or documented enough to run them reliably + +### 14. There is no iPad automated test coverage + +Within `iOS/velocity-ipad`, there are no: + +- unit tests +- UI tests +- snapshot tests + +This is a major production gap for a high-visibility investor-facing app. + +## P2 Important But Non-Blocking Issues + +### 15. Duplicate iOS source trees are already drifting + +There are duplicate implementations under: + +- `iOS/Core`, `iOS/Features` +- `iOS/velocity-ipad/velocity/Core`, `iOS/velocity-ipad/velocity/Features` + +These are not identical. They have already diverged. + +Impact: + +- maintenance confusion +- easy regression risk +- unclear source of truth + +### 16. Committed dependency and project hygiene are incomplete + +Observed issues: + +- Alamofire is referenced in the Xcode project, but the active iPad target code does not use it +- there is no visible iPad test target +- the repo includes user-specific Xcode workspace data + +Assessment: + +- not a product blocker by itself +- strong signal that release engineering needs cleanup + +### 17. The web frontend is buildable but overweight + +`npm run build` succeeds, but the main JS chunk is very large. + +Impact: + +- slower cold load +- weaker production performance profile +- not the immediate investor blocker, but should be addressed after demo hardening + +## Feature-By-Feature Assessment + +### Dashboard + +Status: Working with conditions + +What works: + +- live metrics +- lead focus +- inventory coverage +- backend configuration status + +Dependencies: + +- `/api/leads` +- `/api/inventory/properties` +- `/api/mobile-edge/calendar` +- `/api/mobile-edge/alerts` + +Risks: + +- any one failed call collapses the overall refresh +- sequential follow-up event fetches add latency + +### Communications + +Status: Partially working + +What works: + +- active thread summaries +- alert strip +- thread details + +What is missing: + +- outbound actions +- transcript detail UI +- workflow writeback + +### Calendar + +Status: Partially working + +What works: + +- live agenda loading +- event summaries +- dashboard-grade read visibility + +What is missing: + +- create/edit/delete from iPad +- full operator scheduling workflows + +### Oracle + +Status: Partially working + +What works: + +- pipeline view +- account timeline +- calendar/tasks + +What is disabled: + +- team performance +- lead map + +### Sentinel + +Status: Not production-complete + +What works: + +- truthful operator-posture positioning +- alert posture +- operator urgency +- recent communication timeline + +What is missing: + +- real visitor analytics +- real perception stream +- real sentiment analytics + +### Inventory - Sunseeker + +Status: Working on real device only + +What works: + +- AR overlay architecture +- solar path logic +- location-based positioning + +What is missing: + +- simulator parity +- broader QA evidence + +### Inventory - Dream Weaver + +Status: Materially improved, but still not production-safe without deployed validation + +What works: + +- capture UI +- prompt UI +- upload/poll/download client flow +- dedicated gateway configuration on iPad +- optional dedicated gateway API-key configuration on iPad +- fallback contract handling for minimal or full gateway responses + +What is not proven: + +- deployed endpoint health +- deployed authenticated gateway behavior +- real HTTPS round-trip generation against the deployed gateway +- proxy routing +- investor-demo reliability + +### Inventory - Dollhouse + +Status: Hidden from production scope unless the real asset is shipped + +What works: + +- asset-gated visibility policy +- stale-state fallback to a supported mode +- shared asset-candidate resolution between UI scope gating and SceneKit loading + +What is missing: + +- actual 3D building asset + +### Settings + +Status: Working + +What works: + +- runtime visibility into endpoint, auth mode, operator identity, last refresh, loaded counts +- editable runtime session configuration +- secure on-device session controls with Keychain-backed secret storage +- optional dedicated Dream Weaver endpoint configuration +- optional dedicated Dream Weaver gateway API-key configuration + +What is missing: + +- password recovery / SSO / enterprise session lifecycle features +- full Xcode and real-device validation of the runtime configuration flow + +## Backend Assessment + +### Strengths + +- broad route surface +- real auth path exists +- real inventory routes exist +- real mobile-edge routes exist +- real admin and Oracle surfaces exist +- code compiles under `python3 -m compileall backend` + +### Weaknesses + +- backend boot depends on undeclared Python version assumptions +- environment template does not match actual runtime variables +- CRM route family is still partially legacy-shaped because compatibility routes remain active, though the canonical `/api/crm/*` family is now authenticated, tenant-scoped, and the active iPad CRM bootstrap no longer depends on `/api/leads` +- schema evolution is not migration-driven +- local test execution is not turnkey +- Dream Weaver is separate from the core backend, and production routing ownership still needs to be finalized even though the iPad config now supports separate endpoints + +## Database Assessment + +### Strengths + +- substantial schema work has been done +- inventory, communication, transcription, calendar, insights, and session tables exist +- indexes are present for many critical access paths + +### Weaknesses + +- two CRM worlds exist at once: legacy and canonical +- iPad live CRM bootstrap now aligns to canonical `/api/crm/*`, but compatibility surfaces and some event plumbing still retain legacy assumptions +- no clear migration chain is present in repo +- operational truth may depend on which SQL files were manually applied + +## Security Assessment + +Current security posture is not production-ready. + +Top issues: + +- build-time config fallback still allows teams to embed secrets if release process is sloppy +- legacy CRM routes remain legacy-shaped even though they are now authenticated and tenant-scoped, even if the iPad app no longer targets them directly for live CRM bootstrap +- tenant isolation not properly modeled +- deployed Dream Weaver gateway authentication is still not externally proven even though the repo-local auth posture is now materially stronger + +## Operational Assessment + +Current operational readiness is below production threshold. + +Top issues: + +- public API TLS/proxy problem +- no proven iPad build artifact from this machine +- no Xcode-executed iPad automated test run from this machine, even though smoke-test scaffolding now exists +- incomplete environment documentation +- no demonstrated CI/CD validation chain in this repo review + +## What To Hide, Remove, Or Relabel Before Investor Pitch + +These are my strongest recommendations for next Tuesday: + +1. Completed repo-local on 2026-04-22: Oracle `Team Performance` and `Lead Map` are now hidden from the iPad production scope unless backend routes are implemented later. +2. Completed repo-local on 2026-04-22: the iPad `Sentinel` surface is now relabeled as `Operator Posture` unless true visitor analytics become live later. +3. Completed repo-local on 2026-04-22: `Dollhouse` is now hidden from the production iPad scope unless the real `Building.usdz` or `Building.scn` asset is added and verified. +4. Do not live-demo `Dream Weaver` unless endpoint health, contract alignment, and a full round-trip generation test are verified on the real demo device. +5. Prefer the new runtime session setup flow over build-time embedded credentials for any stakeholder-facing install. + +## Recommended Hardening Plan + +## Phase 0: Must Fix Before Investor Demo + +1. Repair `api.desineuron.in` HTTPS so `/health` succeeds over TLS. +2. Completed repo-local on 2026-04-22: the iPad app now supports a separate Dream Weaver endpoint. + Still required externally: + - decide whether production uses one host with reliable reverse proxying for `/api/*` and `/dream-weaver/*` + - or separate API and Dream Weaver hosts with working DNS, TLS, and routing +3. Confirm the Workstream 1 iPad target fixes in a full Xcode build: + - corrected deployment target + - corrected bundle identifier + - iPad-only targeting +4. Run a full Xcode build on a machine with full Xcode installed. +5. Test on a real iPad: + - app boot + - auth/login path + - Dashboard load + - Communications load + - Calendar load + - Oracle load + - Sunseeker permissions and overlay + - Dream Weaver round-trip +6. Seed a deterministic investor demo dataset. +7. Completed repo-local on 2026-04-22 for Oracle scope honesty: unsupported Oracle modes are now hidden from the production iPad build. + Still required: + - continue removing or relabeling other misleading surfaces if backend reality remains narrower than the product vocabulary used in the UI +8. Completed repo-local on 2026-04-22 for pitch-build honesty: Dollhouse is now removed from the production Inventory scope when its asset is absent. + Still required: + - add and validate the real Dollhouse asset before re-enabling the feature in a production or investor build + +## Phase 1: Production Readiness Sprint + +1. Completed on 2026-04-22: add iPad auth/session UX with Keychain-backed runtime session storage. +2. Completed on 2026-04-22: split backend and Dream Weaver configuration into explicit endpoints at the iPad app layer and repair the minimal gateway contract. +3. Completed on 2026-04-22 for the legacy CRM route family: add authentication and tenant scoping to CRM lead routes. + Remaining limitation: + - the legacy CRM route family is still legacy-shaped even though auth tenant scope is now resolved from the user directory +4. Completed on 2026-04-22 for Oracle production-scope safety: hide unsupported Oracle modes and sanitize invalid selections back to a live-backed mode. + Remaining limitation: + - this does not implement `Team Performance` or `Lead Map`; it only prevents the iPad production UI from advertising them prematurely +5. Completed on 2026-04-22 for Inventory production-scope safety: hide Dollhouse when no verified bundled asset exists and sanitize invalid selections back to a supported mode. + Remaining limitation: + - this does not create the missing 3D building experience; it only prevents the production UI from advertising it prematurely +6. Completed on 2026-04-22 for Sentinel production framing: relabel the iPad surface as `Operator Posture` while preserving `Sentinel` as the product family name. + Remaining limitation: + - this does not implement live perception analytics; it only prevents the iPad UI from overstating that capability today +7. Completed on 2026-04-22 for shared iPad/WebOS parity and refresh discipline: align iPad inventory hydration to the WebOS property slice and coalesce in-flight shared refreshes while parallelizing lead-event hydration. + Remaining limitation: + - this does not add a true bulk mobile-edge event endpoint or remove all timer-driven refresh duplication +8. Completed on 2026-04-22 for shared backend contract hardening: replace role-scoped tenant isolation with `tenant_id` scoping in the shared mobile-edge and inventory route families, with targeted backend tests. + Remaining limitation: + - this does not complete the full canonical tenant model across the backend +9. Completed on 2026-04-22 for shared auth contract hardening: add tenant-aware `users_and_roles` support, resolve JWT tenant scope from the user directory, and scope `/api/auth/users` by tenant. + Remaining limitation: + - this still uses a single direct tenant binding per user plus interim runtime schema backfill rather than a final enterprise tenant-membership model +10. Completed on 2026-04-22 for WebOS-grounded shared auth parity: make the current WebOS legacy CRM bootstrap send the authenticated Velocity bearer token through the same shared session helper used by other protected WebOS surfaces. + Remaining limitation: + - this preserves the current legacy `/api/leads` dependency instead of migrating bootstrap to canonical CRM +11. Completed on 2026-04-22 for Dream Weaver gateway auth hardening: add optional gateway API-key enforcement to both Dream Weaver gateway variants and dedicated iPad runtime support for that key. + Remaining limitation: + - this improves repo-local security posture but does not prove the deployed Dream Weaver endpoint is live, authenticated, and reachable over HTTPS +12. Completed on 2026-04-22 for canonical CRM route safety: require authenticated Velocity sessions across the shared `/api/crm/*` route family used by WebOS canonical CRM surfaces. + Remaining limitation: + - this does not yet add a full tenant-scoped canonical CRM data model or migrate the shared lead bootstrap off `/api/leads` +13. Completed on 2026-04-22 for canonical CRM tenant hardening: add first-pass `tenant_id` scoping across the active canonical CRM route family, canonical read-model helpers, and CRM import workflow tables. + Remaining limitation: + - this still does not move the shared lead bootstrap off `/api/leads` or complete the final enterprise tenant model across all canonical data +14. Completed on 2026-04-22 for shared legacy CRM read convergence: bridge the current `/api/leads` and `/api/chat-logs` read contract into canonical CRM data when available while preserving the existing WebOS/iPad compatibility surface. + Remaining limitation: + - this improves shared read-path convergence only; legacy write paths and final legacy-table retirement are still open +15. Completed on 2026-04-22 for shared legacy CRM write convergence: add best-effort canonical synchronization to the active legacy `/api/leads` and `/api/chat-logs` write surface so compatibility writes create less fresh divergence. + Remaining limitation: + - legacy tables still remain part of the active runtime path and final retirement is still open +16. Completed on 2026-04-22 for iPad canonical CRM alignment: move the active iPad live CRM bootstrap off `/api/leads` and onto canonical `/api/crm/contacts`, with a local adapter that preserves the current shell DTO while filtering to active lead context. + Remaining limitation: + - the iPad app still does not yet expose first-class canonical Contacts, Client 360, Opportunities, Tasks, Kanban, or Imports screens, and mobile-edge event APIs remain lead-ID keyed +17. Completed on 2026-04-22 for iPad canonical reminder coverage: hydrate `/api/crm/tasks` into the shared iPad store and surface canonical task load in Dashboard, Calendar, Oracle, and Settings. + Remaining limitation: + - the iPad app still has read-only task visibility and does not yet support create/complete/snooze/cancel writeback flows +18. Completed on 2026-04-22 for iPad canonical pipeline truth: hydrate `/api/crm/kanban` into the shared iPad store and make Oracle `Pipeline` render the canonical backend board instead of locally grouped contact summaries. + Remaining limitation: + - the iPad app still does not expose dedicated opportunity or stage-writeback actions, and broader canonical CRM screens remain open +19. Completed on 2026-04-22 for iPad canonical client and deals coverage: add live Client 360 access and a live-backed `Deals` surface using canonical `/api/crm/client-360/{person_id}` and `/api/crm/opportunities`. + Remaining limitation: + - the iPad app still lacks dedicated contacts and imports workspaces, and canonical CRM write actions remain open +20. Completed on 2026-04-22 for iPad canonical CRM write actions: add canonical reminder lifecycle writeback and canonical lead stage movement, then expose those actions in Oracle and Calendar against the existing live database. + Remaining limitation: + - opportunity mutation is still open, and the iPad app still lacks dedicated contacts and imports workspaces +21. Completed on 2026-04-23 for iPad canonical opportunity mutation: add canonical opportunity/deal writeback and expose deal-stage, probability, next-action, close-won, and close-lost actions in Oracle Deals and Client 360. + Remaining limitation: + - the iPad app still lacks dedicated contacts and imports workspaces, and opportunity editing is currently preset-action based rather than a free-form edit sheet +22. Completed on 2026-04-23 for iPad dedicated canonical Clients workspace: add a top-level `Clients` section backed by `/api/crm/contacts`, shared AppStore contact state, search/filtering, contact metrics, and Client 360 opening from contact cards. + Remaining limitation: + - the iPad app still lacks a canonical imports review/commit workspace, and the richer write-heavy Client 360 controls remain in Oracle +23. Completed on 2026-04-23 for iPad canonical Imports workspace: add top-level `Imports` section backed by `/api/crm/imports*`, proposal approval/rejection, and commit flow. + Remaining limitation: + - upload-from-iPad is deferred; this pass focuses on review/commit of batches already created by the canonical import path +24. Completed on 2026-04-23 for governed migrations: add backend migration runner, migration checksum discipline, startup migration application, and an initial observability migration. + Remaining limitation: + - existing runtime schema compatibility helpers still remain and should be gradually replaced by explicit migrations in future schema work +25. Completed on 2026-04-23 for automated tests and CI gates: add migration/observability tests and `.github/workflows/production-readiness.yml` for backend contracts, WebOS typecheck, and iPad Swift parse checks. + Remaining limitation: + - Xcode build/test remains excluded by request and must run on a full Xcode machine +26. Completed on 2026-04-23 for iOS source-of-truth cleanup: remove duplicate root-level iPad prototype source files and document `iOS/velocity-ipad` as the active iPad source. + Remaining limitation: + - the separate `iOS/velocity-iphone` target remains intentionally because it is not an iPad duplicate +27. Completed on 2026-04-23 for observability foundation: add request ID propagation, latency headers, recent request metrics, structured logs, protected request-metrics endpoint, and CI/test coverage. + Remaining limitation: + - external crash reporting and production dashboard wiring remain deployment/vendor tasks +28. Completed repo-local on 2026-04-23 for investor-demo robustness after iPad simulator screenshot review: harden Client 360 against live canonical payload drift, normalize backend JSON-string array fields, make iPad refresh/event hydration degrade gracefully instead of poisoning full screens with generic `Not Found`, enrich the top-level Clients 360 sheet, add Settings production-readiness diagnostics, and add an idempotent realistic investor-demo seed script. + Validation completed: + - `python3 -m py_compile backend/scripts/seed_ipad_investor_demo.py backend/services/client_graph/aggregation_service.py` + - `python3 backend/scripts/seed_ipad_investor_demo.py --dry-run` + - `xcrun swiftc -frontend -parse iOS/velocity-ipad/velocity/App/ContentView.swift iOS/velocity-ipad/velocity/Features/Clients/ClientsView.swift iOS/velocity-ipad/velocity/Features/Imports/ImportsView.swift iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift iOS/velocity-ipad/velocity/Core/State/AppStore.swift iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift` + - `PYTHONPATH="$PWD" python3 -m pytest backend/tests/test_auth_tenant_contract.py backend/tests/test_canonical_crm_auth.py backend/tests/test_canonical_crm_tenant_scoping.py backend/tests/test_dream_weaver_gateway_auth.py backend/tests/test_migrations_and_observability.py backend/tests/test_surface_route_tenant_scoping.py` + - live route probes on 2026-04-23 returned HTTP 200 for `https://api.desineuron.in/api/crm/contacts?limit=1`, `/api/crm/kanban`, `/api/crm/opportunities?limit=1`, `/api/crm/tasks?limit=1`, `/api/crm/imports?limit=1`, and `/health` + - live `Client 360` probing confirmed the deployed backend still emits `persona_labels` as a JSON string for at least one real contact; the repo-local backend now normalizes this on serialization and the iPad decoder now tolerates string, array, null, and scalar variants + Remaining limitation: + - direct database seeding could not be executed from this local shell because no `DATABASE_URL` or `VELOCITY_DB_*` credentials are present; `backend/scripts/seed_ipad_investor_demo.py --dry-run` now reports the exact realistic rows it will add once run in an environment with database access + - live canonical CRM probes show contacts and kanban data are present, while opportunities, tasks, and imports currently return valid empty datasets until the seed is run against the production tenant + - the live Dream Weaver host `dreamweaver.desineuron.in` did not resolve during route probing on 2026-04-23, so Dream Weaver remains infrastructure-blocked until DNS/gateway routing is corrected + - full Xcode simulator/device validation still needs to run on the user's Xcode machine after these repo-local changes are pulled into the app build + +## Phase 2: Investor-Grade Product Maturity + +1. Complete mobile Oracle modes. +2. Add real iPad Sentinel perception stream support. +3. Add full calendar actions on iPad. +4. Add communication writeback and transcript workflows. +5. Optimize frontend and API refresh efficiency. +6. Add CI gates for app build, backend tests, and schema validation. + +## Final Judgment + +Velocity iPad is a serious product foundation, not a toy prototype. + +The strongest parts today are: + +- native UI surface area +- coherent product architecture +- live-backed operator dashboards +- meaningful inventory differentiation via Sunseeker +- broad backend capability + +The weakest parts today are: + +- operational reliability +- production integration discipline +- security posture +- schema consistency +- release readiness + +My final call: + +- good enough to harden into a strong investor demo +- not good enough yet to claim full production readiness +- fixable within a focused engineering sprint if scope is controlled + +## Key Evidence + +- iPad runtime session configuration with build-time fallback: `iOS/velocity-ipad/velocity/Core/Config/AppConfig.swift:4-120` +- iPad API client contracts: `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift:239-340` +- Dream Weaver client and health assumptions: `iOS/velocity-ipad/velocity/Core/Networking/ComfyClient.swift:16-176` +- Inventory production mode gating and Dollhouse asset policy: `iOS/velocity-ipad/velocity/Features/Inventory/InventoryModeAvailability.swift:3-33`, `iOS/velocity-ipad/velocity/Features/Inventory/InventoryView.swift:27-130`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:196-234` +- WebOS-grounded shared refresh policy: `app/src/hooks/useCrmBootstrap.ts:22-50`, `app/src/lib/velocityPlatformClient.ts:318-340`, `iOS/velocity-ipad/velocity/Core/State/AppStoreRefreshPolicy.swift:3-27`, `iOS/velocity-ipad/velocity/Core/State/AppStore.swift:13-184`, `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift:243-271`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:265-318` +- Oracle production mode gating: `iOS/velocity-ipad/velocity/Features/Oracle/OracleModeAvailability.swift:3-17`, `iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift:27-126`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:163-194` +- Sentinel production scope framing: `iOS/velocity-ipad/velocity/Features/Sentinel/SentinelScope.swift:3-26`, `iOS/velocity-ipad/velocity/Features/Sentinel/SentinelView.swift:32-69`, `iOS/velocity-ipad/velocity/App/ContentView.swift:3-20`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:27-40`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:251-263` +- iPad plist placeholder-driven configuration and permission strings: `iOS/velocity-ipad/velocity/Info.plist:5-23` +- iPad target hardening state: `iOS/velocity-ipad/velocity.xcodeproj/project.pbxproj:368-419` +- legacy CRM runtime schema creation and authenticated tenant-scoped route family: `backend/api/routes_crm.py:75-143`, `backend/api/routes_crm.py:258-397`, `backend/auth/dependencies.py:33-126` +- shared backend tenant scoping hardening: `backend/api/routes_mobile_edge.py:53-659`, `backend/api/routes_inventory.py:46-399`, `backend/tests/test_surface_route_tenant_scoping.py:1-397` +- shared auth tenant resolution and directory scoping hardening: `backend/auth/user_directory.py:1-40`, `backend/auth/service.py:1-111`, `backend/auth/routes.py:1-111`, `backend/tests/test_auth_tenant_contract.py:1-211`, `backend/db/schema.sql:57-71` +- backend Python UTC portability hardening: `backend/main.py:16-437`, `backend/api/routes_admin_surface.py:28-218` +- WebOS shared session helper and authenticated legacy CRM bootstrap parity: `app/src/lib/velocitySession.ts:1-30`, `app/src/lib/api.ts:1-120`, `app/src/lib/crmApi.ts:1-199`, `app/src/lib/velocityPlatformClient.ts:1-255`, `app/src/oracle/lib/oracleApiClient.ts:1-103` +- Dream Weaver gateway auth hardening: `comfy_engine/scripts/gateway_auth.py:1-43`, `dw_gateway_v2_min.py:1-176`, `comfy_engine/scripts/dw_gateway_v2.py:1-417`, `iOS/velocity-ipad/velocity/Core/Config/AppConfig.swift:4-224`, `iOS/velocity-ipad/velocity/Core/Config/SessionConfiguration.swift:11-214`, `iOS/velocity-ipad/velocity/Core/Networking/ComfyClient.swift:1-322`, `iOS/velocity-ipad/velocity/Features/Settings/SessionConfigurationPanel.swift:1-170`, `iOS/velocity-ipad/velocity/Features/Settings/SettingsView.swift:1-107`, `backend/tests/test_dream_weaver_gateway_auth.py:1-28` +- canonical CRM route authentication hardening: `backend/api/routes_crm_imports.py:1-762`, `backend/tests/test_canonical_crm_auth.py:1-108`, `app/src/lib/crmApi.ts:1-217` +- canonical CRM tenant scoping hardening: `backend/crm/canonical_schema.py:1-73`, `backend/api/routes_crm_imports.py:1-918`, `backend/services/client_graph/aggregation_service.py:1-405`, `backend/services/imports/ingest_service.py:1-232`, `backend/db/schema_crm_canonical.sql:550-664`, `backend/tests/test_canonical_crm_tenant_scoping.py:1-239` +- shared legacy CRM read bridge toward canonical CRM: `backend/api/routes_crm.py:1-601`, `backend/tests/test_legacy_crm_canonical_bridge.py:1-228`, `app/src/hooks/useCrmBootstrap.ts:1-131`, `app/src/lib/api.ts:1-131` +- iPad canonical CRM bootstrap alignment: `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift:1-455`, `iOS/velocity-ipad/velocity/Features/Dashboard/DashboardView.swift:1-220`, `iOS/velocity-ipad/velocity/Features/Communications/CommunicationsView.swift:1-430`, `iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift:1-320`, `iOS/velocity-ipad/velocity/Features/Settings/SettingsView.swift:1-120`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:1-312` +- iPad canonical task and reminder coverage: `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift:1-520`, `iOS/velocity-ipad/velocity/Core/State/AppStore.swift:1-220`, `iOS/velocity-ipad/velocity/Core/State/AppStoreRefreshPolicy.swift:1-30`, `iOS/velocity-ipad/velocity/Features/Dashboard/DashboardView.swift:1-280`, `iOS/velocity-ipad/velocity/Features/Calendar/CalendarView.swift:1-320`, `iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift:1-410`, `iOS/velocity-ipad/velocity/Features/Settings/SettingsView.swift:1-130`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:1-360` +- iPad Oracle canonical kanban alignment: `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift:1-560`, `iOS/velocity-ipad/velocity/Core/State/AppStore.swift:1-230`, `iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift:1-420`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:1-400` +- iPad canonical Client 360 and deals coverage: `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift:1-760`, `iOS/velocity-ipad/velocity/Core/State/AppStore.swift:1-250`, `iOS/velocity-ipad/velocity/Features/Oracle/OracleModeAvailability.swift:1-20`, `iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift:1-760`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:1-700` +- iPad canonical task writeback and lead stage movement: `backend/api/routes_crm_imports.py:1-1023`, `backend/tests/test_canonical_crm_auth.py:1-132`, `backend/tests/test_canonical_crm_tenant_scoping.py:1-392`, `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift:1-860`, `iOS/velocity-ipad/velocity/Core/State/AppStore.swift:1-220`, `iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift:1-980`, `iOS/velocity-ipad/velocity/Features/Calendar/CalendarView.swift:1-460`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:1-760` +- iPad canonical opportunity mutation: `backend/api/routes_crm_imports.py:1-1120`, `backend/tests/test_canonical_crm_auth.py:1-145`, `backend/tests/test_canonical_crm_tenant_scoping.py:1-450`, `app/src/lib/crmApi.ts:1-260`, `app/src/types/crmTypes.ts:1-180`, `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift:1-900`, `iOS/velocity-ipad/velocity/Core/State/AppStore.swift:1-240`, `iOS/velocity-ipad/velocity/Features/Oracle/OracleView.swift:1-1060`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:1-800` +- iPad dedicated canonical Clients workspace: `iOS/velocity-ipad/velocity/App/ContentView.swift:1-220`, `iOS/velocity-ipad/velocity/Features/Clients/ClientsView.swift:1-360`, `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift:1-920`, `iOS/velocity-ipad/velocity/Core/State/AppStore.swift:1-260`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:1-90` +- iPad canonical Imports workspace: `iOS/velocity-ipad/velocity/App/ContentView.swift:1-230`, `iOS/velocity-ipad/velocity/Features/Imports/ImportsView.swift:1-420`, `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift:1-1040`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:1-850` +- iPad investor-demo final pass hardening: `backend/services/client_graph/aggregation_service.py:1-110`, `backend/scripts/seed_ipad_investor_demo.py:1-813`, `iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift:1-1320`, `iOS/velocity-ipad/velocity/Core/State/AppStore.swift:1-290`, `iOS/velocity-ipad/velocity/Features/Clients/ClientsView.swift:1-430`, `iOS/velocity-ipad/velocity/Features/Communications/CommunicationsView.swift:1-360`, `iOS/velocity-ipad/velocity/Features/Settings/SettingsView.swift:1-160`, `iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift:1-760` +- backend migrations and observability foundation: `backend/migrations/runner.py:1-100`, `backend/migrations/versions/202604230001_observability_foundation.sql:1-20`, `backend/observability.py:1-100`, `backend/api/routes_observability.py:1-24`, `backend/main.py:1-275`, `backend/tests/test_migrations_and_observability.py:1-40`, `.github/workflows/production-readiness.yml:1-65`, `iOS/README.md:1-9` +- env template drift: `backend/.env.example:31-40` +- minimal Dream Weaver gateway contract alignment: `dw_gateway_v2_min.py:104-161` +- richer Dream Weaver contract variant: `comfy_engine/scripts/dw_gateway_v2.py:323-330` diff --git a/.github/workflows/production-readiness.yml b/.github/workflows/production-readiness.yml new file mode 100644 index 00000000..7a2d2abd --- /dev/null +++ b/.github/workflows/production-readiness.yml @@ -0,0 +1,63 @@ +name: Production Readiness + +on: + pull_request: + push: + branches: + - main + - master + +jobs: + backend-contracts: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Install backend dependencies + run: | + python -m pip install --upgrade pip + pip install -r backend/requirements.txt + pip install pytest + - name: Run backend contract tests + run: | + PYTHONPATH="$PWD" python -m pytest \ + backend/tests/test_auth_tenant_contract.py \ + backend/tests/test_canonical_crm_auth.py \ + backend/tests/test_canonical_crm_tenant_scoping.py \ + backend/tests/test_dream_weaver_gateway_auth.py \ + backend/tests/test_migrations_and_observability.py \ + backend/tests/test_surface_route_tenant_scoping.py + + webos-typecheck: + runs-on: ubuntu-latest + defaults: + run: + working-directory: app + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "20" + cache: npm + cache-dependency-path: app/package-lock.json + - name: Install WebOS dependencies + run: npm ci + - name: Typecheck WebOS + run: npx tsc --noEmit + + ipad-parse: + runs-on: macos-15 + steps: + - uses: actions/checkout@v4 + - name: Parse active iPad Swift sources + run: | + swiftc -frontend -parse \ + iOS/velocity-ipad/velocity/App/ContentView.swift \ + iOS/velocity-ipad/velocity/Features/Clients/ClientsView.swift \ + iOS/velocity-ipad/velocity/Features/Imports/ImportsView.swift \ + iOS/velocity-ipad/velocity/Core/Networking/VelocityAPIClient.swift \ + iOS/velocity-ipad/velocity/Core/State/AppStore.swift \ + iOS/velocity-ipad/velocityTests/VelocitySmokeTests.swift + diff --git a/app/dist/index.html b/app/dist/index.html index 80f38fd5..d4f6b737 100644 --- a/app/dist/index.html +++ b/app/dist/index.html @@ -1,13 +1,13 @@ - - - - - - Velocity WebOS - - - - -
- - + + + + + + Velocity WebOS + + + + +
+ + diff --git a/app/node_modules/.tmp/tsconfig.app.tsbuildinfo b/app/node_modules/.tmp/tsconfig.app.tsbuildinfo index 48a170b4..1499616c 100644 --- a/app/node_modules/.tmp/tsconfig.app.tsbuildinfo +++ b/app/node_modules/.tmp/tsconfig.app.tsbuildinfo @@ -1 +1 @@ -{"root":["../../src/app.tsx","../../src/main.tsx","../../src/app/admin/page.tsx","../../src/app/oracle/page.tsx","../../src/components/layout/loginscreen.tsx","../../src/components/layout/notificationcenter.tsx","../../src/components/layout/sidebar.tsx","../../src/components/modules/crm.tsx","../../src/components/modules/catalyst.tsx","../../src/components/modules/catalystmarketingtab.tsx","../../src/components/modules/dashboard.tsx","../../src/components/modules/groundtruthpicker.tsx","../../src/components/modules/inventory.tsx","../../src/components/modules/oracle.tsx","../../src/components/modules/sentinel.tsx","../../src/components/modules/settings.tsx","../../src/components/modules/sentinel/perceptionplayer.tsx","../../src/components/modules/sentinel/sentinellivesession.tsx","../../src/components/oracle/leadinspector.tsx","../../src/components/oracle/pipelineview.tsx","../../src/components/sentinel/journeyriver/inspectorpanel.tsx","../../src/components/sentinel/journeyriver/riverpath.tsx","../../src/components/sentinel/journeyriver/index.tsx","../../src/components/ui/accordion.tsx","../../src/components/ui/alert-dialog.tsx","../../src/components/ui/alert.tsx","../../src/components/ui/aspect-ratio.tsx","../../src/components/ui/avatar.tsx","../../src/components/ui/badge.tsx","../../src/components/ui/breadcrumb.tsx","../../src/components/ui/button-group.tsx","../../src/components/ui/button.tsx","../../src/components/ui/calendar.tsx","../../src/components/ui/card.tsx","../../src/components/ui/carousel.tsx","../../src/components/ui/chart.tsx","../../src/components/ui/checkbox.tsx","../../src/components/ui/collapsible.tsx","../../src/components/ui/command.tsx","../../src/components/ui/context-menu.tsx","../../src/components/ui/dialog.tsx","../../src/components/ui/drawer.tsx","../../src/components/ui/dropdown-menu.tsx","../../src/components/ui/empty.tsx","../../src/components/ui/field.tsx","../../src/components/ui/form.tsx","../../src/components/ui/hover-card.tsx","../../src/components/ui/input-group.tsx","../../src/components/ui/input-otp.tsx","../../src/components/ui/input.tsx","../../src/components/ui/item.tsx","../../src/components/ui/kbd.tsx","../../src/components/ui/label.tsx","../../src/components/ui/menubar.tsx","../../src/components/ui/navigation-menu.tsx","../../src/components/ui/pagination.tsx","../../src/components/ui/popover.tsx","../../src/components/ui/progress.tsx","../../src/components/ui/radio-group.tsx","../../src/components/ui/resizable.tsx","../../src/components/ui/scroll-area.tsx","../../src/components/ui/select.tsx","../../src/components/ui/separator.tsx","../../src/components/ui/sheet.tsx","../../src/components/ui/sidebar.tsx","../../src/components/ui/skeleton.tsx","../../src/components/ui/slider.tsx","../../src/components/ui/sonner.tsx","../../src/components/ui/spinner.tsx","../../src/components/ui/switch.tsx","../../src/components/ui/table.tsx","../../src/components/ui/tabs.tsx","../../src/components/ui/textarea.tsx","../../src/components/ui/toggle-group.tsx","../../src/components/ui/toggle.tsx","../../src/components/ui/tooltip.tsx","../../src/hooks/use-mobile.ts","../../src/hooks/usecrmbootstrap.ts","../../src/hooks/usemediapipefacelandmarker.ts","../../src/hooks/usevelocitysocket.ts","../../src/lib/api.ts","../../src/lib/crmapi.ts","../../src/lib/crmmappers.ts","../../src/lib/platformmappers.ts","../../src/lib/utils.ts","../../src/lib/velocityplatformclient.ts","../../src/oracle/components/branchbar.tsx","../../src/oracle/components/canvasviewport.tsx","../../src/oracle/components/componentregistry.tsx","../../src/oracle/components/promptrail.tsx","../../src/oracle/components/rollbackconfirmmodal.tsx","../../src/oracle/components/sharemodal.tsx","../../src/oracle/components/renderers/activitystreamrenderer.tsx","../../src/oracle/components/renderers/barchartrenderer.tsx","../../src/oracle/components/renderers/errornoticerenderer.tsx","../../src/oracle/components/renderers/geomaprenderer.tsx","../../src/oracle/components/renderers/kpitilerenderer.tsx","../../src/oracle/components/renderers/linechartrenderer.tsx","../../src/oracle/components/renderers/pipelineboardrenderer.tsx","../../src/oracle/components/renderers/rendererwrapper.tsx","../../src/oracle/components/renderers/tablerenderer.tsx","../../src/oracle/components/renderers/timelinerenderer.tsx","../../src/oracle/components/review/mergereviewdrawer.tsx","../../src/oracle/hooks/useoracleexecution.ts","../../src/oracle/hooks/useoraclepage.ts","../../src/oracle/lib/oracleapiclient.ts","../../src/oracle/types/canvas.ts","../../src/store/usecurrencystore.ts","../../src/store/usemarketingstore.ts","../../src/store/usestore.ts","../../src/types/crm.ts","../../src/types/crmtypes.ts","../../src/types/index.ts","../../src/utils/curvegenerator.ts","../../src/utils/landmarkpacketencoder.ts"],"version":"5.9.3"} \ No newline at end of file +{"root":["../../src/app.tsx","../../src/main.tsx","../../src/app/admin/page.tsx","../../src/app/oracle/page.tsx","../../src/components/layout/loginscreen.tsx","../../src/components/layout/notificationcenter.tsx","../../src/components/layout/sidebar.tsx","../../src/components/modules/crm.tsx","../../src/components/modules/catalyst.tsx","../../src/components/modules/catalystdreamweavertab.tsx","../../src/components/modules/catalystmarketingtab.tsx","../../src/components/modules/dashboard.tsx","../../src/components/modules/groundtruthpicker.tsx","../../src/components/modules/inventory.tsx","../../src/components/modules/oracle.tsx","../../src/components/modules/sentinel.tsx","../../src/components/modules/settings.tsx","../../src/components/modules/sentinel/perceptionplayer.tsx","../../src/components/modules/sentinel/sentinellivesession.tsx","../../src/components/oracle/leadinspector.tsx","../../src/components/oracle/pipelineview.tsx","../../src/components/sentinel/journeyriver/inspectorpanel.tsx","../../src/components/sentinel/journeyriver/riverpath.tsx","../../src/components/sentinel/journeyriver/index.tsx","../../src/components/ui/accordion.tsx","../../src/components/ui/alert-dialog.tsx","../../src/components/ui/alert.tsx","../../src/components/ui/aspect-ratio.tsx","../../src/components/ui/avatar.tsx","../../src/components/ui/badge.tsx","../../src/components/ui/breadcrumb.tsx","../../src/components/ui/button-group.tsx","../../src/components/ui/button.tsx","../../src/components/ui/calendar.tsx","../../src/components/ui/card.tsx","../../src/components/ui/carousel.tsx","../../src/components/ui/chart.tsx","../../src/components/ui/checkbox.tsx","../../src/components/ui/collapsible.tsx","../../src/components/ui/command.tsx","../../src/components/ui/context-menu.tsx","../../src/components/ui/dialog.tsx","../../src/components/ui/drawer.tsx","../../src/components/ui/dropdown-menu.tsx","../../src/components/ui/empty.tsx","../../src/components/ui/field.tsx","../../src/components/ui/form.tsx","../../src/components/ui/hover-card.tsx","../../src/components/ui/input-group.tsx","../../src/components/ui/input-otp.tsx","../../src/components/ui/input.tsx","../../src/components/ui/item.tsx","../../src/components/ui/kbd.tsx","../../src/components/ui/label.tsx","../../src/components/ui/menubar.tsx","../../src/components/ui/navigation-menu.tsx","../../src/components/ui/pagination.tsx","../../src/components/ui/popover.tsx","../../src/components/ui/progress.tsx","../../src/components/ui/radio-group.tsx","../../src/components/ui/resizable.tsx","../../src/components/ui/scroll-area.tsx","../../src/components/ui/select.tsx","../../src/components/ui/separator.tsx","../../src/components/ui/sheet.tsx","../../src/components/ui/sidebar.tsx","../../src/components/ui/skeleton.tsx","../../src/components/ui/slider.tsx","../../src/components/ui/sonner.tsx","../../src/components/ui/spinner.tsx","../../src/components/ui/switch.tsx","../../src/components/ui/table.tsx","../../src/components/ui/tabs.tsx","../../src/components/ui/textarea.tsx","../../src/components/ui/toggle-group.tsx","../../src/components/ui/toggle.tsx","../../src/components/ui/tooltip.tsx","../../src/hooks/use-mobile.ts","../../src/hooks/usecrmbootstrap.ts","../../src/hooks/usemediapipefacelandmarker.ts","../../src/hooks/usevelocitysocket.ts","../../src/lib/api.ts","../../src/lib/crmapi.ts","../../src/lib/crmmappers.ts","../../src/lib/dreamweaverapi.ts","../../src/lib/platformmappers.ts","../../src/lib/utils.ts","../../src/lib/velocityplatformclient.ts","../../src/lib/velocitysession.ts","../../src/oracle/components/branchbar.tsx","../../src/oracle/components/canvasviewport.tsx","../../src/oracle/components/componentregistry.tsx","../../src/oracle/components/promptrail.tsx","../../src/oracle/components/rollbackconfirmmodal.tsx","../../src/oracle/components/sharemodal.tsx","../../src/oracle/components/renderers/activitystreamrenderer.tsx","../../src/oracle/components/renderers/barchartrenderer.tsx","../../src/oracle/components/renderers/errornoticerenderer.tsx","../../src/oracle/components/renderers/geomaprenderer.tsx","../../src/oracle/components/renderers/kpitilerenderer.tsx","../../src/oracle/components/renderers/linechartrenderer.tsx","../../src/oracle/components/renderers/pipelineboardrenderer.tsx","../../src/oracle/components/renderers/rendererwrapper.tsx","../../src/oracle/components/renderers/tablerenderer.tsx","../../src/oracle/components/renderers/timelinerenderer.tsx","../../src/oracle/components/review/mergereviewdrawer.tsx","../../src/oracle/hooks/useoracleexecution.ts","../../src/oracle/hooks/useoraclepage.ts","../../src/oracle/lib/oracleapiclient.ts","../../src/oracle/types/canvas.ts","../../src/store/usecurrencystore.ts","../../src/store/usemarketingstore.ts","../../src/store/usestore.ts","../../src/types/crm.ts","../../src/types/crmtypes.ts","../../src/types/index.ts","../../src/utils/curvegenerator.ts","../../src/utils/landmarkpacketencoder.ts"],"version":"5.9.3"} \ No newline at end of file diff --git a/app/node_modules/.vite/deps/@radix-ui_react-avatar.js b/app/node_modules/.vite/deps/@radix-ui_react-avatar.js index 8eb97bd1..086ac17c 100644 --- a/app/node_modules/.vite/deps/@radix-ui_react-avatar.js +++ b/app/node_modules/.vite/deps/@radix-ui_react-avatar.js @@ -1,18 +1,18 @@ "use client"; +import { + require_shim +} from "./chunk-TXHHHGR3.js"; import { useCallbackRef, useLayoutEffect2 } from "./chunk-J4JAFMOP.js"; +import { + require_react_dom +} from "./chunk-YF4B4G2L.js"; import { createSlot } from "./chunk-YWBEB5PG.js"; import "./chunk-2VUH7NEY.js"; -import { - require_shim -} from "./chunk-TXHHHGR3.js"; -import { - require_react_dom -} from "./chunk-YF4B4G2L.js"; import { require_jsx_runtime } from "./chunk-2YVA4HRZ.js"; diff --git a/app/node_modules/.vite/deps/@radix-ui_react-dropdown-menu.js b/app/node_modules/.vite/deps/@radix-ui_react-dropdown-menu.js index 406e8a78..e9f544b2 100644 --- a/app/node_modules/.vite/deps/@radix-ui_react-dropdown-menu.js +++ b/app/node_modules/.vite/deps/@radix-ui_react-dropdown-menu.js @@ -3,13 +3,13 @@ import { useCallbackRef, useLayoutEffect2 } from "./chunk-J4JAFMOP.js"; +import { + require_react_dom +} from "./chunk-YF4B4G2L.js"; import { composeRefs, useComposedRefs } from "./chunk-2VUH7NEY.js"; -import { - require_react_dom -} from "./chunk-YF4B4G2L.js"; import { require_jsx_runtime } from "./chunk-2YVA4HRZ.js"; diff --git a/app/node_modules/.vite/deps/@react-three_drei.js b/app/node_modules/.vite/deps/@react-three_drei.js index 2da222d1..0b1fff75 100644 --- a/app/node_modules/.vite/deps/@react-three_drei.js +++ b/app/node_modules/.vite/deps/@react-three_drei.js @@ -1,12 +1,9 @@ +import { + _extends +} from "./chunk-EQCCHGRT.js"; import { create } from "./chunk-7GZ4CI6Q.js"; -import { - subscribeWithSelector -} from "./chunk-O4L7C4YS.js"; -import { - Events -} from "./chunk-OAEA5FZL.js"; import { addAfterEffect, addEffect, @@ -24,6 +21,9 @@ import { useThree } from "./chunk-5ESDTKMP.js"; import "./chunk-NJ4V5H3P.js"; +import { + subscribeWithSelector +} from "./chunk-O4L7C4YS.js"; import { AddEquation, AdditiveBlending, @@ -218,13 +218,13 @@ import { WireframeGeometry, ZeroFactor } from "./chunk-L3Z576C2.js"; +import { + Events +} from "./chunk-OAEA5FZL.js"; import { require_client } from "./chunk-6MXH2QM6.js"; import "./chunk-GUQHL3N7.js"; -import { - _extends -} from "./chunk-EQCCHGRT.js"; import "./chunk-TXHHHGR3.js"; import "./chunk-YF4B4G2L.js"; import "./chunk-2YVA4HRZ.js"; diff --git a/app/node_modules/.vite/deps/_metadata.json b/app/node_modules/.vite/deps/_metadata.json index dfe7b299..6c53a63c 100644 --- a/app/node_modules/.vite/deps/_metadata.json +++ b/app/node_modules/.vite/deps/_metadata.json @@ -1,133 +1,133 @@ { - "hash": "4594f192", + "hash": "d63ca5ca", "configHash": "1dd3b956", - "lockfileHash": "e8550e82", - "browserHash": "7e7e8c10", + "lockfileHash": "db47663b", + "browserHash": "b8dcfecc", "optimized": { "react": { "src": "../../react/index.js", "file": "react.js", - "fileHash": "bc0c1f26", + "fileHash": "0c4ff044", "needsInterop": true }, "react-dom": { "src": "../../react-dom/index.js", "file": "react-dom.js", - "fileHash": "36a8d9c0", + "fileHash": "d9b3477a", "needsInterop": true }, "react/jsx-dev-runtime": { "src": "../../react/jsx-dev-runtime.js", "file": "react_jsx-dev-runtime.js", - "fileHash": "3d8f6460", + "fileHash": "60584ffa", "needsInterop": true }, "react/jsx-runtime": { "src": "../../react/jsx-runtime.js", "file": "react_jsx-runtime.js", - "fileHash": "6f4aca26", + "fileHash": "0909256b", "needsInterop": true }, "@radix-ui/react-avatar": { "src": "../../@radix-ui/react-avatar/dist/index.mjs", "file": "@radix-ui_react-avatar.js", - "fileHash": "2a702dd2", + "fileHash": "3fc2fdda", "needsInterop": false }, "@radix-ui/react-dropdown-menu": { "src": "../../@radix-ui/react-dropdown-menu/dist/index.mjs", "file": "@radix-ui_react-dropdown-menu.js", - "fileHash": "a5efb9bf", + "fileHash": "eef7ef00", "needsInterop": false }, "@radix-ui/react-slot": { "src": "../../@radix-ui/react-slot/dist/index.mjs", "file": "@radix-ui_react-slot.js", - "fileHash": "986d9c0d", + "fileHash": "6745f8b7", "needsInterop": false }, "@react-three/drei": { "src": "../../@react-three/drei/index.js", "file": "@react-three_drei.js", - "fileHash": "6cd60875", + "fileHash": "62f4e280", "needsInterop": false }, "@react-three/fiber": { "src": "../../@react-three/fiber/dist/react-three-fiber.esm.js", "file": "@react-three_fiber.js", - "fileHash": "27a7d4df", + "fileHash": "c4b868b0", "needsInterop": false }, "class-variance-authority": { "src": "../../class-variance-authority/dist/index.mjs", "file": "class-variance-authority.js", - "fileHash": "b0c32b93", + "fileHash": "db4ee666", "needsInterop": false }, "clsx": { "src": "../../clsx/dist/clsx.mjs", "file": "clsx.js", - "fileHash": "c855e729", + "fileHash": "0a67ca45", "needsInterop": false }, "framer-motion": { "src": "../../framer-motion/dist/es/index.mjs", "file": "framer-motion.js", - "fileHash": "e0841dfa", + "fileHash": "9694d550", "needsInterop": false }, "lucide-react": { "src": "../../lucide-react/dist/esm/lucide-react.js", "file": "lucide-react.js", - "fileHash": "4d79a586", + "fileHash": "15d2dc31", "needsInterop": false }, "react-dom/client": { "src": "../../react-dom/client.js", "file": "react-dom_client.js", - "fileHash": "2e02376b", + "fileHash": "a8f9db58", "needsInterop": true }, "react-router-dom": { "src": "../../react-router-dom/dist/index.mjs", "file": "react-router-dom.js", - "fileHash": "bd4cf4c4", + "fileHash": "3a519f93", "needsInterop": false }, "recharts": { "src": "../../recharts/es6/index.js", "file": "recharts.js", - "fileHash": "b44545db", + "fileHash": "1cac0e9f", "needsInterop": false }, "sonner": { "src": "../../sonner/dist/index.mjs", "file": "sonner.js", - "fileHash": "02632b99", + "fileHash": "1ad92981", "needsInterop": false }, "tailwind-merge": { "src": "../../tailwind-merge/dist/bundle-mjs.mjs", "file": "tailwind-merge.js", - "fileHash": "ab22bcc4", + "fileHash": "e2d07b44", "needsInterop": false }, "three": { "src": "../../three/build/three.module.js", "file": "three.js", - "fileHash": "43012f83", + "fileHash": "09fb4882", "needsInterop": false }, "zustand": { "src": "../../zustand/esm/index.mjs", "file": "zustand.js", - "fileHash": "dbfba0e2", + "fileHash": "4607d0bf", "needsInterop": false }, "zustand/middleware": { "src": "../../zustand/esm/middleware.mjs", "file": "zustand_middleware.js", - "fileHash": "e524c2dc", + "fileHash": "e4fd4342", "needsInterop": false } }, @@ -135,57 +135,57 @@ "hls-Q6LDPZPT": { "file": "hls-Q6LDPZPT.js" }, - "chunk-U7P2NEEE": { - "file": "chunk-U7P2NEEE.js" - }, - "chunk-J4JAFMOP": { - "file": "chunk-J4JAFMOP.js" - }, - "chunk-YWBEB5PG": { - "file": "chunk-YWBEB5PG.js" - }, - "chunk-2VUH7NEY": { - "file": "chunk-2VUH7NEY.js" + "chunk-EQCCHGRT": { + "file": "chunk-EQCCHGRT.js" }, "chunk-7GZ4CI6Q": { "file": "chunk-7GZ4CI6Q.js" }, - "chunk-O4L7C4YS": { - "file": "chunk-O4L7C4YS.js" - }, - "chunk-OAEA5FZL": { - "file": "chunk-OAEA5FZL.js" - }, "chunk-5ESDTKMP": { "file": "chunk-5ESDTKMP.js" }, "chunk-NJ4V5H3P": { "file": "chunk-NJ4V5H3P.js" }, + "chunk-O4L7C4YS": { + "file": "chunk-O4L7C4YS.js" + }, "chunk-L3Z576C2": { "file": "chunk-L3Z576C2.js" }, + "chunk-OAEA5FZL": { + "file": "chunk-OAEA5FZL.js" + }, "chunk-6MXH2QM6": { "file": "chunk-6MXH2QM6.js" }, "chunk-GUQHL3N7": { "file": "chunk-GUQHL3N7.js" }, - "chunk-EQCCHGRT": { - "file": "chunk-EQCCHGRT.js" - }, "chunk-TXHHHGR3": { "file": "chunk-TXHHHGR3.js" }, + "chunk-J4JAFMOP": { + "file": "chunk-J4JAFMOP.js" + }, "chunk-YF4B4G2L": { "file": "chunk-YF4B4G2L.js" }, + "chunk-YWBEB5PG": { + "file": "chunk-YWBEB5PG.js" + }, + "chunk-2VUH7NEY": { + "file": "chunk-2VUH7NEY.js" + }, "chunk-2YVA4HRZ": { "file": "chunk-2YVA4HRZ.js" }, "chunk-WUR7D6NS": { "file": "chunk-WUR7D6NS.js" }, + "chunk-U7P2NEEE": { + "file": "chunk-U7P2NEEE.js" + }, "chunk-G3PMV62Z": { "file": "chunk-G3PMV62Z.js" } diff --git a/app/node_modules/.vite/deps/recharts.js b/app/node_modules/.vite/deps/recharts.js index 5761295e..992dc250 100644 --- a/app/node_modules/.vite/deps/recharts.js +++ b/app/node_modules/.vite/deps/recharts.js @@ -1,6 +1,3 @@ -import { - clsx_default -} from "./chunk-U7P2NEEE.js"; import { _extends } from "./chunk-EQCCHGRT.js"; @@ -10,6 +7,9 @@ import { import { require_react } from "./chunk-WUR7D6NS.js"; +import { + clsx_default +} from "./chunk-U7P2NEEE.js"; import { __commonJS, __export, diff --git a/app/src/components/modules/Catalyst.tsx b/app/src/components/modules/Catalyst.tsx index 46e3df69..bd40244d 100644 --- a/app/src/components/modules/Catalyst.tsx +++ b/app/src/components/modules/Catalyst.tsx @@ -5,7 +5,7 @@ import { Zap, TrendingUp, Eye, MousePointerClick, DollarSign, Upload, Play, Image, Film, RefreshCw, ArrowRight, Plus, X, AlertTriangle, ArrowRightLeft, PlusCircle, SlidersHorizontal, - Activity, Check, Link2, + Activity, Check, Link2, WandSparkles, type LucideIcon, } from 'lucide-react'; import { @@ -17,6 +17,7 @@ import { useCurrency } from '@/store/useCurrencyStore'; import type { Campaign, MarketingAsset, LiveOptimizationEvent, LiveEventType } from '@/types'; import { GroundTruthPicker } from './GroundTruthPicker'; import { CatalystMarketingTab } from './CatalystMarketingTab'; +import { CatalystDreamWeaverTab } from './CatalystDreamWeaverTab'; import type { GroundTruthSelection } from './GroundTruthPicker'; // ── Design tokens ───────────────────────────────────────────────────────────── @@ -917,7 +918,7 @@ function WarRoom() { // Tab Bar // ───────────────────────────────────────────────────────────────────────────── -type TabId = 'studio' | 'command' | 'intelligence' | 'war-room' | 'marketing'; +type TabId = 'studio' | 'command' | 'intelligence' | 'war-room' | 'marketing' | 'dream-weaver'; const TABS: Array<{ id: TabId; label: string; icon: LucideIcon }> = [ { id: 'studio', label: 'The Studio', icon: Clapperboard }, @@ -925,6 +926,7 @@ const TABS: Array<{ id: TabId; label: string; icon: LucideIcon }> = [ { id: 'intelligence', label: 'Intelligence & ROI', icon: BarChart3 }, { id: 'war-room', label: 'War Room', icon: Globe }, { id: 'marketing', label: 'Marketing', icon: TrendingUp }, + { id: 'dream-weaver', label: 'Dream Weaver', icon: WandSparkles }, ]; // ───────────────────────────────────────────────────────────────────────────── @@ -940,6 +942,7 @@ export function Catalyst() { 'intelligence': , 'war-room': , 'marketing': , + 'dream-weaver': , }; return ( @@ -998,8 +1001,8 @@ export function Catalyst() { - {/* Live Optimization Feed — always visible */} - + {/* Live Optimization Feed — hidden on Dream Weaver because generation has its own status surface. */} + {activeTab !== 'dream-weaver' && } ); } diff --git a/app/src/components/modules/CatalystDreamWeaverTab.tsx b/app/src/components/modules/CatalystDreamWeaverTab.tsx new file mode 100644 index 00000000..b1081694 --- /dev/null +++ b/app/src/components/modules/CatalystDreamWeaverTab.tsx @@ -0,0 +1,524 @@ +import { useEffect, useRef, useState, type ChangeEvent, type CSSProperties } from 'react'; +import { motion, AnimatePresence } from 'framer-motion'; +import { + AlertTriangle, + Check, + Download, + ExternalLink, + Home, + Image as ImageIcon, + Loader2, + RefreshCw, + Server, + Sparkles, + Upload, + WandSparkles, +} from 'lucide-react'; +import { useMarketingStore } from '@/store/useMarketingStore'; +import { + DREAM_WEAVER_URL, + checkDreamWeaverHealth, + fetchDreamWeaverResult, + getDreamWeaverStatus, + submitDreamWeaverJob, + type DreamWeaverHealth, + type DreamWeaverJobResponse, + type DreamWeaverStatusResponse, +} from '@/lib/dreamWeaverApi'; + +const GLASS: CSSProperties = { + background: 'rgba(8, 10, 18, 0.82)', + border: '1px solid rgba(59,130,246,0.14)', + backdropFilter: 'blur(24px)', + WebkitBackdropFilter: 'blur(24px)', + boxShadow: '0 0 0 1px rgba(255,255,255,0.04), 0 4px 32px rgba(0,0,0,0.55)', +}; + +const INNER: CSSProperties = { + background: 'rgba(255,255,255,0.04)', + border: '1px solid rgba(255,255,255,0.07)', +}; + +const ROOM_TYPES = [ + { id: 'bedroom', label: 'Bedroom' }, + { id: 'living_room', label: 'Living Room' }, + { id: 'bathroom', label: 'Bathroom' }, + { id: 'kitchen', label: 'Kitchen' }, + { id: 'dining_room', label: 'Dining Room' }, + { id: 'home_office', label: 'Office' }, + { id: 'hallway', label: 'Hallway' }, + { id: 'balcony', label: 'Balcony' }, +] as const; + +type ProcessingState = 'idle' | 'checking' | 'submitting' | 'rendering' | 'downloading'; + +interface DreamWeaverOutput { + id: string; + roomLabel: string; + keywords: string; + imageUrl: string; + createdAt: Date; +} + +function sleep(ms: number) { + return new Promise((resolve) => window.setTimeout(resolve, ms)); +} + +function isReadyStatus(status: DreamWeaverStatusResponse) { + const normalized = status.status?.toLowerCase() ?? ''; + return Boolean(status.ready) || ['ready', 'completed', 'complete', 'succeeded', 'success', 'finished'].includes(normalized); +} + +function isFailedStatus(status: DreamWeaverStatusResponse) { + const normalized = status.status?.toLowerCase() ?? ''; + return ['failed', 'error', 'cancelled', 'canceled'].includes(normalized); +} + +function statusLabel(state: ProcessingState, health: DreamWeaverHealth | null) { + if (state === 'checking') return 'Checking gateway'; + if (state === 'submitting') return 'Submitting render'; + if (state === 'rendering') return 'ComfyUI rendering'; + if (state === 'downloading') return 'Fetching result'; + if (!health) return 'Gateway unknown'; + if (health.online && health.routeMounted && health.comfyuiOnline === false) return 'Gateway online · ComfyUI offline'; + if (health.online && health.routeMounted && health.comfyuiOnline && health.checkpointReady === false) return 'Gateway online · Model missing'; + return health.online && health.routeMounted ? 'Gateway online' : 'Gateway offline'; +} + +function ResultActions({ output }: { output: DreamWeaverOutput }) { + function downloadResult() { + const anchor = document.createElement('a'); + anchor.href = output.imageUrl; + anchor.download = `dream-weaver-${output.id}.png`; + anchor.click(); + } + + return ( +
+ + +
+ ); +} + +export function CatalystDreamWeaverTab() { + const { pushLiveEvent } = useMarketingStore(); + const fileInputRef = useRef(null); + const objectUrlsRef = useRef>(new Set()); + + const [sourceFile, setSourceFile] = useState(null); + const [sourcePreview, setSourcePreview] = useState(null); + const [selectedRoomType, setSelectedRoomType] = useState<(typeof ROOM_TYPES)[number]['id']>('bedroom'); + const [keywords, setKeywords] = useState(''); + const [health, setHealth] = useState(null); + const [processingState, setProcessingState] = useState('checking'); + const [progress, setProgress] = useState('Checking Dream Weaver gateway...'); + const [error, setError] = useState(null); + const [currentOutput, setCurrentOutput] = useState(null); + const [history, setHistory] = useState([]); + + const isProcessing = processingState !== 'idle' && processingState !== 'checking'; + const roomLabel = ROOM_TYPES.find((room) => room.id === selectedRoomType)?.label ?? 'Bedroom'; + + useEffect(() => { + void refreshHealth(); + return () => { + objectUrlsRef.current.forEach((url) => URL.revokeObjectURL(url)); + objectUrlsRef.current.clear(); + }; + }, []); + + function rememberObjectUrl(blobOrFile: Blob) { + const url = URL.createObjectURL(blobOrFile); + objectUrlsRef.current.add(url); + return url; + } + + function setSourceFromFile(file: File) { + if (!file.type.startsWith('image/')) { + setError('Dream Weaver needs a source room image.'); + return; + } + const previewUrl = rememberObjectUrl(file); + setSourceFile(file); + setSourcePreview(previewUrl); + setCurrentOutput(null); + setError(null); + } + + function handleFileChange(event: ChangeEvent) { + const file = event.target.files?.[0]; + if (file) { + setSourceFromFile(file); + } + event.target.value = ''; + } + + async function refreshHealth() { + setProcessingState('checking'); + setProgress('Checking Dream Weaver gateway...'); + const nextHealth = await checkDreamWeaverHealth(); + setHealth(nextHealth); + setProcessingState('idle'); + setProgress(nextHealth.online && nextHealth.routeMounted + ? nextHealth.comfyuiOnline === false + ? `Gateway is online and the Dream Weaver route is mounted. ComfyUI is offline${nextHealth.comfyuiUrl ? ` at ${nextHealth.comfyuiUrl}` : ''}.` + : nextHealth.checkpointReady === false + ? `ComfyUI is online${nextHealth.comfyuiUrl ? ` at ${nextHealth.comfyuiUrl}` : ''}, but no checkpoint model is installed. Hydrate RealVisXL into ComfyUI/models/checkpoints.` + : 'Gateway is online and the Dream Weaver route is mounted.' + : nextHealth.detail ?? 'Dream Weaver gateway is not reachable.'); + } + + async function pollUntilReady(job: DreamWeaverJobResponse) { + let latestResultUrl = job.result_url; + for (let attempt = 1; attempt <= 150; attempt += 1) { + const status = await getDreamWeaverStatus(job); + latestResultUrl = status.result_url ?? latestResultUrl; + setProgress(status.status ? `Render ${status.status} · poll ${attempt}/150` : `Render queued · poll ${attempt}/150`); + + if (isReadyStatus(status)) { + return latestResultUrl; + } + if (isFailedStatus(status) || status.error) { + throw new Error(status.error ?? `Dream Weaver render ${status.status ?? 'failed'}.`); + } + await sleep(2000); + } + throw new Error('Dream Weaver timed out after 5 minutes.'); + } + + async function generate() { + if (!sourceFile || isProcessing) return; + setError(null); + setCurrentOutput(null); + + try { + setProcessingState('submitting'); + setProgress(`Submitting ${roomLabel.toLowerCase()} staging request...`); + const job = await submitDreamWeaverJob({ + image: sourceFile, + roomType: selectedRoomType, + keywords, + }); + + setProcessingState('rendering'); + setProgress(`Job ${job.job_id} accepted. Waiting for ComfyUI output...`); + const resultUrl = await pollUntilReady(job); + + setProcessingState('downloading'); + setProgress('Fetching generated image...'); + const resultBlob = await fetchDreamWeaverResult(job.job_id, resultUrl); + const imageUrl = rememberObjectUrl(resultBlob); + const output: DreamWeaverOutput = { + id: job.job_id, + roomLabel, + keywords: keywords.trim(), + imageUrl, + createdAt: new Date(), + }; + + setCurrentOutput(output); + setHistory((items) => [output, ...items].slice(0, 6)); + setProgress('Dream Weaver render complete.'); + pushLiveEvent({ + id: `dw-${job.job_id}-${Date.now()}`, + type: 'create', + campaignName: 'Dream Weaver', + message: `${roomLabel} staging render completed.`, + timestamp: new Date(), + }); + } catch (err) { + const message = err instanceof Error ? err.message : 'Dream Weaver render failed.'; + setError(message); + setProgress(message); + pushLiveEvent({ + id: `dw-error-${Date.now()}`, + type: 'alert', + campaignName: 'Dream Weaver', + message, + timestamp: new Date(), + }); + } finally { + setProcessingState('idle'); + } + } + + return ( +
+ +
+
+
+

+ Dream Weaver +

+

+ Room image transformation pipeline using the same Dream Weaver gateway as the iPad app. +

+
+
+
+ + {statusLabel(processingState, health)} +
+ +
+
+ + +
+ +
+
+

+ Source Room +

+

+ Upload a ground-truth room photograph, choose the target room type, then add optional styling keywords. +

+
+ + + +
+

+ Room type +

+
+ {ROOM_TYPES.map((room) => { + const selected = selectedRoomType === room.id; + return ( + + ); + })} +
+
+ +
+ +