diff --git a/CHANGELOG.md b/CHANGELOG.md index 4140ba6..8fc9f6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,13 @@ Forked from chat-switchboard v0.38.5. Gutted to a pure extension platform. - 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 diff --git a/ROADMAP.md b/ROADMAP.md index d3e7933..ef3db1e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -29,7 +29,7 @@ platform that extensions build on. | 7. Frontend gut | ✅ | Shell + SDK only, 50+ files of chat/notes/projects code removed | | 8. New ICD | 🔧 | Stub in place, full kernel-only spec TBD | | 9. CI/CD + Dockerfile | ✅ | Single unified image, FE/BE split removed, DB names updated, k8s var alignment fixes (resource quantities, image name, rollout deployment name) | -| 10. Smoke test + tag | 🔧 | Deploy passes CI, verify health + ingress routing, tag v0.1.0 | +| 10. Smoke test | ✅ | K8s deploy live at switchboard.gobha.ai/test, nginx BASE_PATH fixed, login→admin flow verified, branding updated | ## v0.2.0 — SDK & Triggers @@ -100,3 +100,6 @@ Extension and operations tracks converge. First externally usable release. | Kernel permissions simplified | From 16 chat-centric permissions to 6 platform permissions. Extensions define their own capability requirements in manifests. | | Preact+htm retained | 3KB runtime, no build step, works for extension authors without bundler config. KISS. | | Single Docker image | Drop the frontend/backend split. Go binary + assets + migrations in one image. Simpler deployment, fewer moving parts. | +| Admin → RBAC group | The `role` column is pre-RBAC. v0.2.0 replaces it with a seeded "Admins" group + `surface.admin.access` grant. All users auto-join "Everyone" group. Admin middleware becomes a grant check, not a role check. | +| Settings cascade | RBAC controls scope auth (who can set at what level). `user_overridable` flag controls whether lower scopes can override higher. Two orthogonal axes, composes cleanly with extension manifests. | +| No new migrations pre-MVP | Edit existing migration SQL files in place. No migration chains until schema is in production. | diff --git a/TURNOVER.md b/TURNOVER.md new file mode 100644 index 0000000..c61dd1d --- /dev/null +++ b/TURNOVER.md @@ -0,0 +1,129 @@ +# 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)