# Switchboard Core — Session Turnover **Date**: 2026-03-26 **Author**: Jeffrey Smith (jasafpro@gmail.com) **Session**: Platform pivot gut — Phase 0 completion --- ## What Was Done ### Phase 0 (Steps 1-10) — COMPLETE Forked from chat-switchboard v0.38.5, gutted all AI/chat features, rebranded as Switchboard Core — a pure extension platform kernel. **By the numbers:** - Started: ~800 files, ~100K+ lines - Now: 462 files, ~75K lines - Removed: ~44K lines of chat/notes/projects/provider code - 15 Go packages deleted, 29 handler files removed - Store interfaces: 40 → 20 - Kernel permissions: 16 → 6 ### Key commits this session: - Steps 5-8: deep gut of code, build clean, tests pass - Step 9: single Docker image CI/CD, drop FE/BE split - Step 10: K8s deploy live, nginx BASE_PATH fixes, login→admin verified - Branding: "Chat Switchboard" → "Switchboard Core" ### Deployment state: - **CI**: Green on Gitea Actions (build + test + deploy) - **K8s**: `switchboard.gobha.ai/test` — live in `gobha-ai-switchboard` namespace - **DB**: Postgres connected, schema at 009_ha.sql - **Storage**: PVC (S3 keys not configured yet) - **Old namespace**: `gobha-ai-chat` — stale ingresses cleaned up --- ## Known Issues 1. **Frontend test job**: Some gutted chat/model/channel tests were removed but the FE test suite may have remaining stale references 2. **Traefik middleware**: `rbac-traefik.yaml` needs one-time manual apply by cluster admin for retry middleware (non-blocking) 3. **`SEED_USERS`**: Not set in K8s secrets — no initial admin user created on the test deployment. Set in Gitea secrets to bootstrap. 4. **Editor modules**: `src/editor/*.mjs` files still reference "Chat Switchboard" — these are CodeMirror build files, low priority --- ## What's Next ### Protect main (DO NOW) Phase 0 is complete. Main should be protected. All future work via PRs. ### v0.2.0 — First PRs **PR 1: Admin → RBAC group migration** - Add `surface.admin.access` to permissions table - Seed "Admins" group with that grant - Seed "Everyone" group, auto-member all users - Change admin middleware: role check → grant check - **Edit existing migration SQL files in place** (no new migrations pre-MVP) **PR 2: Settings cascade** - Add `user_overridable` flag to settings schema - RBAC controls scope auth (admin → global, team-admin → team, user → personal) - `user_overridable` controls whether lower scope can override higher - Resolution: user → team → global (first non-null wins) **PR 3: ICD (API contract)** - Generate full OpenAPI spec from registered routes - Document kernel-only endpoints - Mark extension API surface **PR 4: Trigger system** - Time triggers (cron) - Webhook triggers (inbound HTTP) - Event triggers (bus subscription) - Extensions register match expressions at install **PR 5: SDK stabilization** - `sb.slots()`, `sb.actions`, `sb.api.ext()`, `sb.storage` - Theme tokens exposed to extensions - Primitive UI components (toast, confirm, prompt, dialog) --- ## Architecture Decisions (this session) | Decision | Detail | |----------|--------| | No new migrations pre-MVP | Edit existing SQL files in place. Schema isn't in production. | | Admin → RBAC group | `role` column replaced by "Admins" group + grant. | | Settings: two axes | RBAC = who can change at what scope. `user_overridable` = can lower scope override. Orthogonal. | | Default surface | No surfaces → admin is default. First installed becomes default. Configurable. | | Protect main after Step 7+ | Destructive surgery done on main. Additive work (ICD, triggers) goes through PRs. | | Single Docker image | nginx + Go binary + static assets + migrations. One image, one deployment. | --- ## File Locations | What | Where | |------|-------| | Roadmap | `ROADMAP.md` | | Changelog | `CHANGELOG.md` | | CI workflow | `.gitea/workflows/ci.yaml` | | K8s manifests | `k8s/` (switchboard.yaml, ingress.yaml, storage-pvc.yaml) | | Docker compose (local dev) | `docker-compose.yml` (SQLite, port 3000) | | Nginx template | `nginx.conf.template` | | Entrypoint | `docker-entrypoint.sh` | | Migrations | `server/migrations/postgres/`, `server/migrations/sqlite/` | | Go backend | `server/` | | Frontend shell | `src/` | | Templates | `server/pages/templates/` | | Memory (Claude) | `.claude/projects/-config-Projects-core/memory/` | --- ## Gitea Secrets/Vars Needed **Secrets**: `POSTGRES_USER`, `POSTGRES_USER_PASSWORD`, `POSTGRES_ADMIN_USER`, `POSTGRES_ADMIN_PASSWORD`, `ENCRYPTION_KEY` **Vars**: `DOMAIN`, `NAMESPACE`, `S3_BUCKET`, `S3_ENDPOINT`, `STORAGE_BACKEND`, `STORAGE_CLASS`, `STORAGE_SIZE` **Not yet configured**: `S3_ACCESS_KEY`, `S3_SECRET_KEY` (using PVC for now), `SEED_USERS` (needed for initial admin bootstrap)