HANDOFF INFRASTRUCTURE ENHANCEMENT PLAN

Documentation for Handoffs

GoGrab Platform Infrastructure Enhancement Plan

Date: March 9, 2026 (Updated: March 9, 2026 — post S191 agent changes) Prepared by: Claude (Architecture Review) Assigned to: Internal Dev Agents Scope: 7 Phases | 26 Tasks | ~4 weeks Risk Level: Medium (phased rollout mitigates) APIs Affected: backend-api, backend-ai-api, backend-vitto-api, mcp-gograb-ai


Table of Contents

  1. Executive Summary
  2. Current Architecture
  3. Key Findings
  4. Revised Positions
  5. Phase 1: Circuit Breakers and Resilience
  6. Phase 2: Inter-Service Retry and Caching
  7. Phase 3: AI Module Migration Completion
  8. Phase 4: BullMQ Event-Driven Alerting
  9. Phase 5: Cloudflare Edge Layer
  10. Phase 6: MCP Gateway Enhancement
  11. Phase 7: Cleanup and Operational Hardening
  12. Execution Timeline
  13. Verification Protocol

Executive Summary

This is the complete handoff plan for enhancing the GoGrab platform infrastructure. It covers all three backend APIs (backend-api:3000, backend-ai-api:3001, backend-vitto-api:3003), the MCP server (mcp-gograb-ai), Cloudflare edge infrastructure, and the Railway deployment pipeline.

The plan is organized into 7 phases, ordered by impact and dependency. Each phase can be executed independently by a dev agent session, with clear acceptance criteria and rollback procedures.


Current Architecture

Component Port / URL Database Primary Responsibility
backend-api 3000 / api.gograb.space gograb-api (gograbspace cluster) Platform CRUD: users, spaces, universes, modules, billing, deployments, e-commerce, Yjs collab
backend-ai-api 3001 / ai-api.gograb.space ai-agents, ai-memory, ai-mcp-dev, ai-archive, ai-context (gograbspace cluster) AI brain: agents, chat, learning, super-intelligence, MCP gateway, workflows, orchestration
backend-vitto-api 3003 / vitto-api.gograb.space vitto-mind (separate vitto cluster) Autonomous agent: engine, mind/memory, proactive monitoring, messaging channels, security vault, A2A
backend-docs-api 3002 / docs-api.gograb.space docs-database (separate gograb-docs cluster) Documentation sync and management
mcp-gograb-ai stdio (local MCP) Routes to ai-mcp-dev via backend-ai-api 98 tools via 15 gateways. Single plug-and-play connection for Cursor, Claude Code, Cowork

Inter-Service Dependency Map

Frontend (Angular)
  ├── → backend-api (3000)       [REST, WebSocket, Yjs]
  ├── → backend-ai-api (3001)    [REST, SSE, WebSocket, Native WS]
  └── → backend-vitto-api (3003) [REST, SSE]

backend-api (3000)
  ├── → Stripe, SendGrid, Twilio, Cloudflare, GitLab
  └── ← backend-vitto-api (resolve-channel)

backend-ai-api (3001)
  ├── → backend-api (3000)         [PlatformApiClient: code storage, CRUD]
  ├── → backend-vitto-api (3003)   [VittoClient: task delegation]
  ├── → OpenAI, Anthropic, Google  [LLM providers]
  └── ← MCP server (tool calls via HTTP + WebSocket)

backend-vitto-api (3003)
  ├── → backend-api (3000)         [user resolution, space queries]
  ├── → backend-ai-api (3001)      [LLM routing, intelligence queries]
  ├── → Twilio, WhatsApp, Telegram, Slack [channels]
  ├── → E2B [sandboxed execution]
  └── ← External webhooks (WhatsApp, Telegram inbound)

Critical circular dependency: backend-ai-api delegates tasks TO Vitto, Vitto queries intelligence FROM backend-ai-api. If either is slow, the other cascades.


Key Findings


Revised Positions

Database Architecture: Keep Separated

Initial assessment suggested consolidating 9 databases to 4. After deeper analysis, this was wrong. The current separation is correct because:

