This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
2026-03-01 14:44:55 +00:00
2026-03-01 12:40:15 +00:00
2026-03-01 14:44:55 +00:00
2026-02-28 19:41:59 +00:00
2026-03-01 12:40:15 +00:00
2026-03-01 12:40:15 +00:00
2026-03-01 14:44:55 +00:00
2026-03-01 12:40:15 +00:00
2026-02-19 15:03:20 +00:00
2026-03-01 14:44:55 +00:00
2026-02-25 21:38:49 +00:00
2026-02-26 15:59:26 +00:00
2026-02-23 01:57:28 +00:00
2026-03-01 14:44:55 +00:00
2026-02-28 11:58:27 +00:00
2026-02-03 21:28:18 +00:00
2026-02-19 15:03:20 +00:00
2026-03-01 12:40:15 +00:00
2026-03-01 14:44:55 +00:00

Chat Switchboard

A self-hosted AI chat application for enterprise and government environments. Unified interface for multiple AI providers with admin controls, team management, and security features.

Quick Start

# Clone and start
git clone <repo-url> && cd chat-switchboard
docker compose up -d

# Access at http://localhost:3000
# Default admin: admin / admin

Features

  • Multi-Provider: Anthropic, OpenAI, OpenRouter, Venice AI — with BYOK support
  • Projects: Group related conversations, KBs, and notes into workspaces with scope-aware visibility
  • Team Management: Roles (admin/user) for vertical permissions, Teams for horizontal visibility
  • Personas: Preset configurations (model + system prompt + parameters) at global, team, or personal scope
  • Model Catalog: Three-state visibility (enabled/disabled/team-only) with admin controls
  • Message Trees: Edit and regenerate with full conversation forking — navigate sibling branches
  • Notes: Markdown notes with full-text search, folders, and tags
  • Extensions: Browser extension system with custom renderers, tool bridge, and self-contained styling
    • Built-in: Mermaid diagrams, KaTeX math, CSV tables, diff viewer, JS sandbox, regex tester
  • Server Tools: Calculator and datetime tools (auto-registered, zero config)
  • Audit Log: All admin operations logged with actor, action, and resource details
  • Security: JWT + refresh tokens, AES-256-GCM API key encryption, optional mTLS, optional OIDC/Keycloak, environment classification banners
  • Airgapped: Local vendor files (marked.js, DOMPurify, KaTeX, mermaid.js), no CDN required
  • Mobile: Responsive design, PWA manifest
  • Real-time: WebSocket event bus for tool bridge, live updates
  • Notifications: In-app notification bell with unread badge, per-type email delivery (SMTP), user preference controls, admin SMTP configuration
  • Multi-model: @mention routing for multiple AI models per channel, fan-out completions, model attribution

Architecture

