This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/docs/ICD
2026-03-12 10:22:08 +00:00
..
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-12 10:22:08 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 19:41:04 +00:00
2026-03-12 10:22:08 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00
2026-03-11 14:45:37 +00:00

ICD-API — Chat Switchboard Backend API Contract

Version: 0.28.0 Updated: 2026-03-11 Audience: Frontend developers, integrators, API consumers

Organization principle: Each file is one domain — the complete story. Every endpoint that touches Knowledge Bases is in knowledge.md, every endpoint that touches Personas is in personas.md, etc.

Files

File Domain Endpoints
auth.md Auth — login, register, refresh, OIDC, mTLS 6
channels.md Channels, messages, completions, participants, folders, presence ~35
personas.md Personas, persona groups, avatars, KB bindings, tool grants ~20
knowledge.md Knowledge bases, documents, search, channel/persona bindings ~12
notes.md Notes, wikilinks, graph, search, folders ~10
workspaces.md Workspaces, file ops, git, credentials ~20
projects.md Projects, channel/KB/note associations ~14
memory.md Memory extraction, review, admin 7
providers.md Provider configs, health, capabilities, routing policies ~25
models.md Enabled models, user preferences 4
notifications.md Notifications, preferences 7
extensions.md Extensions, user settings, admin 8
profile.md User profile, avatar, password, app settings 7
teams.md Teams, members, groups, permissions, grants ~25
admin.md Platform admin — users, settings, stats, audit, usage, vault ~25
utility.md Health, export, files, storage ~12
workflows.md Workflow definitions, stages, instances, assignments, entry ~20
tasks.md Task definitions, runs, scheduler, team tasks ~14
surfaces.md Surface registry, extension surfaces 6
websocket.md WebSocket protocol, events, rooms
enums.md All enum values, policies

Conventions

Base URL

{scheme}://{host}{BASE_PATH}/api/v1

BASE_PATH is empty by default. In path-routed K8s deployments (e.g. /staging/), all routes shift accordingly. The frontend reads BASE_PATH from a <meta> tag injected by the Go template engine.

Authentication

JWT bearer tokens. Every request to a protected or admin route requires:

Authorization: Bearer {access_token}

Access token: HS256 JWT, 15-minute TTL. Claims: user_id, email, role, exp, iat, jti.

Refresh token: Opaque, DB-stored, 7-day TTL. Used to obtain new access tokens without re-login.

WebSocket fallback: ?token={access_token} query parameter when the Authorization header isn't available.

Cookie sync: On every token save/refresh, the frontend writes sb_token as a cookie. Go template page routes read this cookie via AuthOrRedirect middleware for server-rendered surfaces.

Auth Modes

Mode AUTH_MODE How it works
Builtin builtin (default) Username/password, bcrypt, JWT
mTLS mtls Reverse proxy cert headers, auto-provision
OIDC oidc Authorization code flow (Keycloak etc.)

All three modes issue the same JWT after authentication. Downstream middleware is auth-mode-agnostic.

Authorization Tiers

Tier Middleware Who
Public none Anyone (health, login, register, public settings)
Session AuthOrSession() JWT user OR anonymous session cookie (workflow visitors)
Authenticated Auth() Any logged-in user
Permission RequirePermission(perm) User whose groups grant perm
Team Admin RequireTeamAdmin() Admin of the specific team
Platform Admin RequireAdmin() Users with role = "admin"

Error Envelope

All errors return:

{ "error": "human-readable message" }

Standard HTTP status codes: 400 (bad request), 401 (not authenticated), 403 (not authorized), 404 (not found), 409 (conflict), 500 (server error), 502 (upstream provider failure).

Response Envelopes

Three patterns. Every endpoint uses exactly one.

List (returns an array) → always wrap in {"data": []}:

{
  "data": [...]
}

If paginated, pagination fields sit alongside data:

{
  "data": [...],
  "page": 1,
  "per_page": 50,
  "total": 142
}

Query params: ?page=1&per_page=50. Not all list endpoints paginate — unpaginated lists still use {"data": [...]}.

This is a hard rule: data is the only array wrapper key. No domain-specific keys (teams, members, configs, etc.) for arrays. Clients parse every list response identically.

Single object (GET by ID, profile, health) → return the object directly:

{
  "id": "uuid",
  "name": "...",
  ...
}

No wrapping. The response is the resource.

Composite (multiple named values, not an array) → named keys:

{
  "active": 5,
  "pending": 2
}

Used for stats, counts, status endpoints — anything returning multiple named scalars or heterogeneous data. The key names are domain-specific and documented per endpoint.

Empty arrays must serialize as [], never null. Go handlers must guard nil slices before serialization:

if result == nil {
    result = []MyType{}
}
c.JSON(http.StatusOK, gin.H{"data": result})

ID Format

All resource IDs are UUIDv4 strings, generated application-side via store.NewID() (Go uuid.New()). This ensures compatibility across both Postgres and SQLite backends.

Timestamps

ISO 8601 with timezone: "2025-06-15T14:30:00Z". Stored as TIMESTAMPTZ (Postgres) or TEXT (SQLite).

Page Routes (Non-API)

Server-rendered Go template surfaces. Not REST endpoints — return HTML.

Route Surface Description
/login Login Standalone login/register page
/ Chat Main chat interface
/chat/:chatID Chat Chat with specific channel loaded
/editor Editor Workspace file editor
/editor/:wsId Editor Editor with specific workspace
/notes Notes Notes interface
/notes/:noteId Notes Notes with specific note loaded
/admin Admin Platform administration
/admin/:section Admin Admin with specific section
/settings Settings User settings
/settings/:section Settings Settings with specific section
/w/:id Workflow Landing Branded workflow entry page
/w/:id/:slug Workflow Landing Slug-suffixed workflow entry
/s/:slug Extension Surface Dynamic surface from registry

All page routes (except /login, /w/) require authentication via AuthOrRedirect middleware. Admin routes additionally require RequireAdminPage(). Workflow landing pages use AuthOrSession.