One consolidation opportunity: ai-context (used by backend-api AI module) should merge into ai-agents once the AI module migration (Phase 3) completes. This is the only database with unclear ownership.

MCP Server: Enhance Gateway, Don't Split

Initial assessment suggested splitting into 3-4 separate MCP servers. This was wrong because:


Phase 1: Circuit Breakers and Resilience

Priority: Critical Estimated effort: 2-3 sessions Risk: Low Dependencies: None Branch: session-{N} (follow SAGP v1.2)

Problem Statement

Backend-vitto-api has a CircuitBreakerService (security/resilience/circuit-breaker.service.ts) but it only covers LLM providers via SmartRouterService. Backend-ai-api and backend-api have zero circuit breaker protection on any external calls. If OpenAI goes down, backend-ai-api accumulates hanging HTTP connections until it runs out of memory or hits the 30-second global timeout on every request.

Tasks

  1. Extract CircuitBreakerService into shared library. Move from APIs/backend-vitto-api/src/app/security/resilience/circuit-breaker.service.ts to libs/libs-api/backend-core/src/lib/resilience/circuit-breaker.service.ts. Keep existing config: 5 failures to open, 60s reset, 2 half-open test attempts.

  2. Extract DeadLetterQueueService similarly. Current location: APIs/backend-vitto-api/src/app/security/resilience/dead-letter-queue.service.ts. Move to shared lib.

  3. Add circuit breakers to backend-ai-api LLM calls. Wrap each provider call in @libs-api/llm-integration with the shared circuit breaker. On Claude failure, auto-route to OpenAI. NOTE (S191): Vitto's SmartRouterService.sendWithFailover() already wraps both primary and fallback calls with this.circuitBreaker.execute(). The ProviderFactoryService.wrapWithResilience() creates ResilientLLMProvider instances with the circuit breaker injected. Replicate this pattern at the shared library level so backend-ai-api gets the same protection.

  4. Add circuit breakers to backend-api external calls: Stripe (billing module), SendGrid (email module), Twilio (SMS/WhatsApp), Cloudflare Pages API (deployment module), GitLab/Gitea API (git module).

  5. Implement provider health endpoint. Expose circuit breaker states at GET /api/health/providers, GET /ai-api/health/providers, GET /vitto-api/health/providers. Return JSON with per-provider state (CLOSED/OPEN/HALF_OPEN), failure count, last failure time.

Key Files to Modify

Acceptance Criteria

Rollback

Circuit breakers default to CLOSED (pass-through). If issues arise, set failureThreshold to 999999 via environment variable to effectively disable without code changes.


Phase 2: Inter-Service Retry and Caching

Priority: High Estimated effort: 2 sessions Risk: Low Dependencies: Phase 1 (shared resilience lib)

Problem Statement

Most inter-service HTTP calls have zero retries. If backend-api is mid-deploy when Vitto tries to resolve a WhatsApp user identity, the call fails silently and the message is lost.

Current State

Service Call Timeout Retries Backoff Failure Mode
Vitto → AI: Learning context 2s 0 N/A Returns empty
Vitto → AI: MCP tools 15s 2 Exponential 1s Throws
Vitto → API: Channel identity 5s 0 N/A Throws (message lost)
AI → Vitto: Orchestrate 10s 0 N/A Throws
AI → API: Platform queries 30s 0 N/A Throws

Tasks

  1. Add retry to BackendApiClientService (Vitto). Channel identity resolution MUST retry 3 times with 1s/2s/4s backoff. A failed identity resolution = dropped WhatsApp message.

  2. Add retry to BackendAiClientService (Vitto). Orchestration events and execution outcomes: 2 retries. Learning context: keep at 0 retries (graceful degradation acceptable).

  3. Add retry to VittoClientService (backend-ai-api). Task orchestration: 2 retries with 2s/4s backoff.

  4. Add retry to PlatformApiClientService (backend-ai-api). Platform CRUD queries: 2 retries.

  5. Add Redis caching for channel identity resolution in Vitto. Cache key: channel:identity:{channelType}:{channelId}. TTL: 5 minutes. Eliminates backend-api dependency for repeat messages from same WhatsApp user.

  6. Add Redis caching for user preferences in Vitto. Cache key: user:prefs:{userId}. TTL: 10 minutes.

