mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 14:25:02 +00:00
1652 lines
50 KiB
Plaintext
1652 lines
50 KiB
Plaintext
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "sqlite"
|
|
}
|
|
|
|
// =============================================================================
|
|
// CORE IDENTITY & AUTH
|
|
// =============================================================================
|
|
|
|
model User {
|
|
id String @id
|
|
username String @unique
|
|
email String @unique
|
|
role String // public|user|moderator|admin|god|supergod
|
|
profilePicture String?
|
|
bio String?
|
|
createdAt BigInt
|
|
tenantId String?
|
|
isInstanceOwner Boolean @default(false)
|
|
tenant Tenant? @relation(fields: [tenantId], references: [id])
|
|
ownedTenants Tenant[] @relation("TenantOwner")
|
|
comments Comment[]
|
|
powerTransfersFrom PowerTransferRequest[] @relation("PowerTransferFrom")
|
|
powerTransfersTo PowerTransferRequest[] @relation("PowerTransferTo")
|
|
passwordChangeTimestamp BigInt?
|
|
firstLogin Boolean @default(false)
|
|
sessions Session[]
|
|
notifications Notification[]
|
|
auditLogs AuditLog[]
|
|
mediaAssets MediaAsset[]
|
|
forumPosts ForumPost[]
|
|
forumThreads ForumThread[]
|
|
|
|
@@index([tenantId])
|
|
@@index([role])
|
|
}
|
|
|
|
model Credential {
|
|
username String @id
|
|
passwordHash String
|
|
}
|
|
|
|
model Session {
|
|
id String @id
|
|
userId String
|
|
token String @unique
|
|
expiresAt BigInt
|
|
createdAt BigInt
|
|
lastActivity BigInt
|
|
ipAddress String?
|
|
userAgent String?
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId])
|
|
@@index([expiresAt])
|
|
@@index([token])
|
|
}
|
|
|
|
// =============================================================================
|
|
// MULTI-TENANCY
|
|
// =============================================================================
|
|
|
|
model Tenant {
|
|
id String @id
|
|
name String
|
|
slug String @unique
|
|
ownerId String
|
|
createdAt BigInt
|
|
homepageConfig String?
|
|
settings String? // JSON: theme, features, limits
|
|
owner User @relation("TenantOwner", fields: [ownerId], references: [id], onDelete: Cascade)
|
|
users User[]
|
|
workflows Workflow[]
|
|
luaScripts LuaScript[]
|
|
pages PageConfig[]
|
|
schemas ModelSchema[]
|
|
notifications Notification[]
|
|
auditLogs AuditLog[]
|
|
mediaAssets MediaAsset[]
|
|
forumCategories ForumCategory[]
|
|
|
|
@@index([slug])
|
|
@@index([ownerId])
|
|
}
|
|
|
|
// =============================================================================
|
|
// ROUTING & PAGES
|
|
// =============================================================================
|
|
|
|
model PageConfig {
|
|
id String @id
|
|
tenantId String?
|
|
packageId String? // Which package defined this route
|
|
path String // Route pattern: /media/jobs, /forum/:id
|
|
title String
|
|
description String? // SEO meta description
|
|
icon String? // Icon for navigation menus
|
|
component String? // Named component reference
|
|
componentTree String // JSON: full component tree
|
|
level Int // Required permission level 1-6
|
|
requiresAuth Boolean
|
|
requiredRole String?
|
|
parentPath String? // Parent route for hierarchy
|
|
sortOrder Int @default(0)
|
|
isPublished Boolean @default(true)
|
|
params String? // JSON: route parameter definitions
|
|
meta String? // JSON: additional metadata (og tags, etc.)
|
|
createdAt BigInt?
|
|
updatedAt BigInt?
|
|
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([tenantId, path])
|
|
@@index([tenantId])
|
|
@@index([packageId])
|
|
@@index([level])
|
|
@@index([parentPath])
|
|
}
|
|
|
|
// =============================================================================
|
|
// WORKFLOWS & SCRIPTING
|
|
// =============================================================================
|
|
|
|
model Workflow {
|
|
id String @id
|
|
tenantId String?
|
|
name String
|
|
description String?
|
|
nodes String // JSON: WorkflowNode[]
|
|
edges String // JSON: WorkflowEdge[]
|
|
enabled Boolean
|
|
version Int @default(1)
|
|
createdAt BigInt?
|
|
updatedAt BigInt?
|
|
createdBy String?
|
|
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([tenantId])
|
|
@@index([enabled])
|
|
}
|
|
|
|
model LuaScript {
|
|
id String @id
|
|
tenantId String?
|
|
name String
|
|
description String?
|
|
code String
|
|
parameters String // JSON: Array<{name, type}>
|
|
returnType String?
|
|
isSandboxed Boolean @default(true)
|
|
allowedGlobals String @default("[]")
|
|
timeoutMs Int @default(5000)
|
|
version Int @default(1)
|
|
createdAt BigInt?
|
|
updatedAt BigInt?
|
|
createdBy String?
|
|
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([tenantId])
|
|
@@index([name])
|
|
}
|
|
|
|
// =============================================================================
|
|
// DATA SCHEMAS
|
|
// =============================================================================
|
|
|
|
model ModelSchema {
|
|
id String @id @default(cuid())
|
|
tenantId String?
|
|
name String
|
|
label String?
|
|
labelPlural String?
|
|
icon String?
|
|
fields String // JSON: field definitions
|
|
listDisplay String? // JSON: columns to show in list
|
|
listFilter String? // JSON: filterable fields
|
|
searchFields String? // JSON: searchable fields
|
|
ordering String? // JSON: default sort order
|
|
validations String? // JSON: validation rules
|
|
hooks String? // JSON: lifecycle hooks (Lua script refs)
|
|
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([tenantId, name])
|
|
@@index([tenantId])
|
|
}
|
|
|
|
model DynamicData {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
schemaId String // Reference to ModelSchema
|
|
data String // JSON: actual record data
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
createdBy String?
|
|
updatedBy String?
|
|
|
|
@@index([tenantId, schemaId])
|
|
@@index([createdAt])
|
|
}
|
|
|
|
// =============================================================================
|
|
// APP CONFIGURATION
|
|
// =============================================================================
|
|
|
|
model AppConfiguration {
|
|
id String @id
|
|
name String
|
|
schemas String // JSON
|
|
workflows String // JSON
|
|
luaScripts String // JSON
|
|
pages String // JSON
|
|
theme String // JSON
|
|
}
|
|
|
|
model SystemConfig {
|
|
key String @id
|
|
value String
|
|
}
|
|
|
|
model SMTPConfig {
|
|
id String @id @default("default")
|
|
host String
|
|
port Int
|
|
secure Boolean
|
|
username String
|
|
password String
|
|
fromEmail String
|
|
fromName String
|
|
}
|
|
|
|
// =============================================================================
|
|
// GENERIC KEY-VALUE STORAGE
|
|
// =============================================================================
|
|
|
|
model KeyValue {
|
|
id String @id @default(cuid())
|
|
tenantId String?
|
|
namespace String // Logical grouping: 'settings', 'cache', 'state', 'user_prefs', etc.
|
|
key String
|
|
value String // JSON or plain text
|
|
type String @default("string") // string, json, number, boolean
|
|
expiresAt BigInt? // Optional TTL for cache-like usage
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
|
|
@@unique([tenantId, namespace, key])
|
|
@@index([tenantId])
|
|
@@index([namespace])
|
|
@@index([expiresAt])
|
|
}
|
|
|
|
model UserPreference {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
tenantId String?
|
|
key String // theme, language, notifications_enabled, sidebar_collapsed, etc.
|
|
value String // JSON or plain value
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
|
|
@@unique([userId, tenantId, key])
|
|
@@index([userId])
|
|
@@index([tenantId])
|
|
}
|
|
|
|
model FeatureFlag {
|
|
id String @id @default(cuid())
|
|
tenantId String?
|
|
name String // dark_mode, beta_features, new_editor, etc.
|
|
enabled Boolean @default(false)
|
|
description String?
|
|
rules String? // JSON: targeting rules (user roles, percentages, etc.)
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
|
|
@@unique([tenantId, name])
|
|
@@index([tenantId])
|
|
@@index([enabled])
|
|
}
|
|
|
|
// =============================================================================
|
|
// COMPONENTS & UI
|
|
// =============================================================================
|
|
|
|
model ComponentNode {
|
|
id String @id
|
|
type String
|
|
parentId String?
|
|
childIds String // JSON: string[]
|
|
order Int
|
|
pageId String
|
|
|
|
@@index([pageId])
|
|
@@index([parentId])
|
|
}
|
|
|
|
model ComponentConfig {
|
|
id String @id
|
|
componentId String
|
|
props String // JSON
|
|
styles String // JSON
|
|
events String // JSON
|
|
conditionalRendering String? // JSON
|
|
|
|
@@index([componentId])
|
|
}
|
|
|
|
model CssCategory {
|
|
id String @id @default(cuid())
|
|
name String @unique
|
|
classes String // JSON: string[]
|
|
}
|
|
|
|
model DropdownConfig {
|
|
id String @id
|
|
name String @unique
|
|
label String
|
|
options String // JSON: Array<{value, label}>
|
|
}
|
|
|
|
// =============================================================================
|
|
// PACKAGES
|
|
// =============================================================================
|
|
|
|
model InstalledPackage {
|
|
packageId String @id
|
|
tenantId String?
|
|
installedAt BigInt
|
|
version String
|
|
enabled Boolean
|
|
config String? // JSON: package-specific configuration
|
|
|
|
@@index([tenantId])
|
|
}
|
|
|
|
model PackageData {
|
|
packageId String @id
|
|
data String // JSON
|
|
}
|
|
|
|
// =============================================================================
|
|
// CONTENT: COMMENTS
|
|
// =============================================================================
|
|
|
|
model Comment {
|
|
id String @id
|
|
tenantId String?
|
|
userId String
|
|
content String
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
parentId String?
|
|
entityType String? // What this comment is on: 'post', 'thread', 'media', etc.
|
|
entityId String? // ID of the entity being commented on
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([tenantId])
|
|
@@index([userId])
|
|
@@index([parentId])
|
|
@@index([entityType, entityId])
|
|
}
|
|
|
|
// =============================================================================
|
|
// CONTENT: FORUM
|
|
// =============================================================================
|
|
|
|
model ForumCategory {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
name String
|
|
description String?
|
|
icon String?
|
|
slug String
|
|
sortOrder Int @default(0)
|
|
parentId String? // For nested categories
|
|
createdAt BigInt
|
|
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
threads ForumThread[]
|
|
|
|
@@unique([tenantId, slug])
|
|
@@index([tenantId])
|
|
@@index([parentId])
|
|
}
|
|
|
|
model ForumThread {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
categoryId String
|
|
authorId String
|
|
title String
|
|
content String
|
|
slug String
|
|
isPinned Boolean @default(false)
|
|
isLocked Boolean @default(false)
|
|
viewCount Int @default(0)
|
|
replyCount Int @default(0)
|
|
lastReplyAt BigInt?
|
|
lastReplyBy String?
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
category ForumCategory @relation(fields: [categoryId], references: [id], onDelete: Cascade)
|
|
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
|
|
posts ForumPost[]
|
|
|
|
@@unique([tenantId, slug])
|
|
@@index([tenantId])
|
|
@@index([categoryId])
|
|
@@index([authorId])
|
|
@@index([isPinned, lastReplyAt])
|
|
}
|
|
|
|
model ForumPost {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
threadId String
|
|
authorId String
|
|
content String
|
|
likes Int @default(0)
|
|
isEdited Boolean @default(false)
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
thread ForumThread @relation(fields: [threadId], references: [id], onDelete: Cascade)
|
|
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([tenantId])
|
|
@@index([threadId])
|
|
@@index([authorId])
|
|
}
|
|
|
|
// =============================================================================
|
|
// MEDIA
|
|
// =============================================================================
|
|
|
|
model MediaAsset {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
userId String
|
|
filename String
|
|
originalName String
|
|
mimeType String
|
|
size BigInt
|
|
path String
|
|
thumbnailPath String?
|
|
width Int?
|
|
height Int?
|
|
duration Int? // For video/audio in seconds
|
|
metadata String? // JSON: EXIF, tags, etc.
|
|
createdAt BigInt
|
|
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([tenantId])
|
|
@@index([userId])
|
|
@@index([mimeType])
|
|
}
|
|
|
|
model MediaJob {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
userId String
|
|
type String // transcode, thumbnail, convert, etc.
|
|
status String // pending, processing, completed, failed
|
|
priority Int @default(0)
|
|
inputPath String
|
|
outputPath String?
|
|
params String // JSON: job-specific parameters
|
|
progress Int @default(0)
|
|
error String?
|
|
startedAt BigInt?
|
|
completedAt BigInt?
|
|
createdAt BigInt
|
|
|
|
@@index([tenantId])
|
|
@@index([status, priority])
|
|
@@index([userId])
|
|
}
|
|
|
|
// =============================================================================
|
|
// NOTIFICATIONS
|
|
// =============================================================================
|
|
|
|
model Notification {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
userId String
|
|
type String // info, warning, success, error, mention, reply, etc.
|
|
title String
|
|
message String
|
|
icon String?
|
|
read Boolean @default(false)
|
|
data String? // JSON: action URLs, entity references, etc.
|
|
createdAt BigInt
|
|
expiresAt BigInt?
|
|
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([tenantId])
|
|
@@index([userId, read])
|
|
@@index([createdAt])
|
|
}
|
|
|
|
// =============================================================================
|
|
// AUDIT & LOGGING
|
|
// =============================================================================
|
|
|
|
model AuditLog {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
userId String?
|
|
username String?
|
|
action String // create, update, delete, login, logout, etc.
|
|
entity String // User, Workflow, Page, etc.
|
|
entityId String?
|
|
oldValue String? // JSON: previous state
|
|
newValue String? // JSON: new state
|
|
ipAddress String?
|
|
userAgent String?
|
|
details String? // JSON: additional context
|
|
timestamp BigInt
|
|
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
|
|
@@index([tenantId])
|
|
@@index([userId])
|
|
@@index([entity, entityId])
|
|
@@index([action])
|
|
@@index([timestamp])
|
|
}
|
|
|
|
model ErrorLog {
|
|
id String @id @default(cuid())
|
|
timestamp BigInt
|
|
level String // error, warning, info
|
|
message String
|
|
stack String?
|
|
context String? // JSON: additional context
|
|
userId String?
|
|
username String?
|
|
tenantId String?
|
|
source String? // Component/file where error occurred
|
|
resolved Boolean @default(false)
|
|
resolvedAt BigInt?
|
|
resolvedBy String?
|
|
|
|
@@index([tenantId])
|
|
@@index([level])
|
|
@@index([timestamp])
|
|
@@index([resolved])
|
|
}
|
|
|
|
// =============================================================================
|
|
// AUTH TOKENS & SECURITY
|
|
// =============================================================================
|
|
|
|
model PasswordResetToken {
|
|
username String @id
|
|
token String
|
|
expiresAt BigInt?
|
|
createdAt BigInt?
|
|
}
|
|
|
|
model PowerTransferRequest {
|
|
id String @id
|
|
fromUserId String
|
|
toUserId String
|
|
status String // pending, accepted, rejected
|
|
createdAt BigInt
|
|
expiresAt BigInt
|
|
fromUser User @relation("PowerTransferFrom", fields: [fromUserId], references: [id], onDelete: Cascade)
|
|
toUser User @relation("PowerTransferTo", fields: [toUserId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([status])
|
|
@@index([expiresAt])
|
|
}
|
|
|
|
// =============================================================================
|
|
// GENERIC ENTITIES FOR PACKAGES
|
|
// =============================================================================
|
|
|
|
// Tags - Attach labels to any entity (posts, media, threads, etc.)
|
|
model Tag {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
name String
|
|
slug String
|
|
color String? // Hex color for UI
|
|
icon String?
|
|
category String? // Group tags: 'topic', 'status', 'priority', etc.
|
|
createdAt BigInt
|
|
|
|
@@unique([tenantId, slug])
|
|
@@index([tenantId])
|
|
@@index([category])
|
|
}
|
|
|
|
// Tagging - Many-to-many junction for tags on any entity
|
|
model Tagging {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
tagId String
|
|
entityType String // 'post', 'media', 'thread', 'user', etc.
|
|
entityId String
|
|
createdAt BigInt
|
|
createdBy String?
|
|
|
|
@@unique([tagId, entityType, entityId])
|
|
@@index([tenantId])
|
|
@@index([tagId])
|
|
@@index([entityType, entityId])
|
|
}
|
|
|
|
// Relationships - Generic many-to-many between any entities
|
|
model EntityRelation {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
sourceType String // 'user', 'post', 'product', etc.
|
|
sourceId String
|
|
targetType String
|
|
targetId String
|
|
relationType String // 'follows', 'blocks', 'related_to', 'parent_of', etc.
|
|
metadata String? // JSON: additional relation data
|
|
createdAt BigInt
|
|
createdBy String?
|
|
|
|
@@unique([sourceType, sourceId, targetType, targetId, relationType])
|
|
@@index([tenantId])
|
|
@@index([sourceType, sourceId])
|
|
@@index([targetType, targetId])
|
|
@@index([relationType])
|
|
}
|
|
|
|
// Generic Task Queue - Background jobs for any package
|
|
model Task {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
queue String // 'email', 'export', 'import', 'cleanup', etc.
|
|
type String // Specific task type within queue
|
|
status String @default("pending") // pending, running, completed, failed, cancelled
|
|
priority Int @default(0)
|
|
payload String // JSON: task input data
|
|
result String? // JSON: task output/result
|
|
error String?
|
|
attempts Int @default(0)
|
|
maxAttempts Int @default(3)
|
|
runAt BigInt? // Scheduled execution time
|
|
startedAt BigInt?
|
|
completedAt BigInt?
|
|
createdAt BigInt
|
|
createdBy String?
|
|
|
|
@@index([tenantId])
|
|
@@index([queue, status])
|
|
@@index([status, priority])
|
|
@@index([runAt])
|
|
}
|
|
|
|
// Webhooks - Outbound event notifications
|
|
model Webhook {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
name String
|
|
url String
|
|
secret String? // For HMAC signing
|
|
events String // JSON: array of event types to trigger on
|
|
headers String? // JSON: custom headers to include
|
|
enabled Boolean @default(true)
|
|
lastTriggered BigInt?
|
|
failCount Int @default(0)
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
|
|
@@index([tenantId])
|
|
@@index([enabled])
|
|
}
|
|
|
|
// Webhook Deliveries - Log of webhook attempts
|
|
model WebhookDelivery {
|
|
id String @id @default(cuid())
|
|
webhookId String
|
|
event String
|
|
payload String // JSON: what was sent
|
|
response String? // JSON: response received
|
|
statusCode Int?
|
|
success Boolean
|
|
duration Int? // ms
|
|
error String?
|
|
createdAt BigInt
|
|
|
|
@@index([webhookId])
|
|
@@index([createdAt])
|
|
@@index([success])
|
|
}
|
|
|
|
// Attachments - Generic file attachments to any entity
|
|
model Attachment {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
entityType String // 'comment', 'post', 'message', etc.
|
|
entityId String
|
|
filename String
|
|
originalName String
|
|
mimeType String
|
|
size BigInt
|
|
path String
|
|
metadata String? // JSON: dimensions, duration, etc.
|
|
sortOrder Int @default(0)
|
|
createdAt BigInt
|
|
createdBy String?
|
|
|
|
@@index([tenantId])
|
|
@@index([entityType, entityId])
|
|
}
|
|
|
|
// Reactions - Likes, emoji reactions on any entity
|
|
model Reaction {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
userId String
|
|
entityType String // 'post', 'comment', 'media', etc.
|
|
entityId String
|
|
type String // 'like', 'love', 'laugh', 'wow', 'sad', 'angry', '+1', etc.
|
|
createdAt BigInt
|
|
|
|
@@unique([userId, entityType, entityId, type])
|
|
@@index([tenantId])
|
|
@@index([entityType, entityId])
|
|
@@index([userId])
|
|
}
|
|
|
|
// Bookmarks/Favorites - Users saving any entity
|
|
model Bookmark {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
userId String
|
|
entityType String // 'post', 'thread', 'media', 'product', etc.
|
|
entityId String
|
|
folder String? // Optional folder/collection
|
|
note String? // User's note about the bookmark
|
|
createdAt BigInt
|
|
|
|
@@unique([userId, entityType, entityId])
|
|
@@index([tenantId])
|
|
@@index([userId])
|
|
@@index([entityType, entityId])
|
|
@@index([folder])
|
|
}
|
|
|
|
// Activity Feed - Timeline events
|
|
model Activity {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
userId String?
|
|
action String // 'created', 'updated', 'deleted', 'shared', 'mentioned', etc.
|
|
entityType String
|
|
entityId String
|
|
targetType String? // Secondary entity (e.g., 'user' mentioned in 'post')
|
|
targetId String?
|
|
metadata String? // JSON: extra context
|
|
isPublic Boolean @default(true)
|
|
createdAt BigInt
|
|
|
|
@@index([tenantId])
|
|
@@index([userId])
|
|
@@index([entityType, entityId])
|
|
@@index([createdAt])
|
|
@@index([isPublic, createdAt])
|
|
}
|
|
|
|
// Counters - Denormalized counts for any entity
|
|
model Counter {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
entityType String
|
|
entityId String
|
|
name String // 'views', 'likes', 'shares', 'downloads', etc.
|
|
value BigInt @default(0)
|
|
updatedAt BigInt
|
|
|
|
@@unique([entityType, entityId, name])
|
|
@@index([tenantId])
|
|
@@index([entityType, entityId])
|
|
}
|
|
|
|
// Versions - Version history for any entity
|
|
model Version {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
entityType String
|
|
entityId String
|
|
version Int
|
|
data String // JSON: snapshot of entity state
|
|
changes String? // JSON: diff from previous version
|
|
message String? // Commit message
|
|
createdAt BigInt
|
|
createdBy String?
|
|
|
|
@@unique([entityType, entityId, version])
|
|
@@index([tenantId])
|
|
@@index([entityType, entityId])
|
|
@@index([createdAt])
|
|
}
|
|
|
|
// Templates - Reusable content templates
|
|
model Template {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
name String
|
|
description String?
|
|
category String // 'email', 'page', 'component', 'workflow', etc.
|
|
content String // JSON or template string
|
|
variables String? // JSON: list of variable placeholders
|
|
isPublic Boolean @default(false)
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
createdBy String?
|
|
|
|
@@unique([tenantId, category, name])
|
|
@@index([tenantId])
|
|
@@index([category])
|
|
@@index([isPublic])
|
|
}
|
|
|
|
// Scheduled Jobs - Cron-like recurring tasks
|
|
model ScheduledJob {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
name String
|
|
description String?
|
|
schedule String // Cron expression: "0 0 * * *"
|
|
taskType String // What to run
|
|
taskPayload String // JSON: parameters
|
|
enabled Boolean @default(true)
|
|
lastRunAt BigInt?
|
|
nextRunAt BigInt?
|
|
lastStatus String? // success, failed
|
|
lastError String?
|
|
runCount Int @default(0)
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
|
|
@@index([tenantId])
|
|
@@index([enabled, nextRunAt])
|
|
}
|
|
|
|
// Locks - Distributed locking for concurrency control
|
|
model Lock {
|
|
id String @id @default(cuid())
|
|
tenantId String?
|
|
resource String // What's being locked
|
|
owner String // Who holds the lock (session ID, worker ID, etc.)
|
|
expiresAt BigInt
|
|
acquiredAt BigInt
|
|
metadata String? // JSON: additional context
|
|
|
|
@@unique([tenantId, resource])
|
|
@@index([expiresAt])
|
|
}
|
|
|
|
// Messages - Generic messaging/inbox system
|
|
model Message {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
senderId String?
|
|
recipientId String
|
|
threadId String? // For threaded conversations
|
|
subject String?
|
|
body String
|
|
isRead Boolean @default(false)
|
|
isArchived Boolean @default(false)
|
|
isDeleted Boolean @default(false)
|
|
metadata String? // JSON: attachments, flags, etc.
|
|
createdAt BigInt
|
|
readAt BigInt?
|
|
|
|
@@index([tenantId])
|
|
@@index([recipientId, isRead])
|
|
@@index([senderId])
|
|
@@index([threadId])
|
|
@@index([createdAt])
|
|
}
|
|
|
|
// Invitations - Generic invite system
|
|
model Invitation {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
type String // 'team', 'project', 'event', etc.
|
|
targetId String? // What they're being invited to
|
|
email String
|
|
token String @unique
|
|
role String? // Role to assign on acceptance
|
|
invitedBy String
|
|
status String @default("pending") // pending, accepted, declined, expired
|
|
expiresAt BigInt
|
|
acceptedAt BigInt?
|
|
createdAt BigInt
|
|
|
|
@@index([tenantId])
|
|
@@index([email])
|
|
@@index([token])
|
|
@@index([status])
|
|
}
|
|
|
|
// =============================================================================
|
|
// GITHUB INTEGRATION (github_tools package)
|
|
// =============================================================================
|
|
|
|
model GitHubRepository {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
owner String
|
|
name String
|
|
fullName String // "owner/repo"
|
|
url String
|
|
cloneUrl String?
|
|
description String?
|
|
isPrivate Boolean @default(false)
|
|
defaultBranch String?
|
|
language String?
|
|
starCount Int @default(0)
|
|
forkCount Int @default(0)
|
|
openIssues Int @default(0)
|
|
license String?
|
|
topics String? // JSON: array of topics
|
|
lastSync BigInt?
|
|
syncError String?
|
|
enabled Boolean @default(true)
|
|
metadata String? // JSON: additional GitHub data
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
actions GitHubAction[]
|
|
workflows GitHubWorkflow[]
|
|
|
|
@@unique([tenantId, fullName])
|
|
@@index([tenantId])
|
|
@@index([owner])
|
|
}
|
|
|
|
model GitHubWorkflow {
|
|
id String @id @default(cuid())
|
|
repositoryId String
|
|
name String
|
|
path String
|
|
state String // active, deleted, disabled_fork, etc.
|
|
badge String? // Badge URL
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
repository GitHubRepository @relation(fields: [repositoryId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([repositoryId, path])
|
|
@@index([repositoryId])
|
|
}
|
|
|
|
model GitHubAction {
|
|
id String @id @default(cuid())
|
|
repositoryId String
|
|
workflowId String?
|
|
workflowName String
|
|
runId BigInt
|
|
runNumber Int
|
|
event String // push, pull_request, schedule, etc.
|
|
status String // queued, in_progress, completed
|
|
conclusion String? // success, failure, cancelled, skipped
|
|
branch String?
|
|
commitSha String?
|
|
commitMsg String?
|
|
actor String? // Who triggered it
|
|
url String
|
|
logsUrl String?
|
|
triggeredAt BigInt?
|
|
startedAt BigInt?
|
|
completedAt BigInt?
|
|
duration Int? // seconds
|
|
createdAt BigInt
|
|
repository GitHubRepository @relation(fields: [repositoryId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([repositoryId, runId])
|
|
@@index([repositoryId])
|
|
@@index([status])
|
|
@@index([conclusion])
|
|
@@index([completedAt])
|
|
}
|
|
|
|
model GitHubIssue {
|
|
id String @id @default(cuid())
|
|
repositoryId String
|
|
issueNumber Int
|
|
title String
|
|
body String?
|
|
state String // open, closed
|
|
author String
|
|
labels String? // JSON array
|
|
assignees String? // JSON array
|
|
milestone String?
|
|
comments Int @default(0)
|
|
locked Boolean @default(false)
|
|
url String
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
closedAt BigInt?
|
|
|
|
@@unique([repositoryId, issueNumber])
|
|
@@index([repositoryId])
|
|
@@index([state])
|
|
}
|
|
|
|
// =============================================================================
|
|
// GAMING & ARCADE (arcade_lobby package)
|
|
// =============================================================================
|
|
|
|
model Game {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
name String
|
|
slug String
|
|
description String?
|
|
thumbnail String?
|
|
bannerImage String?
|
|
category String // platformer, puzzle, arcade, shooter, rpg, etc.
|
|
platform String // retroarch, web, native, etc.
|
|
core String? // RetroArch core name (snes9x, genesis_plus_gx, etc.)
|
|
romPath String?
|
|
romHash String? // SHA256 for integrity
|
|
saveDataPath String?
|
|
configPath String?
|
|
controls String? // JSON: button mappings
|
|
cheats String? // JSON: cheat codes
|
|
achievements String? // JSON: achievement definitions
|
|
metadata String? // JSON: developer, release year, genre tags, etc.
|
|
rating String? // E, T, M, etc.
|
|
players String @default("1") // "1", "1-2", "1-4", etc.
|
|
enabled Boolean @default(true)
|
|
featured Boolean @default(false)
|
|
playCount Int @default(0)
|
|
favoriteCount Int @default(0)
|
|
avgRating Float?
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
sessions GameSession[]
|
|
highScores GameHighScore[]
|
|
saves GameSave[]
|
|
reviews GameReview[]
|
|
|
|
@@unique([tenantId, slug])
|
|
@@index([tenantId])
|
|
@@index([category])
|
|
@@index([platform])
|
|
@@index([featured, playCount])
|
|
}
|
|
|
|
model GameSession {
|
|
id String @id @default(cuid())
|
|
gameId String
|
|
userId String
|
|
startedAt BigInt
|
|
endedAt BigInt?
|
|
duration Int? // seconds
|
|
saveStateId String? // Reference to GameSave
|
|
score BigInt?
|
|
level Int?
|
|
achievements String? // JSON: array of unlocked achievement IDs
|
|
stats String? // JSON: game-specific stats
|
|
metadata String? // JSON: controller used, settings, etc.
|
|
game Game @relation(fields: [gameId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([gameId])
|
|
@@index([userId])
|
|
@@index([startedAt])
|
|
}
|
|
|
|
model GameHighScore {
|
|
id String @id @default(cuid())
|
|
gameId String
|
|
userId String
|
|
username String
|
|
score BigInt
|
|
rank Int?
|
|
level Int?
|
|
character String? // For games with character selection
|
|
mode String? // difficulty, speedrun, etc.
|
|
verified Boolean @default(false)
|
|
replay String? // Path to replay file
|
|
metadata String? // JSON: additional context
|
|
createdAt BigInt
|
|
game Game @relation(fields: [gameId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([gameId, score])
|
|
@@index([gameId, rank])
|
|
@@index([userId])
|
|
}
|
|
|
|
model GameSave {
|
|
id String @id @default(cuid())
|
|
gameId String
|
|
userId String
|
|
name String // User-provided name
|
|
slot Int @default(0)
|
|
filePath String
|
|
screenshot String? // Thumbnail of save state
|
|
level Int?
|
|
progress Float? // Percentage completion
|
|
playTime Int? // seconds
|
|
isAuto Boolean @default(false)
|
|
metadata String? // JSON: location, items, etc.
|
|
createdAt BigInt
|
|
game Game @relation(fields: [gameId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([gameId, userId, slot])
|
|
@@index([gameId, userId])
|
|
@@index([createdAt])
|
|
}
|
|
|
|
model GameReview {
|
|
id String @id @default(cuid())
|
|
gameId String
|
|
userId String
|
|
username String
|
|
rating Int // 1-5 stars
|
|
title String?
|
|
review String?
|
|
helpful Int @default(0)
|
|
notHelpful Int @default(0)
|
|
verified Boolean @default(false) // Did they actually play it?
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
game Game @relation(fields: [gameId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([gameId, userId])
|
|
@@index([gameId])
|
|
@@index([rating])
|
|
}
|
|
|
|
// =============================================================================
|
|
// CSS DESIGNER & THEMING (css_designer package)
|
|
// =============================================================================
|
|
|
|
model CSSTheme {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
name String
|
|
slug String
|
|
description String?
|
|
author String?
|
|
version String @default("1.0.0")
|
|
baseTheme String? // Parent theme to extend
|
|
variables String // JSON: CSS custom properties { "--color-primary": "#ff0000" }
|
|
typography String? // JSON: font families, sizes, weights
|
|
colors String? // JSON: color palette definitions
|
|
spacing String? // JSON: spacing scale
|
|
borders String? // JSON: border radius, widths
|
|
shadows String? // JSON: box shadow definitions
|
|
components String? // JSON: component-specific overrides
|
|
animations String? // JSON: transition/animation settings
|
|
breakpoints String? // JSON: responsive breakpoints
|
|
isDefault Boolean @default(false)
|
|
isPublic Boolean @default(false)
|
|
isDark Boolean @default(false)
|
|
tags String? // JSON: array of tags
|
|
preview String? // Preview image URL
|
|
downloads Int @default(0)
|
|
rating Float?
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
createdBy String?
|
|
|
|
@@unique([tenantId, slug])
|
|
@@index([tenantId])
|
|
@@index([isPublic, isDefault])
|
|
@@index([isDark])
|
|
}
|
|
|
|
model CSSVariable {
|
|
id String @id @default(cuid())
|
|
themeId String?
|
|
category String // color, spacing, typography, etc.
|
|
name String // --color-primary
|
|
value String // #1976d2
|
|
description String?
|
|
fallback String? // Default value if theme not loaded
|
|
scope String @default("global") // global, component-specific
|
|
createdAt BigInt
|
|
|
|
@@unique([themeId, name])
|
|
@@index([category])
|
|
@@index([scope])
|
|
}
|
|
|
|
// =============================================================================
|
|
// DASHBOARD & WIDGETS (dashboard package)
|
|
// =============================================================================
|
|
|
|
model Dashboard {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
userId String?
|
|
name String
|
|
slug String
|
|
description String?
|
|
layout String // JSON: grid layout config
|
|
isDefault Boolean @default(false)
|
|
isShared Boolean @default(false)
|
|
isPublic Boolean @default(false)
|
|
permissions String? // JSON: who can view/edit
|
|
refreshRate Int? // seconds
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
widgets DashboardWidget[]
|
|
|
|
@@unique([tenantId, slug])
|
|
@@index([tenantId])
|
|
@@index([userId])
|
|
@@index([isPublic])
|
|
}
|
|
|
|
model DashboardWidget {
|
|
id String @id @default(cuid())
|
|
dashboardId String
|
|
type String // chart, stats, list, calendar, table, iframe, custom
|
|
title String
|
|
subtitle String?
|
|
dataSource String // JSON: query/API config
|
|
chartType String? // line, bar, pie, donut, area, etc.
|
|
config String // JSON: widget-specific configuration
|
|
position String // JSON: {x, y, w, h} grid position
|
|
minSize String? // JSON: {w, h} minimum dimensions
|
|
maxSize String? // JSON: {w, h} maximum dimensions
|
|
refreshRate Int? // seconds, null = no auto-refresh
|
|
permissions String? // JSON: role-based visibility
|
|
sortOrder Int @default(0)
|
|
enabled Boolean @default(true)
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
dashboard Dashboard @relation(fields: [dashboardId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([dashboardId])
|
|
@@index([type])
|
|
}
|
|
|
|
model WidgetDataCache {
|
|
id String @id @default(cuid())
|
|
widgetId String
|
|
data String // JSON: cached data
|
|
expiresAt BigInt
|
|
cachedAt BigInt
|
|
cacheKey String
|
|
|
|
@@unique([widgetId, cacheKey])
|
|
@@index([expiresAt])
|
|
}
|
|
|
|
// =============================================================================
|
|
// GUIDES & DOCUMENTATION (quick_guide package)
|
|
// =============================================================================
|
|
|
|
model Guide {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
title String
|
|
slug String
|
|
description String?
|
|
content String // Markdown content
|
|
category String? // getting-started, tutorials, reference, api
|
|
difficulty String? // beginner, intermediate, advanced
|
|
estimatedTime Int? // minutes
|
|
tags String? // JSON array
|
|
icon String?
|
|
author String?
|
|
isPublished Boolean @default(true)
|
|
isFeatured Boolean @default(false)
|
|
order Int @default(0)
|
|
version String @default("1.0.0")
|
|
views Int @default(0)
|
|
likes Int @default(0)
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
publishedAt BigInt?
|
|
createdBy String?
|
|
steps GuideStep[]
|
|
|
|
@@unique([tenantId, slug])
|
|
@@index([tenantId])
|
|
@@index([category])
|
|
@@index([isPublished, isFeatured])
|
|
}
|
|
|
|
model GuideStep {
|
|
id String @id @default(cuid())
|
|
guideId String
|
|
title String
|
|
content String // Markdown
|
|
order Int
|
|
actionType String? // click, input, navigate, wait, run, etc.
|
|
actionData String? // JSON: element selector, value, etc.
|
|
validation String? // JSON: success criteria
|
|
hints String? // JSON: array of hints
|
|
screenshot String? // Path to screenshot
|
|
videoUrl String?
|
|
createdAt BigInt
|
|
guide Guide @relation(fields: [guideId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([guideId, order])
|
|
}
|
|
|
|
model GuideProgress {
|
|
id String @id @default(cuid())
|
|
guideId String
|
|
userId String
|
|
completedSteps String // JSON: array of step IDs
|
|
progress Float @default(0) // 0-100
|
|
startedAt BigInt
|
|
lastViewedAt BigInt
|
|
completedAt BigInt?
|
|
|
|
@@unique([guideId, userId])
|
|
@@index([userId])
|
|
@@index([guideId])
|
|
}
|
|
|
|
// =============================================================================
|
|
// ANALYTICS & METRICS (for all packages)
|
|
// =============================================================================
|
|
|
|
model Metric {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
namespace String // package name or feature area
|
|
name String // metric name (page_views, api_calls, etc.)
|
|
value Float
|
|
unit String? // ms, bytes, count, etc.
|
|
dimensions String? // JSON: tags/dimensions
|
|
timestamp BigInt
|
|
|
|
@@index([tenantId, namespace, name])
|
|
@@index([timestamp])
|
|
}
|
|
|
|
model Event {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
userId String?
|
|
category String // user_action, system, error, etc.
|
|
action String // click, view, create, delete, etc.
|
|
label String?
|
|
value Float?
|
|
properties String? // JSON: additional event data
|
|
sessionId String?
|
|
url String?
|
|
referrer String?
|
|
device String? // desktop, mobile, tablet
|
|
os String?
|
|
browser String?
|
|
timestamp BigInt
|
|
|
|
@@index([tenantId, category, action])
|
|
@@index([userId])
|
|
@@index([timestamp])
|
|
}
|
|
|
|
// =============================================================================
|
|
// IRC & CHAT (irc_webchat package)
|
|
// =============================================================================
|
|
|
|
model IRCChannel {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
name String // #general, #help, etc.
|
|
topic String?
|
|
description String?
|
|
mode String @default("public") // public, private, secret
|
|
password String? // For private channels
|
|
maxUsers Int?
|
|
slowMode Int? // Seconds between messages
|
|
isDefault Boolean @default(false)
|
|
createdAt BigInt
|
|
createdBy String?
|
|
messages IRCMessage[]
|
|
memberships IRCMembership[]
|
|
|
|
@@unique([tenantId, name])
|
|
@@index([tenantId])
|
|
@@index([isDefault])
|
|
}
|
|
|
|
model IRCMessage {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
channelId String
|
|
userId String
|
|
username String
|
|
type String @default("message") // message, action, notice, system
|
|
content String
|
|
isCommand Boolean @default(false)
|
|
metadata String? // JSON: mentions, links, etc.
|
|
createdAt BigInt
|
|
channel IRCChannel @relation(fields: [channelId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([channelId])
|
|
@@index([userId])
|
|
@@index([createdAt])
|
|
}
|
|
|
|
model IRCMembership {
|
|
id String @id @default(cuid())
|
|
channelId String
|
|
userId String
|
|
username String
|
|
role String @default("user") // user, voice, halfop, op, admin, owner
|
|
joinedAt BigInt
|
|
lastActive BigInt?
|
|
isBanned Boolean @default(false)
|
|
isKicked Boolean @default(false)
|
|
kickReason String?
|
|
metadata String? // JSON: user preferences
|
|
channel IRCChannel @relation(fields: [channelId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([channelId, userId])
|
|
@@index([userId])
|
|
}
|
|
|
|
// =============================================================================
|
|
// STREAMING (stream_cast package)
|
|
// =============================================================================
|
|
|
|
model StreamChannel {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
name String
|
|
slug String
|
|
description String?
|
|
thumbnail String?
|
|
category String? // gaming, music, talk, art, etc.
|
|
status String @default("offline") // offline, live, scheduled
|
|
viewerCount Int @default(0)
|
|
streamKey String? @unique
|
|
rtmpUrl String?
|
|
hlsUrl String?
|
|
chatEnabled Boolean @default(true)
|
|
isPublic Boolean @default(true)
|
|
isMature Boolean @default(false)
|
|
metadata String? // JSON: bitrate, resolution, etc.
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
createdBy String
|
|
schedules StreamSchedule[]
|
|
scenes StreamScene[]
|
|
|
|
@@unique([tenantId, slug])
|
|
@@index([tenantId])
|
|
@@index([status])
|
|
@@index([category])
|
|
}
|
|
|
|
model StreamSchedule {
|
|
id String @id @default(cuid())
|
|
channelId String
|
|
title String
|
|
description String?
|
|
startTime BigInt
|
|
endTime BigInt?
|
|
duration Int? // minutes
|
|
isRecurring Boolean @default(false)
|
|
recurrence String? // JSON: cron/rrule
|
|
notifyAt BigInt?
|
|
metadata String? // JSON: guests, topics, etc.
|
|
createdAt BigInt
|
|
channel StreamChannel @relation(fields: [channelId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([channelId])
|
|
@@index([startTime])
|
|
}
|
|
|
|
model StreamScene {
|
|
id String @id @default(cuid())
|
|
channelId String
|
|
name String
|
|
layout String // JSON: scene composition
|
|
sources String // JSON: cameras, screens, overlays
|
|
transitions String? // JSON: scene transitions
|
|
isActive Boolean @default(false)
|
|
sortOrder Int @default(0)
|
|
createdAt BigInt
|
|
channel StreamChannel @relation(fields: [channelId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([channelId])
|
|
@@index([isActive])
|
|
}
|
|
|
|
// =============================================================================
|
|
// CODEGEN STUDIO (codegen_studio package)
|
|
// =============================================================================
|
|
|
|
model CodegenProject {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
name String
|
|
slug String
|
|
description String?
|
|
language String // typescript, lua, python, etc.
|
|
framework String? // react, qt, fastapi, etc.
|
|
config String // JSON: project configuration
|
|
output String? // Generated code output path
|
|
status String @default("draft") // draft, generating, complete, error
|
|
lastGenAt BigInt?
|
|
error String?
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
createdBy String
|
|
blueprints CodegenBlueprint[]
|
|
templates CodegenTemplate[]
|
|
|
|
@@unique([tenantId, slug])
|
|
@@index([tenantId])
|
|
@@index([status])
|
|
}
|
|
|
|
model CodegenBlueprint {
|
|
id String @id @default(cuid())
|
|
projectId String
|
|
name String
|
|
type String // model, api, component, service, etc.
|
|
schema String // JSON: blueprint definition
|
|
depends String? // JSON: dependencies on other blueprints
|
|
output String? // JSON: generated artifacts
|
|
validated Boolean @default(false)
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
project CodegenProject @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([projectId, name])
|
|
@@index([projectId])
|
|
@@index([type])
|
|
}
|
|
|
|
model CodegenTemplate {
|
|
id String @id @default(cuid())
|
|
projectId String? // null for global templates
|
|
tenantId String?
|
|
name String
|
|
language String
|
|
type String // model, api, component, test, etc.
|
|
template String // Template content with placeholders
|
|
variables String? // JSON: variable definitions
|
|
isBuiltin Boolean @default(false)
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
project CodegenProject? @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([projectId, name])
|
|
@@index([tenantId])
|
|
@@index([language, type])
|
|
}
|
|
|
|
// =============================================================================
|
|
// API & INTEGRATIONS
|
|
// =============================================================================
|
|
|
|
model APIKey {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
name String
|
|
description String?
|
|
key String @unique
|
|
secret String?
|
|
permissions String // JSON: array of scopes
|
|
rateLimit Int? // requests per minute
|
|
ipWhitelist String? // JSON: array of allowed IPs
|
|
enabled Boolean @default(true)
|
|
lastUsedAt BigInt?
|
|
expiresAt BigInt?
|
|
createdAt BigInt
|
|
createdBy String?
|
|
|
|
@@index([tenantId])
|
|
@@index([key])
|
|
@@index([enabled])
|
|
}
|
|
|
|
model OAuthToken {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
provider String // github, google, etc.
|
|
accessToken String
|
|
refreshToken String?
|
|
tokenType String @default("Bearer")
|
|
scope String?
|
|
expiresAt BigInt?
|
|
metadata String? // JSON: provider-specific data
|
|
createdAt BigInt
|
|
updatedAt BigInt?
|
|
|
|
@@unique([userId, provider])
|
|
@@index([provider])
|
|
@@index([expiresAt])
|
|
}
|
|
|
|
// =============================================================================
|
|
// SEARCH & INDEXING
|
|
// =============================================================================
|
|
|
|
model SearchIndex {
|
|
id String @id @default(cuid())
|
|
tenantId String
|
|
entityType String
|
|
entityId String
|
|
title String
|
|
content String // Searchable text content
|
|
metadata String? // JSON: additional indexed fields
|
|
boost Float @default(1.0)
|
|
updatedAt BigInt
|
|
|
|
@@unique([entityType, entityId])
|
|
@@index([tenantId])
|
|
@@index([entityType])
|
|
}
|
|
|
|
// =============================================================================
|
|
// FEATURE FLAGS (Enhanced)
|
|
// =============================================================================
|
|
|
|
model FeatureFlagOverride {
|
|
id String @id @default(cuid())
|
|
flagId String
|
|
targetType String // user, role, tenant
|
|
targetId String
|
|
enabled Boolean
|
|
createdAt BigInt
|
|
|
|
@@unique([flagId, targetType, targetId])
|
|
@@index([flagId])
|
|
}
|
|
|
|
// =============================================================================
|
|
// PACKAGE ENHANCEMENTS
|
|
// =============================================================================
|
|
|
|
model PackagePermission {
|
|
id String @id @default(cuid())
|
|
packageId String
|
|
tenantId String?
|
|
userId String?
|
|
role String?
|
|
permission String // read, write, execute, admin
|
|
resource String? // Specific resource within package
|
|
granted Boolean @default(true)
|
|
createdAt BigInt
|
|
|
|
@@unique([packageId, tenantId, userId, permission, resource])
|
|
@@index([packageId])
|
|
@@index([tenantId])
|
|
}
|