settings

Settings カタログ

本製品は Frontend-Configurable First — DB 接続などの最小ブートストラップ以外は Settings 画面から編集します。12 セクション・120+ キーの全カタログと scope 継承・hot reload・KMS 暗号化を定義します。

設計原則: Frontend-Configurable First

すべての構成値は Settings 画面から編集できる、を原則とします。これにより新環境のセットアップ・本番テナントの設定変更・機密ローテーションが UI と監査ログだけで完結 します。

ID原則意味
F1 起動時にしか効かない値であっても、Settings 画面に必ず項目を持つ 背後で必要に応じてプロセス再起動 / ホットリロードする。
F2 .env / OS 環境変数はブートストラップ (= DB に到達するまでの最小値) だけに限定 それ以外はすべて DB から動的に読む。
F3 機密値もフロントから登録できる ただし保存は KMS 暗号化、画面再表示時はマスク (sk-•••••abc)。
F4 設定値の読み手は必ず Settings Service 経由 各サービスは getSetting(key, scope) で取得し、変更を SSE で受信して反映する。
F5 設定変更はすべて監査ログに残る (who / when / old / new) 機密値の old/new はハッシュのみ記録。
F6 値には schema (型 + バリデーション) が必ず付随 フロントは schema から自動的にフォームを生成する。

4 つのスコープと継承ルール

継承順は User → Project → Tenant → System で、下位が上位を上書きします。各キーには overridable_at プロパティで「どこまで下りられるか」を定義します (例: GCP プロジェクトは Tenant 止まり)。

スコープ編集権限
System super-admin のみ LLM プロバイダ、GCP プロジェクト、暗号鍵、デフォルトテナント設定
Tenant tenant-admin BQ allowlist、cost cap、ストレージバケット、RBAC ポリシー
Project project owner / scientist 既定プリセット、Copilot モデル選択、レポート雛形
User 本人 UI 言語、テーマ、通知、キーボードショートカット、Copilot 冗長度

解決ロジック

getSetting(key, ctx) の探索順:
  User(user_id, key)
    └ なければ Project(project_id, key)
         └ なければ Tenant(tenant_id, key)
              └ なければ System(*, key)
                   └ なければ DefaultRegistry[key].default

起動時ブートストラップ (純粋な OS 環境変数で残るもの)

これら だけ は OS env / .env から読みます (DB に到達できないため)。それ以外のすべての設定は Postgres settings テーブルに格納し、フロントから編集します。

環境変数値の例用途
SN_ENV dev | staging | prod 環境ラベル。LLM / Cookie domain 等の判定で使う
SN_DB_URL postgresql+asyncpg://... Postgres 接続 (DB に到達するまでに必要)
SN_REDIS_URL redis://... Redis 接続 (queue + pub/sub)
SN_KMS_KEY_URI gcp-kms://... または local fallback 機密復号鍵
SN_SETTINGS_BOOT_TOKEN ワンタイムトークン 初回 super-admin 招待用
SN_LISTEN_HOST 0.0.0.0 等 API バインドアドレス
SN_LISTEN_PORT 8080 等 API ポート
SN_LOG_LEVEL info | debug | warn | error DB 不通時の fallback ログレベル
SN_INTERNAL_TLS_CERT PEM path (任意) mTLS 用
SN_INTERNAL_TLS_KEY PEM path (任意) mTLS 用

例外: ブート env のキー (SN_DB_URL 等) もフロントの Settings 画面に 表示はされます が、編集すると「再起動が必要」バッジが立ち、変更内容は次回起動時に反映されます (DB に書きつつ、boot env を上書きするフォールバックは行わない)。

Settings UI

グローバルナビ右上アバター → Settings から到達。Studio / Workspace の両方から同じ Settings 画面に飛びます。URL: /settings/{scope}/{section} (例: /settings/tenant/bigquery)。

各項目に表示するメタデータ

  • Key (例: bq.cost_cap_usd.ui_preview)
  • (string / int / float / bool / enum / json / secret)
  • 既定値
  • 現在のソース (User / Project / Tenant / System / Default)
  • 影響範囲 (例: 「Studio Step4 dry-run」)
  • 再起動要否 (Hot / Restart-required)
  • 機密フラグ (secret はマスク表示 + 編集時のみ平文入力)

