Files
LangBot/docs/multi-tenant/workspace-multi-user-architecture.md
T
2026-07-20 04:02:24 +08:00

47 KiB
Raw Blame History

LangBot Workspace 多用户与 SaaS 多租户架构

状态:ARCHITECTURE BASELINE — isolation kernel implemented; SaaS activation gates remain

本文描述 Cloud v2 的目标架构和安全边界。详细的 Runtime、Box、PostgreSQL、pgvector 与 stdio MCP 决策以 pending-architecture-decisions.md 为权威来源;已经落地的实现选择记录在 implementation-decisions.md

“隔离内核已实现”仅表示开源 Core/SDK 已具备多租户数据和运行时隔离所需的基础能力, 不表示闭源控制面、计费、生产部署或 Cloud v2 已经可以上线。

1. 架构决策摘要

Cloud v2 采用以下模型:

SaaS 对外只有一个逻辑 LangBot 实例,全部 Workspace 都是该实例内的租户; 开源 Core 提供完整隔离内核,闭源 Cloud Control Plane 管理 SaaS 目录、订阅、权益和计费。

核心决策如下:

  1. Workspace 是数据、成员、权限、用量和不可信执行的租户边界,不是一个 Pod、namespace、数据库或独立 LangBot 部署。
  2. SaaS 注册 Account 时自动创建个人 Workspace;这只新增目录与业务记录,不创建租户专属服务、数据库、队列或 Runtime。
  3. OSS 每个 LangBot 实例只能存在一个 Workspace,但该 Workspace 可以有多个 Account、邀请和固定角色。
  4. SaaS 才允许一个 Account 拥有或加入多个 Workspace,并在 WebUI 中切换当前 Workspace。
  5. MVP 可以各运行一个 Core、Plugin Runtime 和 Box Runtime 进程;未来增加副本或 PostgreSQL shard 仍属于同一个逻辑实例的内部扩展,不改变产品模型和外部 API。
  6. 一个共享 Plugin Runtime 控制面管理所有 Workspace,但每个运行中的 plugin installation 独占一个 nsjail 进程;enabled-resident 是 desired semantics,只读代码和依赖可按已验证摘要共享。
  7. 一个共享 Box Runtime 管理所有 Workspace;首期符合 entitlement 的 Workspace 最多拥有一个持久 global 逻辑 sandbox,实际命令继续以 nsjail 子进程执行。
  8. SaaS 业务数据使用 PostgreSQL shared schema、应用层 scope 与 RLS 双重隔离;pgvector 位于同一个业务数据库并作为 SaaS 默认向量后端。
  9. stdio MCP 有独立实例开关,Cloud v2 首期强制关闭,不能由 Box availability 或套餐能力隐式开启。
  10. 闭源 Control Plane 可以作为模块化单体复用现有账户、支付和运营能力,但历史 Cloud 的租户专属部署模型不进入新架构。
  11. Workspace 创建、释放、export、单 Workspace restore 和在线迁移的具体流程仍待后续决策。

本轮重构的最高目标是:

共享可信控制面和基础设施池,隔离不可信执行单元;减少独立部署和常驻组件,使新增 Account 或空 Workspace 的静态成本接近零。

减少组件数量不意味着合并安全边界。插件进程、sandbox、secret、可写文件和租户数据仍必须严格隔离。

2. 范围与非目标

2.1 本方案覆盖

  • OSS 单 Workspace 多用户、邀请和固定 RBAC。
  • SaaS 多 Workspace 账户、成员和 Workspace 切换模型。
  • HTTP、WebSocket、API Key、Bot、Webhook、后台任务和内部调用的可信 Workspace 上下文。
  • Bot、Pipeline、Provider、Knowledge、Plugin、MCP、RAG、Session、Storage 和 Monitoring 的租户隔离。
  • Plugin Runtime 与 Box Runtime 的共享控制面和进程级隔离。
  • SaaS PostgreSQL shared schema、RLS 与 pgvector 边界。
  • 开源 Core 与闭源 Control Plane 的职责、协议和故障边界。
  • 当前单副本运行和未来同一逻辑实例内横向扩展的兼容约束。
  • 分阶段实施、激活门禁和验收策略。

2.2 本方案不覆盖

  • 兼容或原地升级历史 Cloud 的租户专属部署方案。
  • 为每个 Workspace 创建独立服务、数据库、schema、role、bucket、PVC、队列或 Runtime。
  • 当前阶段实现多副本调度、跨地域 active-active 或 PostgreSQL 在线分片迁移。
  • 第一版自定义角色、SAML、SCIM 或企业离线授权。
  • 第一版 Workspace 级 BYOK E2B WebUI 配置。
  • Cloud v2 首期 stdio MCP。
  • Workspace export、释放、单租户恢复和在线迁移的具体产品流程。

历史客户数据、账户和财务记录如需迁移,应单独立项;旧部署拓扑不作为本架构的设计约束。

3. 术语与不变量

3.1 术语

术语 定义
Account 登录主体。OSS 中是实例本地账户;SaaS 中是全局账户
Workspace 逻辑 LangBot 实例内的租户,是资源、成员、权限、用量和不可信执行的首要边界
Membership Account 与 Workspace 的关系,包含固定角色、状态和权限版本
Invitation 邀请一个 Account 或邮箱加入 Workspace 的一次性凭证
Logical Instance 对外唯一的 LangBot 服务与安全域,拥有稳定 instance_uuid,不等同于某个进程或 Pod
Replica Core、Plugin Runtime 或 Box Runtime 的短期内部运行副本,不是产品实体
Execution Generation Workspace 执行所有权和撤销的单调代数,用于隔离旧任务、旧连接和故障转移
Billing Account SaaS 付款主体,可以为一个或多个 Workspace 付费
Entitlement Control Plane 签发、Core 与 Runtime 本地执行的功能和数值额度快照
Cloud Control Plane 闭源 SaaS 控制面,管理全局身份、Workspace 目录、订阅、权益、计费和生命周期
LangBot Core 开源数据面,执行 Bot、Pipeline、Plugin、MCP、RAG 等业务并实施最终授权与隔离

