{"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":308,"read_minutes":2,"lang":"ja","translated":true,"requested_lang":"ja","content_markdown":"\n# マルチテナント & 分離\n\nSynapse はマルチテナントです — 複数のユーザーが各々複数の mind を持ち、完全に分離されています。本ページでは分離モデルを説明します。\n\n## テナント階層\n\n```\nSynapse Instance\n  │\n  ├── User Account 1 (email: alice@example.com)\n  │   ├── Mind A (Mind Key mk_aaa...)\n  │   │   ├── Memories (only accessible via mk_aaa...)\n  │   │   ├── Tasks\n  │   │   └── Chat\n  │   └── Mind B (Mind Key mk_bbb...)\n  │       └── ... (isolated from Mind A)\n  │\n  ├── User Account 2 (email: bob@example.com)\n  │   └── Mind C (Mind Key mk_ccc...)\n  │       └── ... (isolated from Alice's minds)\n  │\n  └── ... (more users)\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 shares Mind A with 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 Instance                    │\n│  ┌─────────────────────────────────────────┐    │\n│  │         User Account Boundary           │    │\n│  │  ┌──────────────┐  ┌──────────────┐    │    │\n│  │  │  Mind Bound. │  │  Mind Bound. │    │    │\n│  │  │  (Mind Key)  │  │  (Mind Key)  │    │    │\n│  │  │              │  │              │    │    │\n│  │  │  Memories    │  │  Memories    │    │    │\n│  │  │  Tasks       │  │  Tasks       │    │    │\n│  │  │  Chat        │  │  Chat        │    │    │\n│  │  │  Scripts     │  │  Scripts     │    │    │\n│  │  └──────────────┘  └──────────────┘    │    │\n│  └─────────────────────────────────────────┘    │\n└─────────────────────────────────────────────────┘\n```\n\n## よくあるマルチテナントパターン\n\n### パターン 1：単一ユーザー、単一 mind\n\n個人 LLM エージェントユーザーに最も一般的。\n\n- 1 ユーザーアカウント\n- 1 mind\n- 1 Mind Key\n- すべてのメモリが 1 スコープに\n\n### パターン 2：単一ユーザー、複数 mind\n\n複数コンテキスト（仕事、個人、プロジェクト）を持つユーザー向け。\n\n- 1 ユーザーアカウント\n- N mind（例：「work」「personal」「project-x」）\n- N Mind Key\n- 各 LLM セッションは 1 つの 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 の共有は完全な読み書きアクセスを与えます。チーム協業には、Mind Key を直接共有するより Sharing API（JWT ベース）を使用してください。\n\n### パターン 4：SaaS プロバイダー\n\nSynapse をメモリレイヤーとして組み込むアプリ向け。\n\n- 各顧客 = 1 ユーザーアカウント\n- 各顧客プロジェクト = 1 mind\n- アプリが顧客/プロジェクトごとに Mind Key を保存\n- 顧客間の完全な分離\n\n## 分離の検証\n\n### テスト：Mind Key は他の mind にアクセスできない\n\n```bash\n# Mind A's key cannot read Mind B's memories\ncurl -H \"Authorization: Bearer mk_aaa...\" \\\n     \"https://synapse.schaefer.zone/memory/search?q=test\"\n# Returns only Mind A's memories\n\ncurl -H \"Authorization: Bearer mk_bbb...\" \\\n     \"https://synapse.schaefer.zone/memory/search?q=test\"\n# Returns only Mind B's memories (different results)\n```\n\n### テスト：JWT はメモリデータに直接アクセスできない\n\n```bash\n# JWT can list minds\ncurl -H \"Authorization: Bearer YOUR_JWT\" \\\n     https://synapse.schaefer.zone/minds\n# Returns: list of minds\n\n# JWT CANNOT read memories (need Mind Key)\ncurl -H \"Authorization: Bearer YOUR_JWT\" \\\n     https://synapse.schaefer.zone/memory/recall\n# Returns: 401 Unauthorized\n```\n\n## ベストプラクティス\n\n> [!TIP]\n> - **プロジェクト/コンテキストごとに 1 つの mind を使用** — 分離は味方です\n> - **Mind Key を共有しない** — Sharing API を使用\n> - **侵害された場合は Mind Key をローテーション**（mind を削除して新規作成）\n> - **共有 mind を監査** — 定期的に `GET /sharing` を確認\n> - **human UI には JWT を使用** — エンドユーザーに Mind Key を露出しない\n\n## 次のステップ\n\n- [Authentication](/docs/getting-started/authentication)\n- [Mind Key vs JWT](/docs/getting-started/mind-key-vs-jwt)\n- [Architecture](/docs/concepts/architecture)\n","content_html":"<h1>マルチテナント &amp; 分離</h1>\n<p>Synapse はマルチテナントです — 複数のユーザーが各々複数の mind を持ち、完全に分離されています。本ページでは分離モデルを説明します。</p>\n<h2>テナント階層</h2>\n<pre><code class=\"hljs language-plaintext\">Synapse Instance\n  │\n  ├── User Account 1 (email: alice@example.com)\n  │   ├── Mind A (Mind Key mk_aaa...)\n  │   │   ├── Memories (only accessible via mk_aaa...)\n  │   │   ├── Tasks\n  │   │   └── Chat\n  │   └── Mind B (Mind Key mk_bbb...)\n  │       └── ... (isolated from Mind A)\n  │\n  ├── User Account 2 (email: bob@example.com)\n  │   └── Mind C (Mind Key mk_ccc...)\n  │       └── ... (isolated from Alice&#x27;s minds)\n  │\n  └── ... (more users)</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 shares Mind A with 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 Instance                    │\n│  ┌─────────────────────────────────────────┐    │\n│  │         User Account Boundary           │    │\n│  │  ┌──────────────┐  ┌──────────────┐    │    │\n│  │  │  Mind Bound. │  │  Mind Bound. │    │    │\n│  │  │  (Mind Key)  │  │  (Mind Key)  │    │    │\n│  │  │              │  │              │    │    │\n│  │  │  Memories    │  │  Memories    │    │    │\n│  │  │  Tasks       │  │  Tasks       │    │    │\n│  │  │  Chat        │  │  Chat        │    │    │\n│  │  │  Scripts     │  │  Scripts     │    │    │\n│  │  └──────────────┘  └──────────────┘    │    │\n│  └─────────────────────────────────────────┘    │\n└─────────────────────────────────────────────────┘</code></pre><h2>よくあるマルチテナントパターン</h2>\n<h3>パターン 1：単一ユーザー、単一 mind</h3>\n<p>個人 LLM エージェントユーザーに最も一般的。</p>\n<ul>\n<li>1 ユーザーアカウント</li>\n<li>1 mind</li>\n<li>1 Mind Key</li>\n<li>すべてのメモリが 1 スコープに</li>\n</ul>\n<h3>パターン 2：単一ユーザー、複数 mind</h3>\n<p>複数コンテキスト（仕事、個人、プロジェクト）を持つユーザー向け。</p>\n<ul>\n<li>1 ユーザーアカウント</li>\n<li>N mind（例：「work」「personal」「project-x」）</li>\n<li>N Mind Key</li>\n<li>各 LLM セッションは 1 つの 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 の共有は完全な読み書きアクセスを与えます。チーム協業には、Mind Key を直接共有するより Sharing API（JWT ベース）を使用してください。</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&#x27;s key cannot read Mind B&#x27;s memories</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\"># Returns only Mind A&#x27;s memories</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\"># Returns only Mind B&#x27;s memories (different results)</span></code></pre><h3>テスト：JWT はメモリデータに直接アクセスできない</h3>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># JWT can list minds</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\"># Returns: list of minds</span>\n\n<span class=\"hljs-comment\"># JWT CANNOT read memories (need 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\"># Returns: 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 vs JWT</a></li>\n<li><a href=\"/docs/concepts/architecture\">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"]}