A release-readiness QA pass over the whole product. The commits split into defects a user would hit and gates that were reporting green while measuring nothing. ## Fixes that change behaviour Rate limiting was bypassable on every install: TRUST_PROXY defaulted to true, so request.ip came from a client-set header and a forged X-Forwarded-For got past the login limiter. The default is now a private-network trust list. A transient Postgres outage stranded in-flight jobs, leaving finished output on disk with no row pointing at it. A reconciler now resolves those rows and adopts the bytes rather than dropping the work. A Redis connection that moved to a new address wedged every read-blocked consumer, so completions stopped signalling while health still answered 200. Socket timeouts plus subscriber pings recover it. Installing more than one AI bundle left the shared venv multi-versioned and silently broke three tools. The installer now reconciles distributions to one version each. Converting an image to JXL at quality 1 through 4 returned a 500, because libjxl 0.7 rejects the distance those values compute. The quality is floored at what the encoder honours. A missing ffmpeg was also reported to the user as a corrupt upload; it now says the engine is unavailable. RAW uploads reached an unpatched LibRaw on arm64, so it is built from source at 0.22.2, and the release scan was split so it can fail on an unfixed critical instead of hiding it behind ignore-unfixed. ## Gates that could not fail Two mutation lanes ran zero mutants because Stryker crawled the gitignored docs build; coverage discarded its whole report on any failing test; the lint gate skipped root tests, scripts, and two workspaces; and several generated matrices counted a host missing ffmpeg as a passing tool. Each now measures what it claims. Full evidence and the outstanding release items are tracked locally and are not part of this branch.
15 KiB
description, i18n_source_hash, i18n_provenance, i18n_output_hash, i18n_hash_version
| description | i18n_source_hash | i18n_provenance | i18n_output_hash | i18n_hash_version |
|---|---|---|---|---|
| SnapOtter でユーザー、組み込みおよびカスタムロール、権限、API キー、チーム、セッション、監査ログを管理します。 | bea8955f3aff | human | 714dea2a8e1f | 2 |
ユーザー、ロール、権限
SnapOtter は 3 つの組み込みロール、17 の細粒度な権限、そしてツールごとのアクセス制御を任意で設定できるカスタムロールをサポートします。このページでは、認可モデル全体、API キーのスコープ設定、チーム管理、監査ログについて説明します。
::: tip 関連ページ OIDC / SSO | SAML SSO | SCIM プロビジョニング | セキュリティと堅牢化 :::
ユーザー
ユーザーの作成
管理者は管理パネルまたは POST /api/auth/register エンドポイントを通じてユーザーを作成できます。各ユーザーはユーザー名、ロール、チーム割り当て、および任意のメールアドレスを持ちます。
デフォルト管理者
初回起動時に SnapOtter はデフォルトの管理者アカウントを作成します。認証情報は環境変数から取得されます:
| Variable | Default | Description |
|---|---|---|
DEFAULT_USERNAME |
admin |
初期管理者アカウントのユーザー名 |
DEFAULT_PASSWORD |
admin |
初期管理者アカウントのパスワード |
デフォルト管理者は初回ログイン時にパスワードの変更を求められます。
認証プロバイダー
ユーザーはいくつかの方法で認証できます:
- ローカル - SnapOtter データベースに保存されるユーザー名とパスワード
- OIDC - 任意の OpenID Connect プロバイダー(OIDC / SSO を参照)
- SAML - SAML 2.0 アイデンティティプロバイダー(SAML SSO を参照)
- SCIM - アイデンティティプロバイダーからの自動プロビジョニング(SCIM プロビジョニング を参照)
認証の無効化
AUTH_ENABLED=false を設定すると認証を完全に無効化できます。このモードでは、すべてのリクエストに対して admin ロールを持つ合成の匿名ユーザーが使用されます。ログインは不要です。
::: warning 認証を無効化すると、インスタンスに到達できる誰もが完全な管理者アクセスを得ます。信頼できる環境でのみ使用してください。 :::
組み込みロール
SnapOtter には 3 つの組み込みロールが含まれています。これらは変更または削除できません。
管理者 (Admin)
17 のすべての権限。インスタンスを完全に制御します。
tools:use files:own files:all apikeys:own apikeys:all pipelines:own pipelines:all settings:read settings:write users:manage teams:manage features:manage system:health audit:read compliance:manage webhooks:manage security:manage
編集者 (Editor)
7 の権限。すべてのツールを使用し、すべてのファイルとパイプラインを管理できますが、管理者機能にはアクセスできません。
tools:use files:own files:all apikeys:own pipelines:own pipelines:all settings:read
ユーザー (User)
5 の権限。ツールを使用し、自分自身のリソースを管理できます。
tools:use files:own apikeys:own pipelines:own settings:read
権限リファレンス
| Permission | Description |
|---|---|
tools:use |
任意の処理ツールを使用する |
files:own |
自分のファイルを表示・管理する |
files:all |
すべてのユーザーのファイルを表示・管理する |
apikeys:own |
自分の API キーを作成・管理する |
apikeys:all |
すべてのユーザーの API キーを表示する |
pipelines:own |
自分のパイプラインを作成・管理する |
pipelines:all |
すべてのユーザーのパイプラインを表示・管理する |
settings:read |
インスタンス設定を表示する |
settings:write |
インスタンス設定を変更する |
users:manage |
攻撃者の権限境界内でユーザー アカウントを作成および管理する |
teams:manage |
チームを作成・更新・削除する |
features:manage |
AI 機能バンドルをインストール・管理する |
system:health |
ヘルスおよびレディネスのエンドポイントにアクセスする |
audit:read |
監査ログを表示し、ロールを一覧表示する |
compliance:manage |
GDPR ライフサイクルとコンプライアンス機能を管理します。破壊的なユーザー操作は依然として権限に制限されています |
webhooks:manage |
アウトバウンドの Webhook を設定する |
security:manage |
セキュリティ設定を管理する(IP 許可リスト、SSO 強制) |
カスタムロール
security:manage 権限を持つ管理者は、管理パネルまたはロール API を通じてカスタムロールを作成できます。ロールの一覧表示には audit:read が必要です。
カスタムロールの作成
curl -X POST http://localhost:1349/api/v1/roles \
-H "Authorization: Bearer si_..." \
-H "Content-Type: application/json" \
-d '{
"name": "reviewer",
"description": "Can use tools and view all files",
"permissions": ["tools:use", "files:own", "files:all", "settings:read"]
}'
ロール名は 2〜30 文字で、ハイフンとアンダースコアを含む小文字の英数字にする必要があります。
委任された管理の境界
17 個のアクセス許可はすべてカスタム ロールを通じて委任できますが、管理アクセス許可によってそのロールが組み込みの admin ロールと同等になるわけではありません。 users:manage によって承認されたユーザーの変更、compliance:manage によって承認された破壊操作、および security:manage によって承認されたカスタム ロール管理は、アクターの現在の権限によって制限されます。
- 組み込みロールは、
admin>editor>userの順に続きます。カスタム ロールは組み込みロールの下にあります。 - ターゲットの権限は、アクターの有効な権限に含まれている必要があります。したがって、スコープ付き API キーは、そのスコープから省略された権限を行使できません。
- ターゲット ロールのツール アクセスは、アクター自身のツール アクセスに含まれている必要があります。
- 無効化されたアカウントは、そのロールが
disabled:<original-role>として記録されている場合、その元のロールに対してチェックされます。 - カスタム ロールを削除するには、組み込みの
userフォールバックを割り当てる権限も必要です。無効なメンバーはdisabled:userとして無効のままになります。
グローバル認証情報と構成はより厳密です。SCIM トークンの発行または取り消し、およびインスタンス構成のインポートには、完全な有効な管理者権限を持つ組み込みの admin ロールが必要です。
ツールレベルの権限
カスタムロールは、ユーザーがアクセスできるツールを任意で制限できます。2 つのモードが利用可能です:
| Mode | Behavior | License requirement |
|---|---|---|
category |
モダリティ(image、video、audio、document、file)で制限する | なし(無料) |
tool |
個別のツール ID で制限する | per_tool_permissions エンタープライズ機能が必要 |
tool モードが設定されているがエンタープライズ機能が利用できない場合、SnapOtter は正常に劣化し、すべてのツールへのアクセスを許可します。
{
"name": "image-only",
"permissions": ["tools:use", "files:own"],
"toolPermissions": {
"mode": "category",
"allowed": ["image"]
}
}
カスタムロールの削除
カスタムロールが削除されると、それに割り当てられたすべてのユーザーは自動的に user ロールに再割り当てされます。
チーム
チームはストレージと保持の管理のためにユーザーをグループ化します。初回起動時に Default チームが作成されます。
| Field | Type | Description |
|---|---|---|
name |
string | 一意のチーム名(1〜50 文字) |
storageQuota |
number | チームごとのストレージ上限(バイト単位、エンタープライズなしで機能) |
retentionHours |
number | この時間数が経過した後に出力を自動削除する(team_retention_overrides、エンタープライズが必要) |
legalHold |
boolean | チームメンバーのファイルの自動削除を防止する(legal_hold、エンタープライズが必要) |
::: info
Default チームは削除できません。メンバーがまだ在籍しているチームは削除できません。先にメンバーを再割り当てしてください。
:::
API キー
ユーザーはプログラムからのアクセス用に API キーを生成できます。各キーは si_ プレフィックスを使用し、作成時に一度だけ表示されます。
スコープ付き権限
API キーは任意で permissions 配列を持つことができます。設定されている場合、リクエストの実効権限はユーザーのロール権限とキーのスコープ付き権限の積集合になります。つまり、API キーはユーザー自身の権限を超えて昇格することは決してできません。
curl -X POST http://localhost:1349/api/v1/api-keys \
-H "Authorization: Bearer si_..." \
-H "Content-Type: application/json" \
-d '{
"name": "CI pipeline key",
"permissions": ["tools:use", "files:own"],
"expiresAt": "2027-01-01T00:00:00Z"
}'
有効期限
キーは任意の expiresAt タイムスタンプを受け付けます。期限切れのキーは認証時に拒否されます。
監査ログ
SnapOtter はセキュリティに関連するイベントを audit_log データベーステーブルに保存された構造化された監査ログに記録します。
監査ログの表示
GET /api/v1/audit-log?page=1&limit=50&action=LOGIN_FAILED&from=2026-01-01T00:00:00Z&to=2026-12-31T23:59:59Z
audit:read 権限が必要です。ページネーション(page、limit)とフィルター(action、ip、from、to)をサポートします。
ツール操作の監査
::: warning
TOOL_EXECUTED イベントはデフォルトでは記録されません。次の 2 つの方法のいずれかでオプトインします:
auditToolOperations管理設定をtrueに設定する。audit_export機能を持つ有効なライセンスを保持する(team プランと enterprise プランの両方で利用可能)。
これらのいずれかがない場合、個々のツール実行は監査ログに記録されません。 :::
エクスポート
GET /api/v1/enterprise/audit/export?format=csv&from=2026-01-01T00:00:00Z
audit:read 権限と audit_export エンタープライズ機能が必要です(team プランと enterprise プランの両方で利用可能)。CSV と JSON 形式をサポートし、action、actorId、targetType、targetId、from、to でフィルタリングできます。
改ざん耐性のある署名
有効にすると、各監査ログエントリは DATA_ENCRYPTION_KEY から派生した HMAC で署名されます。これには以下が必要です:
- 環境で
DATA_ENCRYPTION_KEYを設定する。 tamperResistantAudit管理設定を有効にする。tamper_resistant_audit機能を持つエンタープライズライセンス。
保持
古いエントリを自動的に削除するには AUDIT_RETENTION_DAYS を設定します。デフォルトは 0 で、エントリを無期限に保持することを意味します。
イベントリファレンス
| Event | Category |
|---|---|
LOGIN_SUCCESS, LOGIN_FAILED |
認証 |
OIDC_LOGIN_SUCCESS, OIDC_LOGIN_FAILED |
認証 |
SAML_LOGIN_SUCCESS, SAML_LOGIN_FAILED |
認証 |
LOGOUT |
認証 |
USER_CREATED, USER_UPDATED, USER_DELETED |
ユーザー管理 |
PASSWORD_CHANGED, PASSWORD_RESET |
ユーザー管理 |
MFA_ENROLLED, MFA_DISABLED, MFA_VERIFIED, MFA_VERIFY_FAILED |
MFA |
MFA_CHALLENGE_ISSUED, MFA_RECOVERY_USED, MFA_RESET |
MFA |
ROLE_CREATED, ROLE_UPDATED, ROLE_DELETED |
ロール |
API_KEY_CREATED, API_KEY_DELETED |
API キー |
SETTINGS_UPDATED, IP_ALLOWLIST_UPDATED |
設定 |
FILE_UPLOADED, FILE_DELETED |
ファイル |
TOOL_EXECUTED |
ツール(オプトイン) |
SCIM_USER_PROVISIONED, SCIM_USER_UPDATED, SCIM_USER_DEPROVISIONED |
SCIM |
SCIM_GROUP_SYNCED |
SCIM |
LEGAL_HOLD_APPLIED, LEGAL_HOLD_RELEASED |
コンプライアンス |
GDPR_EXPORT_INITIATED, GDPR_USER_PURGED, GDPR_TEAM_PURGED |
コンプライアンス |
CONFIG_EXPORTED, CONFIG_IMPORTED |
設定 |
セッション管理
セッションは Cookie ベースで、SESSION_DURATION_HOURS(デフォルト: 168 時間 / 7 日)で制御されます。
ロール変更はセッションを無効化する
管理者がユーザーのロールを変更すると、そのユーザーのすべてのアクティブなセッションが削除されます。ユーザーは新しい権限を反映するために再度ログインする必要があります。
安全ガード
- 最後の管理者の保護: 残っている最後の管理者を下位のロールに降格することはできません。試みると API はエラーを返します。
- 自己削除の防止: 管理者は API を通じて自分自身のアカウントを削除できません。