当前代码中的 placement_generation 字段在迁移完成前保留兼容;其架构语义和目标命名均为 execution_generation,不表达 Workspace 属于某个产品级部署单元。

3.2 必须始终成立的不变量

  1. SaaS 只有一个稳定 instance_uuid;所有副本共享该身份。
  2. replica_idworker_id、Pod 名称、进程地址和数据库连接地址都是短期运行信息,不能进入业务资源的永久主键或外部 URL。
  3. workspace_uuid 是租户数据、任务、缓存、文件、日志、用量和运行时隔离的稳定键,也是未来内部路由与分片的候选键。
  4. OSS 一个实例最多一个 WorkspaceSaaS 才能激活多个 Workspace。
  5. 一个 Workspace 可以有多个 Account;一个 SaaS Account 可以加入多个 Workspace。
  6. 所有租户业务资源都具有非空 workspace_uuid,并使用 (workspace_uuid, resource_uuid) 定位。
  7. Workspace 选择器只是路由输入,不是授权凭证;服务端必须重新验证 Account、Membership、资源所有权和权限。
  8. API Key、Bot、Webhook、后台任务、Plugin 与 Box 调用从可信所有权或绑定派生 Workspace,不能信任调用方自报 scope。
  9. SaaS 缺少有效 Workspace 上下文时必须失败关闭,不能回退到第一个、最近或 OSS 默认 Workspace。
  10. Core 是资源访问、运行时授权和 entitlement 执行的最后一道边界;Control Plane 不同步代理每条消息或普通资源请求。
  11. 一个不可信插件进程只能属于一个 installation;一个 sandbox/session 只能属于一个 Workspace。
  12. execution generation 失效后,旧任务、连接、回调和副作用必须被拒绝。
  13. 本地进程表、缓存和临时目录都可重建,不能成为 desired state、撤销状态或业务数据的唯一真相。
  14. 创建空 Workspace 不启动插件 worker、sandbox 或租户专属常驻组件。
  15. 未来横向扩展不能改变 Workspace UUID、外部 API、权限模型或隔离语义。

4. 产品与部署模型

4.1 SaaS 逻辑拓扑

flowchart LR
    User["Browser / API / Bot traffic"] --> Edge["SaaS Edge"]
    User --> CP["Closed Cloud Control Plane<br/>directory + subscription + billing"]
    Edge --> Core["One logical LangBot instance<br/>Core replica pool; MVP = 1"]
    CP -->|"signed manifest, directory projection,<br/>entitlement and desired state"| Core
    Core -->|"usage outbox and observed state"| CP
    Core --> PG["Shared PostgreSQL business database<br/>RLS + pgvector"]
    Core --> PluginRT["Shared Plugin Runtime<br/>trusted supervisor"]
    Core --> BoxRT["Shared Box Runtime<br/>trusted supervisor"]
    PluginRT --> PluginA["Workspace A installation<br/>isolated nsjail process"]
    PluginRT --> PluginB["Workspace B installation<br/>isolated nsjail process"]
    BoxRT --> SandboxA["Workspace A<br/>persistent global logical sandbox"]
    BoxRT --> SandboxB["Workspace B<br/>persistent global logical sandbox"]
    Core --> ObjectStore["Shared durable object storage<br/>Workspace-scoped keys"]

这里的“一个逻辑实例”是一个服务、安全域和稳定身份,不是“永远只有一个 OS 进程”。 MVP 不实现分布式,但从第一天保留内部扩展所需的身份、幂等、generation 和 owner 抽象。

4.2 容量演进

阶段 内部部署形态 新 Workspace 静态成本 启用条件
M0 单副本 MVP 一个 Core、一个共享 Plugin Runtime、一个共享 Box Runtime、一个 PostgreSQL business database 只新增目录和业务行 当前目标
M1 同逻辑实例横向扩展 按容量增加 Core/Runtime 副本;使用 owner lease、fencing 和 generationPostgreSQL 可增加 shared shard 不创建 Workspace 专属部署 出现容量或可用性证据后
M2 Dedicated 资源等级 特定 workload 使用独享 worker pool、sandbox class 或 database shard,但沿用相同身份、协议和 schema 仅购买该等级的客户承担 合规、驻留或超大负载需求

M1 是 M0 的透明扩容,M2 是相同架构下的资源等级。外部 API 只认识稳定的 instance_uuidworkspace_uuid,不认识 replica、worker、pool 或 shard。

4.3 当前不做分布式时必须预留的能力

  1. 运行时协议携带稳定 instance_uuidworkspace_uuidexecution_generation,不依赖进程地址表达身份。
  2. Plugin installation 和 Box session 使用稳定 owner 抽象;启用第二个副本前再实现带 expiry、CAS 和 fencing token 的 lease。
  3. 创建、重试、回调、worker 注册和 outbox 使用稳定 idempotency key,重复投递不能产生第二个 owner 或副作用。
  4. Repository/UoW 不允许无边界跨 Workspace 事务;workspace_uuid 可直接作为未来 shard key。
  5. schema migration、后台任务扫描、监控聚合和运维接口不能假设永远只有一个 Core 进程。
  6. Runtime 重启通过 durable desired state reconciliation 恢复,不依赖原进程或本地 cache。
  7. 只有出现容量、可用性、地域或合规证据后才增加副本、lease store 或 shard router;预留协议不等于提前部署组件。

4.4 组件边界

  • Core、Plugin Runtime 和 Box Runtime 可以由发布与故障域决定是否共用 Pod,但必须保持独立进程身份、容器和 security context。
  • Core 不能继承 nsjail、cgroup 或 mount namespace 所需的高权限。
  • Plugin Runtime 与 Box Runtime 不合并为一个高权限进程。
  • MVP 不新增 Runtime 专用数据库、Box 专用数据库、Kafka、Redis、租户级 scheduler 或 artifact service。
  • 可信 supervisor、数据库连接池、只读 artifact cache 和基础容量可以多租户共享。

5. OSS 与 SaaS 产品行为

5.1 能力矩阵

