Unclassified

IntegrateWise Continuity Bridge — Canonical Architecture Specification v1.0.1-FINAL

Status: SUPERSEDED ARCHITECTURE LINEAGE. This file is not a current lock.
Its product name, service removal, storage and runtime decisions are retained
for genealogy only. Current authority is
ARCHITECTURE_LOCK.md.

Original Status: LOCKED — Integration Manager service removed; adapter pattern folded into act + connector services. Native builds and deployments are faster without an extra abstraction layer.
Date: 2026-07-02
Version: 1.0.1-FINAL
Supersedes: v1.0.0-FINAL where it conflicts. All §14 conflicts remain locked.


The Revision

The Integration Manager is not a separate service. It is a pattern implemented within the services that actually touch external providers. The 7× agnostic moat is achieved through adapter modules, not a separate orchestrator.

Why: Native builds and deployments work much faster. Adding an extra service hop (act → Integration Manager → provider) adds latency, increases blast radius, and complicates deployment. The adapter pattern inside act achieves the same swappability with zero extra infrastructure.


1. The Doctrine (Unchanged)

Context you own. AI you rent. Approval in between.

The IntegrateWise Continuity Bridge is an OODA Engine for Business Continuity. It preserves organizational context, memory, governance, and execution across all tools, humans, and AI agents through one stable continuity contract.

Product Name: IW Continuity Bridge
Category: The Operational Continuity Platform
Core Promise: One JWT. One SSE connection. One Bridge. The Bridge connects to everything else.


2. The OODA Engine (Unchanged)

Every entity, tool, user, and AI agent operates on the same four-phase decision cycle:

OBSERVE ──► ORIENT ──► DECIDE ──► ACT ──► (memory compounds) ──► OBSERVE...
PhaseWhatServicesSpeed
ObserveIngest signals from webhooks, sync polls, user actions, file changeswebhook-ingress, connector-sync, folder-watcher, mcp-connector (inbound)ms (event) to min (poll)
OrientAssemble Entity360 + Memory + Knowledge into contextnormalizer (8-stage), intelligence (Context Assembly), knowledge (RAG), continuity (memory retrieval)<2s normalizer p99, <10ms cache hit
DecideTwin reasons, proposes action, governance scores confidencetwin-orchestrator (OODA engine), govern (confidence gate), think (LLM orchestration)1-2s simple, 5-10s complex
ActExecute approved action, writeback to Spine, update memoryact (execution + provider adapters), workflow (durable orchestration), hermes (message queue)500ms-2s (external API)

3. The Four Layers (Conceptual Law — Unchanged)

Consumers  ↔  Continuity Bridge  ↔  Continuity Kernel  ↔  Provider Fabric
LayerWhat It IsWhat Consumers See
ConsumersHumans, AI assistants (ChatGPT, Claude, Perplexity, Cursor), apps, toolsOne MCP connection, one JWT, one web workbench, or one SDK call
Continuity BridgeThe public interface and moat: identity, auth, discovery, projections, capabilities, governance entry, eventsIdentity, Discovery, Projections, Capabilities, Events
Continuity KernelThe internal context substrate: Adaptive Spine, Memory, Knowledge, Context, Capability Engine, Governance, Workflow, Continuity EngineNothing. Consumers never import internal topology.
Provider FabricReplaceable external execution: SaaS providers, databases, APIs, queues, agents, runtimesNothing. Entirely behind the Kernel.

Invariant: Consumers never import internal service topology. They see only Identity, Discovery, Projections, Capabilities, and Events.


4. The Two Planes (North / South — Revised)

Consumers → [API Gateway] → Spine (context) → [Act + Connector Services] → Provider Tools
             (North / Ingress)                        (South / Egress)
