Skip to main content

Separate Web Console from Admin Control Plane

Context

Prism's administrative functionality has two distinct concerns:

  1. Control Plane (prism-admin): gRPC-based control plane for:

    • Raft-based HA cluster coordination
    • Namespace management state machine
    • Proxy/launcher registration and heartbeats
    • Backend provisioning and configuration
    • Serves as the source of truth for cluster state
  2. Web Console (planned): Browser-based UI for:

    • Human-friendly namespace management
    • Session monitoring dashboards
    • Backend health visualization
    • Operational tasks through web forms

Current State:

  • prism-admin is implemented as a gRPC control plane server (RFC-038)
  • No web console implementation exists yet
  • Two RFCs propose different web console approaches:
    • ADR-028: FastAPI + gRPC-Web + Vanilla JavaScript (Python-based)
    • RFC-036: templ + htmx + Gin (Go-based)

Problem: Combining the web console with the control plane in a single process would:

  • Mix critical cluster coordination logic with UI rendering
  • Create tight coupling between control plane and UI technology choices
  • Make independent scaling difficult (UI vs control plane load)
  • Increase control plane container size and startup time
  • Complicate testing (need to test both control plane and UI together)

Decision

Create prism-web-console as a separate Go process that communicates with prism-admin via gRPC.

Architecture

┌─────────────────────────────────────────────────┐
│ Browser │
│ ┌──────────────────────────────────────────┐ │
│ │ Web UI (HTML/CSS/JS) │ │
│ │ - Namespace management │ │
│ │ - Session monitoring │ │
│ │ - Health dashboard │ │
│ └────────────┬─────────────────────────────┘ │
│ │ HTTP (htmx AJAX) │
└───────────────┼─────────────────────────────────┘

┌───────────────▼─────────────────────────────────┐
│ prism-web-console (:8000) │
│ - Gin HTTP server │
│ - templ templates (HTML rendering) │
│ - htmx integration │
│ - OIDC authentication │
│ └────────────┬────────────────────────────────┘│
│ │ gRPC │
└───────────────┼──────────────────────────────────┘

┌───────────────▼──────────────────────────────────┐
│ prism-admin (:8981) │
│ - Control Plane gRPC API │
│ - Raft consensus cluster │
│ - Namespace state machine │
│ - Proxy/Launcher coordination │
└──────────────────────────────────────────────────┘

Implementation Approach

Follow RFC-036's Go-based stack:

  • Gin: HTTP routing and middleware
  • templ: Type-safe HTML templates (to be added)
  • htmx: HTML over the wire interactions
  • Tailwind CSS: Styling

Rationale

Why Separate Processes?

  1. Separation of Concerns

    • Control plane focuses on cluster coordination and state management
    • Web console focuses on UI rendering and user interactions
    • Each can evolve independently
  2. Independent Scaling

    • Control plane scales based on cluster size and request rate
    • Web console scales based on number of admin users
    • Different resource requirements (CPU, memory)
  3. Technology Flexibility

    • Control plane stays lean and focused on gRPC
    • Web console can use web-optimized frameworks without affecting control plane
    • Can switch UI framework without touching control plane code
  4. Simpler Testing

    • Control plane tests focus on gRPC APIs and Raft logic
    • Web console tests focus on UI rendering and user flows
    • No need to mock UI components in control plane tests
  5. Container Efficiency

    • Control plane: ~15-20MB (Go binary only)
    • Web console: ~20-30MB (Go binary + static assets)
    • Combined would be 35-50MB but with mixed responsibilities

Why Go-based (RFC-036) over Python-based (ADR-028)?

  1. Language Consolidation

    • All admin tooling in Go: prismctl, prism-admin, prism-web-console
    • No Python runtime dependency for web console
    • Shared code and patterns across admin tools
  2. Type Safety

    • templ provides compile-time template validation
    • Go's type system catches errors early
    • Better IDE support and refactoring
  3. Performance

    • 20-40x faster startup (<50ms vs 1-2s)
    • Lower memory usage (20-30MB vs 50-100MB)
    • Better suited for container environments
  4. Deployment

    • Smaller container images (15-20MB vs 100-150MB)
    • Single binary deployment
    • No Python package dependency management

Consequences

