mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-09 04:40:57 +00:00
feat(tenancy): add Workspace multi-tenant foundation (#2353)
* Document multi-tenant workspace architecture * Add OSS and commercial workspace boundaries * docs: redesign multi-tenant workspace architecture * feat(tenancy): implement workspace isolation * docs(tenancy): record verification evidence * docs(tenancy): revise single-instance SaaS topology * docs(tenancy): refine architecture options * docs: finalize cloud v2 multi-tenant decisions * feat(tenancy): establish cloud isolation foundations * feat(tenancy): harden shared cloud runtime boundaries * docs(tenancy): record final isolation verification * fix(tenancy): close isolation and permission gaps * docs(tenancy): record final isolation verification * feat(tenancy): connect cloud workspace control plane * fix(build): install git for pinned SDK * docs(cloud): update control plane verification * chore: update multi-tenant SDK pin * fix(cloud): skip legacy model sync during startup * test(cloud): preserve minimal model manager fixtures * fix(cloud): preserve authenticated account context * fix(cloud): reuse authenticated account for user info * feat(cloud): complete Workspace settings navigation * test(web): cover Workspace dropdown menu * feat(web): place workspace controls in sidebar * refactor(web): streamline workspace controls * style(web): format workspace layout test * fix(cloud): surface runtime and workspace plan status * fix(plugin): keep runtime identity stable across restarts * fix(ui): widen and center workspace switcher * fix(ui): hide roles from workspace switcher * fix(ui): align workspace switcher with sidebar entries * feat(workspace): add in-product collaboration and direct Cloud launch * style: format collaboration changes * fix(workspace): bind collaboration APIs to tenant UoW * fix(cloud): preserve Core-owned collaboration state * test(cloud): require Space identity for invite registration * feat(cloud): complete secure invitation experience * style(web): format invitation flows * fix(cloud): recover box runtime without unscoped skill reload * feat(oss): enforce invitation account and owner billing flows * style: format OSS account service * test(oss): cover invitation logout handoff * fix(oss): resolve workspace owner in scoped session * feat(cloud): harden multi-tenant runtime resources * fix(cloud): bound runtime restart storms * fix(cloud): eliminate periodic runtime CPU spikes * fix(cloud): enforce instance capacity ceilings * fix(cloud): scope public login capability discovery * fix(cloud): bound tenant maintenance and monitoring work * fix(runtime): bound tenant resource amplification * fix(deps): pin green multi-tenant plugin SDK * fix(cloud): handle unavailable skill capability * fix(security): require authentication for image file endpoint (H-2) - Changed /api/v1/files/image from AuthType.NONE to USER_TOKEN_OR_API_KEY - Added Permission.RESOURCE_VIEW requirement - Prevents unauthenticated cross-tenant file access via leaked keys - Fixes HIGH severity finding from multi-tenant security review docs: add comprehensive database migration guide - Complete migration steps for OSS → multi-tenant - Backup, execution, verification procedures - Rollback scenarios and recovery plans - Performance tuning recommendations * test: add comprehensive cross-tenant isolation tests Added 7 critical test scenarios for multi-tenant boundaries: - Cross-tenant bot access prevention - Viewer role read-only enforcement - Removed member immediate access revocation - Model provider credential isolation - WebSocket message isolation - Invitation token workspace scoping - Multi-workspace context validation These tests address P0-2 coverage gaps for: - workspaces.py (membership & invitation flows) - user.py (authentication & authorization) - websocket_chat.py (real-time isolation) - plugins.py (resource access control) docs: finalize database migration guide * fix(security): resolve M-1, M-2, M-3 security findings M-1: WebSocket authorization TOCTOU race (FIXED) - Changed _revalidate_websocket_authorization to return RequestContext - Ensures validated context is used immediately without race window - Prevents removed members from sending messages during revalidation gap M-2: Model Manager cache workspace isolation (VERIFIED) - Confirmed _CacheKey already uses 4-tuple: (instance, workspace, generation, resource) - Cache is properly scoped per workspace, no cross-tenant leakage possible - No code change needed, documented as working correctly M-3: Invitation lock workspace scoping (FIXED) - Changed lock key from token_digest to workspace_uuid:token_digest - Prevents DoS where attacker locks token in Workspace A to block Workspace B - Locks now isolated per workspace All MEDIUM severity findings from security review now resolved. * fix(cloud): unblock tenant CI and enforce knowledge quotas * fix(tenancy): scope rerank model sync --------- Co-authored-by: dadachann <185672915+dadachann@users.noreply.github.com>
This commit is contained in:
+31
-14
@@ -8,13 +8,21 @@ API keys can be managed through the web interface:
|
||||
|
||||
1. Log in to the LangBot web interface
|
||||
2. Click the "API Keys" button at the bottom of the sidebar
|
||||
3. Create, view, copy, or delete API keys as needed
|
||||
3. Create an API key and copy its secret immediately
|
||||
4. Revoke keys that are no longer needed
|
||||
|
||||
Database-backed API-key secrets are returned exactly once. LangBot stores only
|
||||
a SHA-256 lookup hash, so an existing secret cannot be displayed or recovered
|
||||
later. Each key belongs to one Workspace, has explicit permission scopes, and
|
||||
may have an expiry. The Workspace is derived from the authenticated key; an
|
||||
`X-Workspace-Id` header cannot redirect it to another tenant.
|
||||
|
||||
## Global API Key (config.yaml)
|
||||
|
||||
In addition to web-UI-created keys (stored in the database, prefixed `lbk_`),
|
||||
LangBot supports a **global API key** defined directly in `data/config.yaml`.
|
||||
This is useful for automated deployments, infrastructure-as-code, and AI agents
|
||||
This is a Community-edition bootstrap option for automated deployments,
|
||||
infrastructure-as-code, and AI agents
|
||||
that need API/MCP access **without a login session and without creating a
|
||||
database record first**.
|
||||
|
||||
@@ -27,10 +35,12 @@ api:
|
||||
|
||||
Behavior:
|
||||
|
||||
- When `api.global_api_key` is a non-empty string, that exact value is accepted
|
||||
anywhere a normal API key is accepted — the `X-API-Key` header or
|
||||
`Authorization: Bearer <key>` — across the HTTP service API **and the MCP
|
||||
server**.
|
||||
- In Community edition's singleton Workspace, a non-empty
|
||||
`api.global_api_key` is bound to that Workspace and accepted across the HTTP
|
||||
service API and the MCP server.
|
||||
- The global config key is rejected when multi-Workspace SaaS mode is enabled;
|
||||
SaaS automation must use a database-backed Workspace key or a closed control
|
||||
plane credential.
|
||||
- The global key does **not** require the `lbk_` prefix; use any sufficiently
|
||||
strong secret.
|
||||
- Leave it empty (`''`, the default) to disable it entirely; only database-backed
|
||||
@@ -38,9 +48,10 @@ Behavior:
|
||||
- Existing installs are unaffected until you add the key — config completion only
|
||||
backfills top-level keys, and the lookup is defensive when the field is absent.
|
||||
|
||||
> **Security:** the global key is stored in plaintext in `config.yaml`. Only
|
||||
> enable it on trusted/internal deployments, keep the file permissions tight,
|
||||
> always serve over HTTPS, and rotate the value if it may have leaked.
|
||||
> **Security:** the global key is stored in plaintext in `config.yaml` and has
|
||||
> the singleton Workspace's full fixed permission set. Only enable it on
|
||||
> trusted/internal Community deployments, keep file permissions tight, always
|
||||
> serve over HTTPS, and rotate it if it may have leaked.
|
||||
|
||||
## Using API Keys
|
||||
|
||||
@@ -60,7 +71,9 @@ Authorization: Bearer lbk_your_api_key_here
|
||||
|
||||
## Available APIs
|
||||
|
||||
All existing LangBot APIs now support **both user token and API key authentication**. This means you can use API keys to access:
|
||||
Endpoints that declare API-key authentication accept either a user token or a
|
||||
Workspace API key. The key must include the permission required by the route.
|
||||
This includes:
|
||||
|
||||
- **Model Management** - `/api/v1/provider/models/llm` and `/api/v1/provider/models/embedding`
|
||||
- **Bot Management** - `/api/v1/platform/bots`
|
||||
@@ -227,6 +240,11 @@ or
|
||||
}
|
||||
```
|
||||
|
||||
### 403 Forbidden
|
||||
|
||||
The key is valid for its Workspace but does not include the fixed permission
|
||||
required by the route.
|
||||
|
||||
### 500 Internal Server Error
|
||||
|
||||
```json
|
||||
@@ -240,7 +258,7 @@ or
|
||||
|
||||
1. **Keep API keys secure**: Store them securely and never commit them to version control
|
||||
2. **Use HTTPS**: Always use HTTPS in production to encrypt API key transmission
|
||||
3. **Rotate keys regularly**: Create new API keys periodically and delete old ones
|
||||
3. **Rotate keys regularly**: Create new API keys periodically and revoke old ones
|
||||
4. **Use descriptive names**: Give your API keys meaningful names to track their usage
|
||||
5. **Delete unused keys**: Remove API keys that are no longer needed
|
||||
6. **Use X-API-Key header**: Prefer using the `X-API-Key` header for clarity
|
||||
@@ -317,7 +335,6 @@ curl -X POST \
|
||||
|
||||
## Notes
|
||||
|
||||
- The same endpoints work for both the web UI (with user tokens) and external services (with API keys)
|
||||
- API-key-enabled endpoints use the same resource shapes as the web UI
|
||||
- No need to learn different API paths - use the existing API documentation with API key authentication
|
||||
- All endpoints that previously required user authentication now also accept API keys
|
||||
|
||||
- API keys never select a Workspace from a request header; their persisted binding is authoritative
|
||||
|
||||
Reference in New Issue
Block a user