PlaneDirectionRolePhysical Service
NorthConsumers → PlatformAuthN/Z, tenant routing, rate-limit, capability routing, Discovery, inbound MCPgateway (single Worker)
SouthPlatform → ProvidersAdapter modules inside act and connector services — Nango OAuth, MCP outbound, Native REST, credential fetch from Secrets/KV, Entity360 injectionact (execution + outbound adapters), connector (OAuth callbacks), connector-sync (sync orchestration)

Rule: Neither plane talks to the other except through the Spine. The Gateway and the act + connector services are the only two doors — one in, one out.

The Integration Manager is NOT a separate service. It is the adapter pattern implemented inside act (for outbound execution) and connector/connector-sync (for inbound sync and OAuth). This is faster, simpler, and achieves the same swappability.


5. The Adapter Pattern (Replaces Integration Manager)

The 7× agnostic moat is achieved through adapter modules inside the services that need them, not a separate orchestration service.

5.1 Outbound Adapter Modules (Inside act Service)

services/act/
├── src/
│   ├── index.ts                 # Entry point — handles ACT_QUEUE
│   ├── execute.ts               # Main execution logic
│   ├── adapters/                # Outbound provider adapters
│   │   ├── nango.ts             # Nango OAuth adapter (Salesforce, HubSpot, etc.)
│   │   ├── mcp-outbound.ts      # MCP outbound adapter (calls provider MCP servers)
│   │   ├── native.ts            # Native REST adapter (direct HTTP calls)
│   │   ├── credentials.ts       # Credential wall — fetches from CF Secrets/KV
│   │   └── context-inject.ts    # Entity360 injection before outbound call
│   └── types.ts
├── wrangler.toml
└── package.json

Execution flow inside act:

// services/act/src/execute.ts

export async function executeCapability(
  capability: string, // e.g., "salesforce.opportunity.update"
  tenantId: string,
  payload: any
): Promise<ExecutionResult> {
  // 1. Resolve provider from capability path
  const [provider, resource, operation] = capability.split(".");

  // 2. Fetch tenant credentials (credential wall)
  const credentials = await getCredentials(provider, tenantId);
  //    → reads from Cloudflare Secrets or KV, never hardcoded

  // 3. Fetch Entity360 context for injection
  const context = await getEntity360(tenantId, payload.entity_id);

  // 4. Select adapter based on provider config
  const adapter = selectAdapter(provider, credentials);
  //    → Nango adapter for OAuth-mature providers
  //    → MCP adapter for AI-native providers
  //    → Native adapter for direct REST

  // 5. Inject context and execute
  const enrichedPayload = injectContext(payload, context);
  const result = await adapter.execute(resource, operation, enrichedPayload, credentials);

  // 6. Writeback to Spine (through Pipeline, not direct D1 write)
  await enqueueToPipelineQueue({
    type: "execution_result",
    tenantId,
    capability,
    result,
    timestamp: Date.now(),
  });

  return result;
}

// Adapter selection — no separate Integration Manager service
function selectAdapter(provider: string, credentials: Credentials): Adapter {
  if (credentials.type === "nango") return new NangoAdapter();
  if (credentials.type === "mcp") return new MCPOutboundAdapter();
  if (credentials.type === "native") return new NativeAdapter();
  throw new Error(`Unknown adapter type: ${credentials.type}`);
}

Why this is better than a separate Integration Manager:

  • Zero extra hop: act → adapter → provider. No act → Integration Manager → adapter → provider.
  • Faster deploy: act deploys as one Worker. No coordinating deploys between act and Integration Manager.
  • Smaller blast radius: If Salesforce adapter breaks, only act service is affected. Not a shared Integration Manager that takes down all outbound calls.
  • Same swappability: Adapter interface is the contract. Swap Nango for direct OAuth by changing the adapter implementation. No external orchestrator needed.

5.2 Inbound Adapter Modules (Inside connector + connector-sync)

services/connector/
├── src/
│   ├── index.ts                 # OAuth callback handler
│   ├── nango.ts                 # Nango session creation
│   └── adapters/                # Provider-specific auth handling
│       ├── salesforce.ts
│       ├── hubspot.ts
│       └── slack.ts

