Administration
Operational guide for administrators: users, roles and RBAC, workspaces, audit, licenses, and administrative backups. Every operation requires authMiddleware plus specific permissions - see the API Reference for the full endpoint inventory.
Operational guide for administrators: users, roles and RBAC, workspaces, audit, licenses, and administrative backups. Every operation requires authMiddleware plus specific permissions - see the API Reference for the full endpoint inventory.
Bootstrap admin
On first startup (when SEED_BOOTSTRAP_ADMIN=true), the server creates an admin account from env credentials (SEED_ADMIN_USERNAME=admin, SEED_ADMIN_PASSWORD=admin123, [email protected]). The account carries mustChangePassword=true → the first login forces a rotation. Setup wizard via GET /api/system/is-initialized → POST /api/system/initialize.
Security: change the bootstrap password immediately and set a strong JWT_SECRETin production. ThescryptSync(JWT_SECRET, ...)fallback forENCRYPTION_KEYmakes
JWT_SECRET cryptographic material - never expose it.Users - /api/users
| Operation | Endpoint | Permission |
|---|---|---|
| Paginated list | GET /users | requireAdmin |
| Detail | GET /users/:id | self/admin |
| Update | PUT/PATCH /users/:id | self/admin (updateUserSchema) |
| Delete | DELETE /users/:id | requireAdmin |
| Avatar | POST/DELETE /users/:id/avatar | JWT (multipart) |
Delete: DELETE is a hard delete with relation cleanup (UserRole, ProjectAccess, WorkspaceAccess) and auth-cache invalidation; an admin cannot delete themselves. updateUserSchema validates username/email/password/firstName/lastName/customInstructions/textSize (custom instructions are prepended to the agent's system prompt); non-admins cannot change their own password through this endpoint.
Roles & RBAC - /api/roles
44 permissions defined in packages/shared/src/constants/permissions.ts (PERMISSION_NAMES). 15 menu sections (MENU_SECTIONS, includes uploads, skills, and plugins).
| Operation | Endpoint | Permission |
|---|---|---|
| Visible menu sections | GET /roles/me/menu-sections | JWT |
| List roles | GET /roles | requireAdmin |
| Detail | GET /roles/:roleId | requireAdmin (UUID) |
| Create | POST /roles | requireAdmin (createRoleSchema, isDefault=false) |
| Update | PUT /roles/:roleId | requireAdmin (atomic permission replace) |
| Role menu sections | PUT /roles/:roleId/menu-sections | requireAdmin |
| Per-role visibility | GET/PUT /roles/:roleId/visibility | requireAdmin (per-section visibility matrix) |
| Delete | DELETE /roles/:roleId | requireAdmin |
| Assign/Revoke | POST /roles/assign /revoke | requireAdmin |
Default roles: admin (all 44 permissions) and user (16 permissions: the 9 base ones plus memory:read/memory:write for per-user memories, skill:create/skill:read/skill:write/skill:delete for custom user skills, and widget:manage; filters:manage is reserved for admin/superuser). "Superuser" coincides with admin. Permissions are enforced via requirePermission(name) or the requireAdmin shortcut. Assignment is many-to-many (UserRole).
Workspaces & Projects
Workspace (/api/workspaces): the isolation unit for chats, documents, and agent config.
- Creation:
workspace:create+ licensemax_workspaces(Community 3, Enterprise ∞). - Access:
requireWorkspaceAccessmiddleware (WorkspaceAccessjoin table). - Soft-delete + restore (
PUT /:id/restore). - Chat folders:
/:id/folders[/:folderId]+ restore.
Project (/api/projects): groups related workspaces.
- Creation:
project:create+ licensemax_projects. - Access:
requireProjectAccess(ProjectAccess). - Archive export:
GET /:projectId/export(stream). - Usage stats:
GET /:projectId/usage.
Audit / Event Log - /api/event-logs
License audit_log_immutable (Enterprise). GET with filters entityType/entityId/userId plus limit/offset (pagination). eventLogService.logEvent delegates the write to the enterprise plugin (a no-op in Community) and dispatches fire-and-forget webhooks. Logged entities (EntityType, 24 types): user, role, workspace, project, chat, document, mcp_connection, mcp_catalog_entry, dlp, archive/archive_page/archive_import, ocr_job, synthesis_run, wiki_edit, skill, upload_draft, chat_connector, widget, quota, backup_destination/backup_job, provider, memory. When the immutable flag is active, records cannot be modified or deleted (app-level append-only).
Licenses
- Community (default): limited flags (see 03 - Configuration).
- Enterprise: licenses are RS256 (asymmetric) JWTs - the public key is embedded in the server source (
packages/server/src/services/license-public-key.ts), so onlyLICENSE_KEYis needed (vendor-issued, no secret env: the v0.22-era HS256LICENSE_SECRETdied with the asymmetric rotation). Payload validated againstlicensePayloadSchema. Expired/invalid → Community fallback with a warning, graceful degradation at runtime (no restart). - Endpoint:
GET /api/license/info(public) →{ license, features }. - Runtime instance-license slot (Phase 221, no-.env): **Settings → Security → License** (admin,
admin:settings) pastes the vendor-issued RS256 JWT. Verified probe-first (a rejected key is never stored), stored ONLY as AES-256-GCM ciphertext (SystemConfigINSTANCE_LICENSE- the plaintext and its ciphertext never ride any response), applied to the live instance by the same resolver the boot step runs. Source precedence (identical at boot and runtime):INSTANCE_LICENSEslot → verified plugin row (enterprise-tier license) → ENVLICENSE_KEY→ Community. - Slot APIs:
PUT /api/license/instance({ licenseKey }→200 { licenseStatus: "verified", tier, licensee, expiresAt }; rejects are400 { error, reason }with the closed reasoninvalid/expired/plugin_bound/community_tier),GET /api/license/instance(metadata-only status surface),DELETE /api/license/instance(clears the paste: the instance reverts to what the NEXT BOOT would derive, boot/runtime parity). A paste must be UNCLAIMED (plugin-bound keys act only as that plugin's license - the instance slot rejects them withplugin_bound) and only an ENTERPRISE-tier key can be stored (a community paste would silently downgrade a valid env key - rejected withcommunity_tier). The bulk settings channel (PUT /api/system/settings) rejects the key - the paste route is its sole write path. - Gating:
requireFeature(flag)→ 402;requireFeatureLimit(flag, model)→ 402 whencount >= limit(Enterprise =Infinity).
Administrative backups
See 05 - Feature Guide § Backup. Admin endpoints:
- Logs
/api/system/backups(backup:log:read). - Destinations
/api/backup-destinations(backup:destination:read/write, licensemax_backup_destinations). - Jobs
/api/backup-jobs(backup:job:read/write), manual triggerPOST /:id/run. - Restore
/api/backups/restore/:logId[/dry-run](backup:restore:write). - Test destination
POST /backup-destinations/:id/test.
Settings - /api/system/settings
Bulk GET/PUT (returns { updated, rejected }). Groups: LLM, Embedding/Vector, ports/URL, Auth, Branding (gated white_label), Feature, OCR, Synthesis, Retention. ALWAYS_READONLY keys are rejected. Chat retention only via PUT /api/system/chat-retention (audited, confirmDataLoss: true). Details in 03 - Configuration.
SSO - /api/sso
License sso_enabled. GET/PUT /config, POST /test. Enterprise SAML/OIDC config.
v0.28.1 Provenance
| Statement | Source |
|---|---|
44 permissions / 15 menu sections (+skills/plugins); admin = [...PERMISSION_NAMES] (all 44); user = 16 permissions | packages/shared/src/constants/permissions.ts (row-time source count, 35-02 probe) - F-RBAC-1/2/4 |
GET/PUT /roles/:roleId/visibility (per-section visibility matrix) | packages/server/src/routes/roles.ts (row-time) - F-RBAC-4 |
RS256 license + embedded public key + runtime instance slot + the /api/license/instance routes (+closed reasons) | docs/ADMIN.md (Enterprise License, Runtime license paste - Phase 221) - F-LIC-1 |
EntityType = 24 types (incl. skill, chat_connector, widget, quota) | packages/shared/src/types/index.ts:250 (row-time) - F-AUDIT-1 |
Operational reference - Simmetric Chat v0.28.1 (docs updated 2026-10-02, census SHA `aca5b8ff`).
Cross-links
- Permissions/flags: 03 - Configuration
- Full endpoints: 04 - API Reference
- Operational deployment: 09 - Deployment