Positive

  • Clean Architecture: Clear separation between control plane and UI
  • Independent Evolution: Control plane and UI can be versioned separately
  • Flexible Scaling: Scale control plane and UI independently based on load
  • Simplified Testing: Each component has focused test suites
  • Language Consistency: All admin tooling in Go
  • Container Efficiency: Smaller, faster containers

Negative

  • Additional Process: Need to deploy and manage two processes instead of one
  • Network Hop: Web console → control plane adds latency (mitigated by local gRPC)
  • Configuration: Need to configure web console endpoint separately

Neutral

  • Deployment Options: Can still deploy both in same pod/VM if desired
  • Development: Requires running two processes during development (docker-compose simplifies this)

Implementation Plan

Phase 1: Foundation (Week 1)

  • ✅ Create cmd/prism-web-console directory structure
  • ✅ Implement basic Gin server with health check
  • ✅ Add Makefile auto-discovery support
  • ✅ Create placeholder handlers and middleware
  • ✅ Document separation decision (this ADR)

Phase 2: Core UI (Week 2-3)

  • Add templ template support
  • Implement namespace CRUD handlers
  • Connect to prism-admin gRPC API
  • Add htmx interactions
  • Basic styling with Tailwind CSS

Phase 3: Authentication (Week 4)

  • Integrate OIDC authentication (RFC-010)
  • Session management
  • JWT validation middleware
  • Login/logout flows

Phase 4: Advanced Features (Week 5-6)

  • Session monitoring dashboard
  • Backend health visualization
  • Real-time updates (htmx polling or WebSocket)
  • User testing and feedback

Phase 5: Production Readiness (Week 7-8)

  • Security audit
  • Load testing
  • Documentation
  • Docker deployment
  • CI/CD integration

Deployment Examples

Docker Compose

services:
prism-admin:
image: prism/admin:latest
ports:
- "8981:8981" # gRPC Control Plane
environment:
- PRISM_CLUSTER_NODE_ID=1
- PRISM_CLUSTER_PEERS=1=localhost:8990

prism-web-console:
image: prism/web-console:latest
ports:
- "8000:8000" # HTTP Web UI
environment:
- PRISM_ADMIN_ENDPOINT=prism-admin:8981
- PRISM_LOGGING_LEVEL=info
depends_on:
- prism-admin

Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
name: prism-web-console
spec:
replicas: 2 # Scale UI independently
template:
spec:
containers:
- name: web-console
image: prism/web-console:latest
ports:
- containerPort: 8000
env:
- name: PRISM_ADMIN_ENDPOINT
value: prism-admin:8981
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: prism-admin
spec:
replicas: 3 # Raft cluster
template:
spec:
containers:
- name: admin
image: prism/admin:latest
ports:
- containerPort: 8981 # gRPC
- containerPort: 8990 # Raft

Alternatives Considered

Alternative 1: Embed Web Console in prism-admin

Pros:

  • Single process to deploy
  • No network hop between UI and control plane

Cons:

  • Mixed responsibilities (control plane + UI)
  • Cannot scale independently
  • Tighter coupling between control plane and UI
  • Larger container image

Decision: Rejected - Separation provides better architecture

Alternative 2: Python-based Web Console (ADR-028)

Pros:

  • FastAPI is mature and well-documented
  • gRPC-Web enables browser communication

Cons:

  • Language fragmentation (Python + Go)
  • Larger container (100-150MB vs 15-20MB)
  • Slower startup (1-2s vs <50ms)
  • Different testing infrastructure

Decision: Rejected in favor of Go-based approach (RFC-036)

Alternative 3: Static SPA (React/Vue/Angular)

Pros:

  • Rich client-side interactions
  • Large ecosystem and tooling

Cons:

  • Build complexity
  • Large bundle size (100KB+)
  • Overkill for admin CRUD operations
  • Requires gRPC-Web proxy

Decision: Rejected - htmx provides sufficient interactivity for admin UI

References

  • RFC-036: Minimalist Web Framework for Prism Admin UI
  • RFC-038: Admin Leader Election with Hashicorp Raft
  • ADR-028: Admin UI with FastAPI and gRPC-Web
  • ADR-027: Admin API via gRPC
  • RFC-010: Admin Protocol with OIDC Authentication

Revision History

  • 2025-10-22: Initial ADR for web console separation decision