Chorus はすべてのリクエストを認証して一つの統一された `AuthContext` に解決し、そのうえで、きめ細かな権限
セットに照らしてエージェントに何ができるかを制御します。本ページは、認証方式、エージェント API キーの
仕様、そして MCP ツールの可視性と REST アクセスの両方を駆動する権限モデルを説明します。

引用できる安定したアンカー：[`#統一された-authcontext`](#統一された-authcontext)、
[`#解決カスケード`](#解決カスケード)、[`#agent-api-key`](#agent-api-key)、
[`#権限モデル`](#権限モデル)、[`#ロールプリセット`](#ロールプリセット)、
[`#カスタム権限と有効な権限セット`](#カスタム権限と有効な権限セット)。

## 統一された AuthContext

認証されたすべてのリクエストは、三つのコンテキスト種別のいずれかへ解決されます。マルチテナンシーは
`companyUuid` を通じて強制されます。すべてのデータアクセスはその範囲に限定され、複数のワークスペースにまたがって
操作できるのはスーパー管理者だけです。

| コンテキスト種別 | `type` | 主なフィールド | 生成元 |
| --- | --- | --- | --- |
| User | `user` | `companyUuid`、`actorUuid`、`email`、`name` | OIDC、Default Auth |
| Agent | `agent` | `companyUuid`、`actorUuid`、`roles[]`（プリセット選択子）、`permissions[]`（有効セット）、`agentName`、`ownerUuid` | API キー |
| スーパー管理者 | `super_admin` | `email`（`companyUuid` なし） | スーパー管理者セッション |

エージェントの認可は、その `permissions[]`、つまりフラットな有効セットからすべて生じます。`roles[]`
フィールドはプリセットの選択子にすぎず、認可の源ではありません。

## 解決カスケード

単一の入口が、優先順位に従って各方式を順に試し、最初の成功で返します。

```text
1. Authorization: Bearer <token>
   ├─ cho_… 接頭辞 → API key の検証            → Agent コンテキスト
   ├─ RS*/ES* JWT   → OIDC トークンの検証        → User コンテキスト
   └─ HS256 JWT     → Chorus JWT の検証           → User コンテキスト
2. セッション Cookie
   └─ user_session                         → User
3. OIDC Cookie（SSE / EventSource 用、Authorization ヘッダーなし）
   └─ oidc_access_token cookie                → User コンテキスト
4. 一致なし → 未認証
```

ステップ 1 のトークンは形状で分類されます。`cho_` 接頭辞は API キーです。それ以外の 3 つの部分からなる JWT は、
ヘッダーのアルゴリズムが非対称（`RS*`/`ES*`）なら OIDC、`HS256` なら Chorus の自己署名セッション
トークンです。

## セッション署名用の秘密鍵

`NEXTAUTH_SECRET` は Default Auth の `user_session` とスーパー管理者の `admin_session` JWT
に署名します。スーパー管理者ルートは通常のユーザー認証とは別に `admin_session` を検証します。
OIDC トークンはプロバイダーの鍵で、エージェントの API キーは保存されたハッシュで検証します。
`NEXTAUTH_SECRET` を変更すると Chorus が署名したセッションは無効になりますが、API キーや OIDC トークンには影響しません。

npm ランチャーは生成した鍵を既定で `~/.chorus-data/.secret` に保存し、Docker は `/app/data/.secret`
を使います。どちらも環境変数の既知の公開プレースホルダーを無視し、保存済みの鍵が公開プレースホルダー
なら起動を停止します。直接起動する場合は鍵を自分で設定してください。
0.18.1 での移行、永続化、レプリカの設定は [Docker のセッション秘密鍵](/ja/guides/deploy-docker/#セッションの秘密鍵nextauth_secret)を参照してください。

## Agent API key

エージェントは、すべての MCP と REST リクエストで bearer の API キーにより認証します。

```http
Authorization: Bearer cho_<random>
```

その仕様は次のとおりです。

- **`cho_` 接頭辞。** すべてのキーは `cho_` で始まり、その後に base64url エンコードされたランダム
  バイトが続きます。解決カスケードはこの接頭辞でキーと JWT を見分けます。
- **一度だけ表示。** 生のキーは作成時にのみ返されます。そのとき控えてください。あとから取得はできません。
- **保存時は SHA-256 ハッシュ。** 保存されるのはキーの SHA-256 ハッシュだけです。データベースは生の値を
  決して保持しないため、データベースのダンプから使える認証情報が漏れることはありません。
- **タイミング安全な比較。** 検証は提示されたトークンをハッシュ化し、ハッシュどうしを定数時間で比較します。
  そのため、先頭が何文字一致しても、不一致にかかる時間は同じです。
- **ローテーション、失効、有効期限。** キーは失効させたり、任意の有効期限を与えたりできます。失効した
  キーや期限切れのキーは検証に失敗します。ローテーションは、置き換えのキーを作り、古いものを失効させて
  行います。権限はキーではなくエージェントに設定されているため、キーをローテーションしてもエージェントの
  権限は保たれます。権限を変えるにはエージェントを編集します。

:::caution[キーは一度だけ表示される]
作成後に生のキーを復元する方法はありません。シークレットマネージャーに保管し、パスワードのように扱ってください。
漏れたら失効させ、置き換えを発行してください。
:::

キーの作成、編集、ローテーション、失効は API 呼び出しではなく **設定** 画面で行います。認証情報の作成
手順は[エージェントのアクセスを準備する](/ja/guides/administrator-setup/)、編集と失効は
[エージェントと API キーを管理する](/ja/guides/manage-agents/)、キーをエージェントに組み込む方法は
[エージェントランタイムを接続する](/ja/guides/operator-onboarding/)をご覧ください。

## その他の認証方式

以下は人間のユーザーとプラットフォーム管理者向けです。ここでは要点をまとめます。設定は運用ガイドが扱います。

### OIDC（ユーザー）

人間のユーザー向けのエンタープライズ SSO で、スーパー管理者がワークスペースごとに設定します（issuer、client ID、
有効化トグル）。サインインは **PKCE** 付きの認可コードフローを使い、client secret は不要です。プロバイダーが
リダイレクトで戻したあと、Chorus は `(companyUuid, oidcSub)` でユーザーを検索または作成し、HTTP-only の
Cookie を設定します。

| Cookie | 用途 |
| --- | --- |
| `oidc_access_token` | API 呼び出し用のアクセストークン（約 1 時間） |
| `oidc_refresh_token` | サイレント更新用のリフレッシュトークン（約 30 日） |
| `oidc_client_id` | トークン更新時に使う client ID |
| `oidc_issuer` | JWKS 発見に使う issuer |

アクセストークンはプロバイダーの JWKS（キャッシュ済み）に照らして検証され、edge middleware はリクエストが
アプリに届く前に、期限切れ間近のアクセストークンを透過的に更新します。

### Default Auth（開発用）

OIDC のない開発・デモ向けの、単一のメール／パスワードによるサインインです。`DEFAULT_USER` と `DEFAULT_PASSWORD`
の両方が設定されているときにのみ有効になります。

```bash
DEFAULT_USER="dev@example.local"
DEFAULT_PASSWORD="change-me"
```

サインイン時、Chorus はワークスペースとユーザーを自動プロビジョニングし、長寿命の自己署名 JWT を一つ、`user_session`
Cookie に発行します。更新フローはなく、期限が切れたらユーザーが再度サインインします。本番では Default Auth を
有効にしないでください。

### スーパー管理者

すべてのワークスペースにまたがるプラットフォームレベルの管理（ワークスペースの管理、ワークスペースごとの OIDC 設定）です。環境変数に、
メールと **bcrypt** のパスワードハッシュを設定します。

```bash
SUPER_ADMIN_EMAIL="admin@example.com"
SUPER_ADMIN_PASSWORD_HASH="$2b$10$…"   # bcrypt ハッシュ
```

サインインに成功すると `admin_session` Cookie が設定されます。スーパー管理者コンテキストは **`companyUuid`
を持たない**ため、ワークスペースによる範囲の制限を受けません。テナントをまたいで読める唯一のコンテキストです。

## 権限モデル

エージェントの認可は権限ビットの集合です。エージェントが持つ有効セットが、あらゆる層で、それに何が
できるかを決めます。

### 5 × 3 のマトリクス

権限は `{resource}:{action}` と書きます。五つの資源に三つの動作を掛けて、15 個の可能なビットになります。

| | `read` | `write` | `admin` |
| --- | --- | --- | --- |
| **`idea`** | 着想を閲覧 | 着想の作成 / 担当 / 解除 / 更新；要件詳細化の実行 | 着想のクローズ / 削除 |
| **`proposal`** | 提案とドラフトを閲覧 | 作成 / 提出 / 却下 / 撤回；ドラフトの管理；課題の一括作成；課題 DAG の管理；課題の割り当て | 提案の承認 / クローズ |
| **`document`** | 文書を閲覧 | 文書の作成 / 更新 | 文書の削除 |
| **`task`** | 課題を閲覧 | 担当 / 解除 / 提出 / 報告；受け入れ基準の自己確認 | 課題の検証 / 再オープン / クローズ / 削除；受け入れ基準のマーク |
| **`project`** | プロジェクトとグループを閲覧 | プロジェクトとグループの作成 / 更新 / 削除；プロジェクトの移動 | 予約済み（`admin_agent` に含まれるが、現時点でこれを必要とする操作はない） |

各動作は通常まとめて付与されますが、**どの動作も他の動作を含意しません**。`task:admin` を付与しても
`task:read` や `task:write` は含まれないため、各ビットを明示的に付与します。

:::caution[`*:admin` ビットは人間レベル]
`admin` の列は、通常は人間のレビュー担当者を要する動作、つまり提案の承認、課題の検証、エンティティの
削除を扱います。`*:admin` ビットを付与すると、エージェントがその人間の判断を肩代わりできます。admin ビットの効力は
エージェント自身の作業に限られません。`task:admin` があれば、エージェントが手がけた課題だけでなく、ワークスペース内の任意の課題を検証できます。
admin ビットは、承認ワークフローを意図的に自動化するエージェントにだけ付与してください。
:::

### ロールプリセット

三つの名前付きプリセットは、15 個のビットの固定された部分集合に展開されます。プリセットは近道であって、
独立した認可のしくみではありません。

| プリセット | 個数 | 展開される権限 |
| --- | :---: | --- |
| `developer_agent` | **6** | `*:read` + `task:write` |
| `pm_agent` | **10** | `*:read` + `idea:write` + `proposal:write` + `document:write` + `task:write` + `project:write` |
| `admin_agent` | **15** | すべてのビット（`*:read` + `*:write` + `*:admin`） |

展開すると、各プリセットは次のようになります。

```text
developer_agent (6):
  idea:read  proposal:read  document:read  project:read  task:read
  task:write

pm_agent (10):
  idea:read      idea:write
  proposal:read  proposal:write
  document:read  document:write
  task:read      task:write
  project:read   project:write

admin_agent (15):
  idea:read      idea:write      idea:admin
  proposal:read  proposal:write  proposal:admin
  document:read  document:write  document:admin
  task:read      task:write      task:admin
  project:read   project:write   project:admin
```

### カスタム権限と有効な権限セット

プリセットに加えて、エージェントはカスタムの権限ビットを持てます。**有効セット**は、展開されたプリセットと
カスタムビットの和集合です。

```text
effective = expand(preset) ∪ custom
```

順序は関係ありません。純粋な集合の和です。よくある形は次のとおりです。

- **読み取り専用の監査者** — プリセットなし、カスタムは `*:read` のみ：すべてを閲覧できるが、何も変更できない。
- **自己検証する開発者** — `developer_agent` + `task:admin`：管理者を待たずに課題を検証できる。
- **承認権を持つ PM** — `pm_agent` + `proposal:admin`：提案を直接承認できる。

### 有効セットがどうアクセスを制御するか

同じ有効セットが、次の二つの経路でアクセスを決定します。

- **MCP ツールの可視性。** 権限で制限される各 MCP ツールは、必要な権限をちょうど一つ宣言します。接続時、
  ツールの必要な権限が有効セットに含まれる場合にのみ、そのツールはエージェントのサーバーに登録されます。
  そうでなければ、そのツールは単にエージェントのツール一覧に現れません。共通ツール（discover / read /
  list / search / comment / session、そして `chorus_create_tasks` / `chorus_update_task`）は制限されず、
  すべてのエージェントに現れます。
- **REST のアクセス制御。** 権限で制限される各 REST ルートは、呼び出し元のエージェントが
  特定の `{resource}:{action}` ビットを一つ持っているかを検査します。そのビットを欠くエージェントは
  `403 Missing permission` を受け取ります。人間のユーザーはこのエージェント権限検査の対象ではなく
  （人間のアクセスはセッションを通じて検査されます）、スーパー管理者はすべての権限検査を素通りします。

:::note[エージェントが見るもの]
エージェントのツール一覧は、共通ツールと、その有効な権限で使えるようになる制限付きツールを合わせたものです。
期待するツールが見当たらないなら、そのエージェントは必要な権限を欠いています。キーではなく、エージェントの
権限を編集してください。完全なツール → 権限の対応は、[MCP ツールカタログ](/ja/reference/mcp-tools/)をご覧ください。
:::
