PII分離アーキテクチャ
Authrimは、機微なidentity valueをprotocol、authorization、admin control-plane dataから分離します。現在のモデルはruntime storage profileを前提にしており、共有D1 binding、テナント所有D1 slot、外部storage adapterのいずれを使っても、同じlogical source境界を維持します。
Storage Planes
Section titled “Storage Planes”デフォルトの builtin:storage:shared-d1 profile は、3つのデプロイ単位D1 bindingを使います。
| Binding | Storage plane | 主なデータ |
|---|---|---|
DB | Core identity / protocol data | tenants、OAuth clients、roles、relationships、consent records、legacy users_core、canonical identity graph tables |
DB_PII | Sensitive identity values / PII audit data | legacy users_pii、linked identities、subject identifiers、identity_sensitive_values、PII tombstones、PII audit logs |
DB_ADMIN | Admin / control-plane data | admin users/RBAC、runtime profiles、tenant database registry、field catalogs、operational jobs |
KVとDurable ObjectsはこれらのD1 planeとは別です。KVはcacheや署名済みruntime snapshotに使い、Durable Objectsはsession、authorization code、refresh-token rotation、PAR、DPoP JTI、device flow、CIBA、rate limitなどのhot protocol stateを保持します。
Runtime Profiles
Section titled “Runtime Profiles”PII分離は、hard-codedなregional bindingではなく、logical sourceとstorage sliceで制御します。
| Profile | 挙動 |
|---|---|
builtin:storage:shared-d1 | デプロイ単位の DB、DB_PII、DB_ADMIN bindingを使う |
builtin:storage:tenant-d1 | control dataは共有し、テナント所有のcore/PII/audit sliceをtenant database registryで解決する |
builtin:storage:external-durable | 設定された範囲でdurable stateを外部adapterへ移す |
| External SQL profiles | tenant settingsにcredentialを直接入れず、connection referenceを使う |
tenant-D1 modeでは、tenant database routeが見つからない場合に共有D1へ暗黙fallbackしません。未対応routeはPIIを返さず失敗し、storage境界のbugで機微データが誤ったplaneに移動することを防ぎます。
Current Identity Model
Section titled “Current Identity Model”新しいruntime user pathはcanonical identity graphを使います。Protocol codeは CanonicalRuntimeUserStore 経由で読み書きし、runtime codeが users_core / users_pii rowを直接扱わない構成です。
flowchart TB
subgraph Core["Core DB: DB"]
Subjects["identity_subjects"]
Accounts["identity_accounts"]
Links["subject_account_links"]
Profiles["profiles<br/>display_name_ref"]
Attributes["profile_attribute_values<br/>value_storage_ref, value_hash, purpose"]
Contacts["contact_points<br/>normalized_hash, value_storage_ref, purpose"]
Bindings["identity_bindings"]
SearchIndexes["contact_point_search_indexes"]
end
subgraph PII["PII DB: DB_PII"]
Sensitive["identity_sensitive_values<br/>value_json, value_hash"]
LegacyPII["users_pii / linked_identities"]
SubjectIds["subject_identifiers<br/>identifier_storage_ref"]
Tombstones["users_pii_tombstone / pii_log"]
end
subgraph Control["Admin DB: DB_ADMIN"]
RuntimeProfiles["storage_deployment_profiles"]
TenantRegistry["tenant database registry"]
FieldCatalogs["field_catalogs"]
end
Attributes -->|value_storage_ref| Sensitive
Contacts -->|value_storage_ref| Sensitive
Contacts --> SearchIndexes
SubjectIds --> Sensitive
RuntimeProfiles --> Core
TenantRegistry --> Core
TenantRegistry --> PII
Core graph rowはlifecycle state、metadata、hash、storage referenceを持ちます。email、phone、profile name、address、custom sensitive attributeなどの機微値は DB_PII の identity_sensitive_values に保存します。
Key Tables
Section titled “Key Tables”Core Identity Graph (DB)
Section titled “Core Identity Graph (DB)”CREATE TABLE IF NOT EXISTS identity_subjects ( id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL DEFAULT 'default', subject_type TEXT NOT NULL, lifecycle_state TEXT NOT NULL DEFAULT 'active', display_label TEXT, primary_account_id TEXT, risk_tier TEXT, assurance_level TEXT, metadata_json TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, deleted_at INTEGER);
CREATE TABLE IF NOT EXISTS identity_accounts ( id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL DEFAULT 'default', account_type TEXT NOT NULL, lifecycle_state TEXT NOT NULL DEFAULT 'active', legacy_user_id TEXT, primary_subject_id TEXT, display_label TEXT, metadata_json TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, deleted_at INTEGER);
CREATE TABLE IF NOT EXISTS profiles ( id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL DEFAULT 'default', subject_id TEXT NOT NULL, profile_type TEXT NOT NULL DEFAULT 'person', lifecycle_state TEXT NOT NULL DEFAULT 'active', locale TEXT, zoneinfo TEXT, display_name_ref TEXT, metadata_json TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, deleted_at INTEGER);
CREATE TABLE IF NOT EXISTS profile_attribute_values ( id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL DEFAULT 'default', profile_id TEXT NOT NULL, catalog_entry_id TEXT NOT NULL, value_type TEXT NOT NULL, value_json TEXT, value_storage_ref TEXT, value_hash TEXT, classification TEXT NOT NULL DEFAULT 'internal', purpose TEXT, is_primary INTEGER NOT NULL DEFAULT 0, display_order INTEGER NOT NULL DEFAULT 0, lifecycle_state TEXT NOT NULL DEFAULT 'active', created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, deleted_at INTEGER);
CREATE TABLE IF NOT EXISTS contact_points ( id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL DEFAULT 'default', subject_id TEXT, account_id TEXT, contact_type TEXT NOT NULL, purpose TEXT NOT NULL DEFAULT 'primary', normalized_hash TEXT, value_storage_ref TEXT, display_label TEXT, is_primary INTEGER NOT NULL DEFAULT 0, verification_state TEXT NOT NULL DEFAULT 'unverified', lifecycle_state TEXT NOT NULL DEFAULT 'active', created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, deleted_at INTEGER);Sensitive Values (DB_PII)
Section titled “Sensitive Values (DB_PII)”CREATE TABLE IF NOT EXISTS identity_sensitive_values ( id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL DEFAULT 'default', owner_type TEXT NOT NULL, owner_id TEXT NOT NULL, value_key TEXT NOT NULL, value_json TEXT, value_hash TEXT, classification TEXT NOT NULL DEFAULT 'sensitive', lifecycle_state TEXT NOT NULL DEFAULT 'active', created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, UNIQUE (tenant_id, owner_type, owner_id, value_key));Legacy Runtime Tables
Section titled “Legacy Runtime Tables”Migration baselineにはlegacy compatibility tableも残っています。upgradeや一部management pathでは重要ですが、新しいruntime user writeはcanonical identity graphへprojectされます。
CREATE TABLE users_core ( id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL DEFAULT 'default', email_verified INTEGER DEFAULT 0, phone_number_verified INTEGER DEFAULT 0, email_domain_hash TEXT, password_hash TEXT, is_active INTEGER DEFAULT 1, user_type TEXT NOT NULL DEFAULT 'end_user', pii_partition TEXT NOT NULL DEFAULT 'default', pii_status TEXT NOT NULL DEFAULT 'pending', lifecycle_state TEXT DEFAULT 'active', created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, last_login_at INTEGER);
CREATE TABLE IF NOT EXISTS users_pii ( id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL DEFAULT 'default', pii_class TEXT NOT NULL DEFAULT 'PROFILE', email TEXT NOT NULL, email_blind_index TEXT, phone_number TEXT, name TEXT, given_name TEXT, family_name TEXT, address_country TEXT, declared_residence TEXT, custom_attributes_json TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);Search and Lookup
Section titled “Search and Lookup”Core側の検索surfaceは、plaintext PIIを必要としない構成にします。現在のschemaは以下をサポートします。
| 用途 | Core-side field | PII-side field |
|---|---|---|
| Email/contact lookup | contact_points.normalized_hash, contact_point_search_indexes.index_value | identity_sensitive_values.value_json |
| Profile display | profiles.display_name_ref, profile_attribute_values.value_storage_ref | 対応する identity_sensitive_values row |
| Pairwise subject identifiers | canonical migration後の subject_identifiers.identifier_value_hash / identifier_storage_ref | 必要時のみsensitive identifier value |
| Field catalog metadata | DB_ADMIN.field_catalog_entries | 実際のsensitive field valueは DB_PII に保持 |
Deletion and Audit
Section titled “Deletion and Audit”PII deletionはPII plane上のtombstoneとaudit recordで管理します。
CREATE TABLE IF NOT EXISTS users_pii_tombstone ( id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL DEFAULT 'default', email_blind_index TEXT, deleted_at INTEGER NOT NULL, deleted_by TEXT, deletion_reason TEXT, retention_until INTEGER NOT NULL, deletion_metadata TEXT, created_at INTEGER, updated_at INTEGER);
CREATE TABLE IF NOT EXISTS pii_log ( id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL, user_id TEXT NOT NULL, anonymized_user_id TEXT NOT NULL, change_type TEXT NOT NULL, affected_fields TEXT NOT NULL, values_r2_key TEXT, values_encrypted TEXT, retention_until INTEGER NOT NULL, created_at INTEGER NOT NULL);Best Practices
Section titled “Best Practices”- Feature codeでD1 binding名をhard-codeせず、runtime profile経由でstorageを解決する。
- Sensitive attribute valueは
identity_sensitive_valuesに置き、core graph tableにはhash、reference、state、metadataを置く。 - Legacy
users_core/users_piiはcompatibility surfaceとして扱い、新しいruntime identity featureの主モデルにしない。 - Storage planeをまたぐJOINをしない。Core rowとsensitive valueはrepository/runtime store layerから個別に取得する。
- tenant-D1 routingが関わるcache scopeには、storage profile ID、source generation、schema versionを含める。