services/connector-sync/
├── src/
│   ├── index.ts                 # Sync orchestration
│   ├── sync.ts                  # Main sync loop
│   └── adapters/                # Provider-specific sync logic
│       ├── salesforce-sync.ts
│       ├── hubspot-sync.ts
│       └── slack-sync.ts

Sync flow inside connector-sync:

// services/connector-sync/src/sync.ts

export async function runSync(connectorId: string, tenantId: string): Promise<SyncResult> {
  // 1. Fetch connector config
  const config = await getConnectorConfig(connectorId, tenantId);

  // 2. Get credentials (from Nango vault or CF Secrets)
  const credentials = await getCredentials(config.provider, tenantId);

  // 3. Select sync adapter
  const adapter = selectSyncAdapter(config.provider);
  //    → SalesforceSyncAdapter, HubSpotSyncAdapter, etc.

  // 4. Fetch raw records from provider
  const rawRecords = await adapter.fetch(credentials, config.lastSyncTime);

  // 5. Enqueue to Normalizer (not direct Pipeline write)
  await enqueueToNormalizerQueue({
    tenantId,
    provider: config.provider,
    records: rawRecords,
    timestamp: Date.now(),
  });

  return { recordsFetched: rawRecords.length };
}

5.3 The Adapter Interface (The Contract)

// packages/connectors/src/types.ts (shared adapter contract)

export interface OutboundAdapter {
  execute(
    resource: string,
    operation: string,
    payload: any,
    credentials: Credentials
  ): Promise<ExecutionResult>;
}

export interface InboundSyncAdapter {
  fetch(credentials: Credentials, since: Date): Promise<RawRecord[]>;
}

export interface Credentials {
  type: "nango" | "mcp" | "native";
  tenantId: string;
  // Provider-specific fields
  accessToken?: string;
  refreshToken?: string;
  apiKey?: string;
  // Nango-specific
  connectionId?: string;
  // MCP-specific
  serverUrl?: string;
}

// Adapter registry (simple map, not a separate service)
  salesforce: NangoAdapter,
  hubspot: NangoAdapter,
  slack: NangoAdapter,
  github: MCPOutboundAdapter,
  linear: MCPOutboundAdapter,
  stripe: NativeAdapter,
  custom: NativeAdapter,
};

  salesforce: SalesforceSyncAdapter,
  hubspot: HubSpotSyncAdapter,
  slack: SlackSyncAdapter,
  // ...
};

5.4 Swappability Without a Separate Service

The 7× agnostic moat is achieved through:

DimensionAdapter ModuleLocationSwap Method
Storagedb-adapter.tspackages/lib/Change db-gate.ts to use D1, Supabase, Neon, or HyperDrive
Authauth-adapter.tspackages/lib/Change auth.ts to issue JWT, Clerk, or Stack tokens
AI Modelopenrouter.tspackages/lib/Change model config in think service
Provider (Outbound)NangoAdapter, MCPOutboundAdapter, NativeAdapterservices/act/src/adapters/Change adapter registration in outboundAdapters map
Provider (Inbound)SalesforceSyncAdapter, HubSpotSyncAdapter, etc.services/connector-sync/src/adapters/Change adapter registration in syncAdapters map
Queuequeue-adapter.tspackages/lib/Change from Cloudflare Queues to SQS or Kafka
Cachecache-adapter.tspackages/lib/Change from KV to Redis or Upstash
Deploymentwrangler.tomlPer serviceChange from Workers to Lambda or Vercel

No separate Integration Manager service needed. The adapter pattern inside the services that actually need it is faster, simpler, and more deployable.


6. The 26 Services (Physical Topology — Revised)

All services run on every deployment and serve all tenants. Customer-Zero is a tenant class, not a separate service. All 26 are wired into the Gateway as Cloudflare service bindings.