┌─────────────┐     ┌──────────────────────────────┐
│   Browser    │────▶│ nginx (port 80)              │
│  (vanilla JS)│◀────│  ├─ /api/* → Go backend:8080 │
└─────────────┘     │  ├─ /ws   → WebSocket proxy  │
                    │  └─ /*    → static files      │
                    └──────────────────────────────┘
                              │
                    ┌─────────▼─────────┐
                    │  Go Backend        │
                    │  ├─ handlers/      │
                    │  ├─ store/postgres/ │
                    │  ├─ store/sqlite/  │
                    │  ├─ providers/     │
                    │  └─ capabilities/  │
                    └─────────┬─────────┘
                              │
                    ┌─────────▼─────────┐
                    │ PostgreSQL 16  or  │
                    │ SQLite (embedded)  │
                    └───────────────────┘

Go backend (vanilla, no framework beyond Gin) with a store layer abstracting all database access. Dual-driver architecture: store/postgres for production deployments, store/sqlite for single-user, edge, and development scenarios — selected at startup via DB_DRIVER. Providers package handles LLM API calls. Capabilities package resolves model features from catalog data, known model tables, and heuristic inference. Server tools (calculator, datetime) auto-register via init(). EventBus + WebSocket hub routes tool calls between backend and browser extensions.

Frontend is vanilla JavaScript — no build step, no bundler. 15 files organized by domain: api.js (HTTP client), app.js (state + init), chat.js (send, regen, edit, branch), events.js (event bus + WebSocket), extensions.js (loader, registry, renderer pipeline, tool bridge), ui-core.js (DOM rendering + streaming), ui-format.js (markdown, code blocks), ui-primitives.js (shared components), ui-settings.js / ui-admin.js (settings and admin panels), notes.js, tokens.js, debug.js, settings-handlers.js, admin-handlers.js.

Configuration

All configuration via environment variables. See server/.env.example for the full list.

Variable Default Description
PORT 8080 Backend listen port
BASE_PATH URL prefix (e.g. /chat)
DB_DRIVER postgres Database backend: postgres or sqlite
DATABASE_URL SQLite: path to database file (e.g. /data/switchboard.db)
DB_HOST localhost PostgreSQL host (ignored when DB_DRIVER=sqlite)
DB_NAME chat_switchboard Database name (ignored when DB_DRIVER=sqlite)
JWT_SECRET (required) Token signing key
SWITCHBOARD_ADMIN_USERNAME Bootstrap admin username
SWITCHBOARD_ADMIN_PASSWORD Bootstrap admin password
ENCRYPTION_KEY AES key for API key encryption (required if encrypted keys exist)
SEED_USERS Dev/test only: user:pass:role,user2:pass2:role2
ENVIRONMENT development Environment name: development, test, or production. Auto-sets Gin release mode in production.
GIN_MODE (auto) Gin framework mode: debug, test, or release. Auto-derived from ENVIRONMENT if not set.
STORAGE_BACKEND (auto) pvc or s3. Auto-detects PVC if not set.
STORAGE_PATH /data/storage PVC mount point (also scratch dir for S3 extraction)
S3_ENDPOINT S3 endpoint (e.g. http://minio:9000, required for S3)
S3_BUCKET S3 bucket name (must exist, required for S3)
S3_ACCESS_KEY S3 access key ID
S3_SECRET_KEY S3 secret access key
S3_REGION us-east-1 S3 region
S3_PREFIX Optional key prefix within bucket
S3_FORCE_PATH_STYLE true Path-style URLs (required for MinIO, Ceph)

Deployment

Three Docker images support different scenarios:

Image Dockerfile Use Case
Unified Dockerfile Dev, docker-compose, single-node
Backend server/Dockerfile K8s — scale API pods independently
Frontend Dockerfile.frontend K8s — scale FE pods independently

Docker Compose (development — unified image)

docker compose up -d              # start all services
docker compose up -d --build      # rebuild after code changes
docker compose --profile dev up   # include Adminer DB UI

Kubernetes (split images)

Build and push both images:

docker build -f server/Dockerfile -t your-registry/switchboard-api:0.11.0 server/
docker build -f Dockerfile.frontend -t your-registry/switchboard-fe:0.11.0 .

Backend deployment:

containers:
  - name: api
    image: your-registry/switchboard-api:0.11.0
    ports:
      - containerPort: 8080
    env:
      - name: DB_HOST
        value: "postgres-service"
      - name: BASE_PATH
        value: "/chat"      # must match ingress path
      - name: JWT_SECRET
        valueFrom:
          secretKeyRef:
            name: switchboard-secrets
            key: jwt-secret

Frontend deployment:

containers:
  - name: frontend
    image: your-registry/switchboard-fe:0.11.0
    ports:
      - containerPort: 80
    env:
      - name: BASE_PATH
        value: "/chat"      # injected into index.html at startup
    volumeMounts:
      - name: branding
        mountPath: /branding
        readOnly: true       # optional: custom logo, colors

Ingress routes /api/* and /ws to the backend Service, everything else to the frontend Service. The frontend entrypoint generates the nginx config dynamically based on BASE_PATH.

Path-Based Routing

Set BASE_PATH=/chat to serve the application under a subpath. The frontend reads window.__BASE__ injected at container startup, and all API calls are prefixed automatically.

Airgapped / Disconnected

The Docker build bakes in marked.js, DOMPurify, and KaTeX (JS + CSS + fonts) from npm during the vendor stage. Mermaid.js loads dynamically from local vendor with CDN fallback. No CDN calls at runtime in airgapped deployments. The src/vendor/ directory contains local copies as fallback for development without Docker.

Database

PostgreSQL (default)

PostgreSQL 16+ recommended. The pgcrypto and vector (pgvector) extensions are used for UUID generation and vector similarity search respectively.

SQLite (single-user / edge / dev)

Set DB_DRIVER=sqlite and DATABASE_URL=/path/to/switchboard.db to run with an embedded SQLite database. No external dependencies — the binary is self-contained (pure Go, no CGO). The SQLite backend has full feature parity with Postgres including knowledge base vector search, which uses app-level cosine similarity computed in Go rather than pgvector.

# Minimal single-binary startup
DB_DRIVER=sqlite DATABASE_URL=./data/switchboard.db JWT_SECRET=changeme ./switchboard

SQLite is best suited for single-user workstations, edge deployments, air-gapped laptops, and local development. For multi-user production with concurrent writes, use PostgreSQL.

Schema Management

The Go backend auto-migrates on startup using files in server/database/migrations/. For manual operations:

# Bootstrap database (superuser, creates role + DB)
scripts/db-bootstrap.sh

# Manual migration (usually not needed)
scripts/db-migrate.sh

# Validate schema
scripts/db-validate.sh

Key Tables (v0.19)

Table Purpose
users Accounts with role, avatar, settings, encrypted vault (UEK)
provider_configs API provider configurations (scope: global/team/personal)
model_catalog Synced model list with capabilities, visibility, and type
personas Model presets (scope: global/team/personal)
projects Workspaces grouping channels, KBs, and notes (scope: personal/team/global)
project_channels Ordered channel-to-project membership (UNIQUE channel_id)
project_knowledge_bases KB-to-project binding with auto_search flag
project_notes Note-to-project association
channels Conversations with type (direct/group/channel), optional project_id
messages Message tree with parent_id for forking, tool_calls JSONB
teams / team_members Organizational units
notes Markdown notes with full-text search
knowledge_bases / kb_documents / kb_chunks RAG pipeline with pgvector embeddings
extensions / extension_user_settings Browser extension registry and per-user config
usage_log / model_pricing Token usage tracking and cost calculation
audit_log Admin action audit trail
user_model_settings Per-user model visibility and sort preferences

API

All endpoints under /api/v1/. Authentication via Authorization: Bearer <token> header.

Auth

  • POST /auth/register — Register (if allow_registration policy is true)
  • POST /auth/login — Login, returns access + refresh tokens
  • POST /auth/refresh — Refresh access token
  • POST /auth/logout — Revoke refresh token

Channels & Messages

  • GET/POST /channels — List/create conversations
  • GET/PUT/DELETE /channels/:id — Channel CRUD
  • GET/POST /channels/:id/messages — Message list/create
  • POST /chat/completions — Stream AI completions (SSE)
  • POST /channels/:id/messages/:msgId/edit — Edit and fork
  • POST /channels/:id/messages/:msgId/regenerate — Regenerate response

Models

  • GET /models/enabled — Models available to the user (global + team + personal)
  • GET/PUT /models/preferences — User model visibility settings

Personal Providers (BYOK)

  • GET/POST /api-configs — User's personal provider configs
  • GET/PUT/DELETE /api-configs/:id — Provider CRUD
  • POST /api-configs/:id/models/fetch — Refresh models from provider API
  • GET /api-configs/:id/models — List models for a personal provider

Teams

  • GET /teams — Teams the user belongs to
  • GET/POST /teams/:id/providers — Team provider management (team admins)
  • GET/POST /teams/:id/presets — Team preset management (team admins)

Projects

  • GET/POST /projects — List and create projects
  • GET/PUT/DELETE /projects/:id — Project CRUD (owner-only delete)
  • POST/DELETE /projects/:id/channels/:channelId — Add/remove channel
  • GET /projects/:id/channels — List project channels
  • PUT /projects/:id/channels/reorder — Reorder channels
  • POST/DELETE /projects/:id/knowledge-bases/:kbId — Bind/unbind KB
  • POST/DELETE /projects/:id/notes/:noteId — Bind/unbind note

Admin

  • GET/POST /admin/users — User management
  • GET/PUT /admin/settings/:key — Global settings and policies
  • GET/POST /admin/configs — Global provider configs
  • GET/POST /admin/models/fetch — Model catalog sync
  • GET/PUT /admin/roles/:role — Model role configuration
  • GET /admin/usage — Usage dashboard
  • GET /admin/audit — Audit log
  • GET/POST/PUT/DELETE /admin/extensions — Extension management

Extensions

  • GET /extensions?tier=browser — List enabled browser extensions
  • GET /extensions/:id/assets/*path — Serve extension assets (public, no auth)

WebSocket

  • GET /ws?token=<jwt> — EventBus WebSocket for real-time events and tool bridge

Development

# Backend (requires Go 1.22+)
cd server
cp .env.example .env   # edit with your DB credentials
go run .

# Frontend (just serve static files)
# Use any HTTP server pointed at src/
python3 -m http.server 3000 --directory src

License

Proprietary. All rights reserved.

Description
No description provided
Readme Apache-2.0 23 MiB
v0.9.9 Latest
2026-04-03 20:11:58 +00:00
Languages
Go 52.1%
JavaScript 34.6%
CSS 5.5%
Shell 3.8%
HTML 2%
Other 1.9%