# Changelog All notable changes to Switchboard Core are documented here. ## [Unreleased] — v0.2.0 ### Added - **Full RBAC**: all authorization flows through group membership and permission grants. No magic roles, no implicit group membership, no special-casing. - `surface.admin.access` permission — any group can grant admin panel access - Admins system group seeded with all platform permissions - Everyone system group — all users explicitly added on creation - `EnsureEveryoneGroup()`, `AddToAdminsGroup()`, `RemoveFromAdminsGroup()` helpers - `SeedAdminsGroupMember()`, `SeedEveryoneGroupMember()` test helpers - System groups re-seeded after `TruncateAll` in test helper - OIDC `isIdPAdmin()` — maps IdP role claims to Admins group membership ### Changed - `RequireAdmin()` / `RequireAdminPage()` check `surface.admin.access` grant - `RequirePermission()` no longer bypasses for admin role - `ResolvePermissions()` unions explicit group memberships only (no implicit Everyone) - All user creation paths (builtin, OIDC, mTLS, admin, bootstrap, seed) add to Everyone group. Admin users added to Admins group. - JWT claims no longer include `role` field - Login response no longer includes `role` in user object - Profile endpoint no longer returns `role` - Profile bootstrap resolves permissions from groups (no admin shortcut) - Middleware auth cache tracks `isActive` only (no role) - Admin create user accepts `is_admin` bool (not role string) - Admin update role endpoint accepts `is_admin` bool, manages Admins group directly - Demotion/deletion safeguards check Admins group member count - Notifications `RoleFallbackHandler` queries Admins group members - OIDC syncs Admins group on login (no role column writes) - Kernel permissions: 6 → 7 (added `surface.admin.access`) - Admin users UI: role dropdown removed, admin managed through groups ### Removed - **`users.role` column** — dropped from schema, model, JWT, all handlers - `UserRoleAdmin`, `UserRoleUser` constants - `CountByRole()` store method - `DefaultRole` config for OIDC and mTLS providers - `SyncAdminsGroupMembership()` (replaced by `AddToAdminsGroup`/`RemoveFromAdminsGroup`) - OIDC `resolveRole()` (replaced by `isIdPAdmin()`) - **Token budgets** from groups: columns, `ResolveTokenBudget()`, all store/handler/UI - **Allowed models** from groups: column, `ResolveModelAllowlist()`, UI - Admin groups UI: Token Budgets section, Allowed Models section ### Migration notes - 001_core.sql (both dialects): removed `role` column from users table - 002_teams.sql (both dialects): added Admins group seed, removed `token_budget_daily`, `token_budget_monthly`, `allowed_models` columns - No new migration files — edited in place per pre-MVP policy --- ## [v0.1.0] — 2026-03-26 Forked from chat-switchboard v0.38.5. Gutted to a pure extension platform. ### Removed - **AI/Chat system**: providers, model catalog, routing policies, personas, channels, messages, completion streaming, tool loop, compaction, memory, knowledge bases, notes, workspaces, projects, folders, files, export/import - **Task scheduler**: entire scheduler package, task store, task handlers. Tasks will be rebuilt as a Starlark extension with three trigger primitives (time, webhook, event) - **Session system**: channel-based anonymous sessions. Workflow instances will get new storage in v0.2.0 - **Health accumulator**: provider health windows, tool health tracking. Replaced with kernel-only Prune (ws_tickets, rate_limit_counters, presence) - **15 Go packages**: tools, compaction, extraction, roles, mentions, notelinks, export, memory, knowledge, providers, routing, capabilities, filters, retention, workspace - **29 handler files**, 6 test files, ~44K lines total ### Fixed - CI deploy: k8s resource quantity vars (`BE_MEMORY_REQUEST` → `MEMORY_REQUEST`) aligned with CI workflow outputs — `envsubst` was producing empty strings - CI deploy: image var (`BE_IMAGE` → `IMAGE`) — caused `InvalidImageName` in pods - CI rollout: deployment name (`switchboard` → `switchboard-be`) — rollout verification was looking for wrong deployment name - Nginx BASE_PATH: regex cache-header locations intercepted static asset requests before alias could strip the sub-path prefix — moved inside alias block - Post-login blank page: dead Go template references (`surface-chat`, `surface-notes`, `surface-projects`) caused html/template to silently produce Content-Length: 0 responses - Login branding: "Chat Switchboard" → "Switchboard Core", updated tagline and feature pills to reflect platform pivot ### Changed - Module renamed: `chat-switchboard` → `switchboard-core` - VERSION: `0.1.0` - Default DB name: `switchboard_core` - Fresh migrations: 9 files × 2 dialects (postgres + sqlite), 27 tables - Store interfaces: 40 → 20 (13 in interfaces.go + 7 in separate iface files) - Stage modes: `chat_only` removed, `custom` added - Task output modes: `channel|note|webhook` → `notification|webhook|log` - Kernel permissions: 16 → 6 (`extension.use`, `extension.install`, `workflow.create`, `workflow.submit`, `admin.view`, `token.unlimited`) - Everyone group seed: `["extension.use","workflow.submit"]` - Global settings seed: site name "Switchboard Core" - Config: removed 7 dropped fields (SessionExpiryDays, WorkflowStaleHours, ProviderAutoDisableThreshold, ExtractionConcurrency, etc.) - Health stores rewritten: kernel-only Prune for stale tickets, counters, presence - Maintenance goroutine replaces scheduler for background cleanup ### Retained - Identity & auth (builtin, mTLS, OIDC) - Teams, groups, permissions - Package system (surfaces, extensions, libraries, workflows) - Starlark sandbox with capability-gated modules - Extension connections & dependencies - Workflow definitions, stages, versions - Notifications & preferences - Audit log - Object storage (PVC, S3) - WebSocket hub & presence - Multi-replica HA (ws_tickets, rate_limit_counters) - Frontend shell (preact+htm, SDK, vendor libs)