Tier 0 — Ingress & Routing

ServiceWorker NamePurposeBinding
gatewayintegratewise-gatewaySingle entry; JWT validation; tenant routing; rate-limitN/A
webhook-ingressiw-webhook-ingressReceives external webhooks (Salesforce, HubSpot, Stripe, GitHub)WEBHOOK_INGRESS

Tier 1 — Tenant & Sync

ServiceWorker NamePurposeBinding
tenantsiw-tenantsMulti-tenant context, RBAC, plan limitsTENANTS
connectoriw-connectorOAuth callback handler; Nango session creation; inbound adapter patternCONNECTOR
connector-synciw-connector-syncOrchestrates sync; inbound sync adaptersCONNECTOR_SYNC
normalizeriw-normalizer8-stage pipeline: parse → trait-detect → resolve-type → resolve-entity → link-rels → enrich-map → validate → emit-canonicalNORMALIZER
loaderiw-loaderCold-start pre-loader; Nango webhook handler; triggers immediate "creamy" syncLOADER

Tier 2 — Projection & Rendering

ServiceWorker NamePurposeBinding
pipelineiw-pipelineOnly writer to the Spine; commits to D1; writes audit logPIPELINE
twin-orchestratoriw-twin-orchestratorPersistent per-user OODA engine (Durable Object)TWIN_ORCHESTRATOR
l2iw-l2Department × industry overlay projections (8 lenses)L2
intelligenceiw-intelligenceAnalytics, insights, signal generation, Context AssemblyINTELLIGENCE
knowledgeiw-knowledgeKnowledge base, docs, semantic search (RAG)KNOWLEDGE
governiw-governGovernance rules engine; approval gates; HITL thresholdsGOVERN
storeiw-storePersistence for projections (accounts, deals, tasks)STORE
actiw-actAction execution; outbound adapter modules (Nango, MCP, Native); write-back to providersACT
spine-v2iw-spine-v2Spine normalization & graph servicesSPINE_V2

Tier 3 — Capability Runtime & Orchestration

ServiceWorker NamePurposeBinding
hermesiw-hermesMessage queue + execution engine (Durable Object)HERMES
triageiw-triageConfidence routing + active-memory decay (runs inside Hermes)TRIAGE
workflowiw-workflowDurable orchestration; pause; retry; sagaWORKFLOW
iw-agent-runtimeiw-agent-runtimeMCP-compliant AI agent executionIW_AGENT_RUNTIME
mcp-connectoriw-mcp-connectorInbound MCP bridge; external agents → scoped Spine/MemoryMCP_CONNECTOR

Tier 4 — Supporting

ServiceWorker NamePurposeBinding
agent-registryiw-agent-registryCatalog of available agents/integrationsAGENT_REGISTRY
billingiw-billingUsage tracking + plan enforcementBILLING
adminiw-adminPlatform admin; tenant management; overridesADMIN
folder-watcheriw-folder-watcherDurable Object filesystem watcher (macOS chokidar → DO)FOLDER_WATCHER
continuityiw-continuityMemory consolidation + decay (the continuity substrate)CONTINUITY
telemetryiw-telemetryTraces, metrics, observabilityTELEMETRY
thinkiw-thinkLLM reasoning orchestration (OpenRouter abstraction)THINK

7. The 0–16 Stack (Physical Implementation — Revised)

The 4-layer law is conceptual (trust boundaries). The 0–16 stack is physical (implementation). Both hold simultaneously.