能力 OSS SaaS
Workspace 数量 实例固定一个 Account 可拥有或加入多个,受 ProductPolicy 约束
Workspace 成员 多用户 多用户,受 entitlement 约束
邀请成员 支持 支持
固定 RBAC 支持 支持
自定义角色 不支持 后续商业能力
Workspace 创建 首次初始化创建唯一 Workspace 注册自动创建个人 Workspace;后续创建受 ProductPolicy 约束
Workspace 切换 无需展示 支持
订阅与计费 无远端依赖 闭源 Control Plane 管理
租户隔离 完整实现 完整实现

OSS edition policy 应表达为:

workspace_limit = 1
members_enabled = true
invitations_enabled = true
fixed_rbac_enabled = true
multi_workspace_enabled = false

不能用 member_limit = 1、关闭邀请或移除 RBAC 来实现单租户限制。

5.2 OSS 初始化和邀请

首次初始化在一个事务中完成:

  1. 创建本地 Account。
  2. 创建实例唯一 Workspace。
  3. 创建 owner Membership。
  4. 创建默认 Pipeline、metadata 等 Workspace 初始资源。
  5. 标记实例初始化完成。

初始化后默认关闭公开注册。后续用户由 owner/admin 创建一次性 Invitation,注册或登录后接受邀请并加入唯一 Workspace。 OSS 后续注册不创建第二个 Workspace。未配置 SMTP 时,系统返回只展示一次的邀请链接供管理员通过可信渠道发送。

5.3 SaaS 注册和邀请

普通注册由 Control Plane 通过幂等工作流完成:

  1. 创建或确认全局 Account 与 AuthIdentity。
  2. 创建 personal Workspace 和 owner Membership。
  3. 创建初始 Subscription/Entitlement 投影。
  4. 完成 verified email、速率限制和基础风控。
  5. 将 Account、Workspace 和 Membership 投影到 Core。
  6. Core 达到要求的目录 revision 后返回可访问 route。

注册只创建逻辑记录,不启动 Runtime 或租户专属基础设施。

通过邀请注册的新用户也创建自己的 personal Workspace,同时加入受邀 Workspace;已注册用户接受邀请时只新增目标 Membership。 个人 Workspace 与团队 Workspace 的付费关系必须由 ProductPolicy 明确,不允许代码根据名称或创建路径隐式推断。

5.4 Invitation 安全规则

  • token 使用至少 256-bit 加密安全随机数,数据库只保存 hash。
  • token 具有 expires_ataccepted_atrevoked_at,只能使用一次。
  • Membership 创建与 token 消费在同一事务中提交。
  • Invitation 不能授予 ownerowner 转移使用独立流程。
  • SaaS 接受邀请时必须验证目标邮箱;OAuth 邮箱相同不能跳过 token 和显式确认。
  • Workspace 必须始终至少有一个 active owneradmin 不能移除或降级 owner。
  • 浏览器邀请链接把 secret 放在 URL fragment 中,页面读取后立即清除 fragment,并只短期保存在 sessionStorage

5.5 固定 RBAC

Core 权威定义 owneradmindeveloperoperatorviewer 固定角色。 权限按能力划分,例如资源查看、资源管理、运行操作、成员管理、provider secret 管理、审计查看和数据导出。

规则:

  • 普通资源可见性不自动授予 secret 可见性。
  • 跨 Workspace 猜测资源 UUID 返回 404,不泄露存在性。
  • 同 Workspace 资源存在但缺少权限时返回 403。
  • 最后一个 owner 不能被删除或降级。
  • 前端隐藏或禁用无权限入口只改善体验;后端仍必须执行所有授权检查。

6. 开源与闭源职责边界

6.1 LangBot Core OSS

Core 负责:

  • 本地 Account、Workspace、Membership 和 OSS Invitation。
  • 固定 RBAC 与单 Workspace edition policy。
  • 业务资源及其 Workspace scope。
  • HTTP、WebSocket、后台任务和运行时请求上下文。
  • Plugin、MCP、RAG、Box、Session、Storage 和 Monitoring 隔离。
  • SaaS Account/Workspace/Membership 的版本化执行投影。
  • InstanceManifest、EntitlementSnapshot 和 Runtime 控制通道验证。
  • 通用 capability 与数值 quota enforcement。
  • UsageEvent/business outbox 和基础安全审计。

Core 是 Bot、Pipeline、Model、Knowledge、Plugin installation、MCP configuration 和 Monitoring 数据的权威来源, 也是每个业务和运行时请求的最终授权边界。

6.2 Closed Cloud Control Plane

Control Plane 负责:

  • SaaS 全局 Account、AuthIdentity、Session、OIDC 和后续 SSO。
  • SaaS Workspace、Membership 和 Invitation 的权威目录。
  • Workspace 创建、暂停、归档和删除工作流。
  • BillingAccount、Product、PlanVersion、Price、Subscription、Invoice、Refund 和 provider event。
  • Entitlement 计算、签名与版本。
  • Usage ledger、聚合、额度和欠费策略。
  • 实例 manifest、release、capacity、内部 desired state 和 observed state。
  • SaaS 运营后台、平台角色和高级审计。

首期不把这些职责拆成多个租户、计费和调度微服务。推荐以一个独立于 Core 的闭源模块化单体承载, 并通过模块边界复用已有账户、OAuth、支付、邮件和运营能力。历史 Cloud 的租户专属部署代码不复用。

Control Plane 不保存 Bot、Pipeline、Model 或 Knowledge 等业务内容,也不代理普通消息执行。

6.3 SaaS Adapter

Core 中只保留薄的协议适配层:

  • 验证 InstanceManifest、Account token 和 JWKS。
  • 消费 DirectoryEvent 并写入本地投影。
  • 缓存并验证 EntitlementSnapshot。
  • 将 UsageEvent 写入 durable outbox。
  • 接收 execution desired state 并上报 observed state。

适配层不得 monkey patch ORM、绕过 Core 权限检查或在普通资源请求中同步调用 Control Plane。

6.4 Source of Truth

数据 OSS SaaS
Account、Workspace、Membership Core 本地数据库 Control Plane 权威,Core 保存版本化投影
Invitation Core 本地数据库 Control Plane 权威,不向 Core 投影 pending secret
Bot、Pipeline、Model、KB、Plugin、MCP Core Core
Subscription、Payment、Invoice、Usage ledger 无远端依赖 Control Plane
Feature 和 quota 本地 edition policy Control Plane 签发,Core/Runtime 验证执行
Execution generation OSS 固定本地值 Control Plane desired stateCore 执行
运行时授权 Core Core 根据本地投影和 entitlement 执行

