6.1 KiB
WebSocket Protocol
Real-time bidirectional event bus. Single connection per client.
Connection
ws://{host}{BASE_PATH}/ws?token={access_token}
Lifecycle:
- Server sends
pingevery 54 seconds - Client must respond with
pongwithin 60 seconds or disconnection - Max message size: 4 KB
- Write deadline: 10 seconds
Event Envelope
All messages are JSON:
{
"type": "event.type",
"payload": { ... }
}
Room Subscription
Clients subscribe to rooms for scoped event delivery:
{ "type": "subscribe", "payload": { "room": "channel:uuid" } }
{ "type": "unsubscribe", "payload": { "room": "channel:uuid" } }
Event Routing Table
| Prefix | Direction | Description |
|---|---|---|
channel.created |
→ client | New channel created |
channel.updated |
→ client | Channel metadata changed |
channel.deleted |
→ client | Channel removed |
message.created |
→ client | New message in subscribed channel |
message.updated |
→ client | Message content changed |
message.deleted |
→ client | Message removed |
cursor.updated |
→ client | Branch cursor moved |
typing.start |
↔ both | Participant started typing (payload includes participant_id, participant_type) |
typing.stop |
↔ both | Typing ended |
participant.joined |
→ client | Participant added to channel |
participant.left |
→ client | Participant removed from channel |
participant.updated |
→ client | Participant role changed |
presence.update |
→ client | Participant online/idle/offline status change |
model.changed |
→ client | Channel model roster changed |
persona.updated |
→ client | Persona metadata changed |
kb.updated |
→ client | Knowledge base changed |
kb.document.status |
→ client | Document processing status update |
note.created |
→ client | Note created |
note.updated |
→ client | Note content changed |
note.deleted |
→ client | Note removed |
notification.new |
→ client | New notification |
notification.read |
→ client | Notification marked read |
memory.extracted |
→ client | New memory extracted |
memory.status |
→ client | Memory approved/rejected |
role.fallback |
→ client | Role fallback triggered |
workspace.updated |
→ client | Workspace state changed |
project.updated |
→ client | Project metadata changed |
extension.updated |
→ client | Extension config changed |
settings.updated |
→ client | Global settings changed |
user.updated |
→ client | User profile changed |
file.created |
→ client | File uploaded or generated (§17b.4) |
file.deleted |
→ client | File removed |
Direction: → client = server-to-client only, ← client = client-to-server
only, ↔ both = bidirectional.
19. Appendix: Enums
Channel Types
direct (single-user), group (multi-user/multi-model), workflow (staged)
Participant Types
user, persona, session
Participant Roles
owner, member, observer
Presence Statuses
online, idle, offline
Message Roles
user, assistant, system, tool
Scopes
personal, team, global
Visibility (model catalog)
enabled, disabled, team
User Roles
admin, user
Team Member Roles
admin, member
Provider Types
openai, anthropic, openrouter, venice (extensible via registry)
Model Types
chat, embedding, image
Memory Scopes
user, persona
Memory Statuses
pending, approved, rejected
Workspace Owner Types
user, project
Workspace Statuses
active, archived
Index Statuses
pending, indexing, ready, error
KB Document Statuses
pending, chunking, embedding, ready, error
Provider Health Statuses
healthy, degraded, down
Routing Policy Types
provider_prefer, team_route, cost_limit, model_alias
Extension Tiers
browser (implemented), starlark (future), sidecar (future)
Grant Types
team_only, global, groups
Resource Grant Scopes
persona, kb
Notification Types
role.fallback, memory.extracted, system.announcement, plus
extensible via notification service.
Git Auth Types
https_pat, https_basic, ssh_key
Policies
| Key | Default | Description |
|---|---|---|
allow_registration |
"true" |
Allow new user self-registration |
allow_user_byok |
"true" |
Allow users to add personal API keys |
allow_user_personas |
"true" |
Allow users to create personal Personas |
allow_team_providers |
"true" |
Allow team admins to configure team providers |
kb_direct_access |
"true" |
Show KB picker in channel (false = strict enterprise mode) |
require_email |
"false" |
Require email on registration |
default_system_prompt |
"" |
Injected into all conversations (admin override) |
Page Routes (Non-API)
Server-rendered Go template surfaces. Not REST endpoints — these return HTML pages.
| 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 |
All page routes (except /login) require authentication via
AuthOrRedirect middleware (reads sb_token cookie). Admin routes
additionally require RequireAdminPage().
Dynamic surface routing for admin-installed extension surfaces is not yet implemented. The current five surfaces are hardcoded in Go route registration. Future: extension manifests declare surface routes, the page engine dynamically registers them with appropriate data loaders. See EXTENSIONS.md for the design direction.