#LayerPhysical ServicesData / Storage
0Tenant Lifecycletenants, loader, adminD1 tenants, tenant_spine_config
1Customer Ecosystemconnector, connector-sync, agent-registryNango vault, connectors table, inbound adapter modules
2Surface Layerapps/web, apps/mcp-serverCloudflare Pages, R2 assets
3Gateway LayergatewayN/A — pure routing
4Identity & Organizationtenants (RBAC)D1 rbac_roles, rbac_permissions
5Continuity Bridgeconnector-sync, normalizer, mcp-connector, webhook-ingressD1 sync_jobs, normalizer_state, KV Discovery cache
6Adaptive SpinepipelineD1 entities, relationships, spine_audit_log
7Context Assemblyintelligence, knowledgeVectorize, AI Search, KV context cache
8Shared Memorycontinuity, triageD1 memory (active/staging/archived), KV decay
9Capability Engineiw-agent-runtime, thinkOpenRouter API, KV model config
10Governance LayergovernD1 governance_audit_log, action_proposals
11Capability Runtimehermes, workflow, act, mcp-connectorDurable Objects, Queues (ACT_QUEUE, PIPELINE_QUEUE), outbound adapter modules
12Projection Registryl2, storeD1 projections, projection_registry
13Registry Layeragent-registry, intelligenceD1 capability_registry, endpoint_registry, KV cache
14Continuity Enginecontinuity, twin-orchestratorD1 continuity_graph, KV session handoffs
15Data & Infrastructuretelemetry, folder-watcherD1 audit_logs, R2 telemetry, Workers Analytics
16Endpoint Registrygateway (serves), intelligence (updates)KV + D1 endpoint_registry (living API contract)

Cross-cutting: Security (WAF, DDoS, TLS, CF Secrets, Zero Trust), Observability, Reliability (idempotency, retries, DLQ, backpressure), Compliance (audit & lineage, retention, encryption, tenant isolation).


8. MCP Pool Architecture (Unchanged)

8.1 Inbound MCP Pool (North Plane)

Endpoint: mcp.integratewise.ai/v1/mcp (SSE/stdio)
Role: AI assistants (ChatGPT, Claude, Perplexity, Cursor) connect to us to read scoped Spine/Memory context.
Primary ingress: This is the primary front door. Traditional SaaS webhooks are secondary.

Security gates (P0):

  1. JWT required on /tools, /invoke, /mcp, /sessions — 403 on bypass
  2. tenant_id extracted from JWT claim, never from client payload
  3. Cross-tenant session reuse → 403 (fail-loud, not 404)
  4. Read-only default. Write requires scope: write + governance approval.
  5. Tool catalog filtered by Discovery — tenant cannot discover another tenant's tools
  6. Every invocation logged to spine_audit_log with via: mcp

Consumer config (the ONLY client-side entry):

{
  "mcpServers": {
    "integratewise": {
      "type": "sse",
      "url": "https://mcp.integratewise.ai/v1/mcp",
      "headers": { "Authorization": "Bearer ${input:integratewise_jwt}" }
    }
  }
}

Key rule: One entry. Not 21. Not 5. One.

8.2 Outbound MCP Pool (South Plane — Inside act Service)

Inside act service, not a separate Integration Manager. The act service's MCPOutboundAdapter module connects to provider MCP servers (Salesforce MCP, Slack MCP, GitHub MCP) using MCP as the transport.

Entity360 context injected before every outbound call. Credential wall fetches per-tenant keys from Cloudflare Secrets/KV. No shared tokens across tenants.


9. Governance & Approval Gate (The 0.70/0.85 Law — Unchanged)

Two triage gates run on the same confidence thresholds:

9.1 Governance Triage (Execution Gate)

ConfidenceActionDestinationHuman Touch
≥ 0.85Auto-approveACT_QUEUENone
0.70 – 0.85Queue for reviewMy DeskApprove / Modify / Dismiss
< 0.70Discardspine_audit_log (discard reason)None

9.2 Memory Triage (Knowledge Gate)

ConfidenceActionDestination
≥ 0.85Auto-promoteActive memory (D1 + KV + Vectorize)
0.70 – 0.85StagingStaging memory (D1 only)
< 0.70DiscardR2 cold storage (compliance/audit)

10. The Swappable Layers (7× Agnostic Moat — Revised)

