All checks were successful
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
437 lines
21 KiB
Markdown
437 lines
21 KiB
Markdown
# Changelog
|
||
|
||
All notable changes to Switchboard Core are documented here.
|
||
|
||
## v0.3.0 — Workflow Schema Redesign
|
||
|
||
### Changed
|
||
|
||
- **`workflow_stages` schema modernized**: Dropped chat-era columns (`persona_id`,
|
||
`history_mode`). Renamed `transition_rules` → `stage_config`. Updated
|
||
`stage_mode` CHECK from `(form_only, form_chat, review, custom)` to
|
||
`(form, review, delegated, automated)`.
|
||
- **New stage fields**: Added `audience` (team | public | system), `stage_type`
|
||
(simple | dynamic | automated), `starlark_hook` (package_id:entry_point),
|
||
and `branch_rules` (JSONB array of routing conditions).
|
||
- **Routing engine**: `ResolveNextStage` now reads `branch_rules` (flat array)
|
||
instead of `transition_rules.conditions` (nested object). Cleaner separation
|
||
between routing rules and stage config.
|
||
- **Hook handler**: `FireOnAdvanceHook` reads from `stage_config` instead of
|
||
`transition_rules`. Renamed `channelID` parameter to `instanceID`.
|
||
- **Stage CRUD validation**: New fields validated on create/update. `delegated`
|
||
mode requires `surface_pkg_id`. `dynamic`/`automated` stage_type requires
|
||
`starlark_hook`.
|
||
- **Package export/import**: Updated to use new field names. Workflow packages
|
||
now include `audience`, `stage_type`, `starlark_hook`, `branch_rules`,
|
||
`stage_config`.
|
||
- **Starlark workflow module**: Stage dicts now include `audience` and
|
||
`stage_type` keys. Removed `history_mode` and `persona_id`.
|
||
- **Frontend stage editor**: Both admin and team-admin surfaces updated with
|
||
new mode values, audience selector, stage type selector, and conditional
|
||
Starlark hook input. Fixed pre-existing bug in admin workflows.js where
|
||
`STAGE_MODES` still contained `chat_only`.
|
||
|
||
### Removed
|
||
|
||
- `persona_id` column from `workflow_stages` (personas are extension concerns)
|
||
- `history_mode` column from `workflow_stages` (chat-era context management)
|
||
- `StageModeCustom`, `StageModeFormOnly`, `StageModeFormChat` Go constants
|
||
|
||
---
|
||
|
||
## v0.2.9 — Builtin Extension Retirement
|
||
|
||
### Changed
|
||
|
||
- **6 builtin extensions → standard packages**: csv-table, diff-viewer,
|
||
js-sandbox, katex-renderer, mermaid-renderer, and regex-tester moved from
|
||
`extensions/builtin/` to `packages/` with standard `js/` layout. Each
|
||
manifest now declares `"requires": ["chat"]` and `"type": "extension"`.
|
||
Built via `build.sh` like all other packages — no auto-install.
|
||
|
||
### Removed
|
||
|
||
- **`SeedBuiltinPackages` seeder**: Deleted `seed_packages.go` (function,
|
||
`builtinManifest` struct, `buildFullManifest` helper) and the startup call
|
||
in `main.go`. Extensions are no longer auto-seeded into the DB.
|
||
- **`extensions/builtin/` directory**: Removed from repo and Dockerfile COPY.
|
||
- **Seed tests**: Removed 8 `TestSeed_*` functions and `makeSeedDir` helper
|
||
from `extension_test.go` (~220 lines).
|
||
- **Stale comments**: Removed `SeedBuiltinPackages` references from
|
||
`package_iface.go` and `trigger_sync.go`.
|
||
|
||
---
|
||
|
||
## v0.2.8 — Team Admin Settings Audit (Pass 1)
|
||
|
||
### Removed
|
||
|
||
- **Dead `HasPrivateProviderRequirement`**: Store method checked team settings
|
||
for `require_private_providers` (BYOK vestige). Removed from interface,
|
||
PostgreSQL, and SQLite implementations. No callers existed.
|
||
- **Dead `UserRole` field on `TeamMember`**: Joined `users.role` column
|
||
(deprecated in v0.2.0 RBAC migration). Removed from model, `ListMembers`
|
||
and `GetMember` queries in both stores. Frontend never consumed it.
|
||
- **Dead `allow_team_providers` policy**: Removed from `PolicyDefaults`, both
|
||
test seed data blocks, and ICD test assertions. No handler or UI read it.
|
||
- **Dead personas in workflow stage UI**: Removed `sw.api.teams.personas()`
|
||
call (endpoint doesn't exist), personas state, persona dropdown in
|
||
StageForm, and persona badge in stage list.
|
||
- **Dead `history_mode` in stage UI**: Removed history mode selector and state
|
||
from StageForm. Backend column retained for v0.3.x schema migration.
|
||
- **Dead ICD tests**: Removed assertions for `/teams/:teamId/personas`,
|
||
`/teams/:teamId/providers`, and `/teams/:teamId/models` — endpoints were
|
||
removed in Phase 0 fork.
|
||
- **Stale `chat_only` stage mode**: Frontend `STAGE_MODES` updated from
|
||
`['chat_only', 'form_only', 'form_chat', 'review']` to
|
||
`['form_only', 'form_chat', 'review', 'custom']` matching the backend
|
||
CHECK constraint.
|
||
- **Stale comments**: Removed references to deleted `team_providers.go`,
|
||
`personas.go`, and `apiconfigs.go` files.
|
||
|
||
---
|
||
|
||
## v0.2.7 — User Settings Audit
|
||
|
||
### Changed
|
||
|
||
- **localStorage namespace**: Renamed `cs-appearance` key to `sb-appearance`
|
||
across appearance settings, base template, and workflow template. One-time
|
||
migration preserves existing user preferences.
|
||
- **Policy-gating tests**: Replaced stale `allow_user_byok` / `allow_user_personas`
|
||
assertions with `allow_registration` check (the only policy still in admin UI).
|
||
|
||
### Removed
|
||
|
||
- **Dead BYOK nav section** in user settings: empty `BYOK_ITEMS` array,
|
||
`byokEnabled` state, "BYOK Enabled" footer badge, and the nav group
|
||
that rendered an empty section.
|
||
- **Dead personas gate**: `personasEnabled` state and `.filter()` on
|
||
NAV_ITEMS for a `gate` property no items have. `auth.permissions.changed`
|
||
listener removed (existed solely for BYOK + personas state).
|
||
- **Dead Message Font Size**: Slider, `msgFont` state, and `--msg-font`
|
||
CSS variable application from appearance section and base template.
|
||
- **Dead policy defaults**: `allow_user_byok` and `allow_user_personas`
|
||
removed from `PolicyDefaults`, profile bootstrap, permissions handler,
|
||
and `PublicSettings`. Test seed data cleaned.
|
||
|
||
---
|
||
|
||
## v0.2.6 — Admin Settings Audit
|
||
|
||
### Changed
|
||
|
||
- **Roadmap reorder**: Extension Lifecycle moved from v0.2.6 to v0.3.x
|
||
(Workflows series). Settings audit milestones renumbered: v0.2.7→v0.2.6,
|
||
v0.2.8→v0.2.7, v0.2.9→v0.2.8. Added v0.2.9 for builtin extension
|
||
retirement (chat-centric extensions dormant until chat surface ships).
|
||
|
||
### Removed
|
||
|
||
- **Dead admin section categories** in `sectionCategory()`: AI (providers,
|
||
models, personas, roles, knowledgeBases, memory), routing (health, routing,
|
||
capabilities), and channels. Default category changed from `ai` to `system`.
|
||
- **Dead PublicSettings fields**: `system_prompt`/`has_admin_prompt`,
|
||
`retention_ttl_days`, `paste_to_file_chars`, `allow_user_personas` policy
|
||
— all chat-era with no frontend consumers.
|
||
- **Dead PolicyDefaults**: `allow_raw_model_access`, `default_model`.
|
||
- **Dead policy lookups**: `allow_raw_model_access` and `kb_direct_access`
|
||
from profile bootstrap and permissions handlers.
|
||
- **Dead test seed data**: `model_roles` global setting, `allow_raw_model_access`
|
||
policy from test helper.
|
||
- **Dead CORE_IDS entry**: Removed `chat` from packages admin page.
|
||
|
||
---
|
||
|
||
## [Unreleased] — v0.2.5
|
||
|
||
### Added
|
||
|
||
- **Welcome surface**: New core surface shown as fallback. Detects whether
|
||
extensions exist (shows "Set Default Surface") vs truly empty install
|
||
(shows "Go to Packages"). Topbar + UserMenu included.
|
||
- **User default surface**: Users can set a personal landing page in
|
||
Settings > General, overriding the admin-configured global default.
|
||
- **UserMenu in admin topbar**: Replaced Back button with UserMenu,
|
||
providing consistent surface navigation and eliminating infinite loops.
|
||
- **Package manifest icons**: Added emoji icons to hello-dashboard,
|
||
icd-test-runner, sdk-test-runner, and team-activity-log manifests.
|
||
- **PoC documentation**: README.md for tasks and schedules packages
|
||
documenting Proof of Concept status and graduation criteria.
|
||
|
||
### Changed
|
||
|
||
- **Default surface resolution**: Priority chain is now
|
||
user preference → global config → first extension → `/welcome`.
|
||
User preference read from JWT cookie on unauthenticated `/` route.
|
||
Correctly resolves `type: "full"` extension packages (not just `type: "surface"`).
|
||
- **User settings General section**: Replaced dead chat fields (Default
|
||
Model, System Prompt, Max Tokens, Temperature, Show Thinking) with
|
||
a Default Surface dropdown.
|
||
- **Admin settings**: Removed dead chat sections (System Prompt, Default
|
||
Model, Policies, Web Search, Auto-Compaction, Memory Extraction).
|
||
- **Roadmap restructured**: Workflows → v0.3.x (includes team roles),
|
||
Notes → v0.4.0, MVP → v0.5.0. Added settings audit milestones
|
||
(v0.2.7 admin, v0.2.8 user, v0.2.9 team-admin pass 1).
|
||
- Updated bus doc examples and test labels from `chat.*` to `workflow.*`.
|
||
- Renamed `channel-` prefixed test paths to `test-` in storage tests.
|
||
- Updated doc comments throughout to remove references to gutted surfaces.
|
||
|
||
### Removed
|
||
|
||
- **~500 lines of dead CSS**: Orphaned classes for gutted chat, channel,
|
||
project, notes, editor-chat, sidebar, and router-picker features from
|
||
`layout.css` and `surfaces.css`.
|
||
- **Dead Go types**: `Grant` struct (persona-era), `CompositeModelKey` func,
|
||
comment-only stubs for NoteGraph, ProjectChannel, etc.
|
||
- **Dead event code**: `chat.typing.*` / `channel.typing.*` condition in WS
|
||
subscriber, empty Chat/Channel event route table sections.
|
||
- **Dead test helpers**: `seed_helpers.go` (SeedTestMessage, SeedTestMessages,
|
||
SeedTestCursor — all callerless).
|
||
- **Stale template refs**: CSS link tags for non-existent `sw-chat-pane.css`,
|
||
`sw-notes-pane.css`, `chat.css`. Orphaned `chat-pane.html` component.
|
||
- **Vestigial guards**: `"chat"` surface checks in `IsSurfaceEnabled()` and
|
||
`DisablePackage()` (chat is no longer a surface).
|
||
- **Dead settings UI**: Chat defaults from user settings, System Prompt /
|
||
Default Model / Policies / Web Search / Compaction / Memory from admin.
|
||
- Unused `fmt.Sprintf` references in team stores.
|
||
|
||
---
|
||
|
||
## [Unreleased] — v0.2.4
|
||
|
||
### Added
|
||
|
||
- **`sw.shell.Topbar`**: Standard navigation bar component for surfaces.
|
||
Composes title + extension slot + NotificationBell + UserMenu into a
|
||
consistent 44px bar. Surfaces use `<${sw.shell.Topbar} title="...">` with
|
||
children rendered in the extension slot. Graceful fallback if unavailable.
|
||
- **Schedules surface** (`packages/schedules/`): New package wrapping the
|
||
kernel `/api/v1/schedules` API. Table view with cron badge + human-readable
|
||
preview, next fire time, enable/disable toggle, manual run, and execution
|
||
logs panel. Create/edit dialog with live cron-to-english preview.
|
||
- **Manifest `icon` field**: Packages can declare an emoji icon in
|
||
`manifest.json` (`"icon": "⏰"`). Served via the surfaces API `icon` field.
|
||
Rendered in the UserMenu flyout next to each surface name.
|
||
|
||
### Changed
|
||
|
||
- **UserMenu**: Surface list now driven entirely by the `/api/v1/surfaces`
|
||
API. Removed hardcoded Chat, Notes, Projects links (gutted in Phase 0).
|
||
Core surfaces (Admin, Settings, Team Admin, Workflow) filtered from the
|
||
API list and handled as dedicated menu items with RBAC gating.
|
||
- **Tasks surface**: Replaced custom `.tasks-header` with `sw.shell.Topbar`.
|
||
View tabs and create button rendered in the extension slot.
|
||
|
||
### Fixed
|
||
|
||
- **`sw.isAdmin` RBAC regression**: `isAdmin()` in `can.js` was checking the
|
||
deprecated `user.role === 'admin'` field instead of the v0.2.0 RBAC grant
|
||
`surface.admin.access`. Admin menu item and admin-gated features now appear
|
||
correctly for users in the Admins group.
|
||
|
||
---
|
||
|
||
## [Unreleased] — v0.2.2
|
||
|
||
### Added
|
||
|
||
- **Event bus subscriptions**: Extensions declare event triggers in manifest
|
||
(`"triggers": [{"type": "event", "pattern": "workflow.completed", ...}]`).
|
||
Wired via `bus.Subscribe()` on startup. Handlers fire asynchronously.
|
||
- **Webhook triggers**: Inbound HTTP at `/api/v1/hooks/:package_id/:slug`.
|
||
HMAC-SHA256 verification via `X-Switchboard-Signature` header. 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_templates` array) with configurable params and default
|
||
cron expressions.
|
||
- `triggers.register` extension permission — required for event/webhook triggers
|
||
- `triggers` table — extension-declared event and webhook trigger definitions
|
||
- `scheduled_tasks` table — user-created cron tasks with script, template,
|
||
and identity fields
|
||
- `trigger_logs` table — unified execution audit log for both tiers
|
||
- `TriggerStore` + `ScheduledTaskStore` interfaces (postgres + sqlite)
|
||
- Trigger engine (`server/triggers/`) — orchestrates event subscriptions,
|
||
webhook resolution, and cron scheduling via `robfig/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.fired` and `trigger.error` event 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_surface` global 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 `/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)
|