操作

  • 編集: インライン or モーダル (schema に応じて自動 UI)
  • テスト: Connection 系は "Test connection" ボタン (BQ ping / LLM ping / S3 list)
  • エクスポート / インポート: スコープ単位で JSON エクスポート (機密は除外)
  • 差分: 編集前後の diff プレビュー
  • 履歴: 直近 50 件の変更を表示、ロールバック可能

永続化モデル

-- 非機密値
CREATE TABLE settings (
  id              uuid PK,
  scope           text CHECK (scope IN ('system','tenant','project','user')),
  scope_id        text,
  key             text NOT NULL,
  value_json      jsonb,
  value_secret_id uuid,            -- 機密値は KMS 経由で別表
  schema_version  int NOT NULL,
  updated_by      uuid NOT NULL,
  updated_at      timestamptz NOT NULL,
  UNIQUE(scope, scope_id, key)
);

-- 機密値 (KMS 暗号化 blob)
CREATE TABLE settings_secrets (
  id          uuid PK,
  ciphertext  bytea NOT NULL,       -- KMS encrypted
  kms_key_uri text NOT NULL,
  created_at  timestamptz NOT NULL
);

-- 変更履歴 (監査)
CREATE TABLE settings_audit (
  id          bigserial PK,
  scope       text, scope_id text, key text,
  old_hash    text, new_hash text,  -- 機密は old/new ハッシュのみ
  old_value   jsonb, new_value jsonb,  -- 非機密は raw
  changed_by  text, changed_at timestamptz
);

Hot reload (5 秒以内の配信)

変更時に Settings Service が Redis pub/sub に settings:changed イベントを発火します。各サービス (Studio API / Workspace API / Worker / Agent) は購読してメモリキャッシュを破棄。フロントは SSE でリスナ更新 (開いている Settings 画面の他者編集に即追従)。

Service A (FastAPI)            Redis pub/sub              Service B (Worker)
    │ PUT /v1/settings/...         │                            │
    │─────────────────────────────►│                            │
    │ settings_service.update()    │                            │
    │ → DB write                   │                            │
    │ → publish "settings:changed" │                            │
    │─────────────────────────────►│                            │
    │                              │── subscribe ──────────────►│
    │                              │                            │ cache invalidate
    │                              │                            │ → 次の getSetting で DB から再取得

Restart-required な値: storage.object_store_kind / bq.gcp_project_id / bq.location / bq.service_account_key など、起動時に確立するクライアントが関わる値は変更後にプロセス再起動が必要です。Settings 画面に「再起動が必要」バッジが立ちます。

カタログの読み方 (凡例)

OV (overridable_at)
どこまで下位スコープで上書きできるか。S = System / T = Tenant / P = Project / U = User
HR (Hot reload)
= Hot reload 対応 (5 秒以内に各サービスに反映) / = Restart required
Sec (機密)
= 機密値 (KMS 暗号化、UI マスク表示)

1. Connections (接続情報)

Key既定OVHRSec説明
bq.gcp_project_id string T Restart BigQuery プロジェクト ID
bq.service_account_key secret T Restart Secret サービスアカウント JSON (KMS 保管)
bq.location enum(US,EU,asia-northeast1) US T Hot BQ ジョブのロケーション
bq.workload_identity_audience string T Restart WIF を使う場合の audience
bq.source_allowlist json(list) ["xhro_01.*","xhro_02.*","xhro_03.*","xhro_04.*","xhro_view.*","xhro_04_modeling_v2.*"] T Hot 許可するデータセット/テーブル (glob)。**生 xhro は partition-filter 罠で既定除外**
bq.source_blocklist json(list) ["xhro","xhro_backup","tmp","clns","dataflow_dev"] T Hot 明示的に隠すデータセット。allowlist より強い
storage.object_store_kind enum(gcs,s3,minio) gcs T Restart Bundle 物理保管先種別
storage.bucket string T Restart 既定バケット名
storage.signed_url_ttl_sec int 900 T Hot 署名付き URL の有効期間
auth.oidc_issuer string T Restart OIDC issuer URL
auth.oidc_audience string T Restart OIDC audience
auth.oidc_client_id string T Restart クライアント ID
auth.oidc_client_secret secret T Restart Secret クライアントシークレット
auth.session_ttl_min int 480 T Hot Web セッション TTL

2. LLM / AI Copilot

