Some checks failed
CI/CD / detect-changes (pull_request) Successful in 4s
CI/CD / test-frontend (pull_request) Successful in 4s
CI/CD / test-go-pg (pull_request) Failing after 2m18s
CI/CD / test-sqlite (pull_request) Successful in 2m40s
CI/CD / build-and-deploy (pull_request) Has been skipped
Default surface routing (v0.2.1): - `/` redirects to configurable default surface with fallback chain: configured → first enabled extension surface → /admin - Auto-sets default_surface on first extension surface install - Admin settings UI: Default Surface dropdown - disabledRedirect() and extension surface disabled redirect now go to /admin instead of / to prevent redirect loops Fix Gin route param conflict causing backend startup hang: - Team package settings routes used `:pkgId` while sibling routes used `:id` — Gin's radix tree entered infinite loop on conflicting param names. Unified to `:id`. Docker entrypoint hardening: - Health check timeout 10s → 60s - Stale backend process cleanup on restart - Crash detection (exit early if backend dies) Roadmap direction updates: - v0.3.0: Notes surface (Obsidian-style) replaces Editor surface - v0.4.0: MVP (was v0.5.0) — chat moved to post-MVP - No built-in auto-install — explicit install only Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
166 lines
7.7 KiB
Markdown
166 lines
7.7 KiB
Markdown
# Changelog
|
||
|
||
All notable changes to Switchboard Core are documented here.
|
||
|
||
## [Unreleased] — v0.2.1
|
||
|
||
### Added
|
||
|
||
- **Default surface routing**: `/` redirects to configurable default surface.
|
||
Fallback chain: configured default → first enabled extension surface → `/admin`.
|
||
First installed extension surface auto-becomes default. Admin can change via
|
||
Settings > Default Surface dropdown.
|
||
- `default_surface` global config key (JSON `{"id": "slug"}`)
|
||
- Admin settings UI: Default Surface dropdown (extension surfaces only)
|
||
|
||
### Changed
|
||
|
||
- `disabledRedirect()` now redirects to `/admin` instead of `/` to prevent
|
||
redirect loops when the default surface is disabled
|
||
- Disabled extension surfaces (`/s/:slug`) redirect to `/admin` instead of `/`
|
||
|
||
### Fixed
|
||
|
||
- **Gin route param conflict** causing backend startup hang: team-scoped
|
||
package settings routes used `:pkgId` while sibling routes used `:id`.
|
||
Gin's radix tree entered an infinite loop on the conflicting param names.
|
||
Unified to `:id` across all `/teams/:teamId/packages/` routes.
|
||
- Docker entrypoint: increased health check timeout (10s → 60s), added stale
|
||
process cleanup and crash detection to prevent zombie backends on restart
|
||
|
||
---
|
||
|
||
## [v0.2.0] — 2026-03-26
|
||
|
||
### 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
|
||
- **Settings cascade**: three-tier resolution (global → team → user) with
|
||
`user_overridable` flag per manifest setting key. Admins can lock settings
|
||
that team admins and users cannot override.
|
||
- `package_team_settings` table for team-scoped package setting overrides
|
||
- Team admin API: `GET/PUT/DELETE /api/v1/teams/:teamId/packages/:pkgId/settings`
|
||
- `RunContext.TeamID` for team-aware Starlark settings resolution
|
||
- `store.ResolveSettings()` / `store.FilterOverridableKeys()` pure functions
|
||
- `store.ParseSettingsSchema()` extracts `user_overridable` from manifests
|
||
|
||
### 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
|
||
- Starlark `settings.get()` uses cascade resolver instead of naive merge
|
||
- User settings save (`POST /extensions/:id/settings`) strips non-overridable keys
|
||
|
||
### 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)
|