# Changelog All notable changes to Chat Switchboard. ## [0.22.6] — 2026-03-03 ### Fixed - **Split FE/BE deployment: page route proxying.** Frontend container now supports `BACKEND_URL` env var. When set, the entrypoint generates nginx `proxy_pass` blocks for page routes (`/`, `/login`, `/chat/:id`, `/admin/*`, `/editor/*`, `/notes/*`, `/settings/*`) so Go template rendering works in k8s split-image deployments. When unset, behavior is unchanged (SPA fallback). Both `BASE_PATH=""` and `BASE_PATH="/prefix"` variants supported. - **CI test timeout.** All `go test` commands now include `-timeout 8m` to prevent indefinite hangs from runner resource contention or race-detector compilation stalls. Previously used Go's 10-minute default with no goroutine dump on timeout. ### Removed - **`router.js` (322 lines).** Client-side hash router fully replaced by server-side page routes. All `Router.*` call sites in `chat.js` replaced with `history.replaceState()` for URL updates. All `typeof Router` guards in `app.js` removed. - **`surfaces.js` (368 lines).** Client-side surface registry replaced by Go template surface architecture. Extension API stubs (`surfaces.register`, `surfaces.activate`, etc.) now log deprecation warnings. `surfaces.getCurrent()` returns `window.__SURFACE__` from server-rendered page data. - **`index.html` SPA shell (1,296 lines → 16 lines).** Original monolithic SPA entry point replaced with a minimal redirect page. All real routes now served by Go templates; `index.html` only serves as nginx `try_files` fallback for unknown paths. - **`editor-mode.js` old Surfaces paths (~260 lines).** Removed `_register()`, `openDirect()`, `_unregister()`, `_activate()`, `_deactivate()`, `_embedChat()`, `_returnChat()`, and full `check()`/`checkStartup()` implementations. Only `mountServerRendered()` remains as the entry point. `check()` and `checkStartup()` kept as no-ops for backward compat with `projects-ui.js` callers. - **SPA-only entrypoint code path.** `docker-entrypoint-fe.sh` now requires `BACKEND_URL` (fails fast if unset). Removed dead `%%BASE_HREF%%`, `%%ENVIRONMENT%%`, `%%BRANDING_JSON%%` injection into index.html. Removed branding config file loading (branding now handled by Go templates). ### Changed - `docker-entrypoint-fe.sh`: Simplified from 227 → 184 lines. Requires `BACKEND_URL`. Removed SPA-only fallback path. - `nginx.conf` (unified container): Consolidated repeated `proxy_set_header` blocks. Uses `$backend` variable. Page routes proxy to Go backend for template rendering. - `base.html`: Added `__ENV__` and `__BRANDING__` globals for JS compatibility (previously injected by index.html sed). - `server/pages/pages.go`: Added `Environment` field to `PageData`, populated from config. - `extensions.js`: `ui.replace()`, `ui.restore()`, and `surfaces.*` API methods now log deprecation warnings instead of calling removed Surfaces system. - `app.js`: Removed `Surfaces.init()`, `EditorMode.checkStartup()`, and `Router.init()` calls. Simplified to direct `sessionStorage` chat restore. - `chat.js`: Replaced `Router.update()` calls with `history.replaceState()` for URL-bar sync on chat selection/creation. - `repl.js`: Removed `surfaces.js` import reference. ## [0.22.5] — 2026-03-03 ### Added - **Go template engine.** Server-side HTML rendering via `html/template` with `//go:embed` for compiled-in templates. Custom `FuncMap` with helpers (`roleFilterType`, `toJSON`, `hasPrefix`, `dict`). CSP nonce generation per request. Replaces monolithic `index.html` + client-side DOM construction with composable, server-rendered surfaces. - **Surface architecture.** Each page route renders a dedicated surface template that owns its full layout below the classification banner. Surfaces compose from reusable components (`model-select`, `team-select`, `file-upload`) without sharing CSS layout rules. Banner height handled via CSS custom properties (`--banner-top-h`, `--banner-bot-h`, `--surface-h`). - **Chat surface.** Server-rendered shell at `/` and `/chat/:chatID`. Go template renders banner + layout + script tags; existing JS builds DOM inside the container. Bridge pattern preserves all current chat functionality. - **Admin surface.** Full admin panel at `/admin/:section` with 5 category tabs (People, AI, Routing, System, Monitoring) and section sidebar. Server-rendered pages for providers, models, teams, users, and settings. Hybrid fallback for JS-loaded sections (groups, presets, knowledge, memory, health, capabilities, extensions, storage, usage, audit, stats). - **Editor surface.** Server-rendered layout shell at `/editor/:wsId` with proper CSS height ownership. `mountServerRendered()` method on `EditorMode` bypasses the Surfaces registry for Go template mode. Dedicated CSS owns full viewport below banners — no layout collision with other surfaces. **(Fixes bugs #4, #5: editor layout collapse)** - **Notes surface.** Server-rendered layout at `/notes/:noteId` with notes-main + notes-assist split. Boot script calls `openNotes()` in standalone mode. Responsive: assist pane hidden on mobile. - **Settings surface.** Full-page settings at `/settings/:section` replacing modal-based settings. Left nav with all sections (general, appearance, providers, models, presets, roles, knowledge, memory, notifications, usage). General and Appearance sections server-rendered with form controls; dynamic sections populated by existing JS. - **Login page.** Standalone Go template at `/login` with cookie-based auth. Sets `redirect_after_login` cookie for post-login navigation. - **`AuthOrRedirect` middleware.** Cookie-based JWT validation for page routes. Reads `sb_token` cookie, redirects to `/login` on missing/invalid token (instead of 401 JSON). `RequireAdminPage()` helper aborts with 403 for non-admin users. Skips auth entirely in unmanaged mode. - **Cookie-based auth sync.** `api.js` `saveTokens()` now sets `sb_token` cookie alongside localStorage on every token save/refresh. `clearTokens()` clears the cookie. Bridges API auth (Bearer header) with page auth (cookie). - **Reusable `model-select` component.** Go template partial renders `