All checks were successful
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
10 KiB
10 KiB
Changelog
All notable changes to Switchboard Core are documented here.
[Unreleased] — v0.2.2
Added
- Event bus subscriptions: Extensions declare event triggers in manifest
(
"triggers": [{"type": "event", "pattern": "workflow.completed", ...}]). Wired viabus.Subscribe()on startup. Handlers fire asynchronously. - Webhook triggers: Inbound HTTP at
/api/v1/hooks/:package_id/:slug. HMAC-SHA256 verification viaX-Switchboard-Signatureheader. Synchronous Starlark handler can return custom HTTP status and body. - Scheduled tasks: User-created cron-scheduled Starlark scripts with restricted sandbox (no raw HTTP, no DB table creation, connections-only outbound). Runs as creator identity with RBAC scoping. Admin-created tasks can opt into system context. Creator deactivation auto-pauses schedule.
- Schedule templates: Extensions ship pre-built schedule templates in
manifest (
schedule_templatesarray) with configurable params and default cron expressions. triggers.registerextension permission — required for event/webhook triggerstriggerstable — extension-declared event and webhook trigger definitionsscheduled_taskstable — user-created cron tasks with script, template, and identity fieldstrigger_logstable — unified execution audit log for both tiersTriggerStore+ScheduledTaskStoreinterfaces (postgres + sqlite)- Trigger engine (
server/triggers/) — orchestrates event subscriptions, webhook resolution, and cron scheduling viarobfig/cron/v3 SyncManifestTriggers()— declarative sync of event/webhook triggers from manifest. Hooked into seed, admin install, and package install flows.- Admin trigger API:
GET/PUT/DELETE /admin/triggers,/admin/triggers/:id/logs,/admin/packages/:id/triggers - Admin schedule API:
GET /admin/schedules, enable/disable/delete - User schedule API: full CRUD at
/api/v1/schedules, manual run, execution logs trigger.firedandtrigger.errorevent bus labels (DirLocal) for observability- OpenAPI spec: Trigger, ScheduledTask, TriggerLog schemas + all new endpoints
[v0.2.1] — 2026-03-26
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_surfaceglobal config key (JSON{"id": "slug"})- Admin settings UI: Default Surface dropdown (extension surfaces only)
- ICD (API contract): Full OpenAPI 3.0.3 spec covering all 160 kernel
endpoints. 22 tag groups (System, Auth, Profile, Workflows, Packages,
Connections, Teams, Groups, Extensions, and Admin subsections). Reusable
component schemas for User, Team, Group, Workflow, Package, Extension, etc.
Served at
/api/docs(Swagger UI) and/api/docs/openapi.yaml.
Changed
disabledRedirect()now redirects to/admininstead of/to prevent redirect loops when the default surface is disabled- Disabled extension surfaces (
/s/:slug) redirect to/admininstead of/
Fixed
- Gin route param conflict causing backend startup hang: team-scoped
package settings routes used
:pkgIdwhile sibling routes used:id. Gin's radix tree entered an infinite loop on the conflicting param names. Unified to:idacross 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.accesspermission — 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()helpersSeedAdminsGroupMember(),SeedEveryoneGroupMember()test helpers- System groups re-seeded after
TruncateAllin test helper - OIDC
isIdPAdmin()— maps IdP role claims to Admins group membership - Settings cascade: three-tier resolution (global → team → user) with
user_overridableflag per manifest setting key. Admins can lock settings that team admins and users cannot override. package_team_settingstable for team-scoped package setting overrides- Team admin API:
GET/PUT/DELETE /api/v1/teams/:teamId/packages/:pkgId/settings RunContext.TeamIDfor team-aware Starlark settings resolutionstore.ResolveSettings()/store.FilterOverridableKeys()pure functionsstore.ParseSettingsSchema()extractsuser_overridablefrom manifests
Changed
RequireAdmin()/RequireAdminPage()checksurface.admin.accessgrantRequirePermission()no longer bypasses for admin roleResolvePermissions()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
rolefield - Login response no longer includes
rolein user object - Profile endpoint no longer returns
role - Profile bootstrap resolves permissions from groups (no admin shortcut)
- Middleware auth cache tracks
isActiveonly (no role) - Admin create user accepts
is_adminbool (not role string) - Admin update role endpoint accepts
is_adminbool, manages Admins group directly - Demotion/deletion safeguards check Admins group member count
- Notifications
RoleFallbackHandlerqueries 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.rolecolumn — dropped from schema, model, JWT, all handlersUserRoleAdmin,UserRoleUserconstantsCountByRole()store methodDefaultRoleconfig for OIDC and mTLS providersSyncAdminsGroupMembership()(replaced byAddToAdminsGroup/RemoveFromAdminsGroup)- OIDC
resolveRole()(replaced byisIdPAdmin()) - 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
rolecolumn from users table - 002_teams.sql (both dialects): added Admins group seed, removed
token_budget_daily,token_budget_monthly,allowed_modelscolumns - 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 —envsubstwas producing empty strings - CI deploy: image var (
BE_IMAGE→IMAGE) — causedInvalidImageNamein 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_onlyremoved,customadded - 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)