Work Package: Backend Core

Channel: #ai-dev-gateway-backend
Session: Session 2 (Backend Core)
Namespace: ai-dev-gateway-backend-lab
Estimated Duration: 5-7 days
Dependencies: API Contract v1.0.0


Objective

Build the backend orchestration that manages OpenCode sessions, BMAD routing, workspace initialization, deployment, and testing.


Deliverables

1. FastAPI Service Structure

File: services/gateway/src/main.py

  • FastAPI app initialization
  • API router configuration
  • Middleware (CORS, auth, logging)
  • Health check endpoint
  • OpenAPI spec generation

Endpoints:

  • GET /health - Health check
  • GET /docs - OpenAPI documentation

2. Session Manager

File: services/gateway/src/core/session_manager.py

  • Create session (with workspace init)
  • Get session status
  • List active sessions
  • Send message to session
  • Close/pause session

OpenCode Integration:

class SessionManager:
    async def create_session(self, category, project, repos):
        # 1. Initialize workspace: task builder:init BUILDER_NAME=... REPOS=...
        # 2. Start OpenCode session: opencode serve --session <id>
        # 3. Store session state in git
        
    async def send_message(self, session_id, message):
        # opencode run --session <id> "message"
        
    async def capture_output(self, session_id):
        # Stream output from OpenCode
        # Parse for questions, progress, etc.

3. BMAD Router

File: services/gateway/src/core/bmad_router.py

  • Analyze task complexity
  • Generate routing suggestion with confidence
  • Route to architect/PM/builder/party-mode
  • Handle routing confirmation

Complexity Analysis:

class BMADRouter:
    def analyze_complexity(self, task_title, task_description):
        # Analyze for:
        # - Security keywords → architect
        # - Business logic → PM
        # - Simple implementation → builder
        # - Complex/unknown → party-mode
        
        return {
            "suggested": "architect",
            "confidence": 0.85,
            "reason": "Security-sensitive feature..."
        }

4. Workspace Manager

File: services/gateway/src/core/workspace_manager.py

  • Initialize workspace with git worktrees
  • Invoke task builder:init BUILDER_NAME=... REPOS=...
  • Create workspace directory structure
  • Store workspace metadata

Directory Structure:

.builders/
└── {category}-{project}/
    ├── repos/
    │   ├── repo1/  # git worktree
    │   └── repo2/  # git worktree
    ├── .session-state.yaml
    └── arch-decisions.md

5. Deployment Orchestrator

File: services/gateway/src/deployment/orchestrator.py

  • Generate deployment plan
  • Request confirmation via webhook
  • Execute deployment on confirmation
  • Stream progress via SSE
  • Run tests after deployment

Deployment Flow:

class DeploymentOrchestrator:
    async def request_deployment(self, session_id, branch):
        # 1. Generate deployment plan
        # 2. Send webhook to Slack for confirmation
        # 3. Wait for confirmation
        
    async def execute_deployment(self, deployment_id):
        # 1. Create namespace
        # 2. Create ConfigMaps/PVCs
        # 3. Apply kustomize
        # 4. Setup ingress
        # 5. Wait for pods ready
        # 6. Run tests
        # 7. Stream all progress via SSE

6. Namespace Manager

File: services/gateway/src/deployment/namespace_manager.py

  • Create namespace per builder
  • Setup RBAC
  • Delete namespace (with lifecycle options)
  • List active namespaces

K8s Operations:

class NamespaceManager:
    async def create_namespace(self, project_id):
        namespace = f"{project_id}-lab"
        # kubectl create namespace {namespace}
        # Apply RBAC
        
    async def delete_namespace(self, namespace, after_days=None):
        # Immediate or scheduled deletion

7. Manifest Manager

File: services/gateway/src/deployment/manifest_manager.py

  • Create ConfigMaps from code files
  • Create PVCs for larger files
  • Generate kustomize overlays
  • Apply manifests with kubectl

Fast Deployment:

class ManifestManager:
    async def deploy_code_via_configmap(self, namespace, code_files):
        # Small files → ConfigMap
        # Large files → PVC
        # Mount in pods
        # Use uv/camel-jbang to run

8. Ingress Manager

File: services/gateway/src/deployment/ingress_manager.py

  • Create ingress for namespace
  • Setup domain: <project>.builder.lab.ctoaas.co
  • Configure TLS (cert-manager)
  • Return lab URL

9. Test Orchestrator

File: services/gateway/src/deployment/test_orchestrator.py

  • Run unit tests (pytest from session)
  • Run integration tests (against lab URL)
  • Run acceptance tests (critical flows)
  • Aggregate and format results

Test Execution:

class TestOrchestrator:
    async def run_all_tests(self, session_id, lab_url):
        unit = await self.run_unit_tests(session_id)
        integration = await self.run_integration_tests(session_id, lab_url)
        acceptance = await self.run_acceptance_tests(session_id, lab_url)
        
        return {
            "unit": unit,
            "integration": integration,
            "acceptance": acceptance,
            "all_passing": all([unit.passed, integration.passed, acceptance.passed])
        }

10. OpenCode Bridge