Key既定OVHRSec説明
llm.provider enum(anthropic,openai,vertex) anthropic T Hot LLM プロバイダ
llm.api_base_url string (provider default) T Hot API エンドポイント上書き
llm.api_key secret T Hot Secret API キー
llm.model.copilot_planner string claude-opus-4-7 P Hot 設計系 (hypothesis 提案)
llm.model.copilot_codegen string claude-sonnet-4-6 P Hot コード生成 (denoise/feature 提案)
llm.model.copilot_narrative string claude-sonnet-4-6 P Hot 所見ドラフト
llm.model.studio_assistant string claude-sonnet-4-6 P Hot Studio 内 Window 提案
llm.max_tokens_per_turn int 4096 P Hot 1 ターン上限
llm.temperature float 0.2 P Hot サンプリング温度
llm.prompt_cache_enabled bool true T Hot Anthropic prompt cache 有効
llm.tool_call_timeout_sec int 30 P Hot 各 tool 呼び出しタイムアウト
copilot.verbosity enum(terse,normal,verbose) normal U Hot Copilot 返答の詳しさ
copilot.auto_dryrun_cells bool true U Hot 提案セルを Apply 前に sandbox dry-run
copilot.show_diff_default bool true U Hot 提案を diff で見せる (false=full text)
copilot.allowed_tools json(list) (全許可) P Hot Copilot が呼べるツール allowlist
copilot.cost_alert_usd_per_day float 5.00 U Hot 1 日 LLM 課金しきい値 (超過で警告)

3. Cost & Quota (BQ / sandbox / worker)

Key既定OVHRSec説明
bq.cost_cap_usd.ui_preview float 0.05 T Hot UI プレビュー dry-run キャップ
bq.cost_cap_usd.preview_window float 0.50 T Hot 単一 Window 取り出し
bq.cost_cap_usd.analysis_dataset float 5.00 T Hot 解析データセット import
bq.cost_cap_usd.export float 25.00 T Hot admin 承認エクスポート
bq.scan_bytes_cap.preview_window int(MB) 512 T Hot スキャン MB 上限
bq.window_max_minutes.scientist int 30 T Hot scientist が 1 Window 取れる最大分数
bq.window_max_minutes.admin int 240 T Hot admin の最大分数
bq.windows_per_bundle_max int 12 T Hot 1 Bundle 内の Window 上限
bq.daily_user_cap_usd float 10.00 T Hot ユーザ 1 人 1 日の累計上限
bq.daily_tenant_cap_usd float 100.00 T Hot テナント 1 日の累計上限
sandbox.cpu_cores int 2 T Restart sandbox CPU
sandbox.memory_mb int 2048 T Restart sandbox メモリ
sandbox.wall_time_sec.feature int 15 T Hot feature 1 セル実行時間上限
sandbox.wall_time_sec.hypothesis int 120 T Hot hypothesis 実行上限
sandbox.allow_network bool false T Hot sandbox の外向き通信
worker.fanout_concurrency.feature int 8 T Hot feature 並列度
worker.fanout_concurrency.hypothesis int 4 T Hot hypothesis 並列度
worker.fanout_concurrency.bundle_build int 2 T Hot Bundle build 並列度

4. ECG Defaults (信号処理デフォルト)

Key既定OVHRSec説明
ecg.preset_default enum(default,noisy,xhro-multiday,holter-overnight,custom) xhro-multiday P Hot Studio Step4 既定プリセット。XHRO 連続多日装着用 (holter-overnight は 12 誘導 Holter 想定で XHRO には合わない)
ecg.sample_rate_hz enum(250,500,1000) 250 P Hot 既定サンプリング (Bundle build 時)
ecg.notch_hz enum(50,60) 50 T Hot 既定 notch 周波数
ecg.highpass_hz float 0.5 P Hot 既定 HPF
ecg.lowpass_hz float 40 P Hot 既定 LPF
ecg.r_peak_detector enum(pan_tompkins_v1,hamilton,custom) pan_tompkins_v1 P Hot 既定 R ピーク検出器
ecg.rr_min_ms int 300 P Hot RR 異常値下限
ecg.rr_max_ms int 2000 P Hot RR 異常値上限
ecg.hrv_window_sec int 60 P Hot HRV ローリング窓
ecg.invalid_threshold.acc_g float 0.3 P Hot 体動 RMS しきい値
ecg.invalid_threshold.leadoff_ratio float 0.05 P Hot lead-off 比率
ecg.beat_label_set enum(mit-bih,aha,xhro_ecg_annot,custom) mit-bih P Hot 拍ラベル分類集合
ecg.leads_default json(list) ["xhro_ch1_minus_ch2"] P Hot 既定誘導 (XHRO 固有の差動 ID)
viewer.timescale_sec enum(1,5,10,30,60) 10 U Hot Viewer 初期時間軸
viewer.pyramid_auto_level bool true U Hot ズーム自動レベル切替
viewer.show_r_peaks bool true U Hot R ピークオーバーレイ既定 ON
viewer.show_invalid_intervals bool true U Hot 無効区間オーバーレイ

