エンタープライズセキュリティ
JamJetのマルチテナント分離、PII編集、OAuth委譲、mTLSフェデレーション、データ保持ポリシー
エンタープライズセキュリティ
JamJetのエンタープライズ機能はRustランタイム層で強制されます — 慣習でもなく、追加を忘れる可能性のあるミドルウェアでもありません。
マルチテナント分離
すべてのストレージをテナントIDで分割します。ワークフロー定義、実行状態、イベントログ、監査証跡、スナップショットはすべてテナントごとにスコープされます。
# 同じワークフロー、異なるテナント — 完全に分離
jamjet run workflow.yaml \
--input '{"invoice_id": "INV-001", "amount": 2500}' \
--tenant acme
jamjet run workflow.yaml \
--input '{"invoice_id": "INV-042", "amount": 75000}' \
--tenant globexランタイムの TenantScopedSqliteBackend は、すべてのストレージクエリを WHERE tenant_id = ? でラップします。ワークフロー定義テーブルは複合主キー (tenant_id, workflow_id, version) を使用します。
PII編集
ワークフローに data_policy を宣言します。ランタイムは状態が監査ログに到達する前にそれを適用します。
data_policy:
pii_detectors: [email, ssn, phone, credit_card, ip_address]
pii_fields: ["$.email", "$.ssn", "$.credit_card"]
redaction_mode: mask # または: hash, remove
retain_prompts: false # 監査ログからプロンプトを削除
retain_outputs: false # 監査ログからモデル出力を削除
retention_days: 90 # 90日後に自動削除3つの編集モード:
| モード | 動作 | 例 |
|---|---|---|
mask | デバッグ用の部分表示 | ***-**-6789 |
hash | 分析用のSHA-256疑似匿名化 | a3f2c91b...e71b |
remove | フィールドの完全削除 | (フィールド削除済み) |
Python SDK同等機能:
@workflow(
id="customer-onboarding",
version="0.1.0",
data_policy={
"pii_detectors": ["email", "ssn", "phone", "credit_card"],
"pii_fields": ["$.email", "$.ssn"],
"redaction_mode": "mask",
"retain_prompts": False,
"retain_outputs": False,
"retention_days": 90,
},
)
class CustomerOnboarding:
...データ保持
retention_days は、すべての監査ログエントリに expires_at タイムスタンプを設定します。ランタイムの purge_expired() メソッドはバックグラウンドタスクとして実行され、有効期限を過ぎたエントリを削除します。
追加コントロール:
retain_prompts: false— 書き込み前に監査エントリからモデルプロンプトを削除retain_outputs: false— モデル出力についても同様
監査ログはコンテンツなしでメタデータ(ノードID、トークン数、タイムスタンプ)を保持します。
OAuth 2.0 委任
RFC 8693 トークン交換。ユーザーのトークンを、スコープを絞ったエージェントトークンに交換します。
oauth:
token_endpoint: "${JAMJET_OAUTH_TOKEN_ENDPOINT}"
grant_type: "urn:ietf:params:oauth:grant-type:token-exchange"
client_id: "${JAMJET_OAUTH_CLIENT_ID}"
client_secret: "${JAMJET_OAUTH_CLIENT_SECRET}"
requested_scopes: ["expenses:read", "expenses:write"]スコープの絞り込み
エージェントの有効なスコープは、エージェントが要求するものとユーザーが持つものの交差です。交差が空の場合、ランタイムは OAuthError::ScopeNarrowingFailed を返します。
ステップごとのスコープ設定
異なるノードは異なるスコープ要件を宣言できます:
nodes:
authenticate:
oauth_scopes:
required_scopes: ["expenses:read"]
submit-expense:
oauth_scopes:
required_scopes: ["expenses:read", "expenses:write"]ランタイムはワークフロー開始時ではなく、各ノード実行前にスコープを解決します。
トークンの有効性
check_token_validity() は、すべてのツールとモデル呼び出しの前に実行されます。期限切れまたは失効したトークンは、明確なエラー(OAuthError::TokenExpired、OAuthError::TokenRevoked)を生成し、人間にエスカレーションします。
mTLS と A2A フェデレーション
組織間エージェント通信の場合:
トランスポート: 相互 TLS。両側が証明書を提示し、両側が検証します。
export JAMJET_TLS_CERT=/etc/certs/agent.pem
export JAMJET_TLS_KEY=/etc/certs/agent-key.pem
export JAMJET_TLS_CA_CERT=/etc/certs/ca.pem
export JAMJET_MTLS_REQUIRED=trueアプリケーション: 機能スコープ付き Bearer トークンとエージェント許可リスト。
federation:
require_auth: true
public_agent_card: true
tokens:
- token: "tok-alpha"
name: "Research Agent"
agent_id: "agent-alpha"
scopes: ["read", "write"]
allowed_agents: ["agent-alpha"]
method_scopes:
"tasks/send": ["write"]
"tasks/get": ["read"]federation_auth_layer ミドルウェアは、すべての受信 A2A リクエストを検証します。未承認のリクエストは、ハンドラに到達する前に JSON-RPC エラーを受け取ります。
プラガブルなシークレットバックエンド
優先順位付けで複数のシークレットソースを連鎖できます:
| バックエンド | ユースケース |
|---|---|
| 環境変数 | ローカル開発、CI |
| ファイルベース | Kubernetes シークレット、マウントボリューム |
| HashiCorp Vault | 本番シークレット管理 |
| AWS Secrets Manager | AWS ネイティブデプロイ |
ランタイムは起動時に、バックエンドを優先順にチェックしてシークレットを解決します。
実装例
各エンタープライズ機能の実行可能なサンプル:
git clone https://github.com/jamjet-labs/examples
cd examples/multi-tenant # テナント分離
cd examples/data-governance # PII編集 + 保持ポリシー
cd examples/oauth-delegation # OAuth 2.0 + スコープ制限ヒント: 詳細な解説記事:データガバナンスとPII編集、OAuth委譲とフェデレーション認証