21 KiB
🗺️ Chat Switchboard — Roadmap
See also:
- ARCHITECTURE.md — Core services design (Notes, KBs, Tasks, Channels, Embeddings)
- EXTENSIONS.md — Extension system spec (Browser/Starlark/Sidecar tiers, tools, surfaces)
Versioning (pre-1.0): 0.<major>.<minor> — hotfixes use quad: 0.x.y.z
No compatibility guarantees before 1.0. Post-1.0: major = long-lived (break nothing),
minor = add features (deprecate, don't remove), patch = fix something.
Current State: v0.7.4
✅ Done
Backend (Go)
- PostgreSQL schema + auto-migrations (go:embed, startup)
- JWT auth with refresh token rotation
- Unified channel model — chats→channels, "everything is a channel"
- Channel CRUD + message persistence (
/api/v1/channels) - Message tree (
parent_id) with linear backfill - Participant tracking (
participant_type/participant_idon messages) channel_members+channel_modelstables (schema foundation)channel_cursorsfor branch tracking (schema foundation)- Folders + Projects tables for organization
- Environment banner system (global_settings, admin presets, position control)
- Streaming completion proxy (OpenAI + Anthropic + Venice + OpenRouter)
- Per-user + global API config management
- Admin endpoints (users, providers, models, settings, stats)
- Admin bootstrap from env vars (K8s secret → upsert on every restart)
- Registration with pending state (admin approval workflow)
- Registration default state setting (active / pending)
- User providers toggle (admin can restrict to global-only providers)
- Bulk model enable/disable
- Public settings endpoint (non-admin users read safe subset)
- Rate limiting, error middleware, request logging
- Health check endpoint (includes schema_version)
- EventBus with WebSocket hub (rooms, JWT auth, heartbeat, reconnection)
- Provider capability system (known models, heuristic detection, resolution chain)
- Dynamic max_tokens resolution
- User + admin provider model listing with capabilities
- Model presets (named wrappers: global/personal scope, system prompt, temp, max_tokens)
- Preset unwrap in completion handler (transparent to provider)
- Tool framework: registry, type system, execution loop (tool→result→model)
- Note tools: note_create, note_search, note_update, note_list
- Notes API: CRUD, full-text search (tsvector), folder listing
- Provider tool calling: OpenAI + Anthropic function calling in request/response/stream
- Message tree: edit creates sibling, regenerate creates sibling, cursor tracking
- Avatar system: user + preset avatars, server-side resize to 128×128 PNG
Frontend (Vanilla JS)
- Professional splash page (split-panel hero + tabbed auth)
- Split "New Chat" button with dropdown (Group Chat, Channel — coming soon)
- Environment banner system (CSS custom props + JS init from settings)
- Collapsible sidebar with time-grouped chat history
- User menu flyout (Settings, Admin, Debug, Sign Out)
- Model selector with capability badges (output, context, tools, vision, thinking)
- Settings modal with tabs (General, Providers, Models)
- Admin modal with tabs (Users, Providers, Models, Settings, Stats)
- Admin settings: registration, user providers, banner config with presets
- Pending user badge + approve workflow in admin Users tab
- Streaming SSE display with smart scroll
- Full markdown rendering (marked.js + DOMPurify, vendor + CDN fallback)
- Thinking block display (
<think>/<thinking>tags) - Debug modal (console intercept, network log, state inspector)
- EventBus client with exponential backoff + max retries
- Export (Markdown, JSON, Text)
- Model selector with preset grouping (⚡ Presets optgroup)
- Admin Presets tab (create, toggle, delete global presets)
- Preset-aware completion flow (preset_id sent to backend)
- Custom dropdown for model selector (full CSS control, dark theme)
- Admin edit buttons for providers and presets (inline form reuse)
- Appearance settings tab (UI scale, message font size)
- Mobile responsive layout (hamburger menu, sidebar overlay, dvh)
- Model/preset name in message headers (replaces generic "Assistant")
- Notes modal: list/detail views, folder sidebar, create/edit/delete, search
- Message editing + forking: inline edit, regen, branch navigation ‹ 1/2 ›
- Conversation path: active-path context assembly, cursor-aware
- White-label branding: volume mount, org name, logo, favicon, accent color, pills
- Avatar system: user profile upload, preset avatars, avatar in messages/sidebar/dropdown
- Chat search / filter in sidebar (real-time title filtering)
- Command palette (Ctrl+K) with fuzzy search, chat jumping, keyboard nav
- PWA manifest + service worker (offline shell, install prompt)
CI/CD (Gitea Actions)
- Three-env pipeline (dev/test/prod)
- Dev: upgrade test → schema validate → wipe → fresh install test
- Backend auto-migrates on startup (no CI migration step)
- Admin secret sync (Gitea secrets → K8s secret → env vars)
- Shared PG safety (_dev suffix guard on wipe)
- Post-deploy schema verification via /api/v1/health
Architecture Design
- ARCHITECTURE.md: core services spec (13 sections)
- EXTENSIONS.md: three-tier extension system spec
- "Everything is a channel" — unified model with type:'direct'
- Message tree (parent_id for conversation forking)
- Auth strategy design (builtin/mTLS/OIDC)
0.7.0 — Custom Models / Presets ✅
Named wrappers around base models with bundled configuration. Admins create org-wide presets, users create personal ones (if user providers are enabled).
model_presetstable: name, base_model_id, system_prompt, temperature, max_tokens, tools_enabled (jsonb), created_by, scope (global/team/personal), team_id (nullable, for future team scoping), is_shared- Permission gating: personal presets require user_providers_enabled
- Admin preset management UI (create, edit, delete org-wide presets)
- User preset management UI in Settings (personal presets)
- Presets appear as first-class entries in model selector ("Code Reviewer (GPT-4o)", "Research Assistant (Claude Opus)")
- Completion handler unwraps preset → base model + config overrides
0.7.x — Branding + Polish ✅
White-label support and UX improvements that exploit existing infrastructure.
Branding
- Admin branding settings in global_settings: org name, tagline, accent color
/branding/volume mount (K8s ConfigMap, optional) for favicon, logo- Splash page reads branding config on load, falls back to Switchboard defaults
- CSS accent color override from branding settings
Profile Pictures / Avatars
avatar_urlcolumn onuserstable (already existed, now wired)avatarcolumn onmodel_presets(migration 015)- Avatar upload in user Settings → Profile section (server-side resize to 128×128)
- Admin/user preset avatar upload endpoint
avatarHTML()helper: returns<img>if avatar set, emoji fallback otherwise- Avatar displayed in message headers, stream, typing indicator, sidebar user area
Message Editing + Forking
- Edit message → creates sibling (uses existing parent_id tree)
- Regenerate → creates sibling model response
- Branch indicator at fork points (← 1/2 →)
- Context assembly follows active path, not full channel history
UX Polish
- Chat search / filter in sidebar
- UI preferences: font size + UI scale (Appearance tab, localStorage)
- Mobile responsive: hamburger menu, sidebar overlay, auto-collapse
- Model name in message headers (preset name or model ID, not "Assistant")
- Keyboard shortcuts (Ctrl+K command palette)
- PWA manifest + offline shell + install prompt
0.8.0 — Teams + Onboarding
The missing middle tier: scoped administration without system-admin access.
Schema
teamstable: id, name, description, created_byteam_memberstable: team_id, user_id, role ('admin' | 'member')- Add
team_id(nullable) to: model_presets, channels, notes - Team admin role: scoped per-team, not system-wide (one person can be admin of Team A, member of Team B)
Onboarding
- Registration approval → assign role + team(s) during approval (upgrade from current binary approve → assign-and-activate)
- System admin creates teams + assigns first team admin
- Team admin self-manages: add/remove members (RequireTeamAdmin middleware, scoped /teams/:teamId routes)
- Team admin: create team presets (Settings → Teams tab, self-service UI)
- Team admin: manage team channels, view team usage
Private Provider Policy
is_privateflag on provider configs (marks local/self-hosted endpoints)require_private_providerspolicy per team (via teams.settings JSONB)- Completion handler enforces policy — team members restricted to private providers
- Enables HIPAA/compliance posture: provable data boundary per team
0.8.x — Audit + Usage Tracking
Required for enterprise and compliance. Cheap to build, expensive to retrofit.
Audit Log
audit_logtable: actor_id, action, resource_type, resource_id, metadata (jsonb), ip_address, timestamp- Every mutating handler inserts audit entry (user CRUD, team CRUD, member management, presets, auth)
- Admin audit viewer (filter by action, resource type, paginated)
- Team admin sees audit entries scoped to their team
Model Visibility (0.8.3)
- Three-state visibility: enabled (all users) / team (preset-building only) / disabled
- Migration replaces
is_enabledboolean withvisibilityvarchar - Admin model list: 3-state cycle button, bulk set all to any state
GET /teams/:teamId/modelsreturns enabled+team models for preset builders- User-facing
ListEnabledModelsstrictly filtersvisibility = 'enabled'
Preset Form Unification + UX (0.8.4)
- Single
renderPresetForm(options)function shared across admin/team contexts — parameterized: showAvatar, showProviderConfig, onSubmit, onCancel - Remove icon field from preset forms (not rendered anywhere meaningful)
- Team admin preset form includes avatar upload (reuse admin component)
- Hide Providers tab in Settings when
user_providers_enabledis false - Settings Models tab: only show
visibility='enabled'base models (team-only models must not leak to user model list; presets filtered out) - Model provenance labels: badge indicating global vs personal source — same model_id from both sources shown separately (different API keys)
- Admin presets list: show created_by name + team name for attribution (e.g. "Code Reviewer · 👥 Engineering · by sarah")
User Presets + Model Filtering (0.8.5)
- Users can create personal presets from any enabled base model (removed user_providers_enabled gate; uses shared renderPresetForm)
- Settings Models tab reworked as "My Models": toggle to hide/show base models from selector, "My Presets" section with create/delete
user_model_preferencestable: user_id, model_id, hidden boolean — lightweight filter, not access control- Hidden models filtered from main model selector dropdown
- User personal provider models: simple enable/disable toggle (same visibility toggle — hide from selector)
Team Providers (0.8.6)
team_idcolumn onapi_configs(nullable FK, indexed)- Team admins manage team-scoped provider configs (add/remove API keys, toggle active, same UI as personal providers)
allow_team_providerscheck: global_settings + team.settings JSONB- Team provider models available in team preset builder (ListAvailableModels) — grouped by source: Global Models / Team Provider Models (optgroup)
- Team provider models NOT exposed directly in model selector — team members access team models ONLY through curated presets — keeps model selector clean, avoids visibility confusion
- Three-tier provider hierarchy: global → team (presets only) → personal
- ListConfigs excludes team-scoped providers (team_id IS NULL filter)
Usage / Cost Tracking
- Capture from provider responses: prompt_tokens, completion_tokens, cache_creation_tokens, cache_read_tokens
usage_logtable: channel_id, user_id, model_id, provider_id, token counts, timestamp- Model pricing fields on
model_configs: cost_input, cost_output, cost_cache_input, cost_cache_output (per M tokens, nullable, decimal) cost_sourcefield: 'provider' | 'admin' | null — provider APIs populate on model fetch, admin can override, source tracking prevents silent overwrites on re-fetch- Cost calculated at query time (join usage × pricing) — never store computed cost; pricing changes and historical token counts should recalculate against current rates
- Per-user and per-team usage stats in admin panel
- Team admins see usage for their team scope
0.9.0 — Tool Execution + Notes ✅ (pulled into 0.7.x)
Pulled forward and shipped ahead of schedule. See TOOLS_IMPL.md and FORKING_IMPL.md.
Tool Framework
- Tool calling pipeline in completion handler (OpenAI + Anthropic)
- Tool registry (built-in + future plugin tools)
- Tool execution loop: model requests tool → backend executes → result fed back
- Tool permission model (which tools enabled per preset/channel)
Notes
notestable: title, content, folder, tags, source_channel_id, full-text search- Notes CRUD endpoints + search
note_create,note_update,note_search,note_listtools- Full-text search (PostgreSQL
tsvector+ts_rank+ts_headline) - Notes UI: modal with list/detail views, folder sidebar, Markdown editor
- Team-scoped notes (awaits 0.8.0 teams)
Conversation Forking UI
- Edit-and-resubmit creates siblings (tree structure)
- Branch indicator ← 1/2 → at fork points
- Context assembly follows active path
0.9.x — Context Management
Usability before compaction exists — long conversations shouldn't silently fail.
- Token counting on outbound requests (estimate before sending)
- Truncation strategy (sliding window or drop oldest, configurable)
- "Conversation is getting long" warning in UI
- Manual "summarize and continue" action (user-triggered pre-compaction)
- Groundwork for automated compaction in 0.14.0
0.10.0 — Web Search + URL Fetch
First external tools, using the tool framework shipped in 0.7.x.
web_searchtool: search provider abstraction (DuckDuckGo, SearXNG, Brave)url_fetchtool: retrieve and extract content from URLs- Sidecar or direct HTTP from backend (configurable)
- Results injected into context
- Paired with Notes: "research X and save findings to my notes"
0.11.0 — File Handling + Vision
File input into chat — table stakes for serious use. Blobs live in object storage, metadata and search indexes live in PostgreSQL.
Storage Backend Abstraction
- S3-compatible API as primary interface (MinIO, Ceph RGW, AWS S3, GCS — anything with S3 API)
- Local PVC as zero-config fallback (single-node / dev)
- Admin config: storage backend selection, endpoint, credentials, bucket/path, per-file and total size limits
- Reused by 0.13.0 (KB documents) and 0.14.0 (compaction snapshots)
Metadata + Search Index (PostgreSQL)
attachmentstable (metadata only, never blobs): id, message_id, channel_id, team_id, filename, mime_type, size_bytes, storage_backend ('s3' | 'pvc'), storage_path, checksum_sha256, uploaded_by, created_at, search_text (tsvector, nullable)- Text extraction on upload (PDF, DOCX, TXT, MD → tsvector)
- Full-text search across attachment content
- Access control via JOIN: attachments → channels → team_members
Chat Integration
- Image/file upload in chat messages
- Multimodal message assembly for vision-capable models
- Document preview in chat (images inline, files as download links)
- Paste-to-upload (clipboard image support)
Note: media generation (image gen, video models) is a separate concern — those are tool-use actions that depend on the tool framework and produce attachments as output. Tracked under Future.
0.12.0 — @mention Routing + Multi-model
The channel schema already supports multiple models. This phase adds the routing logic.
- @mention parsing in messages (users and AI models)
- Resolve mentions against
channel_models - Multi-model channels: fire completions per mentioned model
- "Add a model" UI per channel
- Enables: editor mode, second opinions, cross-model conversations
0.13.0 — Embeddings + Knowledge Bases
- Embedding pipeline: chunking (recursive, semantic), generation (OpenAI, local)
pgvectorstorage and similarity searchknowledge_basestable: name, description, team_id (nullable), created_by- KB document storage via 0.11.0 storage backend (same S3/PVC abstraction)
- KB CRUD endpoints + admin UI
kb_searchtool (uses existing tool framework)- Context injection in completion flow
- Notes get embedded too (once pipeline exists)
- Team admins manage team KBs (permission layer from 0.8.0)
- Per-channel KB toggle
0.14.0 — Compaction
Replaces the manual 0.9.x context management with automated background processing.
- Auto-compaction service: background job that calls an LLM to summarize
- Channel-scoped: triggers when channel exceeds context threshold
- Compaction summaries stored as system messages in the channel
- Configurable: per-channel opt-in/out, summary model selection
- Admin controls for resource limits
0.15.0 — Smart Model Routing
Rules-based routing engine — not ML, just policy.
- Admin defines routing policies: "cheapest model with required capabilities", "prefer private providers, fallback to cloud", "for this team, use X; for that team, use Y"
- Model capability system already exists — routing is policy on top
- Fallback chains: primary provider down → next provider with same model
- Cost-aware: factor pricing into routing decisions
- Latency-aware: track response times per provider, prefer faster
0.16.0 — Tasks / Autonomous Agents
The capstone: everything below it combined into autonomous workflows.
- Scheduler + task runner
task_createtool- Creates
type: 'service'channels with no human members - Depends on: completion handler, tool execution, notes, web search
- Admin controls for resource limits, execution budgets
0.17.0 — Auth Strategy (mTLS/OIDC) + Full RBAC
Enterprise auth modes and fine-grained permissions on top of the teams foundation.
AUTH_MODEenv var:builtin|mtls|oidc- All three resolve to the same internal user model
auth_source+external_idcolumns on users table- mTLS: header trust, auto-provision from cert DN
- OIDC: Keycloak/Okta token validation, claim extraction, role mapping
- WebSocket auth per mode
- Per-source auto-activate policy: auto_activate (bool), default_team, default_role
- Fine-grained permissions: model access, KB write, task create, admin delegation, token budgets per user/team
- SSO/SAML (may fold in or follow as 0.17.x)
Future (post-1.0 candidates)
Items that are real but don't yet have a version assignment. Any of these could pull left based on need.
Desktop + Mobile
- Desktop app (Tauri)
- Full PWA with offline capability
- Mobile-optimized layouts
Generation + Media
- Image generation tools (DALL-E, Stable Diffusion endpoints)
- Video model integration
- Audio/TTS tools
Data + Portability
- Bulk export/import (account data, conversations, settings)
- ChatGPT/other tool import
- GDPR-style "download my data"
- Backup/restore CronJob manifests + operational docs
Platform
- Rate limiting per user/team/tier (token budgets)
- Provider health monitoring + key rotation
- Multi-tenant SaaS mode
- Workflow builder (visual DAG for chaining models + tools)
- Plugin/extension marketplace
- Live collaboration (typing indicators, presence, co-editing)
- Virtual scroll for long conversations
Extension / Plugin Architecture
Deferred to post-1.0. The tool execution framework (0.7.x) provides the internal hook points. A formal plugin API, manifest format, and marketplace are tracked in the dedicated design documents:
- EXTENSIONS.md — Three-tier extension system spec (Browser JS, Starlark sandbox, Sidecar containers)
- ARCHITECTURE.md — Core backend services that extensions build on