5. Storage & Retention

Key既定OVHRSec説明
bundle.retention_days int 365 T Hot Bundle 保管期間
bundle.archive_after_days int 90 T Hot コールドストレージ移行
bundle.max_size_gb int 10 T Hot 1 Bundle サイズ上限
evidence.retention_days int 1825 T Hot Evidence 保管 (= 5 年)
audit.retention_days int 2555 S Hot 監査ログ (= 7 年)
cache.feature_value_ttl_days int 30 T Hot feature 値キャッシュ TTL
cache.preview_ttl_sec int 600 T Hot Studio プレビューキャッシュ
cache.waveform_pyramid_ttl_days int 0 T Hot 0 = Bundle と同じ寿命

6. Auth & RBAC

RBAC マトリクスの実体は operations § RBAC マトリクス 参照。

Key既定OVHRSec説明
rbac.matrix_json json (組込既定) T Hot role × 操作の許可マトリクス
rbac.default_role_for_new_users enum(viewer,annotator,scientist) viewer T Hot 新規ユーザ既定
rbac.scientist_can_pre_register bool true T Hot scientist の pre-reg 権限
rbac.who_can_verdict enum(scientist,admin,project_owner) project_owner T Hot verdict 付与者
rbac.who_can_edit_bundle_retention enum(admin) admin T Hot retention 編集
auth.mfa_required bool true T Hot MFA 強制
auth.allowed_ip_cidrs json(list) [] T Hot IP allowlist (空=制限なし)
auth.session_idle_timeout_min int 30 T Hot アイドルタイムアウト

7. Reports & Templates

Key既定OVHRSec説明
report.brand_logo_url string T Hot レポート左上ロゴ
report.brand_color_primary string(hex) #1f2937 T Hot プライマリ色
report.template_session_pdf string(template id) default P Hot per-session PDF 雛形
report.template_hypothesis_pdf string default P Hot per-hypothesis PDF 雛形
report.template_pptx string default P Hot PPTX 雛形
report.include_code_snippets bool true P Hot コードを埋めるか
report.include_evidence_table bool true P Hot evidence 表を埋めるか
report.signature_block_text string (空) P Hot 末尾署名ブロック

8. Notifications

Key既定OVHRSec説明
notify.channel.email bool true U Hot メール通知
notify.channel.slack bool false U Hot Slack 通知
notify.slack_webhook_url secret T Hot Secret Slack incoming webhook
notify.events.bundle_ready bool true U Hot Bundle 完成通知
notify.events.hypothesis_done bool true U Hot 仮説実行完了
notify.events.stale_evidence bool true U Hot evidence stale 化
notify.events.cost_threshold bool true U Hot コスト警告
notify.daily_digest_time_local string(HH:MM) 09:00 U Hot 日次サマリ時刻

9. Locale & UI

Key既定OVHRSec説明
ui.locale enum(ja,en) ja U Hot 表示言語
ui.theme enum(light,dark,system) system U Hot テーマ
ui.density enum(compact,comfortable) comfortable U Hot UI 密度
ui.timezone string(IANA) Asia/Tokyo U Hot 表示タイムゾーン
ui.number_format enum(en-US,ja-JP) ja-JP U Hot 数値表示
ui.units_voltage enum(uV,mV) mV U Hot ECG 表示単位
ui.units_time enum(ms,s) s U Hot 時間表示
ui.show_lineage_chips bool true U Hot Bundle lineage バッジ表示

10. Keyboard Shortcuts

