Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/prisma/schema/featureFlags.prisma
T

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")
}