File: services/gateway/src/integrations/opencode_bridge.py

  • Spawn OpenCode sessions
  • Send messages to sessions
  • Capture and parse output
  • Detect questions and progress

OpenCode CLI Integration:

class OpenCodeBridge:
    async def spawn_session(self, session_id, workspace_path):
        # opencode serve --session {session_id} --project {workspace_path}
        
    async def send_message(self, session_id, message):
        # opencode run --session {session_id} "{message}"
        
    async def capture_output(self, session_id):
        # Stream and parse output
        # Detect: questions, progress, completions

11. Webhook Client

File: services/gateway/src/integrations/webhook_client.py

  • Send events to Slack webhook
  • Retry logic
  • Event queue for reliability

Events:

  • Progress updates
  • Questions
  • Deployment ready
  • Test results

12. SSE Endpoint for Deployment Progress

File: services/gateway/src/api/deployments.py

  • SSE stream for deployment progress
  • Event types: progress, step_complete, test_results, complete
  • Handle client disconnections
@router.get("/api/deployments/{deployment_id}/progress")
async def deployment_progress(deployment_id: str):
    async def event_stream():
        async for event in deployment_service.stream_progress(deployment_id):
            yield {
                "event": event.type,
                "data": json.dumps(event.data)
            }
    
    return EventSourceResponse(event_stream())

Testing Strategy

Unit Tests

Directory: services/gateway/tests/core/

  • Session manager (mock OpenCode CLI)
  • BMAD router (complexity analysis)
  • Workspace initialization (mock subprocess)
  • Deployment orchestrator (mock K8s)

Integration Tests

Directory: services/gateway/tests/integration/

  • Full workflow with mock Slack
  • Deployment pipeline with mock K8s
  • Test orchestrator with mock pytest

Mocking: Use api-contract.md to create mock Slack webhook.


Development Environment

Local Setup

# Install dependencies
cd repos/ai-dev/services/gateway
uv venv
source .venv/bin/activate
uv pip install -r requirements.txt
 
# Run locally
uvicorn src.main:app --reload --port 8000
 
# Access docs
open http://localhost:8000/docs

Mock Slack Webhook

File: services/gateway/tests/mocks/slack_mock.py

from fastapi import FastAPI
 
app = FastAPI()
 
@app.post("/webhook/slack")
async def mock_slack_webhook(payload):
    print(f"Received event: {payload['event_type']}")
    return {"ok": True}

Dependencies

Python Packages

fastapi==0.110.0
uvicorn==0.27.0
kubernetes==28.1.0
pyyaml==6.0.1
httpx==0.26.0
pydantic==2.5.0
sse-starlette==1.8.2

External Dependencies

  • kubectl (for K8s operations)
  • OpenCode CLI (installed)
  • Git (for workspace management)

Configuration

File: services/gateway/config/backend.yaml

opencode:
  cli_path: /usr/local/bin/opencode
  sessions_dir: /workspace/.opencode-sessions
 
kubernetes:
  namespace_prefix: builder
  service_account: gateway-sa
  ingress_domain: builder.lab.ctoaas.co
 
deployment:
  default_strategy: configmap_pvc
  max_configmap_size: 1048576  # 1 MB
  test_timeout: 300  # 5 minutes
 
workspace:
  base_path: /workspace/.builders
  taskfile_path: /workspace/Taskfile.yaml
 
webhooks:
  slack_url: ${SLACK_WEBHOOK_URL}
  retry_attempts: 3
  retry_delay: 1000  # ms

Acceptance Criteria

  • Session creation initializes workspace correctly
  • OpenCode sessions spawn and accept messages
  • BMAD routing provides accurate suggestions
  • Deployment creates namespace and applies manifests
  • ConfigMap/PVC strategy works for fast deployment
  • Ingress creates accessible URLs
  • Test orchestrator runs all test types
  • SSE streams deployment progress correctly
  • Webhook events send to Slack
  • All contract endpoints implemented
  • Unit tests: 80%+ coverage
  • Integration tests: All workflows covered

K8s Setup Required

Service Account

apiVersion: v1
kind: ServiceAccount
metadata:
  name: gateway-sa
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: gateway-role
rules:
- apiGroups: [""]
  resources: ["namespaces", "pods", "services", "configmaps", "persistentvolumeclaims"]
  verbs: ["create", "get", "list", "delete", "watch"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["create", "get", "list", "delete", "watch"]
- apiGroups: ["networking.k8s.io"]
  resources: ["ingresses"]
  verbs: ["create", "get", "list", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: gateway-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: gateway-role
subjects:
- kind: ServiceAccount
  name: gateway-sa
  namespace: default

Notes

  • Contract Compliance: All endpoints must match api-contract.md
  • OpenCode CLI: Ensure OpenCode is available and sessions work
  • K8s Access: Service needs proper RBAC to create namespaces
  • Fast Deployment: Prioritize ConfigMap/PVC over image builds

Handoff to Slack Team

When ready to integrate:

  1. Deploy backend API to test environment
  2. Provide API URL to Slack team
  3. Configure webhook URL for Slack events
  4. Run contract tests together
  5. Integration testing in shared environment