# Roadmap — Chat Switchboard **See also:** - [ARCHITECTURE.md](ARCHITECTURE.md) — Core services design, store layer, scope model - [EXTENSIONS.md](EXTENSIONS.md) — Extension system spec (Browser/Starlark/Sidecar tiers, manifests, browser tool bridge, surfaces/modes, model roles) - [CHANGELOG.md](../CHANGELOG.md) — Detailed release notes for all completed versions **Versioning (pre-1.0):** `0..` — hotfixes use quad: `0.x.y.z` No compatibility guarantees before 1.0. --- ## Dependency Graph Features have real dependencies. This ordering respects them. ``` v0.9.x Stability + Quick UX Wins ✅ │ v0.9.3 Content Visibility & Block Controls ✅ │ v0.9.4 API Key Encryption + Vault ✅ │ v0.10.0 Model Roles (utility + embedding) ✅ + Usage Tracking │ v0.10.2 Summarize & Continue ✅ │ v0.10.3 Frontend Refactor ✅ │ v0.10.4 Model Type Pipeline + Role Fixes ✅ │ v0.10.5 UI Primitives + Extension Surfaces ✅ │ v0.11.0 Extension Foundation (browser tier) ✅ │ ┌───────┴──────────────┐ │ │ v0.12.0 File Handling v0.13.0 Admin Panel + Vision ✅ Refactor (fullscreen) ✅ │ │ │ v0.13.1 Web Search │ + url_fetch ✅ │ │ └───────┬──────────────┘ │ v0.14.0 Knowledge Bases ✅ (embedding role + file storage + pgvector) │ v0.15.0 Compaction ✅ (utility role + background job) │ v0.15.1 Context Recall Tools ✅ (attachment_recall, conversation_search) │ ┌───────┴──────────────┐ │ │ v0.16.0 User Groups v0.17.0 Persona-KB Binding + Resource Grants ✅ + Enterprise KB Mode │ + QOL / UX Wins └───────┬──────────────┘ │ ┌───────┴──────────────┐ │ │ v0.17.1 SQLite Backend ✅ v0.17.2 CodeMirror 6 ✅ v0.17.3 Notes Graph + Wikilinks ✅ (dual DB) (editor bundle, chat │ input, ext editor) └───────┬──────────────┘ │ v0.18.0 Memory ✅ (user + persona scopes, review pipeline) │ v0.18.1 Side Panel Architecture ✅ (single-slot, ctx.ui primitives, mermaid refactor) │ v0.19.0 Projects / Workspaces ✅ (project groups, KB resolution, drag-drop sidebar) │ v0.19.1 Active Project + System Prompt + Detail Panel ✅ │ v0.19.2 Project Persona Default + Archive + Reorder ✅ │ v0.20.0 Notifications + @mention Routing + Multi-model ✅ │ v0.21.0 Workspace Storage Primitive ✅ │ ┌───────┴──────────────┐ │ │ v0.21.1 Workspace ✅ v0.21.3 Surface Infra ✅ Tools + Bindings + REPL (parallel) │ │ v0.21.2 Workspace ✅ v0.21.5 Editor Surface ✅ Indexing + Search (Development Mode) │ │ v0.21.4 Git ✅ v0.21.6 Editor Surface ✅ Integration + Document Output └───────┬──────────────┘ │ v0.21.7 Bugfix: scanJSON driver buffer aliasing ✅ │ v0.22.0 Provider Health + Capability Overrides ✅ + Workspace Pane Refactor (FE) │ v0.22.1 Provider Extensions (declarative config) ✅ │ v0.22.2 Routing Policies + Fallback Chains ✅ │ v0.22.3 Provider Admin UI + Deferred Polish ✅ │ v0.22.4 Provider Health UX + Project Files + Export ✅ │ v0.22.5 Surfaces + Go Templates + Admin Bug Fixes ✅ │ v0.22.6 Split Deployment Fix + CI Timeout + Code Pruning ✅ │ v0.22.7 Surface Prototypes (Theme + ChatPane + Splash) ✅ │ v0.22.8 Surface Integration (Wire into existing JS) ✅ │ v0.23.0 @mention Routing + Persona Handles + Proxy ✅ │ v0.23.1 Multi-User Navigation + Conversation Taxonomy ✅ │ v0.23.2 Multi-User Polish + Channel Lifecycle ✅ │ v0.24.0 Auth Abstraction + User Identity ✅ │ ├── v0.24.1 mTLS + OIDC Providers (parallel) ✅ │ │ │ └── v0.24.3 Anonymous Sessions ✅ │ └── v0.24.2 Fine-Grained Permissions (parallel) ✅ │ v0.25.0 Dynamic Surfaces + Context-Aware Tools (pane system, manifest-driven surfaces, editor rebuild, tool predicates, persona tool grants) │ v0.26.0 Workflow Engine (team-owned staged processes, human + AI collab, visitor intake, assignment queue) │ v0.27.0 Tasks / Autonomous Agents (service channels, scheduler, unattended execution) ``` --- ## Completed Releases > Full details for all completed versions are in [CHANGELOG.md](../CHANGELOG.md). ### ✅ v0.9.0 — Schema Consolidation + BYOK 21 migrations → single schema, store layer abstraction, persona-as-trust-boundary, BYOK with auto-fetch, composite model IDs, journey integration tests. ### ✅ v0.9.1 — Capability Architecture + Docs Removed static known model table. Resolution chain: catalog → heuristic only. Frontend relies solely on backend for capabilities. Docs rewrite. ### ✅ v0.9.2 — Quick UX Wins + Hardening Collapsible code blocks, HTML preview, token counter, context warning, proxy interception detection, environment injection, team admin audit scoping. ### ✅ v0.9.3 — Content Visibility & Block Controls Button-driven code collapse, always-rendered thinking blocks, tool call persistence in history, Notes panel → unified side panel, streaming refactor (`streamWithToolLoop`), regenerate fix. ### ✅ v0.9.4 — API Key Encryption + Vault Two-tier AES-256-GCM: env-var key for global/team, per-user UEK (Argon2id) for personal BYOK. `server/crypto/` package. Migration 003. Startup backfill. DOMPurify strict allowlist (XSS fix). ### ✅ v0.10.0 — Model Roles + Usage Tracking + Vault Debt Named role slots (utility, embedding) with fallback. `Provider.Embed()` interface. `usage_log` + `model_pricing` tables. Streaming token capture. Vault debt: UEK re-wrap on password change, destruction on admin reset. ### ✅ v0.10.1 — Polish + UX Admin system prompt injection, Personas tab, Team Management modal extraction, preview pane enhancements, code download, personal usage scoped to BYOK. ### ✅ v0.10.2 — Summarize & Continue + Role Cleanup User-triggered conversation compaction via utility role. Summary as tree node with boundary metadata. BYOK role overrides (personal → team → global). Utility rate limiting. Generation role removed. ### ✅ v0.10.3 — Frontend Refactor 2 monolith files → 13 domain-scoped files (~544 lines avg). Zero features, no function renames. Vanilla JS, no build step. See [REFACTOR-0.10.3.md](REFACTOR-0.10.3.md). ### ✅ v0.10.4 — Model Type Pipeline + Role Fixes `model_type` (chat/embedding/image) captured end-to-end from provider API through catalog to frontend. Role dropdowns filter by type. ### ✅ v0.10.5 — UI Primitives + Extension Surfaces Shared `Providers`/`Roles` registries, 6 consolidated render primitives, `showConfirm()` replacing native dialogs, `.popup-menu` CSS primitive. Removed ~400 lines of duplication. ### ✅ v0.11.0 — Extension Foundation (Browser Tier) Full extension lifecycle: manifest, loader, scoped `ctx.*` API, browser tool bridge via WebSocket. Custom renderer pipeline. 2 server tools (calculator, datetime), 6 built-in browser extensions (Mermaid, KaTeX, CSV, Diff, JS Sandbox, Regex). See [EXTENSIONS.md](EXTENSIONS.md). ### ✅ v0.12.0 — File Handling + Vision S3/PVC storage backend, image/file upload (📎, drag-drop, paste), multimodal message assembly, text extraction pipeline (PDF/DOCX/XLSX/PPTX/ODT/RTF), vault CLI (`rekey`/`status`), per-chat model persistence. ### ✅ v0.13.0 — Admin Panel Refactor 12-tab modal → fullscreen admin panel. 4 categories (People, AI, System, Monitoring) × section sidebar. URL-based routing, responsive, banner-aware. CSS design token cleanup. ### ✅ v0.13.1 — Web Search + URL Fetch `web_search` + `url_fetch` tools. Search provider abstraction (DuckDuckGo, SearXNG). Tool categories with per-tool toggle UI in chat bar. ### ✅ v0.14.0 — Knowledge Bases RAG: upload → chunk → embed (pgvector) → `kb_search` tool. Channel KB toggle. Team/personal KB scopes. Notes semantic search. Admin panel KB management. See [DESIGN-0.14.0.md](DESIGN-0.14.0.md). ### ✅ v0.15.0 — Compaction Background scanner with configurable thresholds. Automatic summarization via utility role. Per-channel opt-in/out. Context budget guard rail (80% ceiling). ### ✅ v0.15.1 — Context Recall Tools `attachment_recall` (list + read, channel-scoped), `conversation_search` (full-text via `plainto_tsquery`). Token estimator attachment awareness. ### ✅ v0.16.0 — User Groups + Resource Grants Groups (global/team-scoped ACLs) decoupled from team membership. Three-way resource grants (team_only/global/groups) for Personas and KBs. Grant picker UI. Schema consolidation: 9 migrations → single `001_v016_schema.sql`. ### ✅ v0.17.0 — Persona-KB Binding + Enterprise KB Mode + QOL Personas as KB gateways. `persona_knowledge_bases` binding, auto-search mode, enterprise KB discoverability controls. Team admin workflow. `HandleFromName()` auto-generation. Store layer sole DB interface. ### ✅ v0.17.1 — SQLite Backend Dual-database support (Postgres + SQLite). `database/compat.go` dialect abstraction, `database.Q()` query rewriting, SQLite-specific migration set. Single-user / dev deployment mode. See [v0171-sqlite-backend.md](v0171-sqlite-backend.md). ### ✅ v0.17.2 — CodeMirror 6 Integration CM6 replaces textarea: `codeEditor()` + `chatInput()` + `noteEditor()` factories. 20+ languages bundled, Vim/Emacs keybindings, `[[wikilink]]` autocomplete. esbuild bundle. See [DESIGN-CM6.md](DESIGN-CM6.md). ### ✅ v0.17.3 — Notes Graph + Wikilinks `[[wikilink]]` bi-directional linking, `note_links` junction table, Canvas force-directed graph visualization. Daily notes, folder tree, markdown preview. See [DESIGN-0.17.3.md](archive/DESIGN-0.17.3.md). ### ✅ v0.18.0 — Memory (User + Persona Scopes) User + persona memory extraction pipeline. Background summarization via utility role. Memory injection into system prompt. Admin review panel. `memories` + `persona_memories` tables. ### ✅ v0.18.1 — Side Panel Architecture Single-slot panel system. Panel registry with independent open/close. Dual-view mode (two panels side-by-side). `ctx.ui.openPreview()`, keyboard shortcuts. Extension UI participation. Mobile swipe. ### ✅ v0.19.0 — Projects / Workspaces Project container: channels, KBs, personas, system prompt, team scope. `projects` + `project_channels` tables. Drag-drop sidebar. ### ✅ v0.19.1 — Active Project + System Prompt + Detail Panel Active project context in chat. Project system prompt prepend. Detail panel (info, members, KBs, channels). Channel-project binding UI. ### ✅ v0.19.2 — Project Persona Default + Archive + Reorder Project-level default persona. Archive/unarchive. Drag-to-reorder sidebar items. Project settings persistence. ### ✅ v0.20.0 — Notifications + @mention Routing + Multi-model Bell dropdown notifications. `@mention` resolves to persona handles and model IDs. Multi-model chat. `notifications` table, WebSocket push, `channel_participants` table. AI-to-AI chaining, context poisoning prevention (Anthropic rewrite, OpenAI Name field). ### ✅ v0.21.x — Workspace Platform + Extension Surfaces Seven-release series. v0.21.0: workspace storage primitive. v0.21.1: workspace tools + channel/project binding. v0.21.2: workspace indexing + semantic search. v0.21.3: surface infrastructure + REPL. v0.21.4: git integration (clone/push/pull/commit, credential management). v0.21.5: editor surface (IDE-like: file tree + CM6 + chat pane). v0.21.6: article surface + document output pipeline + hash router. v0.21.7: scanJSON driver buffer aliasing bugfix. See [DESIGN-0.21.0.md](archive/DESIGN-0.21.0.md). ### ✅ v0.22.0 — Provider Health + Capability Overrides `provider_health` accumulator (5-min windows, 1h retention). Health badges. `capability_overrides` table. Two-tier capability resolution (catalog sync → heuristic → optional admin override). Provider-scoped capabilities. ### ✅ v0.22.1 — Provider Extensions (Declarative Config) YAML-based provider type registration. Settings schema per provider type. Venice.ai provider. Provider-specific parameter pass-through. Extended thinking support (Anthropic). ### ✅ v0.22.2 — Routing Policies + Fallback Chains `routing_policies` table. Three policy types: `model_preference`, `provider_failover`, `cost_optimize`. Channel-bindable. Failover execution in completion handler. Health-aware skip. ### ✅ v0.22.3 — Provider Admin UI + Deferred Polish Provider health dashboard, capability override editor, routing policy builder. Model catalog sync trigger. Dynamic provider config form. ### ✅ v0.22.4 — Provider Health UX + Project Files + Export Health dots in model selector. Project files tab (channel file aggregation). Conversation export (JSON, Markdown). Bulk file download. ### ✅ v0.22.5 — Surfaces + Go Templates + Admin Bug Fixes Go `html/template` engine with `//go:embed`. Six surfaces (chat, editor, notes, settings, admin, login). Reusable components (model-select, team-select, file-upload). `AuthOrRedirect` middleware. CSP nonces. ### ✅ v0.22.6 — Split Deployment Fix + CI Timeout + Code Pruning `BACKEND_URL` fail-fast, ~2,430 lines OBE code removed (router.js, surfaces.js, SPA shell). Extension surfaces intentionally broken pending pane refactor (→ v0.25.0). Service worker BUILD_HASH cache key. ### ✅ v0.22.7 — Surface Prototypes (Theme + ChatPane + Splash) `theme.css` with CSS custom properties. `ChatPane.create()` factory pattern. Login/splash redesign. Toast stack, badges, icon buttons, avatar upload, confirm dialog. Settings feature gates (BYOK, Personas). ### ✅ v0.22.8 — Surface Integration (Wire into Existing JS) `ChatPane.primary` bridge from server-rendered mount points. Theme wired to settings appearance. Admin hybrid section loaders. Naming cleanup: preset → persona, APIConfigID → ProviderConfigID. --- ## Technical Debt + Deferred Items Items deferred from completed releases that remain outstanding. Organized by domain. Pull into a version when the surrounding work makes them a natural addition. **Surfaces + Editor (→ v0.25.0 natural home)** - [ ] Extension loader: surfaces from manifest.json (was v0.21.3) - [ ] Editor drag-drop file reorder (was v0.21.5) - [ ] Article drag-to-reorder outline sections (was v0.21.6) - [ ] Article-specific AI tools: suggest_outline, expand_section, check_citations (was v0.21.6) - [ ] PDF export via pandoc (was v0.21.6) - [ ] Mobile: mode selector collapses to hamburger/bottom nav (was v0.21.3) **Workspace + Git** - [ ] Workspace settings UI: git config section in channel/project settings (was v0.21.4) - [ ] User settings: git credentials management UI (was v0.21.4) - [ ] `.gitignore` respect in workspace indexing (was v0.21.4) - [ ] Integration tests: clone, commit, push/pull cycle — requires git binary in CI (was v0.21.4) **Provider Health + Routing** - [ ] `RecordOutcome` for web_search and url_fetch (search provider health tracking) - [ ] Rate limit tracking per provider config (requests/minute counter in health accumulator) - [ ] Auto-disable: mark provider inactive when `down` for N consecutive health windows - [ ] `capability_match` policy type ("cheapest model with tool_calling") - [ ] Latency-aware routing: track response time percentiles, prefer faster providers - [ ] Cost-aware routing with budget ceiling per request - [ ] New provider types registrable via config file (OpenAI-compatible + custom schema) - [ ] Provider profile editor: key-value config per provider type, preview of effective settings - [ ] Fallback chain visualizer: drag-to-reorder provider priority per model family --- ## ✅ v0.23.0 — @mention Routing + Persona Handles + Proxy @mention routing works in any chat against the full model catalog and persona registry. No roster, groups, or participant setup required — just type `@handle` or `@model-id` and send. **@mention Resolution** - [x] `resolveMention()`: direct DB lookup — persona handle (exact/prefix) → model catalog (exact/prefix) - [x] Autocomplete popup on `@` in any chat — all enabled models + personas - [x] Handle field on personas: auto-generated from name, unique, editable - [x] @mention pill rendering in message content (accent-colored, code-aware) - [x] Context boundaries: persona→plain and persona→persona style isolation - [x] Participant list injection: system prompt tells LLM who it can @mention **AI-to-AI Chaining** - [x] `chainIfMentioned()`: uses `resolveMention()` on assistant response content - [x] Self-mention blocked, depth capped at 5 - [x] WebSocket delivery (`message.created` + typing indicators) - [x] Same resolution path for user→LLM and LLM→LLM routing **Provider Proxy** - [x] `proxy_mode` (system/direct/custom) + `proxy_url` on `provider_configs` - [x] All four providers use `cfg.Client()` with mode-aware HTTP transport - [x] Bad custom URL falls back to system (not direct) — safe for mandatory-proxy environments **Channel Infrastructure** - [x] `channel_participants` table with polymorphic types and roles - [x] `channel_models` partial indexes: persona entries keyed per-persona, raw models per-provider - [x] Per-provider model preferences (composite keys in `user_model_settings`) - [x] `persona_groups` + `persona_group_members` tables (schema ready, CRUD not yet wired) --- ## ✅ v0.23.1 — Multi-User Navigation + Conversation Taxonomy Conversation type taxonomy (direct/dm/group/channel/workflow), three-section sidebar (Projects → Channels → Chats), folder system for chats, DM plumbing, channel configuration with `ai_mode`, presence heartbeat, and the unified active conversation model. Depends on: @mention routing (v0.23.0), WebSocket infrastructure (exists). See [DESIGN-0_23_1.md](DESIGN-0_23_1.md) for the full spec. **Conversation Types:** - [x] Five-type taxonomy: direct (1:1 AI), dm (human-to-human), group (multi-participant), channel (named persistent), workflow (staged, deferred) - [x] Channel type constraint extended: `dm`, `channel` added to `type` CHECK - [x] `ai_mode` column on channels: `auto` | `mention_only` | `off` - [x] `ai_mode` guard in completion handler — `off` returns 403, `mention_only` without @mention delivers without AI - [x] `topic` column on channels for header display **Sidebar Architecture:** - [x] Three collapsible sections: Projects → Channels → Chats - [x] `renderChannelsSection()` with # / person icons, unread badges, online dots - [x] Channel items: context menu (rename, set topic, delete), ⋯ hover button - [x] Section collapse/expand state in localStorage **Folder System:** - [x] `chat_folders` table, CRUD handler (`handlers/folders.go`) - [x] Drag chats into/out of folders; folder context menu (rename, delete) - [x] Folder delete modal: "Keep chats" / "Delete chats too" / Cancel - [x] Unfiled drop zone when folders exist **DM Plumbing:** - [x] `resolveMention()` extended to resolve users (exact + prefix on username) - [x] User @mention skips AI, delivers `user.mentioned` WebSocket notification - [x] DM creation flow with user search modal - [x] DM dedup guard — one channel per participant pair **Presence:** - [x] `user_presence` table with heartbeat upsert - [x] `POST /presence/heartbeat` (30s interval), `GET /presence?users=...` (90s threshold) - [x] Presence WebSocket events: `presence.changed` **Channel Participants:** - [x] `channel_participants` CRUD handler, auto-created on channel creation - [x] Persona group CRUD endpoints wired (`persona_groups`, `persona_group_members`) - [x] DM participant auto-creation from `req.Participants` **Migration:** - [x] 016_v023_multiuser: `ai_mode`, `topic`, `user_presence`, channel type extension --- ## ✅ v0.23.2 — Multi-User Polish + Channel Lifecycle Bug fixes, unified active conversation refactor, channel lifecycle (archive/delete), group chat leader routing, `@all` fan-out, message attribution, and deferred surface integration from v0.22.8. Depends on: v0.23.1 sidebar and conversation taxonomy. **Unified Active Conversation:** - [x] `App.activeConversation = { id, type }` replaces `currentChatId` + `currentChannelId` - [x] `setActive(id, type)`, `activeId` getter, `getActiveChat()` helper - [x] Send path, model bar, streaming, session restore all keyed off `activeConversation.id` - [x] Sidebar highlight works across both chat and channel sections **Group Chat + Persona Groups:** - [x] Group leader default response: no @mention in group → leader persona responds - [x] `@all` fan-out: routes to every persona participant, depth-1 only - [x] Participant mutation guards: DMs keep ≥2 humans, groups keep ≥1 persona - [x] "New Group Chat" flow with ad-hoc persona picker **Message Attribution:** - [x] Human sender display: other participants show avatar + display name (not "You") - [x] Persona sender display verified for loaded history in channel context **Channel Lifecycle:** - [x] Archive action via context menu (`is_archived`, `archived_at`) - [x] Delete gated by `channel_retention.mode` (flexible/retain) - [x] Admin purge with `purge_after_days` floor - [x] Retention config keys in `global_config` **Bug Fixes:** - [x] Channel persistence through refresh (resp.channels → resp.data) - [x] Folder drag-and-drop (folderId mapping, drop handlers, unfiled zone) - [x] DM creation 404 → added `GET /users/search` endpoint - [x] Channel ⋯ menu consistency (replaced ✕ with hover ⋯ pattern) - [x] Folder ⋯ button reflow (visibility:hidden instead of display:none) - [x] Unread subquery using `last_read_at` (not migration-017-dependent column) - [x] Settings Models section template wiring - [x] `u.avatar` → `u.avatar_url` in ListMessages JOIN and treepath **Surface Integration (deferred v0.22.8):** - [x] `ChatPane.primary` bridge from server-rendered mount points - [x] Theme save/load cycle wired to settings appearance - [x] Admin hybrid section loaders completed - [x] Settings surface: models toggles, persona CRUD, BYOK, teams **@mention UX:** - [x] Autocomplete includes users alongside personas and models - [x] User mention pill styling (distinct color from persona pills) - [x] `user.mentioned` WebSocket notification with toast **Migration:** - [x] 017_unread: `last_read_message_id` on `channel_participants` --- ## v0.24.0 — Auth Abstraction + User Identity ✅ Auth provider interface decoupling builtin auth from the handler/middleware layer. User model extended with `auth_source`, `external_id`, `handle`. @mention resolution upgraded to use handles. Zero behavior change for existing users — builtin mode goes through the new abstraction identically. See [DESIGN-0.24.0.md](DESIGN-0.24.0.md) for the full spec including v0.24.1–v0.24.3 subversions. Depends on: v0.23.0 (channel_participants), v0.16.0 (groups), v0.9.4 (vault). **Auth Provider Interface (`server/auth/`):** - [x] `Provider` interface: `Mode()`, `Authenticate()`, `SupportsRegistration()`, `Register()` - [x] `BuiltinProvider`: extracts login/register from `handlers/auth.go` - [x] `UniqueHandle()`: collision-safe handle generation with `-2`, `-3` suffixes - [x] `ErrorToHTTPStatus()`: maps auth errors to HTTP codes - [x] `ParseMode()`: validates `AUTH_MODE` string with error return **Auth Handler Refactor:** - [x] `AuthHandler` gains `provider auth.Provider` field - [x] `Login()` delegates to `provider.Authenticate()`, then vault unlock + JWT - [x] `Register()` delegates to `provider.Register()`, then vault init + JWT - [x] `generateTokens()` response includes `handle`, `auth_source` - [x] `BootstrapAdmin()` / `SeedUsers()` backfill handles for existing users **User Model Extension:** - [x] `AuthSource` (builtin/mtls/oidc), `ExternalID` (nullable), `Handle` (unique) - [x] All user store queries (PG + SQLite) include three new columns - [x] `GetByHandle()`, `GetByExternalID()` on both store implementations - [x] Unified `scanOneUser` / `scanOne` helpers replace per-method scan blocks **Config + Middleware:** - [x] `AUTH_MODE` env var (default `builtin`) - [x] `main.go` dispatch: builtin wired, mTLS/OIDC fail-fast at startup - [x] Middleware unchanged — JWT validation is auth-mode-agnostic **@mention Resolution:** - [x] `resolveMention()` uses `LOWER(handle)` instead of `LOWER(username)` - [x] `SearchUsers` returns `handle`, filters on handle - [x] Frontend autocomplete matches on handle, uses handle as @mention token **Migration:** - [x] 018_auth_abstraction: `auth_source`, `external_id`, `handle` columns + unique indexes + backfill --- ## v0.24.1 — mTLS + OIDC Providers ✅ Two external auth implementations plugging into v0.24.0's provider interface. Keycloak integration test environment via docker-compose overlay. Depends on: auth abstraction (v0.24.0). See [DESIGN-0.24.0.md](DESIGN-0.24.0.md) §v0.24.1 for full spec. - [x] mTLS provider: trusted header extraction, cert DN parsing, auto-provision - [x] OIDC provider: well-known discovery, JWKS caching, token validation, claim extraction - [x] OIDC authorization code flow: login redirect, code exchange, token handoff via fragment - [x] Split-horizon issuer support (`OIDC_EXTERNAL_ISSUER_URL` for Docker/K8s) - [x] OIDC claim → group mapping (external groups sync to internal groups with `source=oidc`) - [x] Login page adapts by `AUTH_MODE` (form / cert status / SSO button) - [x] Keycloak docker-compose overlay with pre-configured realm (`ci/keycloak-realm.json`) - [x] `QArgs()` dialect adapter: handles Postgres `$N` reuse for SQLite arg expansion - [x] `database.QueryRow/Query/Exec` wrappers with automatic arg expansion - [x] Migration 019: `oidc_auth_state` table, `groups.source` column - [x] Unit tests: mTLS (ParseDN, config), OIDC (discovery, auth URL, mode), QArgs (5 tests) - [x] Regression test: `TestIntegration_ChannelListWithTypeFilter` - [x] SQLite local dev fixes: `_time_format` DSN, store wiring, nginx resolver, extension assets --- ## v0.24.2 — Fine-Grained Permissions Groups become capability carriers. Permission model on top of existing group infrastructure. Depends on: auth abstraction (v0.24.0). Parallel to v0.24.1. See [DESIGN-0.24.0.md](DESIGN-0.24.0.md) §v0.24.2 for full spec. - [x] Permission constants (`domain.action` convention, code-level enum) - [x] `permissions` JSONB column on groups - [x] `ResolvePermissions()`: union of group permissions + Everyone group - [x] `RequirePermission()` middleware - [x] Token budgets: per-group daily/monthly ceilings, enforced in completion handler - [x] Model access control: per-group model allowlists - [x] Admin UI: permission checklist, budget fields, model picker on group edit - [x] Everyone group supersedes `DefaultUserPerms` (seeded in migration, editable in admin) - [x] Migration 020: permissions, budgets, allowed_models on groups --- ## v0.24.3 — Anonymous / Session Participants Unauthenticated visitors for workflow intake channels. Direct prerequisite for v0.26.0 (Workflow Engine). Depends on: mTLS provider (v0.24.1) for cert-based anonymous identity. See [DESIGN-0.24.0.md](DESIGN-0.24.0.md) §v0.24.3 for full spec. - [x] `session_participants` table (channel-scoped, ephemeral token) - [x] `AuthOrSession()` middleware: tries JWT first, falls back to session cookie (cookie-based, no separate session JWT needed) - [x] Capability scoping: session participants limited to their bound channel - [x] mTLS anonymous path: cert fingerprint as stable session identity - [x] `channels.allow_anonymous` flag - [x] Session added as channel participant (`participant_type=session`, `role=visitor`) - [x] Workflow entry page: `GET /w/:id` (Go template, standalone chat UI) - [x] Migration 021: `session_participants` table, `allow_anonymous` column --- ## v0.25.0 — Dynamic Surfaces + Context-Aware Tools Pane-based surface architecture and context-aware tool system. Replaces the "one surface active at a time" model (v0.21.3) with composable multi-pane layouts. Establishes manifest-driven surface registration, component extraction, and the tool predicate system. Editor surface rebuilt as proof-of-concept — eat our own dog food. Depends on: Go template engine (v0.22.5), ChatPane component (v0.22.7), surface integration (v0.22.8). See [DESIGN-SURFACES.md](DESIGN-SURFACES.md) for the layer model. See [DESIGN-0.25.0.md](DESIGN-0.25.0.md) for full spec. **Pane System** - [ ] Pane container: workspace area holds 1+ panes side-by-side (replaces single-surface model) - [ ] Pane lifecycle: create, mount, resize, minimize, destroy — independent of surface lifecycle - [ ] Resizable splits: drag handles between panes, user-resizable, persisted per-user/per-project - [ ] Layout presets: single (default), split-2 (editor+chat), split-3 (tree+editor+chat) - [ ] Default: single Chat pane — zero cognitive overhead, identical to current UX - [ ] Pane registry: named panes with independent state (scroll, selection, open file) **Surface Manifest + Registration** - [ ] Surface manifest schema: `id`, `route`, `title`, `components`, `data_requires`, `script`, `auth` - [ ] Dynamic route generation in page engine from registered surfaces - [ ] Data loader registry: surfaces declare data requirements, engine assembles loaders - [ ] `/s/:slug` route namespace for extension/dynamic surfaces - [ ] Core surfaces (chat, admin, settings, notes) migrated to manifest pattern - [ ] `window.__PAGE_DATA__` injection from declared `data_requires` (existing pattern, formalized) **Component Extraction** - [ ] FileTree: extracted from `editor-mode.js`, standalone component with Go template partial + JS hydration - [ ] CodeEditor: CM6 `codeEditor()` factory formalized as component (already exists, needs instance pattern) - [ ] NoteEditor: extracted from `notes.js`, standalone component - [ ] ModelSelector: extracted from chat surface, reusable across surfaces - [ ] Each component: Go template partial (server shell) + JS class (hydration) + CSS (scoped) **Editor Surface Rebuild (Dog Food)** - [ ] Editor surface rebuilt on pane system: file tree pane + code editor pane + ChatPane (assist) - [ ] Surface manifest declares three panes with resizable splits - [ ] File tree pane: workspace_ls backed, context menu, nested directories, file icons, git status badges - [ ] Code editor pane: CM6 with language detection, tab bar, Ctrl+S save, auto-save on pane switch - [ ] Chat pane: `ChatPane.create()` in assist role — same channel context, workspace-scoped tools - [ ] Proves: multi-pane layout, ChatPane embedding, resizable splits, surface lifecycle - [ ] Replaces broken `editor-mode.js` (48K, dead since v0.22.6 code pruning) **Shared Surface Routes** - [ ] `/s/editor/:wsId` — editor surface via direct URL (replaces hash routing for external links) - [ ] `/s/article/:wsId/:path` — article surface via direct URL - [ ] `/p/:id` — shared project view (server-rendered shell) - [ ] Auth gating: public pages skip auth, authenticated pages require JWT **Context-Aware Tool System** - [ ] `ToolContext` struct: channel type, workspace ID, workflow ID, team ID, persona ID, is_visitor - [ ] `Require` predicate type on Tool interface: `Availability() Require` - [ ] `BaseTool` embed for backward compat (defaults to `AlwaysAvailable`) - [ ] Built-in predicates: `RequireWorkspace`, `RequireWorkflow`, `RequireTeam`, `DenyVisitor`, `All()` - [ ] `tools.AvailableFor(tctx, disabled)` replaces `AllDefinitionsFiltered()` - [ ] Workspace tools: `RequireWorkspace + DenyVisitor` (self-declared, eliminates manual suppression lists) - [ ] Git tools: `RequireWorkspace + DenyVisitor` (same — kills `WorkspaceToolNames()`/`GitToolNames()`) - [ ] `workspace_create` tool: available only when no workspace bound, disappears once one exists - [ ] Memory/notes tools: `DenyVisitor` **Persona Tool Grants (Wire Existing Infrastructure)** - [ ] Completion handler applies `GetToolGrants()` as second-pass allowlist on context-available tools - [ ] Empty grants = inherit all (backward compat). Explicit grants = allowlist only those tools. - [ ] Persona create/edit UI: "Tools" section — multi-select checklist grouped by category - [ ] Version snapshot includes persona tool grants at snapshot time (frozen for running instances) - [ ] No migration needed — `persona_grants` table, `grant_type='tool'`, `GetToolGrants()` already exist **`ExecutionContext` Extension** - [ ] Add `WorkflowID`, `TeamID` fields to `ExecutionContext` (tools/types.go) - [ ] Populated from channel record in completion handler before tool execution --- ## v0.26.0 — Workflow Engine Team-owned, stage-based process execution. The channel is the runtime, personas drive each stage, and the existing tool/notes infrastructure handles structured data collection. Dynamic surfaces (v0.25.0) provide the pane system for visitor chat, team member views, and the workflow builder. See [ARCHITECTURE.md — Workflow Architecture](ARCHITECTURE.md#workflow-architecture-future--v0210) for the conceptual model. Depends on: dynamic surfaces (v0.25.0), multi-participant channels (v0.23.0), anonymous identity (v0.24.3), permissions (v0.24.2). See [DESIGN-0.26.0.md](DESIGN-0.26.0.md) for full spec. **Workflow Definitions** - [ ] `workflows` table: `team_id`, `name`, `slug` (globally unique), `description`, `branding` (JSONB), `entry_mode`, `is_active`, `version` - [ ] `workflow_stages` table: `workflow_id`, `ordinal`, `persona_id`, `assignment_team_id`, `form_template` (JSONB), `auto_transition`, `transition_rules` (JSONB) - [ ] `workflow_versions` table: immutable snapshots (full JSON: definition + stages + persona tool grants) - [ ] Team-admin CRUD: create/edit/delete workflows and stages, reorder stages - [ ] Workflow versioning: edits increment version, active instances continue on creation-time snapshot **Workflow Instances (Channels)** - [ ] Workflow-typed channels: `type='workflow'`, `workflow_id`, `workflow_version`, `current_stage`, `stage_data` (JSONB) - [ ] `workflow_status` enum: `active`, `completed`, `stale`, `cancelled` - [ ] `last_activity_at` tracking for staleness detection - [ ] Entry point: public link generates workflow channel, adds anonymous participant, binds stage 1 persona, auto-creates workspace - [ ] Stage transitions: AI-triggered (`workflow_advance` tool), human-triggered (button), rejection (return to previous stage with reason) - [ ] On transition: swap active persona, notify assignment team, update channel metadata, create channel-scoped note with form data - [ ] Staleness sweep: background job marks idle instances as `stale` (configurable threshold per-workflow) - [ ] Stale instance UX: visitor sees "Continue or Start Over" (start over creates new instance on latest version) **Visitor Experience (Surfaces)** - [ ] Workflow landing page surface: `/w/:slug` — branded page with persona avatar, description, "Start" button - [ ] Visitor chat surface: `/w/:slug/c/:channelId` — purpose-built bubble chat (NOT full ChatPane) - [ ] `workflow-chat.js`: lightweight JS — WebSocket, markdown rendering, typing indicator, stage transition animation - [ ] Branded CSS: accent color from `workflow.branding`, system dark/light mode - [ ] Visitor tool scoping: `DenyVisitor` predicates + persona tool grants restrict tool set - [ ] Dynamic form pages deferred — persona IS the form (collects data conversationally) **AI Intake** - [ ] `workflow_advance` tool: `RequireWorkflow` availability, collects form data, triggers stage transition - [ ] Form template → persona system prompt injection ("collect these fields: ...") - [ ] Tool calls create channel-scoped notes as form responses - [ ] Stage rejection: persona sees rejection reason in conversation history, re-collects **Assignment + Queue** - [ ] `workflow_assignments` table: `channel_id`, `stage`, `team_id`, `assigned_to`, `status` - [ ] Assignment queue: unassigned workflow channels visible to team members - [ ] Claim model: optimistic lock (`UPDATE ... WHERE status = 'unassigned'`) - [ ] Round-robin auto-assignment (optional, per-stage `transition_rules`) - [ ] Assignment notifications via existing notification infrastructure + WebSocket **Team Member Collaboration** - [ ] Assigned member sees full history (AI intake + artifacts + notes) - [ ] Persona remains active — assists both visitor and team member - [ ] Member can trigger stage transitions (advance / reject), add notes, invoke tools - [ ] Member can reassign to different team member or escalate to different team **Frontend** - [ ] Workflow builder UI in team admin panel (stage list, persona picker, form template editor) - [ ] Queue sidebar section showing unassigned workflow channels for user's teams - [ ] Channel header: workflow stage indicator, advance/reject controls - [ ] Persona tool grants display in workflow builder (read-only — shows what tools each stage persona has) **Migration** - [ ] 022_workflows.sql: `workflows`, `workflow_stages`, `workflow_versions`, `workflow_assignments`, channel columns - [ ] Session cleanup job for completed/cancelled workflow channels --- ## v0.27.0 — Tasks / Autonomous Agents Unattended execution — workflows without a human in the loop. Depends on: workflow engine (v0.26.0). _(Shifted from v0.23.0 — no content changes, dependency refs updated to v0.26.0)_ - [ ] Scheduler + task runner (cron-like triggers for workflow instantiation) - [ ] `task_create` tool (AI can spawn sub-workflows) - [ ] `type: 'service'` channels: workflow instances with no human participants - [ ] Execution budgets: max tokens, max tool calls, max wall-clock per stage - [ ] Admin controls for resource limits and kill switches - [ ] Completion webhooks (notify external systems when workflow completes) - [ ] Workflow chaining: one workflow's completion triggers another workflow's start --- ## TBD (unscheduled — real features, no immediate need) Items that are real but don't yet have a version assignment. Pull left based on need. **Extension System — Additional Extensions** - Image generation tool (browser or sidecar, provider-agnostic) - STT/TTS (browser extension, Web Speech API — personal use case) - Code execution sandbox (server-side, container isolation) **Extension System — Server Tiers** - Starlark runtime integration (Tier 1 — server sandbox) - Sidecar HTTP tool protocol (Tier 2 — container isolation) - Server-side tool execution in completion handler **Desktop + Mobile** - Desktop app (Tauri) - Full PWA with offline capability - Mobile-optimized layouts (beyond current responsive) **Data + Portability** - Bulk export/import (account data, conversations, settings) - ChatGPT/other tool import - GDPR-style "download my data" - Backup/restore CronJob manifests **UX / Multi-Seat** - "Group" scope badge on model selector / KB list: show access-source annotation so users see _why_ they have access (global, team, group grant). Requires backend to include `access_source` in list responses. - Per-provider model preferences: `user_model_settings` unique key is `(user_id, model_id)` — same model from different providers shares one visibility toggle. Needs `provider_config_id` dimension in DB constraint, store, API, and frontend `hiddenModels` keying. Frontend composite key (`configId:modelId`) already exists in `App.models[].id`. **Projects — Future** - Project-specific files: full project-level upload (own endpoint, storage path, UI surface — not just channel attachment re-linking) - Project templates: create new projects from predefined configurations (persona, KBs, system prompt) - Project creation dialog: replace `prompt()` with proper modal (name, description, persona, KB picker) - Admin-level project management: cross-instance visibility, reassign ownership, enforce team policies (scope: enterprise only, BYOK personal projects stay private) - Sub-projects / nested hierarchy: child inherits parent KBs, system prompt, persona (deferred until usage patterns clarify need vs tags/labels) **Knowledge Bases — Future** - KB auto-injection: top-K chunk prepend to system prompt, context budget aware, per-channel toggle (latency budgeting required) - Hybrid search: combine vector similarity with full-text `tsvector`, re-rank - Semantic chunking: embedding-based boundary detection for smarter splits - HNSW index: better query performance than IVFFlat for large datasets - Web scraping source: ingest URLs as KB documents (extends url_fetch) - Scheduled re-indexing: periodic rebuild when source documents update - ~~Store cleanup: add `UpdateDocumentStorageKey()` to `KnowledgeBaseStore` interface~~ _(done in v0.17.0)_ (currently uses direct `database.DB.ExecContext` in handler — works but bypasses store layer) **Memory — Future** - Memory compaction: summarize old memories to save context tokens - Memory confidence decay: reduce confidence over time, prune low-confidence entries - Memory export/import: portable memory format across instances - Cross-persona memory sharing (opt-in): e.g. "coding assistant" can read facts from "project manager" - Memory analytics: dashboard showing what Personas are learning, memory growth trends **Platform** - Rate limiting per user/team/tier (token budgets) - ~~Provider health monitoring~~ → v0.22.0 + key rotation - Multi-tenant SaaS mode - Plugin/extension marketplace - Virtual scroll for long conversations - ~~SQLite backend option (single-user / dev)~~ → v0.17.1 - **Helm chart.** The k8s/ raw manifests with `${VAR}` substitution have served well but are friction for external adopters and make values management manual. A Helm chart wraps the same backend + frontend deployments with a `values.yaml` (replicas, image tags, ingress host, storage class, secret refs, resource limits, feature flags). Target: `helm install switchboard ./chart` for a fresh cluster, `helm upgrade` for rolling deploys. Subcharts for optional Postgres (for dev/test — prod uses external). Candidate for v0.28+ or a parallel track once the core feature set stabilizes. ~~**Pane Architecture (Workspace Container)**~~ → moved to v0.25.0 ~~**Surfaces as Extensions**~~ → moved to v0.25.0 (core infrastructure). Marketplace, Surface IDE, and project-bound defaults remain future items: - Surface IDE: built-in surface for building surfaces — Go template editor for server-rendered shells, JS/CSS editor for client behavior, live preview in sandboxed region - Surface marketplace: share custom surfaces across instances (presentation mode, kanban, form builder, dashboard, etc.) - Project-bound surface/pane defaults: project config specifies which panes are available and default layout