SaaS 不维护两套可写目录。Control Plane 是目录权威写模型;Core 只保存带 revision 的执行投影。

7. 控制面协议

7.1 InstanceManifest

仅设置 system.edition=cloud、环境变量或前端 feature flag 不得启用 SaaS 多 Workspace。 Cloud bootstrap 必须验证由预置根信任签名的 InstanceManifest,并据此安装闭源 Workspace policy。

Manifest 至少绑定:

iss, aud, sub, jti, iat, nbf, exp
instance_uuid
release
capabilities
tenant_isolation_version
execution_generation
delegated issuers and keyset revision

签名错误、audience 不匹配、过期、generation 回滚或信任链缺失时必须失败关闭,不能降级为 OSS 默认 Workspace。

7.2 DirectoryEvent 与目录新鲜度

Control Plane 通过 transactional outbox 发布 Account、Workspace 和 Membership 的版本化事件。 Core 使用 inbox 按 event_id 去重,以 aggregate revision 拒绝旧写,并追踪连续应用水位。

要求:

  • 事件和 batch 经过实例绑定的强认证与签名。
  • 重复、乱序、延迟、断流和全量 replay 都安全。
  • 删除使用 tombstone。
  • 新实例先导入带 high watermark 的 snapshot,再消费增量。
  • projection 未就绪或落后于授权 lease 要求时,交互与自动化请求按策略失败关闭。
  • SaaS pending Invitation、email 和 token hash 不进入 Core 投影。

MVP 可采用一个共享、原子且可恢复的 Control Plane store;未来多副本不能继续使用进程内状态承担一次性 token 或目录水位。

7.3 EntitlementSnapshot

Entitlement 使用版本化签名快照,至少绑定:

instance_uuid
workspace_uuid
plan_revision
entitlement_revision
status
features
limits
nbf, exp, grace_until

Core 校验 issuer、audience、subject、instance、revision、时间和签名;旧 revision 不覆盖新快照。 套餐名称和价格规则只存在于闭源 Control PlaneCore 与 Runtime 只理解通用 capability 和数值限额。

Control Plane 故障时,已缓存且仍有效的快照可继续执行;过期后只能进入明确、有限的 grace 模式或失败关闭。

7.4 UsageEvent 与 outbox

用量事件 append-only、至少一次投递,Control Plane 按 event_id 去重。事件至少包含:

event_id
instance_uuid
workspace_uuid
execution_generation
meter
quantity_integer
unit
source
occurred_at
entitlement_revision
schema_version

Core 不计算账单金额,也不在普通请求中同步扣费。业务写入与相应 business outbox 必须在同一事务中提交; generation-aware write fence 与 outbox 原子性尚是 SaaS 激活门禁。

7.5 Desired state 与 observed state

闭源控制面发布版本化的 release、capacity 和 execution desired stateCore/Runtime 幂等 reconcile 并上报 observed state。 desired state 只描述同一逻辑实例内部的执行所有权和容量,不产生新的产品级实例或租户实体。

Workspace 安全状态由 directory revision 决定,订阅状态由 entitlement revision 决定,执行撤销由 execution generation 决定。三者取最严格有效状态,但任何通道都不能修改另一个通道的权威字段。

8. 身份、鉴权与请求上下文

8.1 上下文模型

租户业务入口统一解析不可变的 RequestContext

@dataclass(frozen=True)
class RequestContext:
    instance_uuid: str
    workspace_uuid: str
    execution_generation: int
    principal_type: str
    principal_uuid: str
    permissions: frozenset[str]
    auth_method: str
    entitlement_revision: int | None
    request_id: str

不同入口的 Workspace 来源:

入口 Workspace 来源
Browser Account token X-Workspace-Id 只作候选;服务端校验 Membership
API Key key 记录绑定的 Workspace,忽略 caller selector
Public Bot / Webhook Bot 或 webhook route 的可信所有权
Background job durable payload 中的完整 scope,执行前重新验证 generation
Plugin Host API 认证控制连接和 immutable action context
Box operation 已验证 entitlement、admission grant 和 Runtime namespace
System operation 显式、最小能力的 SystemContext,禁止隐式全局上下文

禁止从模块全局变量、进程默认 Workspace、请求 payload 或“第一个 Workspace”推断 scope。

8.2 Account token 与 Workspace discovery

  • 新 JWT 使用稳定 Account UUID 作为 sub,并绑定 issuer、当前 instance_uuid audience 和 expiry。
  • 账户级 Workspace discovery 是一个窄 bootstrap capability,只列出该 Account 的 active Membership,不能执行租户业务。
  • multi-Workspace 模式下,tenant route 缺少 selector 必须拒绝;OSS singleton 模式可由 policy 选择唯一 Workspace。
  • Account token 不直接证明任一 Workspace 权限;Membership 必须在服务端解析并验证状态与 revision。

8.3 API Key、WebSocket 与长任务

  • API Key 只持久化 hashraw secret 仅返回一次;记录绑定 Workspace、固定 scopes、状态、expiry 和 creator。
  • Dashboard WebSocket 在升级后认证,并在每条入站消息前重新验证 Account、Membership、权限、资源所有权和 generation。
  • 长时间 LLM、MCP、Plugin 或 Box 调用在产生副作用或接受结果前再次校验 execution generation。
  • 临时凭证交换绑定发起者、Workspace、instance 和 generation;其他 scope 查询返回与不存在相同的 404。

8.4 错误语义

场景 语义
未认证或 token 无效 401
同 Workspace 资源存在但权限不足 403
资源不存在或属于其他 Workspace 404
edition / entitlement / quota 禁止 稳定领域错误码,不伪装为 500
execution generation 过期 fail closed,并停止旧运行态
未处理异常 稳定 internal_error + request ID;细节只进入服务端日志

9. Core 数据模型

9.1 Account、Workspace 与 Membership

核心实体至少包含:

Account
  uuid
  email_normalized
  display_name
  status
  auth bindings

Workspace
  uuid
  name
  status
  source: local | cloud_projection
  directory_revision

