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.
Files
core/docs/ROADMAP.md
2026-03-08 16:54:17 +00:00

859 lines
43 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.<major>.<minor>` — 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.1v0.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