106 lines
4.5 KiB
Plaintext
106 lines
4.5 KiB
Plaintext
enum FeatureFlagLifecycleStage {
|
|
beta
|
|
rollout
|
|
ga
|
|
deprecated
|
|
}
|
|
|
|
model FeatureFlag {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
key String?
|
|
scope String @default("global")
|
|
tenantId String?
|
|
userId String?
|
|
name String
|
|
description String
|
|
enabled Boolean @default(false)
|
|
defaultValue Boolean?
|
|
lifecycleStage FeatureFlagLifecycleStage @default(beta)
|
|
ownerAdminUserId String?
|
|
targetModule String?
|
|
archivedAt DateTime?
|
|
// v2 targeting engine fields (task #53). All nullable / defaulted so
|
|
// legacy rows continue to evaluate via boolean `enabled` only.
|
|
rules Json?
|
|
variants Json[] @default([])
|
|
enabledFrom DateTime?
|
|
enabledUntil DateTime?
|
|
parentFlagId String?
|
|
parentFlag FeatureFlag? @relation("FeatureFlagDependency", fields: [parentFlagId], references: [id], onDelete: SetNull)
|
|
childFlags FeatureFlag[] @relation("FeatureFlagDependency")
|
|
audits FeatureFlagAudit[]
|
|
events AnalyticsEvent[]
|
|
filters FeatureFlagFilter[]
|
|
tenantOverrides AdminFeatureFlagOverride[]
|
|
|
|
@@unique([name, description])
|
|
@@index([key, scope], name: "feature_flag_key_scope_idx")
|
|
@@index([tenantId, key], name: "feature_flag_tenant_key_idx")
|
|
@@index([userId, key], name: "feature_flag_user_key_idx")
|
|
@@index([parentFlagId], name: "feature_flag_parent_idx")
|
|
@@index([lifecycleStage, archivedAt], name: "feature_flag_lifecycle_archive_idx")
|
|
@@index([ownerAdminUserId, archivedAt], name: "feature_flag_owner_archive_idx")
|
|
@@index([targetModule, archivedAt], name: "feature_flag_module_archive_idx")
|
|
}
|
|
|
|
model FeatureFlagFilter {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @default(now()) @updatedAt
|
|
featureFlagId String
|
|
featureFlag FeatureFlag @relation(fields: [featureFlagId], references: [id], onDelete: Cascade)
|
|
type String // [FeatureFlagsFilterType] percentage, darkMode, language.is, page.is, analytics.browser.is...
|
|
value String? // 0-100, true, false, en, de, fr, ...
|
|
action String?
|
|
name String @default("Legacy filter")
|
|
priority Int @default(0)
|
|
resultValue Boolean?
|
|
criteria Json?
|
|
active Boolean @default(true)
|
|
createdByAdminUserId String?
|
|
|
|
@@index([featureFlagId, active, priority, createdAt], name: "feature_flag_filter_evaluation_idx")
|
|
}
|
|
|
|
/// Operator-managed rollout override. This is deliberately not the
|
|
/// subscription/entitlement TenantFeatureOverride model.
|
|
model AdminFeatureFlagOverride {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
featureFlagId String
|
|
tenantId String
|
|
value Boolean
|
|
note String?
|
|
expiresAt DateTime?
|
|
setByAdminUserId String
|
|
|
|
featureFlag FeatureFlag @relation(fields: [featureFlagId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([featureFlagId, tenantId], name: "admin_feature_flag_override_flag_tenant_key")
|
|
@@index([tenantId, featureFlagId], name: "admin_feature_flag_override_tenant_flag_idx")
|
|
@@index([featureFlagId, expiresAt], name: "admin_feature_flag_override_expiry_idx")
|
|
@@index([setByAdminUserId, updatedAt], name: "admin_feature_flag_override_actor_idx")
|
|
}
|
|
|
|
/// Append-only audit trail for every mutation of a FeatureFlag (create / update / delete / toggle).
|
|
/// Never UPDATE or DELETE rows from app code — preserves tamper-resistance for compliance.
|
|
model FeatureFlagAudit {
|
|
id String @id @default(cuid())
|
|
flagId String
|
|
flag FeatureFlag @relation(fields: [flagId], references: [id], onDelete: Cascade)
|
|
actorUserId String?
|
|
actorType String @default("admin")
|
|
action String // create | update | delete | toggle
|
|
oldValue Json?
|
|
newValue Json?
|
|
metadata Json?
|
|
createdAt DateTime @default(now())
|
|
|
|
@@index([flagId, createdAt], name: "feature_flag_audit_flag_idx")
|
|
@@index([actorUserId, createdAt], name: "feature_flag_audit_actor_idx")
|
|
@@index([actorType, createdAt], name: "feature_flag_audit_scope_idx")
|
|
}
|