WorkspaceExecutionState
  workspace_uuid
  instance_uuid
  execution_generation
  status
  write_fenced_at
  revision

WorkspaceMembership
  workspace_uuid
  account_uuid
  role
  status
  directory_revision

约束:

  • Membership 对 (workspace_uuid, account_uuid) 唯一。
  • Workspace 的 source 不允许通过可变本地配置从 local 升级成 cloud projection。
  • Cloud projection 只有在 manifest、instance binding、目录 revision 和 execution state 均有效时才可路由。
  • OSS bootstrap 只创建或修复 local singleton Workspace。

9.2 Invitation

OSS Invitation 存在 Core 本地数据库;SaaS Invitation 只存在于闭源目录。

WorkspaceInvitation
  uuid
  workspace_uuid
  email_normalized
  role
  token_hash
  expires_at
  accepted_at
  revoked_at
  created_by

数据库约束必须保证同一 Workspace 与邮箱只有一个有效邀请,并保证 token hash 全局唯一。

9.3 业务资源

所有租户资源显式包含 workspace_uuid,包括但不限于:

  • Bot、Pipeline、Provider、Model、Knowledge Base 和 vector record。
  • Plugin installation、MCP configuration、API Key 和 webhook binding。
  • Query、Message、Session、Monitoring、Usage 和 AuditEvent。
  • Upload、ObjectRef、Skill、Runtime desired state 和 temporary credential session。

唯一键、索引、缓存 key、object key、日志维度和幂等键都必须包含 Workspace scope。 服务层不得暴露可绕过 Workspace 条件的普通 get(id)list()delete(id)

9.4 防御性约束

  • tenant table 的 workspace_uuid 非空并有外键。
  • SaaS PostgreSQL 关键表启用并强制 RLS。
  • 需要全局唯一的 opaque token 使用 hash 唯一索引,不依赖 Workspace 内唯一。
  • owner 保底、Membership revision、invitation one-shot 等规则同时由 service 和数据库事务保护。
  • 任何跨 Workspace 运维操作必须走显式受审计的 system capability,不得复用普通 repository。

10. PostgreSQL、pgvector 与存储

10.1 数据库边界

  • OSS 继续默认 SQLite,并可显式选择自托管 PostgreSQL。
  • SaaS 使用一个 PostgreSQL business database、一个 public shared schema 和共享连接池。
  • 创建 Workspace 不创建 database、schema、role 或专属连接池。
  • 每个 tenant transaction 使用 SET LOCAL 建立 scope,并由统一 TenantUnitOfWork 保证 context 与 SQL 使用同一事务和连接。
  • 应用层 Workspace scope 是第一道边界,ENABLE + FORCE ROW LEVEL SECURITY 是第二道边界。
  • runtime role 必须是非 owner、最小权限、无 superuser、无 BYPASSRLS、无 role membership 和跨 schema 权限。
  • schema、extension、policy 和 ACL 只由独立 release migrator 创建与验证;Cloud runtime 不执行 DDL。
  • PostgreSQL 仅承载业务数据和 pgvector,不成为 Plugin/Box 通用协调数据库、进程目录或新的控制面数据库。

首期 migrator 和 runtime URL 必须连接同一个 host、port、database,但使用不同 role。 生产部署还必须证明 runtime credential 无法连接 PostgreSQL 集群中的其他 database;专用 endpoint 或经验证的 HBA/proxy 隔离仍是激活门禁。

10.2 Transaction 与后台任务

  • 一个 TenantUnitOfWork 只绑定一个 Workspace、一个 execution generation 和一个事务所有者任务。
  • 子任务不能继承并提交、回滚或关闭父任务的 tenant session。
  • 长时间 LLM 或网络等待不持有数据库连接;每次数据库 helper 打开短事务。
  • detached task 只在父事务提交后启动,并自行建立新 scope;父事务回滚时取消待启动任务。
  • generation-aware write fence 必须保持到 commit,并与 business outbox 原子提交;该能力完成前不得激活 SaaS 写流量。

10.3 pgvector

  • SaaS 默认使用同一业务 PostgreSQL 中的 pgvector,不静默回退到 Chroma。
  • 向量身份至少为 (workspace_uuid, knowledge_base_uuid, vector_id)
  • 向量操作使用相同 tenant context 与 RLS 契约。
  • embedding 维度显式存储和校验;不匹配时失败关闭,不截断、补齐或改用无界扫描。
  • extension、表、constraint 和 ANN index 由 release migration 创建。
  • OSS 默认仍可使用 SQLite + Chroma;选择 pgvector 时遵守相同 scope。

10.4 Object storage

  • 大对象、plugin artifact、upload、knowledge 文件和 sandbox 文件不作为 PostgreSQL blob 存储。
  • durable object key 和 metadata 都包含 Workspace scope;临时 staging 可包含 generation,但稳定业务引用不能因未来 generation 切换而永久失效。
  • 现有 generation-scoped opaque key 在固定 generation 的 OSS 中安全,但 Cloud cutover 前必须实现稳定 final identity 或原子引用迁移。
  • public image 与 private document 使用不同 capability;不能把通用 upload key 当作公开读取凭证。

11. Plugin Runtime

11.1 共享 supervisor、独立 worker

整个逻辑实例共享一个可信 Plugin Runtime 逻辑控制面;M0 由一个 supervisor replica 承担。新 Workspace 不创建专属 Runtime、连接、卷或进程。

每个运行中的 plugin installation 独占一个 nsjail worker process treeenabled-resident 是 desired semantics。worker 运行期间永久绑定:

instance_uuid
workspace_uuid
execution_generation
installation_uuid
runtime_revision
artifact_digest

插件不能通过 payload、Host API 参数、环境变量或重连改变该绑定。Supervisor 不在自身解释器中加载第三方插件代码。 停用、删除、revision/generation 变化或 entitlement 撤销时,旧 worker 必须停止并失去 Host API 权限。

11.2 文件和进程边界

