{"title":"多租户与隔离","slug":"multi-tenancy","category":"concepts","summary":"Synapse 如何在用户与 Mind 之间隔离数据 — 详解安全边界。","audience":["human","llm"],"tags":["concept","multi-tenancy","security","isolation"],"difficulty":"intermediate","updated":"2026-06-27","word_count":301,"read_minutes":2,"lang":"zh","translated":true,"requested_lang":"zh","content_markdown":"\n# 多租户与隔离\n\nSynapse 是多租户的：多个用户，每个用户可有多个 Mind，彼此完全隔离。本页说明隔离模型。\n\n## 租户层级\n\n```\nSynapse 实例\n  │\n  ├── 用户账户 1 (邮箱: alice@example.com)\n  │   ├── Mind A (Mind Key mk_aaa...)\n  │   │   ├── 记忆 (仅可通过 mk_aaa... 访问)\n  │   │   ├── 任务\n  │   │   └── 聊天\n  │   └── Mind B (Mind Key mk_bbb...)\n  │       └── ... (与 Mind A 隔离)\n  │\n  ├── 用户账户 2 (邮箱: bob@example.com)\n  │   └── Mind C (Mind Key mk_ccc...)\n  │       └── ... (与 Alice 的 Mind 隔离)\n  │\n  └── ... (更多用户)\n```\n\n## 隔离层级\n\n### 第 1 级：用户隔离\n\n每个用户账户相互隔离。Alice 不能：\n\n- 查看 Bob 的 Mind\n- 访问 Bob 的记忆（即使有她的 JWT）\n- 列出 Bob 的账户信息\n\n强制方式：所有表上都有 `user_id` 列，JWT 包含 `user_id`，所有查询按 `user_id` 过滤。\n\n### 第 2 级：Mind 隔离\n\n在同一用户下，每个 Mind 相互隔离。Mind A 不能：\n\n- 查看 Mind B 的记忆\n- 访问 Mind B 的任务、聊天、脚本\n\n强制方式：所有数据表都有 `mind_id` 列，Mind Key 包含 `mind_id`，所有查询按 `mind_id` 过滤。\n\n> [!CRITICAL]\n> Mind Key 隔离是首要的安全边界。泄露的 Mind Key 会授予对该 Mind 数据的完全访问权限 — 但仅限该 Mind。\n\n## 认证令牌\n\n| 令牌 | 范围 | 可访问内容 |\n|-------|-------|-------------------|\n| Mind Key | 单个 Mind | 仅该 Mind 的数据 |\n| JWT | 用户账户 | 账户管理（创建/列出/删除 Mind） |\n| Computer Token | 单台计算机 | 该计算机的命令 |\n\n## 跨 Mind 访问\n\n### 同一用户内\n\n用户可通过 JWT 访问自己所有的 Mind（例如 `GET /minds` 列出全部）。但要读写记忆数据，需要具体的 Mind Key。\n\n### 跨用户\n\n用户之间不能互访数据 — 除非通过 Sharing API 显式共享某个 Mind：\n\n```bash\n# Alice 将 Mind A 共享给 Bob\ncurl -X POST https://synapse.schaefer.zone/sharing \\\n  -H \"Authorization: Bearer ALICE_JWT\" \\\n  -d '{\"mind_id\": \"m_aaa\", \"email\": \"bob@example.com\", \"role\": \"read\"}'\n```\n\n共享后，Bob 可通过他的 JWT 访问 Mind A（若 `role=read` 则只读）。\n\n## 安全边界\n\n```\n┌─────────────────────────────────────────────────┐\n│              Synapse 实例                       │\n│  ┌─────────────────────────────────────────┐    │\n│  │         用户账户边界                     │    │\n│  │  ┌──────────────┐  ┌──────────────┐    │    │\n│  │  │  Mind 边界   │  │  Mind 边界   │    │    │\n│  │  │  (Mind Key)  │  │  (Mind Key)  │    │    │\n│  │  │              │  │              │    │    │\n│  │  │  记忆        │  │  记忆        │    │    │\n│  │  │  任务        │  │  任务        │    │    │\n│  │  │  聊天        │  │  聊天        │    │    │\n│  │  │  脚本        │  │  脚本        │    │    │\n│  │  └──────────────┘  └──────────────┘    │    │\n│  └─────────────────────────────────────────┘    │\n└─────────────────────────────────────────────────┘\n```\n\n## 常见多租户模式\n\n### 模式 1：单用户，单 Mind\n\n个人 LLM Agent 用户最常见。\n\n- 1 个用户账户\n- 1 个 Mind\n- 1 个 Mind Key\n- 所有记忆在同一范围\n\n### 模式 2：单用户，多 Mind\n\n适合有多种上下文的用户（工作、个人、项目）。\n\n- 1 个用户账户\n- N 个 Mind（例如 \"work\"、\"personal\"、\"project-x\"）\n- N 个 Mind Key\n- 每个 LLM 会话使用一个 Mind Key\n\n### 模式 3：团队共享 Mind\n\n适合团队协作某个项目。\n\n- 1 个用户创建 Mind（获得 Mind Key）\n- 创建者通过 JWT 共享给团队成员\n- 所有团队成员通过 JWT 访问（或共享的 Mind Key）\n\n> [!WARNING]\n> 共享 Mind Key 会授予完全读写权限。团队协作时，请优先使用 Sharing API（基于 JWT），而不是直接共享 Mind Key。\n\n### 模式 4：SaaS 提供商\n\n适合将 Synapse 作为记忆层嵌入的应用。\n\n- 每个客户 = 1 个用户账户\n- 每个客户项目 = 1 个 Mind\n- 应用按客户/项目存储 Mind Key\n- 客户之间完全隔离\n\n## 隔离验证\n\n### 测试：Mind Key 不能访问其他 Mind\n\n```bash\n# Mind A 的 key 不能读取 Mind B 的记忆\ncurl -H \"Authorization: Bearer mk_aaa...\" \\\n     \"https://synapse.schaefer.zone/memory/search?q=test\"\n# 仅返回 Mind A 的记忆\n\ncurl -H \"Authorization: Bearer mk_bbb...\" \\\n     \"https://synapse.schaefer.zone/memory/search?q=test\"\n# 仅返回 Mind B 的记忆（不同结果）\n```\n\n### 测试：JWT 不能直接读取记忆数据\n\n```bash\n# JWT 可以列出 Mind\ncurl -H \"Authorization: Bearer YOUR_JWT\" \\\n     https://synapse.schaefer.zone/minds\n# 返回：Mind 列表\n\n# JWT 不能读取记忆（需要 Mind Key）\ncurl -H \"Authorization: Bearer YOUR_JWT\" \\\n     https://synapse.schaefer.zone/memory/recall\n# 返回：401 Unauthorized\n```\n\n## 最佳实践\n\n> [!TIP]\n> - **每个项目/上下文使用一个 Mind** — 隔离是你的朋友\n> - **绝不共享 Mind Key** — 改用 Sharing API\n> - **泄露时轮换 Mind Key**（删除 Mind、创建新 Mind）\n> - **审计共享的 Mind** — 定期检查 `GET /sharing`\n> - **人类 UI 用 JWT** — 不要把 Mind Key 暴露给最终用户\n\n## 下一步\n\n- [Authentication](/docs/getting-started/authentication)\n- [Mind Key 与 JWT](/docs/getting-started/mind-key-vs-jwt)\n- [架构](/docs/concepts/architecture)\n","content_html":"<h1>多租户与隔离</h1>\n<p>Synapse 是多租户的：多个用户，每个用户可有多个 Mind，彼此完全隔离。本页说明隔离模型。</p>\n<h2>租户层级</h2>\n<pre><code class=\"hljs language-plaintext\">Synapse 实例\n  │\n  ├── 用户账户 1 (邮箱: alice@example.com)\n  │   ├── Mind A (Mind Key mk_aaa...)\n  │   │   ├── 记忆 (仅可通过 mk_aaa... 访问)\n  │   │   ├── 任务\n  │   │   └── 聊天\n  │   └── Mind B (Mind Key mk_bbb...)\n  │       └── ... (与 Mind A 隔离)\n  │\n  ├── 用户账户 2 (邮箱: bob@example.com)\n  │   └── Mind C (Mind Key mk_ccc...)\n  │       └── ... (与 Alice 的 Mind 隔离)\n  │\n  └── ... (更多用户)</code></pre><h2>隔离层级</h2>\n<h3>第 1 级：用户隔离</h3>\n<p>每个用户账户相互隔离。Alice 不能：</p>\n<ul>\n<li>查看 Bob 的 Mind</li>\n<li>访问 Bob 的记忆（即使有她的 JWT）</li>\n<li>列出 Bob 的账户信息</li>\n</ul>\n<p>强制方式：所有表上都有 <code>user_id</code> 列，JWT 包含 <code>user_id</code>，所有查询按 <code>user_id</code> 过滤。</p>\n<h3>第 2 级：Mind 隔离</h3>\n<p>在同一用户下，每个 Mind 相互隔离。Mind A 不能：</p>\n<ul>\n<li>查看 Mind B 的记忆</li>\n<li>访问 Mind B 的任务、聊天、脚本</li>\n</ul>\n<p>强制方式：所有数据表都有 <code>mind_id</code> 列，Mind Key 包含 <code>mind_id</code>，所有查询按 <code>mind_id</code> 过滤。</p>\n<div class=\"callout callout-critical\">Mind Key 隔离是首要的安全边界。泄露的 Mind Key 会授予对该 Mind 数据的完全访问权限 — 但仅限该 Mind。</div><h2>认证令牌</h2>\n<table>\n<thead>\n<tr>\n<th>令牌</th>\n<th>范围</th>\n<th>可访问内容</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Mind Key</td>\n<td>单个 Mind</td>\n<td>仅该 Mind 的数据</td>\n</tr>\n<tr>\n<td>JWT</td>\n<td>用户账户</td>\n<td>账户管理（创建/列出/删除 Mind）</td>\n</tr>\n<tr>\n<td>Computer Token</td>\n<td>单台计算机</td>\n<td>该计算机的命令</td>\n</tr>\n</tbody></table>\n<h2>跨 Mind 访问</h2>\n<h3>同一用户内</h3>\n<p>用户可通过 JWT 访问自己所有的 Mind（例如 <code>GET /minds</code> 列出全部）。但要读写记忆数据，需要具体的 Mind Key。</p>\n<h3>跨用户</h3>\n<p>用户之间不能互访数据 — 除非通过 Sharing API 显式共享某个 Mind：</p>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># Alice 将 Mind A 共享给 Bob</span>\ncurl -X POST https://synapse.schaefer.zone/sharing \\\n  -H <span class=\"hljs-string\">&quot;Authorization: Bearer ALICE_JWT&quot;</span> \\\n  -d <span class=\"hljs-string\">&#x27;{&quot;mind_id&quot;: &quot;m_aaa&quot;, &quot;email&quot;: &quot;bob@example.com&quot;, &quot;role&quot;: &quot;read&quot;}&#x27;</span></code></pre><p>共享后，Bob 可通过他的 JWT 访问 Mind A（若 <code>role=read</code> 则只读）。</p>\n<h2>安全边界</h2>\n<pre><code class=\"hljs language-plaintext\">┌─────────────────────────────────────────────────┐\n│              Synapse 实例                       │\n│  ┌─────────────────────────────────────────┐    │\n│  │         用户账户边界                     │    │\n│  │  ┌──────────────┐  ┌──────────────┐    │    │\n│  │  │  Mind 边界   │  │  Mind 边界   │    │    │\n│  │  │  (Mind Key)  │  │  (Mind Key)  │    │    │\n│  │  │              │  │              │    │    │\n│  │  │  记忆        │  │  记忆        │    │    │\n│  │  │  任务        │  │  任务        │    │    │\n│  │  │  聊天        │  │  聊天        │    │    │\n│  │  │  脚本        │  │  脚本        │    │    │\n│  │  └──────────────┘  └──────────────┘    │    │\n│  └─────────────────────────────────────────┘    │\n└─────────────────────────────────────────────────┘</code></pre><h2>常见多租户模式</h2>\n<h3>模式 1：单用户，单 Mind</h3>\n<p>个人 LLM Agent 用户最常见。</p>\n<ul>\n<li>1 个用户账户</li>\n<li>1 个 Mind</li>\n<li>1 个 Mind Key</li>\n<li>所有记忆在同一范围</li>\n</ul>\n<h3>模式 2：单用户，多 Mind</h3>\n<p>适合有多种上下文的用户（工作、个人、项目）。</p>\n<ul>\n<li>1 个用户账户</li>\n<li>N 个 Mind（例如 &quot;work&quot;、&quot;personal&quot;、&quot;project-x&quot;）</li>\n<li>N 个 Mind Key</li>\n<li>每个 LLM 会话使用一个 Mind Key</li>\n</ul>\n<h3>模式 3：团队共享 Mind</h3>\n<p>适合团队协作某个项目。</p>\n<ul>\n<li>1 个用户创建 Mind（获得 Mind Key）</li>\n<li>创建者通过 JWT 共享给团队成员</li>\n<li>所有团队成员通过 JWT 访问（或共享的 Mind Key）</li>\n</ul>\n<div class=\"callout callout-warn\">共享 Mind Key 会授予完全读写权限。团队协作时，请优先使用 Sharing API（基于 JWT），而不是直接共享 Mind Key。</div><h3>模式 4：SaaS 提供商</h3>\n<p>适合将 Synapse 作为记忆层嵌入的应用。</p>\n<ul>\n<li>每个客户 = 1 个用户账户</li>\n<li>每个客户项目 = 1 个 Mind</li>\n<li>应用按客户/项目存储 Mind Key</li>\n<li>客户之间完全隔离</li>\n</ul>\n<h2>隔离验证</h2>\n<h3>测试：Mind Key 不能访问其他 Mind</h3>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># Mind A 的 key 不能读取 Mind B 的记忆</span>\ncurl -H <span class=\"hljs-string\">&quot;Authorization: Bearer mk_aaa...&quot;</span> \\\n     <span class=\"hljs-string\">&quot;https://synapse.schaefer.zone/memory/search?q=test&quot;</span>\n<span class=\"hljs-comment\"># 仅返回 Mind A 的记忆</span>\n\ncurl -H <span class=\"hljs-string\">&quot;Authorization: Bearer mk_bbb...&quot;</span> \\\n     <span class=\"hljs-string\">&quot;https://synapse.schaefer.zone/memory/search?q=test&quot;</span>\n<span class=\"hljs-comment\"># 仅返回 Mind B 的记忆（不同结果）</span></code></pre><h3>测试：JWT 不能直接读取记忆数据</h3>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># JWT 可以列出 Mind</span>\ncurl -H <span class=\"hljs-string\">&quot;Authorization: Bearer YOUR_JWT&quot;</span> \\\n     https://synapse.schaefer.zone/minds\n<span class=\"hljs-comment\"># 返回：Mind 列表</span>\n\n<span class=\"hljs-comment\"># JWT 不能读取记忆（需要 Mind Key）</span>\ncurl -H <span class=\"hljs-string\">&quot;Authorization: Bearer YOUR_JWT&quot;</span> \\\n     https://synapse.schaefer.zone/memory/recall\n<span class=\"hljs-comment\"># 返回：401 Unauthorized</span></code></pre><h2>最佳实践</h2>\n<div class=\"callout callout-ok\"></div><h2>下一步</h2>\n<ul>\n<li><a href=\"/docs/getting-started/authentication\">Authentication</a></li>\n<li><a href=\"/docs/getting-started/mind-key-vs-jwt\">Mind Key 与 JWT</a></li>\n<li><a href=\"/docs/concepts/architecture\">架构</a></li>\n</ul>\n","urls":{"html":"/docs/concepts/multi-tenancy","text":"/docs/concepts/multi-tenancy?format=text","json":"/docs/concepts/multi-tenancy?format=json","llm":"/docs/concepts/multi-tenancy?format=llm"},"translations_available":["en","zh","hi","es","fr","ar","pt","ru","ja","de","it","ko","nl","pl","tr","sv","vi","th","id","uk"]}