Key既定OVHRSec説明
keys.viewer.add_rpeak string + U Hot R ピーク追加
keys.viewer.remove_rpeak string - U Hot R ピーク削除
keys.viewer.mark_invalid string i U Hot 無効区間マーク
keys.viewer.next_window string ] U Hot 次 Window
keys.viewer.prev_window string [ U Hot 前 Window
keys.notebook.run_cell string Shift+Enter U Hot セル実行
keys.notebook.apply_proposal string Cmd+. U Hot AI 提案 Apply
keys.global.search string Cmd+K U Hot 検索パレット

11. Feature Flags

Key既定OVHRSec説明
flag.studio.ai_window_suggest bool true T Hot Studio AI Window 提案
flag.studio.derive_spo2_in_bundle bool false T Hot Bundle build 時の SpO2 派生
flag.workspace.beat_classifier bool false T Hot 拍分類モデルセル
flag.workspace.live_collab bool false T Hot Notebook 共同編集
flag.workspace.outcome_projects bool true T Hot outcome 種別 Project
flag.copilot.narrative_drafts bool true P Hot AI 所見ドラフト
flag.export.async_large_jobs bool false T Hot 大規模エクスポートジョブ
flag.annotation.continuous_learning bool false T Hot Annotation Continuous learning

12. Audit & Diagnostics

Key既定OVHRSec説明
audit.export_destination enum(gcs,s3,none) gcs T Restart 監査ログの夜次エクスポート先
audit.export_bucket string T Restart エクスポート bucket
diag.otel_endpoint string T Hot OpenTelemetry コレクタ
diag.log_level enum(debug,info,warn,error) info T Hot 実行時ログレベル
diag.trace_sample_rate float 0.1 T Hot トレースサンプリング率
diag.slow_query_threshold_ms int 1000 T Hot スロークエリしきい値

バリデーションとスキーマ (DefaultRegistry)

各キーには DefaultRegistry[key] として以下が紐づきます。このレジストリはコードに同梱 (型安全のため)、フロント Settings 画面はこの定義から フォームを自動生成 します。新しい設定キーの追加 = DefaultRegistry への 1 行追加で済みます。

{
  key: "bq.cost_cap_usd.ui_preview",
  type: "float",
  min: 0,
  max: 100,
  default: 0.05,
  scope_max: "tenant",      // T までしか下りない
  overridable_at: ["tenant"],
  hot_reload: true,
  secret: false,
  description: "UI プレビュー dry-run 1 回あたりの USD 上限",
  affects: ["Studio Step4", "BigQueryAccessService.dry_run"],
  ui: { component: "money", currency: "USD" }
}

既存 suntory-nedo からの移行

旧リポの env-var で散らかっていた値は次の通り分類されます。9 割の env-var を消して Settings 画面に移し、残る OS env はブートストラップ 10 個前後だけです。

既存 env-varv2 での行き先
DATABASE_URLブート env (SN_DB_URL) — そのまま残す
REDIS_URLブート env (SN_REDIS_URL)
BQ_PROJECT_IDDB / Settings (bq.gcp_project_id)
BQ_LOCATIONDB / Settings (bq.location)
BQ_SA_KEY_FILEDB / Settings (bq.service_account_key, KMS 暗号化済 secret)
S3_BUCKET / S3_ACCESS_KEY / S3_SECRET_KEY / S3_ENDPOINTDB / Settings (storage.*)
AUTH_MODE / JWT_DEV_SECRET / JWT_ISSUER / JWT_AUDIENCE / JWT_ALGDB / Settings (auth.*)
ANTHROPIC_API_KEYDB / Settings (llm.api_key) — KMS 暗号化
LOG_LEVELDB / Settings (diag.log_level) — boot fallback は env
OTEL_EXPORTER_OTLP_ENDPOINTDB / Settings (diag.otel_endpoint)
NEXT_PUBLIC_API_BASE_URLフロント側のビルド時 env (Studio Web のみ)

受け入れ基準 (Settings)

  • 新しいインスタンスを立てるとき、.env にはブート env 10 個程度だけ書けばよい。
  • それ以外の全設定値は Settings 画面から編集できる (機密含む)。
  • Settings 画面のフォームは DefaultRegistry から自動生成される (画面コードに値ごとの分岐がない)。
  • 設定変更は監査ログに残り、機密は old/new がハッシュのみで記録される。
  • Hot reload 対象の値は変更 5 秒以内に各サービスに反映される。
  • 機密値は再表示時にマスクされ、平文では返らない。
  • RBAC により、編集権限のないスコープは UI で disabled、API では 403。
  • テナント新規作成時に System の値を継承した雛形が自動で settings に投入される。
  • JSON エクスポート / インポートで Tenant 設定をまるごと別環境に移植できる (機密は除外)。