設定スキーマ
Authrimのプラグイン設定は、検証とAdmin UIの自動生成にZodスキーマを使用します。このガイドでは設定スキーマ定義のベストプラクティスを説明します。
Zodスキーマの基本
Section titled “Zodスキーマの基本”すべてのプラグインはZodを使用してconfigSchemaを定義する必要があります:
import { z } from 'zod';
const configSchema = z.object({ apiKey: z.string().min(1), timeout: z.number().int().min(1000).max(30000).default(10000), retries: z.number().int().min(0).max(5).default(3), enabled: z.boolean().default(true),});
type MyConfig = z.infer<typeof configSchema>;describe()によるUIヒント
Section titled “describe()によるUIヒント”.describe()を使用してAdmin UI用のラベルとヘルプテキストを提供します:
const configSchema = z.object({ apiKey: z .string() .min(1) .describe('プロバイダーダッシュボードからのAPIキー'),
endpoint: z .string() .url() .default('https://api.example.com') .describe('APIエンドポイントURL。カスタムサーバー使用時のみ変更してください。'),
timeout: z .number() .int() .min(1000) .max(30000) .default(10000) .describe('リクエストタイムアウト(ミリ秒)(1000-30000)'),
logLevel: z .enum(['debug', 'info', 'warn', 'error']) .default('info') .describe('ログの詳細レベル'),});Admin UIはこれらの説明に基づいてフォームを自動生成します:
| フィールドタイプ | UIコンポーネント |
|---|---|
z.string() | テキスト入力 |
z.string().url() | URL入力 |
z.number() | 数値入力 |
z.boolean() | トグルスイッチ |
z.enum([...]) | ドロップダウン選択 |
機密名を持つz.string() | パスワード入力 |
機密フィールド
Section titled “機密フィールド”Authrimは以下のパターンに一致するフィールドを自動的に検出し、PLUGIN_ENCRYPTION_KEY または KEY_MANAGER_SECRET が設定されている場合に暗号化します:
apiKey,apiSecretsecretKey,clientSecretpassword,tokenauthToken,accessToken,refreshTokenprivateKey,credential
暗号化keyが利用できない場合でもAdmin APIのwriteは継続し、値は平文で保存され、warning logが出ます。本番secretを保存する前に暗号化keyを設定してください。
const configSchema = z.object({ // 自動的に検出されて暗号化 apiKey: z.string().describe('あなたのAPIキー'), clientSecret: z.string().describe('OAuthクライアントシークレット'), authToken: z.string().describe('認証トークン'),
// 暗号化されない(パターンに一致しない) endpoint: z.string().url(), timeout: z.number(),});手動での機密フィールド宣言
Section titled “手動での機密フィールド宣言”カスタムの機密フィールド名の場合は、APIリクエストで指定します:
curl -X PUT "/api/admin/plugins/my-plugin/config" \ -H "Content-Type: application/json" \ -d '{ "config": { "customCredential": "super-secret-value", "endpoint": "https://api.example.com" }, "secret_fields": ["customCredential"] }'APIレスポンスでのマスキング
Section titled “APIレスポンスでのマスキング”機密値はすべてのAPIレスポンスでマスキングされます:
{ "config": { "apiKey": "sk_l****XYZ1", "clientSecret": "cs_a****bcde", "endpoint": "https://api.example.com" }}マスキング形式:
- 先頭4文字と末尾4文字を表示(例:
sk_l****XYZ1) - 短い値は完全にマスク
****
JSONスキーマ変換
Section titled “JSONスキーマ変換”プラグインスキーマはAdmin UI用にJSONスキーマに自動変換されます:
// Zodスキーマconst configSchema = z.object({ apiKey: z.string().min(1).describe('あなたのAPIキー'), timeout: z.number().min(1000).max(30000).default(10000), algorithm: z.enum(['sha1', 'sha256', 'sha512']).default('sha256'),});
// JSONスキーマに変換{ "type": "object", "properties": { "apiKey": { "type": "string", "minLength": 1, "description": "あなたのAPIキー" }, "timeout": { "type": "number", "minimum": 1000, "maximum": 30000, "default": 10000 }, "algorithm": { "type": "string", "enum": ["sha1", "sha256", "sha512"], "default": "sha256" } }, "required": ["apiKey"]}設定の優先順位
Section titled “設定の優先順位”Plugin Management Admin APIは以下の順序で設定を解決します:
┌─────────────────────────────────────────┐│ 1. 環境変数 + built-in env値 │├─────────────────────────────────────────┤│ 2. KVストレージ(グローバル設定) │├─────────────────────────────────────────┤│ 3. KVストレージ(テナント固有override) │├─────────────────────────────────────────┤│ 4. plugin schema default(parse時) │└─────────────────────────────────────────┘Runtime plugin loaderはresolved plugin registry/configをcacheすることがあります。Admin APIのconfig、enable、disable endpointへのwrite後は、対象pluginとtenant scopeのplugin runtime cacheがinvalidateされます。
環境変数の規約
Section titled “環境変数の規約”# 形式: PLUGIN_{PLUGIN_ID}_CONFIG=<JSON>
# ハイフン付きのプラグインIDはアンダースコアになる組み込みnotifier pluginはdeployment env値からもbootstrapできます。たとえば notifier-resend は RESEND_API_KEY と EMAIL_FROM、notifier-cloudflare は EMAIL_FROM と EMAIL_FROM_NAME を読み、その後KV overrideが適用されます。
マルチテナント設定
Section titled “マルチテナント設定”KVキー構造
Section titled “KVキー構造”| キーパターン | 説明 |
|---|---|
plugins:config:{pluginId} | グローバル設定 |
plugins:config:{pluginId}:tenant:{tenantId} | テナント固有のオーバーライド |
plugins:enabled:{pluginId} | グローバル有効/無効 |
plugins:enabled:{pluginId}:tenant:{tenantId} | テナント有効/無効 |
テナントオーバーライドの例
Section titled “テナントオーバーライドの例”// グローバル設定const globalConfig = { apiKey: 'default-api-key',};
// テナントAはFromアドレスのみオーバーライドconst tenantAConfig = {};
// テナントAの解決された設定(マージ){ apiKey: 'default-api-key', // グローバルから}API使用法
Section titled “API使用法”# platform settings screenからtenant固有設定を取得curl "/api/admin/platform/plugins/notifier-resend/config?tenant_id=tenant_123"
# platform settings screenからtenant固有設定を更新curl -X PUT "/api/admin/platform/plugins/notifier-resend/config" \Tenant-facing /api/admin/plugins/... routeは現在のtenant contextを使います。tenant_id を明示的に渡す必要がある場合は /api/admin/platform/plugins/... を使ってください。
ネストされた設定
Section titled “ネストされた設定”設定構造はフラットまたは浅いネストに保ちます:
// ✅ 良い例:フラットまたは浅いネストconst configSchema = z.object({ apiKey: z.string(), smtp: z.object({ host: z.string(), port: z.number(), secure: z.boolean(), }), retries: z.object({ max: z.number().default(3), delay: z.number().default(1000), }),});// ❌ 悪い例:過度に深いネストconst badConfigSchema = z.object({ level1: z.object({ level2: z.object({ level3: z.object({ // ... 20レベル以上 - 機密情報がマスクされない! }), }), }),});高度なスキーマパターン
Section titled “高度なスキーマパターン”オプションとデフォルト
Section titled “オプションとデフォルト”const configSchema = z.object({ // 必須(デフォルトなし) apiKey: z.string().min(1),
// デフォルト付きオプション timeout: z.number().default(10000),
// デフォルトなしオプション webhook: z.string().url().optional(),
// nullableオプション fallbackUrl: z.string().url().nullable().default(null),});const configSchema = z.object({ // 異なる認証方式 auth: z.union([ z.object({ type: z.literal('api_key'), apiKey: z.string(), }), z.object({ type: z.literal('oauth'), clientId: z.string(), clientSecret: z.string(), }), ]),});条件付き検証
Section titled “条件付き検証”const configSchema = z.object({ useTLS: z.boolean().default(true), tlsCert: z.string().optional(), tlsKey: z.string().optional(),}).refine( (data) => !data.useTLS || (data.tlsCert && data.tlsKey), { message: 'TLSが有効な場合、証明書と鍵が必要です' });const configSchema = z.object({ endpoints: z .array(z.string().url()) .min(1) .max(5) .describe('APIエンドポイントのリスト(1-5)'),
allowedDomains: z .array(z.string()) .default([]) .describe('コールバックに許可されるドメイン'),});ベストプラクティス
Section titled “ベストプラクティス”適切なデフォルト値を使用
Section titled “適切なデフォルト値を使用”const configSchema = z.object({ // セキュアなデフォルト timeout: z.number().default(10000), // 10秒 retries: z.number().default(3), validateCerts: z.boolean().default(true), // セキュリティ:常に検証
// 本番環境で安全なデフォルト logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info'), rateLimit: z.number().default(60),});制約を文書化
Section titled “制約を文書化”const configSchema = z.object({ timeout: z .number() .int() .min(1000) .max(30000) .default(10000) .describe('リクエストタイムアウト(ms)(1000-30000)。低速ネットワークでは増加。'),
batchSize: z .number() .int() .min(1) .max(100) .default(10) .describe('バッチあたりのアイテム数(1-100)。大きい値はメモリを多く使用。'),});関連設定をグループ化
Section titled “関連設定をグループ化”const configSchema = z.object({ // 接続設定 host: z.string().default('smtp.example.com'), port: z.number().default(587), secure: z.boolean().default(true),
// 認証 username: z.string().optional(), password: z.string().optional(),
// メッセージのデフォルト defaultFrom: z.string().email(), defaultReplyTo: z.string().email().optional(),});次のステップ
Section titled “次のステップ”- デプロイと配布 - プラグインのパッケージングと公開
- Admin UI管理 - Admin Consoleでのプラグイン管理
- プラグイン管理API - APIリファレンス