data/plugin-runtime/
├── artifacts/sha256/<artifact_digest>/code/   # 已验证、只读共享
├── environments/sha256/<environment_digest>/ # 原子发布、只读共享
└── installations/<installation_uuid>/
    ├── home/                                  # 私有可写
    ├── tmp/                                   # 私有可写
    └── data/                                  # 私有持久数据
  • 同插件同版本只有在 package digest 完全相同且完整性已验证时才共享只读代码。
  • dependency environment key 包含 artifact/requirements digest、Python ABI、Runtime version 和 installer schema。
  • installation 进程、配置、secret、home、tmp、data 和日志永不合并。
  • namespace、private /proc、mount、PID、IPC、UTS、cgroup 与 rlimit 阻止读取其他文件、枚举或 signal 其他进程。
  • Cloud 不从 artifact 自动加载 .env;secret 只由可信控制面按 installation 注入。
  • 插件 egress 必须阻止访问 Core loopback、Box Runtime、数据库和平台 metadata endpoint。

11.3 统一资源上限

资源限制只来自实例级 data/config.yaml,并支持现有环境变量覆写;plugin manifest 不能声明、放宽或覆盖。

plugin:
  worker:
    max_cpus: 1.0
    max_memory_mb: 512
    max_pids: 128
    max_open_files: 256
    max_file_size_mb: 512
    require_hard_limits: true

CPU、内存和 PID 使用 cgroup 硬限制,open files 和单文件大小使用 rlimit。 Cloud deployment profile 强制 nsjail;硬限制不可用时 readiness 失败,不能降级为普通子进程。 installation 总磁盘配额需要可原子拒绝写入的 quota provider,不能以目录扫描冒充硬限制。

11.4 Desired state 与恢复

  • PostgreSQL 中的 installation desired state 与 durable binary storage 是权威状态。
  • Runtime 本地进程表、nsjail 目录、artifact/venv cache 都可重建。
  • Runtime 重连执行实例范围 full reconciliation,清理 stale worker 并恢复 enabled installation。
  • dependency preparation 失败记录在对应 installation,不启动半就绪 worker,也不阻塞其他 installation。
  • desired semantics 要求 enabled installation 常驻,不做 idle eviction;是否按负载回收以后再决定。
  • 当前 Supervisor 可在 Runtime 重连或 Core apply/reconcile 时恢复 desired state,但尚未为意外退出的 worker 实现带有界 backoff 的 completion callback;这项可靠性缺口在 Cloud 激活前必须补齐并验证。

真实 Linux/nsjail/cgroup 与受控 egress 的 Cloud 部署验证尚未完成,是生产激活门禁。

12. Box Runtime 与 stdio MCP

12.1 共享 Box 控制面

整个逻辑实例共享一个可信 Box Runtime 逻辑控制面;M0 由一个 Runtime replica 承担。Core 与 Runtime 控制通道绑定稳定 instance identity 每个 operation 绑定 workspace_uuidexecution_generation、session revision 和短期 admission grant。

首期 entitlement 模型:

{
  "features": {
    "managed_sandbox": true,
    "external_sandbox": false
  },
  "limits": {
    "managed_sandbox_sessions": 1
  }
}

闭源订阅模块把套餐映射为该通用 capabilityCore 与 Runtime 不判断 plan == pro。 预期 Pro 得到 managed_sandbox_sessions = 1,其他套餐为 0

12.2 Sandbox 模型

  • 合资格 Workspace 首次使用时懒创建一个持久 global 逻辑 session。
  • global 表示 Workspace 内默认逻辑 sandbox,不表示跨 Workspace 共享。
  • session TTL 不自动回收;Runtime 重启后进程和临时目录失效,但 /workspace 持久数据保留。
  • 每次普通命令在 Box Runtime 容器内启动一个 one-shot nsjail 子进程。
  • 首期禁止 managed background process 和 network,避免 session 被当成常驻共享主机。
  • Core 与 Runtime 通过认证 random-marker challenge 证明看到同一 durable volume,不能只比较路径字符串。
  • 文件同步、attachment 和 skill mount 沿用现有 nsjail 机制,但所有 host path 解析必须由可信 Workspace context 派生并防止 symlink/path escape。

Cloud readiness 必须证明 cgroup、namespace、mount、Workspace/Skill/ephemeral byte quota 和 inode quota 均为硬限制。 当前普通 nsjail backend 不具备全部硬磁盘能力,因此 Cloud Box 应失败关闭,直到绿地部署提供并验证真实 quota provider; 不能把软目录扫描写成“生产已就绪”。

12.3 外部 E2B

非 Pro 用户后续可在 WebUI 配置 Workspace 自有的远程 E2B sandbox。该功能尚未实现,首期不纳入。 未来 credential 必须属于 Workspace、加密存储且读取受 secret 权限保护,不消耗 Cloud managed sandbox 配额。

12.4 stdio MCP 独立开关

mcp:
  stdio:
    enabled: true
  • OSS 默认 true 保持兼容。
  • Cloud v2 通过 MCP__STDIO__ENABLED=false 强制关闭。
  • 该 gate 独立于 box.enabled、managed sandbox entitlement 和 session quota。
  • gate 同时覆盖 create、update、test、bootstrap load 和最终 Runtime execution。
  • 已有 stdio 配置在 gate 关闭时保留但不启动,并返回明确的 feature-disabled 错误。
  • HTTP/SSE 等远程 MCP transport 不受影响。

13. HTTP API 与 WebUI

13.1 Core API

OSS 与 SaaS 执行面共用通用 Workspace API

GET    /api/v1/workspaces
GET    /api/v1/workspaces/{workspace_uuid}
GET    /api/v1/workspaces/{workspace_uuid}/members
POST   /api/v1/workspaces/{workspace_uuid}/invitations
PATCH  /api/v1/workspaces/{workspace_uuid}/members/{account_uuid}
DELETE /api/v1/workspaces/{workspace_uuid}/members/{account_uuid}

Cloud policy 下,目录 mutation 由闭源 Control Plane 负责;Core 对本地创建、邀请和成员修改返回稳定的 control_plane_required,只提供执行投影的安全读取。

所有 tenant resource route 必须经过统一 decorator/middleware

  1. 认证 principal。
  2. 解析可信 Workspace。
  3. 校验 Workspace/ExecutionState。
  4. 校验 Membership 或资源绑定。
  5. 校验 permission 和 entitlement。
  6. 创建 RequestContext 与 TenantUnitOfWork。

13.2 SaaS Control Plane API

SaaS 产品 API 包含:

POST /cloud/workspaces
GET  /cloud/workspaces
POST /cloud/workspaces/{workspace_uuid}/invitations
POST /cloud/invitations/{token}/accept
GET  /cloud/workspaces/{workspace_uuid}/subscription
POST /cloud/workspaces/{workspace_uuid}/checkout
GET  /cloud/workspaces/{workspace_uuid}/usage

这些 API 管理目录、产品和计费,不直接操作 Bot/Pipeline 等 Core 业务资源。

13.3 WebUI

OSS

  • 首次注册进入唯一 Workspace。
  • owner/admin 可邀请成员并管理固定角色。
  • 不展示 Workspace 切换器和创建第二 Workspace 的入口。

SaaS

  • 登录先获取 Account 级 Workspace 列表,再显式选择当前 Workspace。
  • 当前 Workspace UUID 保存在受控客户端状态中;所有 tenant request 自动附带 selector。
  • 切换 Account 或 Workspace 时清理缓存、WebSocket、上传、表单、错误和 optimistic state,不能显示前一租户数据。
  • 页面 refresh、新 tab 和邀请跳转恢复同一个经过授权的 Workspace;失效 Membership 不回退到其他 Workspace。
  • UI 权限变化必须响应式更新,但 API 仍是最终授权边界。

14. 故障、安全与降级

14.1 Fail-closed 场景

以下情况必须拒绝新的租户业务和副作用:

  • Cloud manifest 缺失、签名失败、audience 错误或回滚。
  • Account token、Membership、Workspace status 或 execution generation 无效。
  • 目录投影未就绪或落后于有效 lease 要求。
  • Entitlement 缺失、过期且不在明确 grace 范围内。
  • Runtime 控制通道认证失败或实例绑定不一致。
  • Plugin nsjail/cgroup hard limit 在 Cloud profile 下不可用。
  • Box 的任一硬存储或 namespace capability 无法证明。
  • PostgreSQL RLS、runtime role、schema、catalog 或 endpoint 隔离校验失败。
  • stdio MCP 在 Cloud profile 下被尝试启用。

不能把上述错误静默降级为 OSS singleton、普通子进程、Chroma、软 quota 或 caller-supplied Workspace。

14.2 撤销语义

  • Membership 删除或降权必须影响下一次 HTTP 请求,并使长连接在下一条消息前重新授权。
  • Workspace 暂停禁止新交互、自动化工作负载和新副作用;恢复只允许当前 generation。
  • entitlement 到期按 capability 明确停止新创建或新执行,不隐式删除已有数据。
  • generation 变化使旧 worker、session、callback、cached runtime object 和 outbox publisher 失效。
  • 控制面暂时不可达时,只能在有效签名快照和本地投影允许的范围内继续;过期后失败关闭。

14.3 安全清单

  • 所有 identifier 使用不可猜 UUID,但不把随机性当成授权。
  • 所有 token/secret 只存 hash 或加密值,raw secret 一次展示。
  • 日志、trace、metric、cache 和 object key 都包含 Workspace 维度并过滤 secret。
  • Provider、Bot、Plugin、MCP 配置的 read response 递归遮蔽 credential。
  • Runtime control、debug、registration 和 attachment capability 分离,不能复用万能 secret。
  • untrusted code 不访问 Core loopback、数据库、其他 Runtime、宿主文件系统或 metadata endpoint。
  • bulk operation、后台扫描和 monitoring 聚合使用显式 tenant/system capability。
  • 所有跨 Workspace 运维操作记录 principal、reason、scope、request ID 和结果。

15. 实现状态与 SaaS 激活门禁

15.1 已实现的隔离内核

当前分支已经实现或具备基础的部分包括:

  • OSS singleton Workspace、多 Account、Invitation 和固定 RBAC。
  • trusted RequestContext、Workspace-scoped repository 和资源所有权检查。
  • tenant-aware Plugin SDK protocol 与 Runtime installation binding。
  • shared Plugin Runtime / Box Runtime 控制协议和 execution generation fence。
  • stdio MCP 独立 gate。
  • PostgreSQL shared schema、transaction-local scope、FORCE RLS 与 pgvector adapter。
  • Cloud bootstrap 默认不可由普通配置激活,并对缺失安全能力失败关闭。

这些是代码能力边界,不等于完成闭源 SaaS 产品或生产部署验收。

15.2 尚未完成的激活门禁

以下事项完成并取得真实环境证据前,不得宣称 Cloud v2 production-ready

  1. 闭源 Control Plane 的全局目录、注册、邀请、订阅、计费、entitlement 签发和签名 manifest bootstrap;横向扩展前 OAuth exchange 与目录投影还必须使用原子共享存储。
  2. 普通业务写入贯穿 commit 的 generation-aware fence,以及与外部副作用同事务的 business outbox。
  3. generation cutover 后稳定的 durable object identity 或原子对象引用迁移。
  4. 所有 tenant-configurable outbound URL 的 SSRF 防护与 tenant-safe egressPlugin Runtime 还需在真实 Linux/nsjail/cgroup v2 环境验证 namespace、资源限制和文件隔离。
  5. Plugin Runtime 对意外退出的 enabled worker 实现 completion callback、有界 backoff 和自动恢复,并验证不会形成跨租户重启风暴。
  6. Plugin installation data 的 production hard disk quota provider,能够在写入边界原子拒绝超额,不能以目录扫描代替。
  7. Box Runtime 的 production hard quota provider,包括 Workspace、Skill、root/tmp/home 的 byte 与 inode quota;真实部署还必须在启动和重连时通过共享卷 marker challenge。
  8. PostgreSQL runtime credential 的专用 endpoint 或 HBA/proxy 跨 database 隔离证明、生产 migration/rollback 流程,以及 legacy pgvector migration 失败后精确恢复 RLS/FORCE 并可安全重试的集成证据。
  9. 闭源目录事件、lease、snapshot、entitlement 和 usage/outbox 的重放、断流与灾难恢复验证。
  10. 真实浏览器多 Account/RBAC/邀请/刷新场景已完成;仍需生产 Runtime 重启、worker crash、断流、异常回滚和闭源 Control Plane 的 fault-injection 验收。

15.3 有意暂缓的产品决策

  • Workspace 创建后的休眠、释放、删除和保留策略。
  • Workspace export 与单 Workspace restore。
  • 非 Pro Workspace 的 BYOK E2B WebUI。
  • 多副本 owner lease 的 store、TTL、fencing token 和转移顺序。
  • PostgreSQL shard resolver、在线迁移和 dedicated shard 产品规则。
  • artifact/cache 的签名来源、撤销、GC 和磁盘配额机制。
  • custom roles、SSO、SCIM 和企业合规能力。

暂缓项不得被实现代码用隐式默认值提前固化。

16. 实施顺序

Phase 0:契约和基线

  • 固定术语、RequestContext、角色矩阵、edition policy 和错误语义。
  • 建立升级备份、回滚和跨租户负向测试基线。

Phase 1OSS tenancy kernel

  • Account、Workspace、Membership、Invitation。
  • singleton bootstrap、多用户邀请、RBAC 和前端权限。

Phase 2:数据与入口隔离

  • 为所有资源补充 Workspace scope。
  • HTTP、API Key、Bot、Webhook、WebSocket、后台任务和 storage 统一上下文。
  • SQLite migration recovery 与 PostgreSQL RLS 集成测试。

Phase 3Runtime 与 SDK 隔离

  • Plugin installation binding、nsjail、资源上限和 artifact replay。
  • Box admission、session namespace、skill/attachment 文件边界。
  • MCP gate、RAG/vector 与 long-running generation revalidation。

Phase 4:闭源 SaaS 控制面

  • signed manifest bootstrap。
  • 全局目录、注册、邀请、Subscription、Entitlement 和 Usage ledger。
  • projection、lease、outbox、reconciliation 和运维后台。

Phase 5:生产部署激活

  • 真实 Linux Plugin/Box hard isolation。
  • PostgreSQL credential、migration、backup 和 rollback 验证。
  • 完整浏览器/API/Runtime E2E 和故障注入。
  • 所有激活门禁通过后才开启多 Workspace Cloud policy。

Phase 6:同逻辑实例内部扩展

  • 有容量证据后增加副本、owner lease 和 fencing。
  • 有地域、合规或规模证据后增加 shared/dedicated shard。
  • 保持外部身份、API 和 Workspace URL 不变。

17. 测试与验收

17.1 数据隔离

  • 两个 Workspace 使用相同 resource UUID、name、vector ID 和 cache key,不发生冲突或越权。
  • 故意遗漏应用层 Workspace filter 时,PostgreSQL RLS 仍阻止跨租户读写。
  • 连接池复用、异常回滚、子任务、后台任务和 transaction pooling 不残留 tenant context。
  • 跨 Workspace 猜测返回 404;同租户缺权限返回 403。

17.2 产品行为

  • OSS 首个 Account 创建唯一 Workspace;第二个 Account 只能通过邀请加入;创建第二 Workspace 返回 edition error。
  • 邀请覆盖有效、已使用、撤销、过期、邮箱不匹配和并发接受。
  • owner/admin/developer/operator/viewer 的 API 和 WebUI 权限一致。
  • SaaS 普通注册和邀请注册都创建个人 Workspace,但不创建专属部署或 Runtime。

17.3 Runtime

  • 两个 Workspace 安装同一已验证 artifact 时只共享只读 code/env,进程、secret、home/tmp/data、日志和 Host API 完全隔离。
  • cgroup、rlimit、namespace、egress 和 generation fence 在真实 Linux 环境生效。
  • Runtime restart/cache loss 通过 durable desired state 与 binary storage 恢复。
  • 两个 Workspace 的 Box session、files、process、skill、attachment 和 quota 完全隔离。
  • stdio MCP gate 对 UI、API、bootstrap 和最终 execution 同时生效。

17.4 Control Plane 与故障

  • DirectoryEvent 重复、乱序、缺口、snapshot + replay 和过期 lease 均安全。
  • Entitlement 旧 revision、签名错误、过期和撤销均失败关闭。
  • UsageEvent 重放不重复计费;业务事务回滚不发送副作用。
  • Runtime、Core 或 Control Plane 重启不创建重复 Workspace、worker 或 sandbox。
  • manifest、数据库安全校验或 hard quota 缺失时实例保持不可激活,而不是静默降级。

17.5 浏览器端到端

真实浏览器至少覆盖:

  1. clean database 首位 owner 注册与 singleton Workspace bootstrap。
  2. owner 创建邀请,第二个用户注册/登录并接受。
  3. 角色在 viewer/operator/developer/admin 间变化时,导航、控制项和 API 结果同步变化。
  4. Account/Workspace 切换清空前一 scope 状态,refresh 和新 tab 恢复正确 Workspace。
  5. 第二 Workspace edition limit,以及 invitation used/revoked/expired/email mismatch 的可见错误。
  6. 直接 API 越权、伪造 selector 和跨租户 UUID 猜测不能绕过 UI。

18. 最终结论

Cloud v2 的产品模型只有一个逻辑 LangBot 实例和实例内多个 Workspace。 当前选择单副本 MVP 是为了减少组件和新增租户成本,不是把单进程假设写进业务身份或协议。 未来需要容量或高可用时,在同一逻辑实例内部增加 Core/Runtime 副本和 PostgreSQL shard Workspace 的 UUID、权限、数据边界和外部 API 均保持不变。

开源 Core 必须完整实现安全的 Workspace 隔离和 OSS 单 Workspace 多用户;闭源 Control Plane 管理 SaaS 的全局目录、订阅、权益、计费和生命周期。共享可信控制面、连接池、只读 artifact 和数据库组件, 同时让每个不可信插件进程、sandbox、secret、可写文件和 tenant transaction 保持独占边界, 才能在不增加每租户部署的前提下最大化降低新增用户成本。

在闭源控制面、事务 fence/outbox、真实 Runtime hard isolation、Box hard quota 和 PostgreSQL 生产隔离等门禁完成之前, 本架构仍处于隔离内核阶段,不应被描述为可上线的 SaaS 多租户部署。