The swappability is achieved through adapter modules, not a separate Integration Manager service.

DimensionAdapter ModuleLocationSwap Method
FrontendUI frameworkapps/web/Vite → Next.js → Electron by replacing framework
Authauth-adapter.tspackages/lib/JWT → Clerk → Stack by changing verify() implementation
Relational Storedb-adapter.tspackages/lib/D1 → Supabase → Neon by changing query() implementation
Cachecache-adapter.tspackages/lib/KV → Redis → Upstash by changing get()/set() implementation
Queuequeue-adapter.tspackages/lib/Queues → SQS → Kafka by changing enqueue()/dequeue() implementation
AI / Modelopenrouter.tspackages/lib/gpt-5-mini → Claude → Grok by changing model config
Provider (Outbound)NangoAdapter, MCPOutboundAdapter, NativeAdapterservices/act/src/adapters/Change adapter registration in outboundAdapters map
Provider (Inbound)SalesforceSyncAdapter, HubSpotSyncAdapter, etc.services/connector-sync/src/adapters/Change adapter registration in syncAdapters map
Deploymentwrangler.tomlPer serviceWorkers → Lambda → Vercel by changing deploy target

The adapter interface is the contract. The implementation is swappable. No separate orchestrator needed.


11. Security Posture (P0 & P1 — Unchanged)

P0 — Tenant Safety (Must Close Before Production)

#VulnerabilityFixOwner
1Cross-tenant data leakWHERE tenant_id = ? on every query; 403 fail-loudALL services
2Tenant-id spoofingExtract from JWT claim only; reject client-providedgateway
3Tenant middleware no-opEnforce service bindings carry tenant_id implicitlygateway
4HITL DO using idFromName("global")Use idFromName(tenant_id + user_id)govern
5Invitation cross-tenant scanAdd WHERE tenant_id = ? to invitation lookuptenants
6Hardcoded secretsMove to Cloudflare Secrets; rotateadmin
7.env committedRemove from git; add .gitignore; scan historyadmin
8SQL injection in shimsUse Drizzle ORM parameterized queriescontinuity, knowledge
9MCP-JWT bypassRequire Authorization: Bearer <jwt> on all MCP endpointsmcp-connector
10Auth root thrashingFreeze on API Keys + JWT; remove Clerk/Stack/Descope importsgateway

P1 — Hardening (Post-Production)

#VulnerabilityFixOwner
1Billing still on SupabaseMigrate to D1 + Workers billingbilling
2Gateway rate-limiter fails openAdd Cloudflare Rate Limiting; fail-closedgateway
3CORS reflects arbitrary originsWhitelist app.integratewise.ai + Pages domainsgateway
4MCP JWT bypassClose P0 #9 firstmcp-connector
5Unsigned-webhook auto-approveVerify Nango webhook signatures; reject unsignedloader
6Webhook replay/timing leaksAdd idempotency keys; deduplicatewebhook-ingress
7Weak password hashingArgon2id via Cloudflare Workerstenants
8Remove @supabase/supabase-jsDECISION 22 completionAll services

12. The One Invariant (Unchanged)

Identity gates the door. Discovery advertises the capabilities. The act and connector services are the only hands that touch outside tools (through their adapter modules). Spine is the only place context is written. Govern sits between reasoning and execution. Memory is scoped and compounds. Agents and tools coordinate through the Spine, never directly. Every hop carries tenant_id.


13. Resolution of All Conflicts (Unchanged from v1.0.0)

All §14 conflicts from v1.0.0-FINAL remain locked. The only change in v1.0.1 is the removal of the Integration Manager as a separate service and the formalization of the adapter pattern inside act + connector + connector-sync.


END OF DOCUMENT

IntegrateWise Continuity Bridge — Canonical Architecture Specification v1.0.1-FINAL. The Integration Manager is not a separate service. It is the adapter pattern inside the services that actually touch providers. Native builds and deployments are faster this way.