Implementation Pattern

Create a shared retryWithBackoff() utility in @libs-api/backend-core that wraps RxJS firstValueFrom calls. Pattern: retry N times with exponential backoff, integrate with circuit breaker state (skip retries if circuit is OPEN), log each retry attempt at WARN level.

Acceptance Criteria


Phase 3: AI Module Migration Completion

Priority: High Estimated effort: 2-3 sessions (reduced from 3-4 — S191 completed pricing centralization) Risk: Medium Dependencies: None (can run in parallel with Phases 1-2)

What S191 Already Completed

The coding agent in Session 191 made significant progress on the DRY foundation needed for this phase:

What Still Needs to Be Done

The pricing config is unified, but the storage targets are still split:

Current Dual Modules

Module In backend-api In backend-ai-api Action
AI (text/image/video gen) /api/ai/* (ACTIVE) /ai-api/chat/* (partial) Proxy from backend-api to backend-ai-api
AI Agents /api/ai-agents/* (MIGRATING) /ai-api/agents/* (canonical) Remove from backend-api, add proxy
AI Learning /api/ai/learning/* (MIGRATING) /ai-api/learning/* (canonical) Remove from backend-api, add proxy
Cost Tracking ai_usage + llm_usage + spending_records (3 locations!) Consolidated via AI_MODEL_CAPABILITIES pricing Unify storage to single collection

Tasks

  1. Audit all frontend calls to /api/ai/ endpoints.* Search Angular apps (gograb-space, gograb-admin, gograb-dev, gograb-ai) for API_BASE_URL + '/ai/' patterns. Document every active call.

  2. Create thin proxy controller in backend-api that forwards AI requests to backend-ai-api. Pattern: @Controller('ai') with HttpService forwarding. Maintains backward compatibility while centralizing logic.

  3. Unify cost tracking storage. Create a shared LLMUsageTrackingService in @libs-api/backend-core that writes to a single llm_usage collection. Both LlmCostTrackerService (backend-ai-api) and CostTrackerService (Vitto) should use this shared service. The pricing calculation already uses AI_MODEL_CAPABILITIES in both — only the write target differs. Vitto's CostTrackerService has richer features (per-user budgets, context window recommendations) that should be preserved; the shared service handles only the write-path unification.

  4. Migrate historical data. Write a migration script that copies ai_usage records from gograb-api and spending_records from vitto-mind into the canonical llm_usage collection in ai-agents. Run in dry-run mode first.

  5. Remove AiAgentsModule from backend-api after verifying no direct dependencies. Keep proxy controller.

  6. Remove AiLearningModule from backend-api after same verification.

  7. Merge ai-context database into ai-agents. Once backend-api AI modules are proxied, update AI_CONNECTION_NAMES.CONTEXT references to point to ai-agents.

Risk Mitigation


Phase 4: BullMQ Event-Driven Alerting

Priority: High Estimated effort: 1-2 sessions Risk: Low Dependencies: None (can run in parallel with Phase 1)

Problem Statement

Vitto's proactive monitoring runs on 30-minute heartbeats. Between heartbeats, failed tasks, stalled jobs, and unresponsive tools go undetected. BullMQ already emits completed, failed, and stalled events but these are only used for logging.

Current BullMQ Config

Tasks

  1. Create EventAlertService in backend-vitto-api/src/app/engine/. Subscribe to BullMQ QueueEvents for failed, stalled, error events. On failure of critical tasks (WhatsApp message, security audit, proactive check), trigger immediate notification.

  2. Add Slack/WhatsApp notification channel for critical failures. Use existing connectivity module's ChannelGatewayService to send alerts to a configured admin channel.

  3. Create stall detection. If a job has been active for >5 minutes without progress events, emit stall warning.

  4. Reduce heartbeat interval from 30 minutes to 5 minutes in the proactive module. 30 minutes is too coarse for real-time messaging.

  5. Add metrics endpoint: GET /vitto-api/metrics/queue returning current queue depth, active jobs, failed count (last hour), average processing time. Enables external monitoring.

Acceptance Criteria


Phase 5: Cloudflare Edge Layer

Priority: Medium Estimated effort: 3-4 sessions Risk: Medium Dependencies: Phase 4 (metrics endpoint)

Overview

Deploy two new Cloudflare Workers in front of Vitto. The existing vitto-updater Worker proves the pattern works and the deployment infrastructure (wrangler, deploy scripts) is already in place at deployment/cloudflare/.

Worker 1: vitto-gateway (Webhook Preprocessor)

Purpose: Sit between WhatsApp/Telegram/Slack webhooks and backend-vitto-api. Acknowledge webhooks instantly at the edge (preventing provider retries), deduplicate, and forward to Railway asynchronously.

Endpoints:

Tasks:

  1. Create deployment/cloudflare/vitto-gateway-worker/ with wrangler.toml. Domain: gateway.gograb.space.

  2. Implement Twilio HMAC verification using Web Crypto API. Store TWILIO_AUTH_TOKEN as Worker secret.

  3. Implement message deduplication using Cloudflare KV. Key: sha256(messageId + timestamp). TTL: 5 minutes.

  4. Forward verified payloads to vitto-api.gograb.space/vitto-api/connectivity/webhook/* via fetch(). Use waitUntil() for async forwarding after acknowledgment.

  5. Update Twilio webhook URL from vitto-api.gograb.space to gateway.gograb.space/webhook/whatsapp. Update Telegram bot webhook similarly.

  6. Add Cloudflare DNS CNAME for vitto-gateway subdomain. Create deploy script following vitto-updater pattern.

Rollback: Revert webhook URLs back to direct vitto-api.gograb.space endpoints. Backend webhook handlers remain unchanged.

Worker 2: vitto-pulse (Edge Health Monitor)

Purpose: Run lightweight health checks from the edge every 1 minute. Only wake up Railway backend when something needs attention.

Tasks:

  1. Create deployment/cloudflare/vitto-pulse-worker/ with Cron Trigger at 1-minute intervals.

  2. Check /vitto-api/health and /vitto-api/metrics/queue (from Phase 4) every minute. Store results in KV with 5-minute TTL.

  3. If health check fails 3 consecutive times, send alert to admin Slack/WhatsApp via direct Slack webhook (no backend dependency for alerting about backend failure).

  4. If queue depth exceeds threshold (configurable, default: 50 pending jobs), trigger alert.

  5. Expose GET /status endpoint returning last-known health of all 4 APIs. Single pane of glass for platform health.

Rollback: Disable Cron Trigger in Cloudflare dashboard. Worker is read-only, makes no changes to backend state.


Phase 6: MCP Gateway Enhancement

Priority: Medium Estimated effort: 2 sessions Risk: Low Dependencies: None (can run in parallel with Phase 5)

Problem Statement

All 15 gateways (98 tools) are exposed to every client equally. Cursor users see browser automation tools they'll never use. Cowork users see git protocol tools that are irrelevant. This wastes context window tokens.

Current State

The MCP server already detects platform via env vars (CLAUDE_CODE_AGENT, CURSOR_AGENT, etc.). The gateway-router.ts routes through a centralized handler. The infrastructure to filter per-platform exists but isn't used for tool filtering.

Tasks

  1. Define tool capability tiers in discover-tools.ts. Map each gateway to tiers: core (always), code (Cursor, Claude Code), automation (Cowork, Desktop), intelligence (all), infrastructure (Claude Code only).

  2. Add platform-to-tier mapping in gateway-router.ts. Filter GATEWAY_TOOLS in ListToolsRequest based on detected platform.

  3. Add capability action to session gateway that returns available tools for current platform.

  4. Add dynamic tool loading based on project context. If workspace has package.json, expose code tools. If it has deployment/, expose infrastructure tools.

Tier Mapping

Gateway Claude Code Cursor Cowork Desktop
session Yes Yes Yes Yes
intelligence Yes Yes Yes Yes
outcome Yes Yes Minimal Minimal
code Yes Yes No No
git Yes Yes No No
browser Yes No Yes Yes
desktop Yes Minimal Yes Yes
task Yes No Yes Yes
platform Yes Yes Read-only Read-only
agent Yes Yes Minimal Minimal
stats Yes Yes No No
convention Yes Yes No No
research Yes Yes Yes Yes
computer_use Yes No Yes Yes
skill Yes Yes Yes Yes

Acceptance Criteria


Phase 7: Cleanup and Operational Hardening

Priority: Low Estimated effort: 2 sessions Risk: Low Dependencies: Phase 3 (AI migration)

Tasks

  1. Remove function-bun service from GoGrab Railway project. Accidentally created during domain migration session.

  2. Remove custom domain vitto-api.gograb.space from the WRONG Railway project (standalone Vitto API, project 8d9b4864-25f4-4c4e-b479-f5e49cea4001). Correct domain is on the GoGrab project.

  3. Standardize health check endpoints. All 4 APIs return same JSON schema:

    {
      "status": "ok",
      "uptime": 12345,
      "version": "1.0.0",
      "connections": { "mongodb": "connected", "redis": "connected" },
      "circuitBreakers": { "anthropic": "CLOSED", "openai": "CLOSED" }
    }
    
  4. Add GITHUB_TOKEN rotation reminder. The vitto-updater Worker PAT expires May 27, 2026. Add proactive check that alerts 30 days before expiry.

  5. Consolidate environment variable naming. Standardize to SYSTEM_TOKEN everywhere. Keep BACKEND_API_INTERNAL_TOKEN as deprecated alias.

  6. Document the complete inter-service dependency map in docs/english/Infrastructure/. Include timeout values, retry counts, circuit breaker config, and failure modes for every inter-service call.


Execution Timeline

Week Phase Sessions Risk Blocks
1 Phase 1: Circuit Breakers 2-3 Low None
1-2 Phase 4: BullMQ Event Alerting 1-2 Low None (parallel with Phase 1)
2 Phase 2: Inter-Service Retry + Caching 2 Low Phase 1 (shared resilience lib)
2-3 Phase 3: AI Module Migration 2-3 Medium Frontend audit first (S191 completed pricing DRY)
3 Phase 5: Cloudflare Edge Layer 3-4 Medium Phase 4 (metrics endpoint)
3-4 Phase 6: MCP Gateway Enhancement 2 Low None (parallel with Phase 5)
4 Phase 7: Cleanup + Hardening 2 Low Phase 3 (AI migration)

Parallel Execution

Phases 1 and 4 can run in parallel (different codebases, no overlap). Phases 5 and 6 can run in parallel (Cloudflare Workers vs MCP server). This compresses 7 sequential phases to ~4 weeks.


Verification Protocol

After ALL phases complete, run this checklist:

  1. Health checks: curl all 4 API /health endpoints. Verify standardized JSON format with circuit breaker states.

  2. Circuit breaker test: Set one LLM provider API key to invalid. Verify calls auto-route to fallback within 5 failed attempts.

  3. Retry test: Deploy backend-api while sending a WhatsApp message to Vitto. Verify message processes after backend-api comes back up.

  4. Cache test: Send two WhatsApp messages from same number within 5 minutes. Verify second resolves identity from Redis cache (no HTTP call to backend-api).

  5. Edge test: Send webhook to vitto-gateway Worker. Verify instant 200 acknowledgment at edge and delayed processing at Railway.

  6. Monitoring test: Kill a BullMQ job mid-execution. Verify admin receives alert within 5 minutes (not 30).

  7. Cost tracking: Make one LLM call from each API. Verify all appear in single llm_usage collection. Verify pricing matches AI_MODEL_CAPABILITIES values (S191 centralized config).

  8. MCP test: Connect from Cursor and Claude Code. Verify Cursor sees fewer tools than Claude Code.


Git Protocol Reminder

All implementation work MUST follow SAGP v1.2: