{"slug":"architecture/CLOUDFLARE_ZERO_TRUST_TWIN_OPENWEBUI_PROVISIONING","title":"IntegrateWise — Cloudflare Zero Trust → Twin/OpenWebUI Provisioning","section":"architecture","sectionLabel":"Architecture","status":"superseded","type":"document","path":"architecture/CLOUDFLARE_ZERO_TRUST_TWIN_OPENWEBUI_PROVISIONING.mdx","bytes":34540,"description":null,"updated":null,"source":"integratewise/Integratewise-docs-wiki","content":"\n> ⚠️ **SUPERSEDED (v3.7, June 12 2026) — see AGENTS.md DECISION 22.**\n> The product Twin is **NOT** OpenWebUI/Agent Zero on a VPS. The Twin runs **entirely in Cloudflare**\n> (`services/iw-agent-runtime` — Cloudflare Agents SDK: TwinAgent + TenantBrainDO + TwinSessionDO).\n> No OpenWebUI, no Hostinger/VPS, no Supabase in the product. This doc is retained for historical\n> context on the Zero Trust identity flow only; ignore the OpenWebUI/Agent-Zero/Hostinger runtime parts.\n> Canonical: `docs/architecture/USER_SYSTEM_JOURNEY_BLUEPRINT.md` + `AGENTS.md` (DECISION 22) + `CLAUDE.md`.\n\n> **Date:** 2026-06-09\n> **Status:** SUPERSEDED (was \"Canonical\")\n> **Scope:** User provisioning, session handoff, and trusted identity flow for L3 Twin / OpenWebUI\n> **Architecture:** Cloudflare Zero Trust already implemented\n> **Auth Authority:** Cloudflare Access + Gateway D1 JWT\n> **Runtime Authority:** IW Continuity Bridge\n> **Twin Surface:** ~~Open WebUI + Agent Zero~~ → Cloudflare-native (iw-agent-runtime)\n> **Rule:** OpenWebUI is not the identity authority. It is a trusted downstream runtime.\n\n---\n\n## 1. Executive Decision\n\nBecause Cloudflare Zero Trust is already implemented, IntegrateWise does not need OpenWebUI-native signup, password auth, or SCIM as the primary path.\n\nThe correct provisioning model is:\n\n```\nCloudflare Access proves who the user is.\nGateway + D1 prove what the user can access.\nContinuity Bridge provides what the Twin should know.\nOpenWebUI provides where the user thinks.\n```\n\nTherefore, OpenWebUI provisioning should be treated as:\n\n```\nedge-authenticated runtime session injection\n```\n\nnot:\n\n```\nstandalone user registration\n```\n\n---\n\n## 2. Canonical Flow\n\n```\nUser\n  │\n  ▼\nCloudflare Access\n  - Google / GitHub SSO\n  - Zero Trust policy\n  - Access JWT\n  │\n  ▼\nGateway\n  - validates CF Access identity\n  - resolves D1 user\n  - resolves tenant\n  - resolves role / department / plan\n  - resolves awareness profile\n  - issues Gateway JWT\n  - creates Twin launch session\n  │\n  ▼\nIW Continuity Bridge\n  - stores context key\n  - hydrates Entity 360\n  - controls Spine / Memory / Signals access\n  │\n  ▼\nOpenWebUI / Agent Zero\n  - receives trusted user identity\n  - receives continuity session pointer\n  - loads context through Bridge\n  - proposes, reasons, briefs\n  - never becomes source of truth\n```\n\n---\n\n## 3. Identity Ownership\n\n| Concern                   | Owner                       |\n| ------------------------- | --------------------------- |\n| Human authentication      | Cloudflare Access           |\n| Application authorization | Gateway + D1                |\n| Tenant membership         | D1 tenant_users             |\n| Department / role         | D1                          |\n| Awareness profile         | D1 / KV                     |\n| Twin continuity session   | Gateway + Continuity Bridge |\n| Runtime chat UI           | OpenWebUI                   |\n| Operational truth         | D1 spine_vault              |\n| Memory                    | D1 + R2 + AI Search         |\n| External agent access     | MCP, separately gated       |\n\n---\n\n## 4. Provisioning Is Just-in-Time\n\nA user is provisioned when Cloudflare proves identity and the Gateway sees them.\n\nProvisioning states:\n\n```\nidentity_seen\n  → d1_user_created\n  → tenant_bound\n  → awareness_profile_assigned\n  → twin_entitlement_checked\n  → continuity_session_created\n  → openwebui_runtime_user_ready\n```\n\nOpenWebUI user records are only runtime convenience records. They are not the product identity layer.\n\n---\n\n## 5. Primary Pattern: Trusted Header + Signed Launch Session\n\n### Why this is the right model\n\nSince Twin is behind Cloudflare Zero Trust, IntegrateWise can safely pass identity downstream only after the request crosses the Cloudflare/Gateway boundary.\n\nOpenWebUI should receive a trusted identity envelope such as:\n\n```\nX-User-Email\nX-User-Name\nX-IW-User-ID\nX-IW-Tenant-ID\nX-IW-Role\nX-IW-Department\nX-IW-Groups\nX-IW-Continuity-Session\nX-IW-Context-Key\nX-IW-Launch-JWT\n```\n\nOnly the Gateway or trusted reverse proxy may inject these headers.\nBrowsers must never be allowed to provide these headers directly.\n\n---\n\n## 6. Cloudflare Access Input Headers\n\nGateway should consume Cloudflare Access identity from:\n\n```\nCf-Access-Authenticated-User-Email\nCf-Access-Jwt-Assertion\n```\n\nThe Gateway must validate:\n\n```\nAccess JWT signature\nAccess JWT audience\nAccess JWT issuer expiration\nemail claim\n```\n\nThen Gateway maps the identity into IntegrateWise's internal model.\n\n---\n\n## 7. Gateway → Internal Identity Model\n\nCanonical internal identity object:\n\n```typescript\nexport interface IWResolvedUser {\n  userId: string;\n  email: string;\n  displayName: string;\n\n  tenantId: string;\n  tenantSlug?: string;\n\n  role: \"founder\" | \"admin\" | \"manager\" | \"member\" | \"viewer\";\n  department:\n    | \"founder\"\n    | \"bizops\"\n    | \"account-success\"\n    | \"sales\"\n    | \"marketing\"\n    | \"finance\"\n    | \"engineering\"\n    | \"hr\"\n    | \"legal\"\n    | \"security\"\n    | \"partnerships\"\n    | \"personal\";\n\n  plan: \"free\" | \"starter\" | \"pro\" | \"enterprise\";\n\n  awarenessProfileId: string;\n  signalThreshold: number;\n\n  groups: string[];\n\n  status: \"active\" | \"invited\" | \"disabled\";\n}\n```\n\n---\n\n## 8. Twin Launch Contract\n\nL2 should never send trusted user or tenant data from the browser.\n\nThe browser may request Twin like this:\n\n```typescript\nexport interface TwinLaunchRequest {\n  source: \"l2\" | \"l1\" | \"l4\";\n  domain: string;\n\n  entityId?: string;\n  entityType?: string;\n  entityName?: string;\n\n  insightId?: string;\n  insightTitle?: string;\n\n  returnUrl?: string;\n}\n```\n\nThe Gateway enriches it server-side into:\n\n```typescript\nexport interface TwinLaunchSession {\n  sessionId: string;\n  contextKey: string;\n\n  userId: string;\n  email: string;\n  tenantId: string;\n\n  role: string;\n  department: string;\n  groups: string[];\n\n  source: \"l1\" | \"l2\" | \"l3\" | \"l4\";\n  domain: string;\n\n  entityId?: string;\n  entityType?: string;\n  entityName?: string;\n\n  insightId?: string;\n  insightTitle?: string;\n\n  createdAt: string;\n  expiresAt: string;\n\n  status: \"created\" | \"opened\" | \"expired\" | \"revoked\";\n}\n```\n\nThe launch session should be short-lived.\n\nRecommended TTL:\n\n```\nLaunch JWT: 60–180 seconds\nContinuity session: 4–8 hours\nContext key: 1 hour\n```\n\n---\n\n## 9. Launch JWT Claims\n\nGateway should create a signed one-time Twin launch JWT.\n\n```typescript\nexport interface TwinLaunchJwtClaims {\n  iss: \"gateway.dev.integratewise.ai\";\n  aud: \"twin.integratewise.ai\";\n\n  sub: string; // IW user id\n  email: string;\n\n  tenant_id: string;\n  role: string;\n  department: string;\n\n  context_key: string;\n  continuity_session_id: string;\n\n  jti: string;\n  iat: number;\n  exp: number;\n}\n```\n\nRules:\n\n```\njti must be one-time-use\ntoken must be short-lived\ncontext data must not be embedded directly if large/sensitive\ntenant_id must be server-derived\nrole must be server-derived\ndepartment must be server-derived\n```\n\n---\n\n## 10. D1 Tables\n\nMinimum D1 tables required for canonical provisioning:\n\n```sql\nCREATE TABLE IF NOT EXISTS tenant_users (\n  id TEXT PRIMARY KEY,\n  tenant_id TEXT NOT NULL,\n  email TEXT NOT NULL,\n  display_name TEXT,\n  role TEXT NOT NULL,\n  department TEXT NOT NULL,\n  plan TEXT NOT NULL DEFAULT 'free',\n  status TEXT NOT NULL DEFAULT 'active',\n  awareness_profile_id TEXT,\n  created_at TEXT NOT NULL,\n  updated_at TEXT NOT NULL,\n  UNIQUE (tenant_id, email)\n);\n\nCREATE TABLE IF NOT EXISTS awareness_profiles (\n  id TEXT PRIMARY KEY,\n  tenant_id TEXT NOT NULL,\n  role TEXT NOT NULL,\n  department TEXT NOT NULL,\n  signal_threshold REAL NOT NULL,\n  signal_entitlements TEXT NOT NULL,\n  panel_entitlements TEXT NOT NULL,\n  created_at TEXT NOT NULL,\n  updated_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS twin_sessions (\n  id TEXT PRIMARY KEY,\n  tenant_id TEXT NOT NULL,\n  user_id TEXT NOT NULL,\n  email TEXT NOT NULL,\n  context_key TEXT NOT NULL,\n  source TEXT NOT NULL,\n  domain TEXT NOT NULL,\n  entity_id TEXT,\n  entity_type TEXT,\n  entity_name TEXT,\n  insight_id TEXT,\n  insight_title TEXT,\n  status TEXT NOT NULL DEFAULT 'created',\n  created_at TEXT NOT NULL,\n  expires_at TEXT NOT NULL,\n  opened_at TEXT,\n  revoked_at TEXT\n);\n\nCREATE TABLE IF NOT EXISTS twin_audit_events (\n  id TEXT PRIMARY KEY,\n  tenant_id TEXT NOT NULL,\n  user_id TEXT NOT NULL,\n  session_id TEXT,\n  event_type TEXT NOT NULL,\n  payload TEXT,\n  created_at TEXT NOT NULL\n);\n```\n\n---\n\n## 11. KV Keys\n\nUse KV for hot session/context lookup.\n\n```\ntwin:session:{sessionId}\ntwin:context:{contextKey}\ntwin:jti:{launchJwtId}\nuser:profile:{tenantId}:{email}\nawareness:{tenantId}:{profileId}\n```\n\nRecommended TTLs:\n\n```\ntwin:context:*   1 hour\ntwin:session:*   4–8 hours\ntwin:jti:*       same as launch JWT expiry\nawareness:*      5–15 minutes\n```\n\n---\n\n## 12. OpenWebUI Runtime Mode\n\nOpenWebUI should run as a trusted downstream app.\n\nRecommended settings conceptually:\n\n```\ndisable public signup\ndisable password-first product flow\nenable trusted email/name header mode if supported\ndefault runtime role = user\nadmin managed separately\n```\n\nCanonical headers to OpenWebUI:\n\n```\nX-User-Email: nirmal@integratewise.ai\nX-User-Name: Nirmal\nX-IW-User-ID: usr_xxx\nX-IW-Tenant-ID: iw-customer-zero\nX-IW-Role: founder\nX-IW-Department: bizops\nX-IW-Groups: founder,bizops,all-employees\nX-IW-Continuity-Session: tws_xxx\nX-IW-Context-Key: ctx_xxx\nX-IW-Launch-JWT: eyJ...\n```\n\nIf stock OpenWebUI only consumes email/name headers, that is fine.\nRole, tenant, department, and context should be consumed by the IW Continuity Bridge, not by OpenWebUI's native RBAC.\n\n---\n\n## 13. Origin Protection Requirement\n\nBecause OpenWebUI runs on Hostinger, the origin must not be directly reachable without Cloudflare.\n\nAcceptable origin protection:\n\n```\nPreferred:\n  Cloudflare Tunnel from Hostinger to Cloudflare\n\nAlso acceptable:\n  Cloudflare proxy + Access policy\n  origin firewall allows only Cloudflare IP ranges\n  authenticated origin pull\n  no direct public bypass\n```\n\nCritical rule:\n\n```\nTrusted headers are safe only if users cannot bypass Cloudflare and hit the origin directly.\n```\n\n---\n\n## 14. Twin Handoff Endpoint\n\nCanonical endpoint:\n\n```\nPOST /v1/twin/handoff\n```\n\nResponsibilities:\n\n```\n1. Validate Cloudflare Access identity\n2. Resolve Gateway/D1 user\n3. Validate tenant membership\n4. Validate Twin entitlement by plan\n5. Resolve department and awareness profile\n6. Create context key\n7. Create Twin session row\n8. Create one-time launch JWT\n9. Store context/session in KV\n10. Return Twin launch URL\n11. Write audit event\n```\n\nResponse:\n\n```json\n{\n  \"success\": true,\n  \"twinUrl\": \"https://twin.integratewise.ai/launch?token=...\",\n  \"sessionId\": \"tws_123\",\n  \"contextKey\": \"ctx_123\",\n  \"expiresAt\": \"2026-06-09T12:00:00.000Z\"\n}\n```\n\n---\n\n## 15. Continuity Context Resolution\n\nOpenWebUI / Agent Zero should not directly query D1.\n\nThe Twin should call the Continuity Bridge:\n\n```\nPOST /v1/continuity/session/resolve\n```\n\nWith:\n\n```json\n{\n  \"contextKey\": \"ctx_123\",\n  \"sessionId\": \"tws_123\"\n}\n```\n\nThe Continuity Bridge returns:\n\n```json\n{\n  \"entity360\": {},\n  \"signals\": [],\n  \"memory\": [],\n  \"permissions\": {},\n  \"availableTools\": [\"spine.entity.get\", \"spine.entity.search\", \"memory.search\", \"proposal.create\"]\n}\n```\n\n---\n\n## 16. Approval Boundary\n\nThe Twin may reason and propose.\nThe Twin must not be the final approval authority.\n\nCanonical rule:\n\n```\nU3 Reason happens in Twin.\nU4 Decide happens in Governance / L2 approval surface.\nU5 Act happens only after policy or human approval.\n```\n\nTherefore:\n\n```\nOpenWebUI chat is not the audit trail.\nOpenWebUI approval buttons are not canonical unless they write through Governance.\nAll decisions must write to D1 governance/audit tables.\n```\n\n---\n\n## 17. L2 → L3 Behavior\n\nWhen L2 awareness drawer shows a signal:\n\n```\nUser clicks: Open Twin ↗\n```\n\nThe frontend sends only contextual hints:\n\n```json\n{\n  \"source\": \"l2\",\n  \"domain\": \"sales\",\n  \"entityId\": \"ent_acme\",\n  \"entityType\": \"opportunity\",\n  \"entityName\": \"Acme Corp\",\n  \"insightTitle\": \"Deal stalled 21 days\"\n}\n```\n\nThe Gateway derives:\n\n```\nuser\ntenant\nrole\ndepartment\nplan\nawareness profile\npermissions\n```\n\nNever trust these from browser input.\n\n---\n\n## 18. User Provisioning Rules\n\n### Existing active user\n\n```\nCF Access identity found\nD1 tenant_user active\nTwin entitlement valid\nCreate session\nOpen Twin\n```\n\n### New user\n\n```\nCF Access identity found\nNo tenant_user found\nCreate edge user\nCreate or attach tenant\nSet onboarding_required = true\nAssign default awareness profile\nRoute to L0 onboarding\nDo not open Twin until entitlement allows it\n```\n\n### Disabled user\n\n```\nCF Access may prove identity\nD1 status = disabled\nGateway denies\nNo Twin session created\nAudit event written\n```\n\n### Free-plan user\n\n```\nCan access L0/L1\nNo Twin unless plan allows\nReturn upgrade/entitlement response\n```\n\n---\n\n## 19. Awareness Profile Mapping\n\nDefault profile thresholds:\n\n```\nFounder  → 0.65\nManager  → 0.75\nMember   → 0.85\nViewer   → 0.95\n```\n\nExample profile:\n\n```json\n{\n  \"role\": \"manager\",\n  \"department\": \"account-success\",\n  \"signalThreshold\": 0.75,\n  \"signalEntitlements\": [\"renewal_risk\", \"health_drop\", \"escalation\", \"engagement_drop\"],\n  \"panelEntitlements\": [\"spine\", \"context\"]\n}\n```\n\n---\n\n## 20. Security Controls\n\nRequired controls:\n\n```\nStrip all inbound X-User-* and X-IW-* headers from public requests.\nInject trusted headers only after CF Access validation.\nValidate Access JWT at Gateway.\nUse one-time launch JWT.\nStore jti to prevent replay.\nKeep tenant_id server-derived.\nKeep role server-derived.\nKeep raw context out of query strings.\nUse contextKey instead of full payload in URL.\nRequire service auth between Twin and Continuity Bridge.\nAudit every handoff.\nAudit every proposal.\nAudit every approval.\nAudit every act.\n```\n\nForbidden:\n\n```\nOpenWebUI as primary auth\nSupabase auth\nbrowser-provided tenant_id\nbrowser-provided role\nOpenWebUI direct D1 access\nOpenWebUI direct source-tool access\nNango token exposure to Twin\napproval only in chat\npublic Hostinger origin bypassing Cloudflare\n```\n\n---\n\n## 21. SCIM Position\n\nSCIM is not required for the current architecture.\n\nUse SCIM later only for enterprise lifecycle automation:\n\n```\nOkta\nAzure AD\nGoogle Workspace\nenterprise provisioning\nautomatic deprovisioning\ngroup sync\n```\n\nPrimary path remains:\n\n```\nCloudflare Access → Gateway D1 identity → Continuity session → OpenWebUI runtime\n```\n\n---\n\n## 22. MCP Position\n\nThe Twin should use:\n\n```\ncontinuity-tool-server → pipeline → Spine\n```\n\nExternal agents should use:\n\n```\nmcp.integratewise.ai\n```\n\nMCP is the external door.\nThe Bridge is the product runtime.\n\nTherefore:\n\n```\nOpenWebUI / Agent Zero should not be treated as an external MCP client by default.\nIt is inside the Bridge experience.\n```\n\n---\n\n## 23. Rollout Plan\n\n### P0 — Required\n\n```\n1. Lock OpenWebUI behind Cloudflare Access.\n2. Prevent direct Hostinger origin bypass.\n3. Add /v1/twin/handoff to Gateway.\n4. Add twin_sessions table.\n5. Add twin_audit_events table.\n6. Add KV context/session keys.\n7. Generate one-time launch JWT.\n8. Inject trusted user headers to OpenWebUI.\n9. Make Twin resolve context through Continuity Bridge.\n10. Disable OpenWebUI public signup/password path.\n```\n\n### P1 — Operational\n\n```\n1. Add awareness profile resolution.\n2. Add plan/tier Twin entitlement checks.\n3. Add proposal.create from Twin.\n4. Route approval to Governance Workbench.\n5. Add audit trail UI.\n6. Add session revocation.\n7. Add disabled-user denial test.\n```\n\n### P2 — Enterprise\n\n```\n1. Add SCIM only for enterprise tenants.\n2. Add custom domain Twin routing.\n3. Add per-tenant encryption keys.\n4. Add enterprise group sync.\n5. Add admin lifecycle dashboard.\n```\n\n---\n\n## 24. Definition of Done\n\nProvisioning is complete when:\n\n```\nA Cloudflare-authenticated active user can open Twin with no OpenWebUI login.\nA disabled D1 user cannot open Twin even if Cloudflare authenticates them.\nA free-plan user cannot open Twin unless entitled.\nA replayed launch token fails.\nA browser-spoofed X-IW-Tenant-ID is ignored or stripped.\nOpenWebUI cannot be reached directly outside Cloudflare.\nTwin loads Entity 360 only through Continuity Bridge.\nTwin can propose but not approve.\nGovernance approval writes to D1 audit trail.\nNo source tool credentials are exposed to OpenWebUI.\nNo Supabase auth is involved.\n```\n\n---\n\n## 25. Final Canonical Statement\n\n```\nCloudflare Zero Trust is the identity membrane.\nGateway is the authorization brain.\nD1 is the edge identity and Spine substrate.\nContinuity Bridge is the runtime access path.\nOpenWebUI is the Twin surface.\n\nProvisioning is not account creation inside OpenWebUI.\nProvisioning is continuity session creation after Cloudflare and Gateway trust are established.\n\nThe user does not log into Twin.\nThe user is carried into Twin by the Bridge.\n```\n\n---\n\n## Final System Architecture\n\n> **Status:** Canonical\n> **Date:** 2026-06-09\n> **Architecture Principle:** One Twin. One Spine. One Memory. One Bridge.\n> **Auth:** Cloudflare Zero Trust + Gateway D1 JWT\n> **Product:** IW Continuity Bridge\n> **Runtime Surface:** OpenWebUI + Agent Zero\n> **Operational Truth:** Cloudflare D1 spine_vault\n> **External Agent Door:** MCP\n> **Tool Token Vault:** Nango\n> **Supabase:** No auth. Usage-allocated fortress storage only for promoted tenants.\n\n### Final One-Line Architecture\n\n```\nTools → Nango → Connector Sync/Webhooks → Loader → Normalizer → Cloudflare Spine\n→ Signals + Memory + Intelligence → IW Continuity Bridge → L1/L2/L3/L4 Surfaces\n→ Human Approves → Act → Tools → Spine Updates Again\n```\n\nThe system never starts cold because every session, signal, decision, and memory loops back into the Spine and Memory substrate.\n\n### System Map\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                              USER SURFACES                                  │\n│                                                                             │\n│  L0 Onboarding                                                              │\n│  L1 Workspace: BI Hub / Account Success / Ops Board / Personal / Work       │\n│  L2 Awareness Drawer: signals, context, HITL approval surface               │\n│  L3 Twin: OpenWebUI + Agent Zero + Grok + Voice                             │\n│  L4 Library: Coda / Knowledge / Memory / Playbooks                          │\n│                                                                             │\n└───────────────────────────────┬─────────────────────────────────────────────┘\n                                │\n                                ▼\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                      IW CONTINUITY BRIDGE                                   │\n│                                                                             │\n│  Runtime path for Twin                                                       │\n│                                                                             │\n│  OpenWebUI / Agent Zero                                                      │\n│      → continuity-tool-server                                                │\n│      → Gateway                                                               │\n│      → Pipeline / Intelligence / Knowledge                                   │\n│      → Spine + Memory + Signals                                              │\n│                                                                             │\n│  The Bridge is the product experience.                                       │\n│  MCP is only the external agent door.                                        │\n│                                                                             │\n└───────────────────────────────┬─────────────────────────────────────────────┘\n                                │\n                                ▼\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                         CLOUDFLARE EDGE                                     │\n│                                                                             │\n│  Cloudflare Zero Trust                                                       │\n│  Gateway                                                                     │\n│  D1 JWT                                                                      │\n│  Workers                                                                     │\n│  Queues                                                                      │\n│  KV                                                                          │\n│  R2                                                                          │\n│  Vectorize / AI Search                                                       │\n│  D1 spine_vault                                                              │\n│                                                                             │\n│  Cloudflare is the edge substrate.                                           │\n│  D1 spine_vault is the operational Spine.                                    │\n│                                                                             │\n└───────────────────────────────┬─────────────────────────────────────────────┘\n                                │\n                                ▼\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                         EXTERNAL TOOLS                                      │\n│                                                                             │\n│  HubSpot / Salesforce / Jira / Stripe / Slack / Gmail / Drive / GitHub      │\n│  Intercom / Linear / Notion / ERP / Calendar / Documents                    │\n│                                                                             │\n│  Tool identity dies at the Normalizer.                                      │\n│  Spine stores canonical truth, not source labels.                           │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n### Hard Rules\n\n```\n1. Cloudflare Zero Trust is the identity membrane.\n2. Gateway is the authorization brain.\n3. D1 spine_vault is operational truth.\n4. Pipeline is the only Spine writer.\n5. Normalizer erases source identity.\n6. Nango owns tool credentials.\n7. Twin reads through Continuity Bridge.\n8. MCP is for external agents.\n9. L2 is an awareness service, not a page.\n10. Twin proposes; Governance decides; Act executes.\n11. Chat is not the audit trail.\n12. Coda is projection, not truth.\n13. Supabase is not auth.\n14. Supabase is not default.\n15. Every query is tenant-scoped.\n16. No surface reads source tools directly.\n17. No agent gets raw source credentials.\n18. Every action loops back through Spine.\n19. Every useful learning can become Memory.\n20. The system never starts cold.\n```\n\n### Final Architecture Statement\n\n```\nIntegrateWise is an edge-native continuity system.\n\nCloudflare provides the identity membrane, routing layer, compute substrate,\nqueues, cache, encrypted operational store, and semantic memory infrastructure.\n\nThe Spine is the canonical D1 operational truth.\nThe Pipeline is the only writer to that truth.\nThe Normalizer turns every tool into one source-agnostic model.\nNango protects all external credentials.\nThe Intelligence layer turns state changes into signals and proposals.\nL2 manifests only entitled awareness.\nL3 Twin reasons through the IW Continuity Bridge.\nL4 projects governed organizational memory.\nMCP lets external agents reach the same Spine without becoming the runtime path.\n\nThe user buys the IW Continuity Bridge: the guarantee that their AI, dashboards,\nagents, memory, and tools all share one continuous context.\n\nConnect once. Normalize once. Render anywhere.\nReason continuously. Approve deliberately. Act safely. Remember forever.\n```\n\n---\n\n## 26. Implementation Status (2026-06-09)\n\nThis section maps the **canonical target** (sections 1–25) to what is **live in code and ops today**.\n\n### 26.1 Identity & Auth\n\n| Component                        | Target                                    | Live today                             | Gap                                   |\n| -------------------------------- | ----------------------------------------- | -------------------------------------- | ------------------------------------- |\n| Cloudflare Access SSO            | Primary identity membrane                 | ✅ Implemented (Google + GitHub)       | —                                     |\n| Gateway CF JWT verification      | Validates `Cf-Access-Jwt-Assertion`       | ✅ `services/gateway/src/index.ts`     | —                                     |\n| Gateway D1 JWT + `x-tenant-id`   | App session for L0–L2                     | ✅ Live                                | —                                     |\n| OpenWebUI trusted headers        | `WEBUI_AUTH_TRUSTED_*` from gateway/proxy | ❌ Not in VPS compose                  | Add when Twin is CF-fronted           |\n| OpenWebUI public signup disabled | No standalone Twin login                  | ⚠️ Partial — OWUI has local auth today | Lock when trusted-header path is live |\n| SCIM 2.0                         | Enterprise lifecycle only                 | ❌ Not configured                      | P2 — optional                         |\n\n### 26.2 L2 → L3 Handoff (Continuity, not account creation)\n\n| Component                                     | Target                           | Live today                                                         | Gap                                            |\n| --------------------------------------------- | -------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------- |\n| `POST /v1/twin/handoff` (Gateway)             | Server-side session + launch JWT | ❌ Not implemented                                                 | **P0** — see §14                               |\n| `twin_sessions` / `twin_audit_events` (D1)    | Session + audit trail            | ❌ Tables not migrated                                             | **P0**                                         |\n| KV `twin:context:*` / `twin:session:*`        | Hot context lookup               | ❌ Not wired for Twin launch                                       | **P0**                                         |\n| Client handoff (`twin-owui-handoff.ts`)       | Browser opens Twin with context  | ✅ Live                                                            | Interim path — query params + `sessionStorage` |\n| `IW_HANDOFF:` envelope in prompt              | L1/L2 context in first message   | ✅ `iw-l1-handoff-inlet.py` filter on VPS                          |\n| `TwinInsightsSurface` → `openTwinWorkbench()` | L2 \"Open Twin ↗\"                 | ✅ `apps/web/src/components/l2/insights/twin-insights-surface.tsx` |\n| Server-derived tenant/role in handoff         | Never trust browser              | ❌ Client passes entity hints only today                           | Gateway handoff closes this                    |\n\n**Interim handoff (live):**\n\n```\nL1/L2 click \"Open Twin\"\n  → writeTwinHandoffContext() (sessionStorage)\n  → buildTwinOwuiUrl() with iw_context, iw_prompt, iw_domain, iw_source\n  → window.open(\"https://twin.integratewise.ai?...\")\n  → OWUI inlet filter parses IW_HANDOFF: from first user message\n  → continuity-tool-server reads Spine/Memory via pipeline\n```\n\n**Target handoff (canonical):**\n\n```\nL1/L2 POST /v1/twin/handoff { entityId, domain, source }  (hints only)\n  → Gateway validates CF Access + D1 user + plan entitlement\n  → Creates twin_sessions row + KV context key + one-time launch JWT\n  → Returns twinUrl with token (60–180s TTL)\n  → User lands on CF-protected Twin; proxy injects X-IW-* headers\n  → Continuity Bridge resolves contextKey → Entity 360\n```\n\n### 26.3 L3 Runtime (Hostinger VPS)\n\n| Component                          | Target                        | Live today                                                   | Gap                                        |\n| ---------------------------------- | ----------------------------- | ------------------------------------------------------------ | ------------------------------------------ |\n| `twin.integratewise.ai`            | Primary L3 surface            | ✅ Traefik + OWUI (`integratewise-ops/vps-operations-stack`) | —                                          |\n| `twin.operations.integratewise.ai` | Ops-branded first-win Twin    | ❌ DNS/route not provisioned                                 | See CONTINUITY_BRIDGE_DEPLOYMENT_STATUS §8 |\n| `continuity-tool-server`           | Bridge read path to pipeline  | ✅ Container in openwebui compose                            | Extend for `session/resolve`               |\n| `agentzero-tool-server`            | Multi-step execution          | ✅ Container live                                            | —                                          |\n| LiteLLM + Ollama fallback          | Local models when cloud fails | ✅ `iw-ollama` + LiteLLM                                     | —                                          |\n| CF Tunnel / origin lock            | No direct Hostinger bypass    | ⚠️ Traefik on host :443                                      | Prefer CF Tunnel or origin firewall        |\n| Infisical secrets wire             | Runtime env from vault        | ⚠️ Deployed, not wired to stack                              | `infisical-wire-stack.sh`                  |\n\n### 26.4 L2 Cognitive Layer (from `l2.zip` contract)\n\n| L2 surface                                | Maps to S-series        | OWUI / Bridge role                       | Status               |\n| ----------------------------------------- | ----------------------- | ---------------------------------------- | -------------------- |\n| Spine panel                               | S2 Awareness / evidence | `spine.entity.get` via continuity        | ✅ Partial in drawer |\n| Context panel                             | S2 / think substrate    | Entity 360 assembly                      | ✅ Live              |\n| LiveSignalsStrip                          | S2 / U2 Notice          | Signal cards in L1 shell                 | ✅ Live              |\n| HITL / PendingApprovals                   | S2 / **U4 Decide**      | Governance workbench — **not** OWUI chat | ✅ Live in L2        |\n| TwinInsightsSurface                       | S2 digest → S3 handoff  | `openTwinWorkbench()`                    | ✅ Live              |\n| Domain happy path (Today/Queue/Decisions) | S2 per-domain           | Routes in workbench                      | ✅ Live              |\n| SlidingPanel / cognitive triggers         | S2 overlay              | `cognitive-triggers.tsx`                 | ⚠️ Partial triggers  |\n\n### 26.5 Code References\n\n| Artifact                            | Path                                                                               |\n| ----------------------------------- | ---------------------------------------------------------------------------------- |\n| Client handoff library              | `integratewise-live/apps/web/src/lib/twin-owui-handoff.ts`                         |\n| L2 Twin insights + Open Twin button | `integratewise-live/apps/web/src/components/l2/insights/twin-insights-surface.tsx` |\n| OWUI handoff inlet filter           | `integratewise-ops/vps-operations-stack/openwebui/filters/iw-l1-handoff-inlet.py`  |\n| VPS Twin compose                    | `integratewise-ops/vps-operations-stack/openwebui/docker-compose.yml`              |\n| Continuity tool server              | `integratewise-ops/vps-operations-stack/tool-servers/tool_server.py`               |\n| Gateway CF Access verification      | `integratewise-live/services/gateway/src/index.ts`                                 |\n| L2 surface contract                 | `integratewise-docs/docs/internal/architecture/l2-twin-surface-contract.md`        |\n| MCP / Bridge canon                  | `integratewise-docs/docs/internal/architecture/mcp-continuity-bridge.md`           |\n\n### 26.6 Next implementation sequence\n\n```\nP0 (closes provisioning gap)\n  1. Add POST /v1/twin/handoff to Gateway (§14 request/response)\n  2. Migrate twin_sessions + twin_audit_events (§10)\n  3. Wire KV context keys (§11)\n  4. Put Twin origin behind Cloudflare Access (§13)\n  5. Add WEBUI_AUTH_TRUSTED_* to openwebui/docker-compose.yml when CF proxy injects headers\n\nP1 (continuity hardening)\n  6. POST /v1/continuity/session/resolve from continuity worker (§15)\n  7. Plan-tier Twin entitlement check in handoff (§18)\n  8. Switch openTwinWorkbench() to call Gateway handoff instead of direct URL\n\nP2 (enterprise)\n  9. SCIM for Okta/Azure AD lifecycle (§21)\n  10. twin.operations.integratewise.ai branded route\n```\n"}