# Changelog All notable changes to Chat Switchboard. ## [0.17.0] — 2026-02-27 ### Added - **Persona-KB binding.** Personas can now have knowledge bases directly bound to them. When a user selects a persona with bound KBs, the `kb_search` tool is automatically scoped to those KBs and the persona's system prompt includes a KB listing hint. Admin and team admin preset forms include a KB picker with per-KB auto-search toggles. Migration adds `persona_knowledge_bases` join table. - **Enterprise KB mode.** New `discoverable` flag on knowledge bases controls whether users can see and attach KBs directly. When `kb_direct_access` platform policy is set to `true`, users cannot attach KBs to channels directly — they access KBs exclusively through persona bindings curated by admins. New `ListDiscoverableKBs` and `SetDiscoverable` endpoints. - **Role fallback alerts (issue #69).** When a role's primary provider fails and the fallback activates, the resolver emits a `role.fallback` event on the EventBus with audit log entry. Admin users see a persistent dismissable banner. 5-minute per-role cooldown prevents flooding. - **Chat rename.** Double-click any chat title in the sidebar to edit inline. Enter saves, Escape cancels. - **Utility model auto-naming.** After the first assistant response, a background request to the utility role generates a concise title. Falls back to truncation when no utility model is configured. New endpoint: `POST /channels/:id/generate-title`. - **Chat token count.** Conversation token estimate shown in the model bar, color-coded against context budget. - **State restore on refresh.** Active chat ID persisted to `sessionStorage`, auto-restored on page reload. ### Fixed - **ResolvePreset group access bypass.** `ResolvePreset()` used raw SQL that skipped `resource_grants` checks from v0.16.0. Now uses `PersonaStore.UserCanAccess()`. - **KB create scope authorization.** Now enforces admin role for global KBs and team admin role for team KBs. - **Completion handler persona ID scoping.** `personaID` variable scoped inside an `if` block but referenced downstream. Fixed by threading through function signatures. - **Nil slice JSON marshaling.** `ListDiscoverableKBs` returns `[]` instead of `null` when no KBs match. ### Changed - `UpdateDocumentStorageKey` moved from raw `ExecContext` to store method. - EventBus route table: `role.fallback` → `DirToClient`. - Resolver gains `.WithBus(bus)` builder (nil-safe, backwards compatible). - Service worker: `/extensions/` excluded from fetch handler. - Mermaid renderer v2.0 (pan/zoom, export) promoted to builtin. - Removed DIAG diagnostics from `TestGroupBasedPersonaAccess`. - Paste-to-file threshold synced from backend `PublicSettings` (`storage.paste_to_file_chars`, admin-configurable, default 2000). Resolves hardcoded constant in `attachments.js`. - Embedding dropdown already had tolerant type filter, manual model ID fallback, and auto-switch on empty — confirmed complete, checkbox updated. ## [0.12.0] — 2026-02-25 ### Added - **File handling and vision support.** Upload images, PDFs, and documents into chat via 📎 button, drag-and-drop, or paste. Multimodal message assembly injects base64 images for vision-capable models and extracted text for documents. Staged attachment strip shows upload progress and extraction status. Auth-aware blob rendering with Bearer tokens. Image lightbox viewer. Vision capability hints on image attachments. - **Storage backend abstraction.** `ObjectStore` interface with two implementations: PVC (local filesystem) for single-node/dev and S3 (minio-go) for multi-node production. S3 backend works with any S3-compatible API: MinIO, Ceph RGW, AWS S3. Auto-detection when `STORAGE_BACKEND` is not set (tries PVC, disables if not writable). Both backends share identical semantics — all handlers, attachment CRUD, multimodal assembly, and orphan cleanup work regardless of backend. - **S3 configuration.** `S3_ENDPOINT`, `S3_BUCKET`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`, `S3_REGION`, `S3_PREFIX`, `S3_FORCE_PATH_STYLE` env vars. Endpoint auto-detects SSL from scheme. Path-style URLs default on (required for MinIO/Ceph). Optional key prefix for shared buckets. CI pipeline syncs S3 secrets to K8s when `STORAGE_BACKEND=s3`. - **Text extraction pipeline.** PDF, DOCX, XLSX, PPTX, ODT, RTF text extraction via filesystem-based queue. Inline and sidecar modes. Crash recovery for items stuck in processing state. - **Admin storage panel.** Backend health, file count, total size, orphan detection and cleanup. Shows PVC path or S3 endpoint/bucket depending on active backend. Extraction queue status. - **Vault CLI commands.** `switchboard vault rekey` re-encrypts all provider API keys when rotating the encryption key. `switchboard vault status` shows encryption health. Admin UI encryption status indicator in Settings tab. - **Per-chat model persistence.** Server-side `channels.settings` JSONB field stores `last_selector_id`. Roams across devices with localStorage write-through cache as fallback. ## [0.11.0] — 2026-02-25 ### Added - **Browser extension system.** Full lifecycle: manifest registration, script injection, scoped context (`ctx.renderers`, `ctx.tools`, `ctx.events`, `ctx.storage`, `ctx.ui`), permission-aware API proxying. Extensions self- register via `Extensions.register()` and receive isolated contexts during `initAll()`. Admin CRUD endpoints, asset serving (public, no auth needed for `