- v2 foundation: ActionResult/DevError/ActorContext/ResourceRef/Execution types - ActionRegistry + ResourceRegistry (namespaced types, FAIL FAST on duplicates) - ActionRuntime pipeline: validate -> authorize -> middleware -> handler -> output validation -> audit -> event -> execution persisted (devos_action_executions) - Legacy bridge: v1 services registered as devops.*/core.* resources & actions (47 actions, 9 resources) - Unified Action API: POST /api/v2/actions/:actionId, GET discovery (actions/resources) - 10 v2 unit tests (registry fail-fast, validation, authz, failure audit, events)
761 lines
22 KiB
Plaintext
761 lines
22 KiB
Plaintext
// DevOS v1 — PostgreSQL + Prisma schema
|
||
// 设计原则(04-DATABASE-SCHEMA.md):
|
||
// - resources 表承担统一身份/发现/图谱公共字段;
|
||
// - 具备大量运行状态的资源使用类型化领域表(servers/websites/...),通过 resourceId 与 resources 一对一关联;
|
||
// - 资源关系独立成表(resource_relations),图谱可演进而非堆在一张大表;
|
||
// - 凭据密文独立存储,绝不与普通元数据混放。
|
||
|
||
generator client {
|
||
provider = "prisma-client-js"
|
||
}
|
||
|
||
datasource db {
|
||
provider = "postgresql"
|
||
url = env("DATABASE_URL")
|
||
}
|
||
|
||
// ============ 枚举 ============
|
||
|
||
enum ResourceType {
|
||
SERVER
|
||
DOMAIN
|
||
WEBSITE
|
||
REPOSITORY
|
||
CERTIFICATE
|
||
DATABASE
|
||
CONTAINER
|
||
EMAIL_ACCOUNT
|
||
PROJECT
|
||
TASK
|
||
NOTE
|
||
DOCUMENT
|
||
BACKUP
|
||
DEPLOYMENT
|
||
MONITOR
|
||
CREDENTIAL
|
||
AUTOMATION
|
||
AI_RUN
|
||
}
|
||
|
||
enum ResourceStatus {
|
||
PENDING
|
||
ACTIVE
|
||
ERROR
|
||
OFFLINE
|
||
ARCHIVED
|
||
UNKNOWN
|
||
}
|
||
|
||
enum WorkspaceRole {
|
||
OWNER
|
||
ADMIN
|
||
MEMBER
|
||
VIEWER
|
||
}
|
||
|
||
enum RiskLevel {
|
||
LOW
|
||
MEDIUM
|
||
HIGH
|
||
CRITICAL
|
||
}
|
||
|
||
enum ActorType {
|
||
USER
|
||
SYSTEM
|
||
AGENT
|
||
MCP
|
||
}
|
||
|
||
enum JobStatus {
|
||
PENDING
|
||
RUNNING
|
||
SUCCEEDED
|
||
FAILED
|
||
CANCELLED
|
||
DEAD
|
||
}
|
||
|
||
enum DeploymentStatus {
|
||
QUEUED
|
||
RUNNING
|
||
SUCCEEDED
|
||
FAILED
|
||
CANCELLED
|
||
}
|
||
|
||
enum CredentialType {
|
||
SSH_PASSWORD
|
||
SSH_KEY
|
||
API_TOKEN
|
||
DNS_PROVIDER
|
||
GIT_TOKEN
|
||
}
|
||
|
||
enum ServerAuthType {
|
||
PASSWORD
|
||
SSH_KEY
|
||
}
|
||
|
||
enum TriggerType {
|
||
MANUAL
|
||
CRON
|
||
EVENT
|
||
WEBHOOK
|
||
}
|
||
|
||
enum AiRunStatus {
|
||
PLANNING
|
||
AWAITING_APPROVAL
|
||
RUNNING
|
||
SUCCEEDED
|
||
FAILED
|
||
REJECTED
|
||
}
|
||
|
||
// ============ 身份与工作区 ============
|
||
|
||
/// # 数据库表 users:平台用户
|
||
model User {
|
||
/// # 数据库字段 邮箱(登录名,唯一)
|
||
id String @id @default(uuid())
|
||
email String @unique
|
||
/// # 数据库字段 密码哈希(argon2id/scrypt,绝不明文)
|
||
passwordHash String
|
||
name String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
memberships WorkspaceMember[]
|
||
|
||
@@map("users")
|
||
}
|
||
|
||
/// # 数据库表 workspaces:租户/安全边界
|
||
model Workspace {
|
||
id String @id @default(uuid())
|
||
name String
|
||
slug String @unique
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
members WorkspaceMember[]
|
||
resources Resource[]
|
||
|
||
@@map("workspaces")
|
||
}
|
||
|
||
/// # 数据库表 workspace_members:用户-工作区关系与角色
|
||
model WorkspaceMember {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
userId String
|
||
role WorkspaceRole @default(MEMBER)
|
||
createdAt DateTime @default(now())
|
||
|
||
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([workspaceId, userId])
|
||
@@index([userId])
|
||
@@map("workspace_members")
|
||
}
|
||
|
||
// ============ 统一资源模型 ============
|
||
|
||
/// # 数据库表 resources:统一资源身份/发现/图谱公共字段
|
||
model Resource {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
type ResourceType
|
||
name String
|
||
provider String?
|
||
status ResourceStatus @default(PENDING)
|
||
/// # 数据库字段 扩展元数据(敏感信息禁止写入)
|
||
metadata Json @default("{}")
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||
outgoingRelations ResourceRelation[] @relation("source")
|
||
incomingRelations ResourceRelation[] @relation("target")
|
||
credential Credential?
|
||
server Server?
|
||
container Container?
|
||
website Website?
|
||
domain Domain?
|
||
deployment Deployment?
|
||
monitor Monitor?
|
||
automation Automation?
|
||
aiRun AiRun?
|
||
gitConnection GitConnection?
|
||
repository Repository?
|
||
task Task?
|
||
note Note?
|
||
certificate Certificate?
|
||
|
||
@@index([workspaceId])
|
||
@@index([type, status])
|
||
@@index([workspaceId, type])
|
||
@@map("resources")
|
||
}
|
||
|
||
/// # 数据库表 resource_relations:资源关系图(有向边)
|
||
model ResourceRelation {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
sourceId String
|
||
targetId String
|
||
/// # 数据库字段 关系类型,如 deployed_on / has_domain / resolves_to / monitors
|
||
relationType String
|
||
metadata Json @default("{}")
|
||
createdAt DateTime @default(now())
|
||
|
||
source Resource @relation("source", fields: [sourceId], references: [id], onDelete: Cascade)
|
||
target Resource @relation("target", fields: [targetId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([sourceId, targetId, relationType])
|
||
@@index([sourceId])
|
||
@@index([targetId])
|
||
@@index([workspaceId])
|
||
@@map("resource_relations")
|
||
}
|
||
|
||
// ============ 凭据保险库 ============
|
||
|
||
/// # 数据库表 credentials:加密凭据(信封加密后的密文,禁止记录明文)
|
||
model Credential {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String? @unique
|
||
name String
|
||
type CredentialType
|
||
provider String?
|
||
/// # 数据库字段 AES-256-GCM 密文 JSON(iv/tag/ciphertext,base64)
|
||
encryptedData String
|
||
metadata Json @default("{}")
|
||
lastUsedAt DateTime?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
resource Resource? @relation(fields: [resourceId], references: [id], onDelete: SetNull)
|
||
|
||
@@index([workspaceId])
|
||
@@map("credentials")
|
||
}
|
||
|
||
// ============ 审计 / 事件 / 任务 ============
|
||
|
||
/// # 数据库表 audit_logs:审计日志(每个变更必写)
|
||
model AuditLog {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
actorType ActorType
|
||
actorId String?
|
||
action String
|
||
resourceType String?
|
||
resourceId String?
|
||
riskLevel RiskLevel @default(LOW)
|
||
status String @default("SUCCESS")
|
||
requestId String?
|
||
ip String?
|
||
metadata Json @default("{}")
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([workspaceId, createdAt])
|
||
@@index([resourceType, resourceId])
|
||
@@map("audit_logs")
|
||
}
|
||
|
||
/// # 数据库表 events:领域事件(持久化 + 分发)
|
||
model EventRecord {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
eventType String
|
||
resourceId String?
|
||
payload Json @default("{}")
|
||
correlationId String?
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([eventType, createdAt])
|
||
@@index([workspaceId, createdAt])
|
||
@@map("events")
|
||
}
|
||
|
||
/// # 数据库表 jobs:异步任务(持久化状态机 + Redis 派发)
|
||
model Job {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
type String
|
||
status JobStatus @default(PENDING)
|
||
payload Json @default("{}")
|
||
result Json?
|
||
error String?
|
||
attempts Int @default(0)
|
||
maxAttempts Int @default(3)
|
||
runAt DateTime @default(now())
|
||
startedAt DateTime?
|
||
finishedAt DateTime?
|
||
correlationId String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@index([status, runAt])
|
||
@@index([workspaceId])
|
||
@@map("jobs")
|
||
}
|
||
|
||
// ============ 基础设施领域表 ============
|
||
|
||
/// # 数据库表 servers:受管计算目标(SSH)
|
||
model Server {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String @unique
|
||
name String
|
||
host String
|
||
port Int @default(22)
|
||
username String
|
||
authType ServerAuthType @default(SSH_KEY)
|
||
provider String @default("ssh")
|
||
credentialId String?
|
||
osInfo String?
|
||
labels Json @default("{}")
|
||
lastSeenAt DateTime?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
resource Resource @relation(fields: [resourceId], references: [id], onDelete: Cascade)
|
||
containers Container[]
|
||
websites Website[]
|
||
monitors Monitor[]
|
||
|
||
@@index([workspaceId])
|
||
@@map("servers")
|
||
}
|
||
|
||
/// # 数据库表 containers:Docker 容器发现结果
|
||
model Container {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String @unique
|
||
serverId String
|
||
containerId String
|
||
name String
|
||
image String
|
||
state String
|
||
ports Json @default("{}")
|
||
labels Json @default("{}")
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
resource Resource @relation(fields: [resourceId], references: [id], onDelete: Cascade)
|
||
server Server @relation(fields: [serverId], references: [id], onDelete: Cascade)
|
||
|
||
@@index([serverId])
|
||
@@index([workspaceId])
|
||
@@map("containers")
|
||
}
|
||
|
||
/// # 数据库表 websites:可部署应用资源
|
||
model Website {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String @unique
|
||
name String
|
||
primaryDomain String?
|
||
serverId String?
|
||
repositoryUrl String?
|
||
/// # 数据库字段 关联仓库(Git Provider 凭据克隆;优先于 repositoryUrl)
|
||
repositoryId String?
|
||
/// # 数据库字段 部署环境:development / staging / production
|
||
environment String @default("production")
|
||
/// # 数据库字段 部署类型:DOCKER / STATIC / NODE
|
||
deployType String @default("DOCKER")
|
||
/// # 数据库字段 容器对外端口
|
||
port Int @default(80)
|
||
healthPath String @default("/")
|
||
env Json @default("{}")
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
resource Resource @relation(fields: [resourceId], references: [id], onDelete: Cascade)
|
||
server Server? @relation(fields: [serverId], references: [id], onDelete: SetNull)
|
||
deployments Deployment[]
|
||
monitors Monitor[]
|
||
repository Repository? @relation(fields: [repositoryId], references: [id])
|
||
|
||
@@index([workspaceId])
|
||
@@map("websites")
|
||
}
|
||
|
||
/// # 数据库表 domains:域名与 DNS 提供商绑定
|
||
model Domain {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String @unique
|
||
name String
|
||
provider String @default("MANUAL")
|
||
credentialId String?
|
||
expiresAt DateTime?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
resource Resource @relation(fields: [resourceId], references: [id], onDelete: Cascade)
|
||
records DomainRecord[]
|
||
|
||
@@index([workspaceId])
|
||
@@map("domains")
|
||
}
|
||
|
||
/// # 数据库表 domain_records:域名记录(手动 provider 时为本地事实源)
|
||
model DomainRecord {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
domainId String
|
||
type String
|
||
name String
|
||
value String
|
||
ttl Int @default(300)
|
||
proxied Boolean @default(false)
|
||
providerRecordId String?
|
||
updatedAt DateTime @updatedAt
|
||
createdAt DateTime @default(now())
|
||
|
||
domain Domain @relation(fields: [domainId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([domainId, type, name, value])
|
||
@@index([workspaceId])
|
||
@@map("domain_records")
|
||
}
|
||
|
||
/// # 数据库表 deployments:部署执行记录
|
||
model Deployment {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String @unique
|
||
websiteId String
|
||
status DeploymentStatus @default(QUEUED)
|
||
trigger String @default("MANUAL")
|
||
progress Int @default(0)
|
||
/// # 数据库字段 失败原因(截断存储,不含敏感信息)
|
||
error String?
|
||
commit String?
|
||
/// # 数据库字段 部署环境:development / staging / production
|
||
environment String?
|
||
/// # 数据库字段 构建策略:DOCKERFILE / STATIC_COPY
|
||
buildStrategy String?
|
||
/// # 数据库字段 部署策略:DOCKER_CONTAINER / STATIC_DIR
|
||
deployStrategy String?
|
||
/// # 数据库字段 健康验证证据 {ok,status,latencyMs,checkedAt}
|
||
verification Json?
|
||
/// # 数据库字段 部署参数快照(分支、镜像 tag 等)
|
||
config Json @default("{}")
|
||
createdAt DateTime @default(now())
|
||
finishedAt DateTime?
|
||
|
||
resource Resource @relation(fields: [resourceId], references: [id], onDelete: Cascade)
|
||
website Website @relation(fields: [websiteId], references: [id], onDelete: Cascade)
|
||
logs DeploymentLog[]
|
||
|
||
@@index([websiteId, createdAt])
|
||
@@index([workspaceId, createdAt])
|
||
@@map("deployments")
|
||
}
|
||
|
||
/// # 数据库表 deployment_logs:部署日志行(顺序)
|
||
model DeploymentLog {
|
||
id String @id @default(uuid())
|
||
deploymentId String
|
||
seq Int
|
||
stream String @default("stdout")
|
||
line String
|
||
createdAt DateTime @default(now())
|
||
|
||
deployment Deployment @relation(fields: [deploymentId], references: [id], onDelete: Cascade)
|
||
|
||
@@index([deploymentId, seq])
|
||
@@map("deployment_logs")
|
||
}
|
||
|
||
/// # 数据库表 monitors:健康检查配置
|
||
model Monitor {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String @unique
|
||
websiteId String?
|
||
serverId String?
|
||
name String
|
||
/// # 数据库字段 检查类型:HTTP / TCP
|
||
kind String @default("HTTP")
|
||
target String
|
||
intervalSec Int @default(60)
|
||
timeoutMs Int @default(10000)
|
||
enabled Boolean @default(true)
|
||
lastStatus String @default("UNKNOWN")
|
||
consecutiveFailures Int @default(0)
|
||
lastCheckedAt DateTime?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
resource Resource @relation(fields: [resourceId], references: [id], onDelete: Cascade)
|
||
website Website? @relation(fields: [websiteId], references: [id], onDelete: Cascade)
|
||
server Server? @relation(fields: [serverId], references: [id], onDelete: Cascade)
|
||
results MonitorResult[]
|
||
|
||
@@index([enabled, lastCheckedAt])
|
||
@@index([workspaceId])
|
||
@@map("monitors")
|
||
}
|
||
|
||
/// # 数据库表 monitor_results:监控结果历史
|
||
model MonitorResult {
|
||
id String @id @default(uuid())
|
||
monitorId String
|
||
ok Boolean
|
||
status String?
|
||
latencyMs Int?
|
||
error String?
|
||
createdAt DateTime @default(now())
|
||
|
||
monitor Monitor @relation(fields: [monitorId], references: [id], onDelete: Cascade)
|
||
|
||
@@index([monitorId, createdAt])
|
||
@@map("monitor_results")
|
||
}
|
||
|
||
// ============ 自动化 ============
|
||
|
||
/// # 数据库表 automations:Trigger → Condition → Action 工作流
|
||
model Automation {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String @unique
|
||
name String
|
||
enabled Boolean @default(false)
|
||
triggerType TriggerType
|
||
/// # 数据库字段 触发器配置(cron 表达式 / 事件名 / webhook token)
|
||
triggerConfig Json @default("{}")
|
||
/// # 数据库字段 条件列表 [{path,op,value}]
|
||
conditions Json @default("[]")
|
||
/// # 数据库字段 动作列表 [{type,args,timeoutMs,retries}]
|
||
actions Json @default("[]")
|
||
lastTriggeredAt DateTime?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
resource Resource @relation(fields: [resourceId], references: [id], onDelete: Cascade)
|
||
runs AutomationRun[]
|
||
|
||
@@index([workspaceId])
|
||
@@index([triggerType, enabled])
|
||
@@map("automations")
|
||
}
|
||
|
||
/// # 数据库表 automation_runs:自动化执行历史
|
||
model AutomationRun {
|
||
id String @id @default(uuid())
|
||
automationId String
|
||
workspaceId String
|
||
status String @default("RUNNING")
|
||
trigger Json @default("{}")
|
||
stepIndex Int @default(0)
|
||
logs Json @default("[]")
|
||
error String?
|
||
correlationId String?
|
||
startedAt DateTime @default(now())
|
||
finishedAt DateTime?
|
||
|
||
automation Automation @relation(fields: [automationId], references: [id], onDelete: Cascade)
|
||
|
||
@@index([automationId, startedAt])
|
||
@@map("automation_runs")
|
||
}
|
||
|
||
// ============ AI Gateway ============
|
||
|
||
/// # 数据库表 ai_runs:AI 运行(计划→风控→审批→执行→验证)
|
||
model AiRun {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String @unique
|
||
objective String
|
||
status AiRunStatus @default(PLANNING)
|
||
/// # 数据库字段 来源:UI / CHAT / MCP / AUTOMATION
|
||
source String @default("UI")
|
||
riskLevel RiskLevel @default(LOW)
|
||
/// # 数据库字段 计划步骤 [{tool,args,reason,risk}]
|
||
plan Json @default("[]")
|
||
/// # 数据库字段 执行历史 [{tool,args,result,ok}]
|
||
toolCalls Json @default("[]")
|
||
/// # 数据库字段 验证结果 {ok, checks[]}
|
||
verification Json?
|
||
result Json?
|
||
error String?
|
||
approvedBy String?
|
||
approvedAt DateTime?
|
||
correlationId String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
resource Resource @relation(fields: [resourceId], references: [id], onDelete: Cascade)
|
||
|
||
@@index([workspaceId, createdAt])
|
||
@@map("ai_runs")
|
||
}
|
||
|
||
// ============ Phase 2:Git / 生产力 / 通知 / 证书 ============
|
||
|
||
/// # 数据库表 git_connections:Git Provider 连接(GitHub/GitLab/Gitea + 凭据引用)
|
||
model GitConnection {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String @unique
|
||
name String
|
||
/// # 数据库字段 提供商:GITHUB / GITLAB / GITEA
|
||
provider String
|
||
/// # 数据库字段 自建实例 API 基址(Gitea/GitLab 自托管时填写)
|
||
apiBase String?
|
||
credentialId String
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
resource Resource @relation(fields: [resourceId], references: [id], onDelete: Cascade)
|
||
repositories Repository[]
|
||
|
||
@@index([workspaceId])
|
||
}
|
||
|
||
/// # 数据库表 repositories:外部代码仓库聚合(不实现 Git 托管)
|
||
model Repository {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String @unique
|
||
connectionId String?
|
||
provider String @default("GENERIC")
|
||
/// # 数据库字段 全名 owner/repo
|
||
fullName String
|
||
/// # 数据库字段 HTTPS 克隆地址(不含凭据)
|
||
cloneUrl String
|
||
defaultBranch String @default("main")
|
||
/// # 数据库字段 private 标记
|
||
visibility String @default("private")
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
resource Resource @relation(fields: [resourceId], references: [id], onDelete: Cascade)
|
||
connection GitConnection? @relation(fields: [connectionId], references: [id], onDelete: SetNull)
|
||
websites Website[]
|
||
|
||
@@unique([workspaceId, cloneUrl])
|
||
@@index([workspaceId])
|
||
}
|
||
|
||
/// # 数据库表 tasks:工作项(backlog/todo/doing/review/done)
|
||
model Task {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String @unique
|
||
title String
|
||
description String @default("")
|
||
/// # 数据库字段 状态:BACKLOG / TODO / DOING / REVIEW / DONE
|
||
status String @default("TODO")
|
||
/// # 数据库字段 优先级:LOW / MEDIUM / HIGH / URGENT
|
||
priority String @default("MEDIUM")
|
||
labels Json @default("[]")
|
||
dueAt DateTime?
|
||
/// # 数据库字段 关联项目资源 ID(可空)
|
||
projectId String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
resource Resource @relation(fields: [resourceId], references: [id], onDelete: Cascade)
|
||
|
||
@@index([workspaceId, status])
|
||
@@index([projectId])
|
||
}
|
||
|
||
/// # 数据库表 notes:笔记/知识(markdown 存储)
|
||
model Note {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String @unique
|
||
title String
|
||
/// # 数据库字段 正文(HTML,TipTap 富文本)
|
||
content String @default("")
|
||
tags Json @default("[]")
|
||
projectId String?
|
||
/// # 数据库字段 置顶
|
||
pinned Boolean @default(false)
|
||
/// # 数据库字段 文件夹(分组)
|
||
folder String?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
resource Resource @relation(fields: [resourceId], references: [id], onDelete: Cascade)
|
||
|
||
@@index([workspaceId])
|
||
}
|
||
|
||
/// # 数据库表 notifications:站内通知(自动化/事件投递)
|
||
model Notification {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String?
|
||
title String
|
||
body String @default("")
|
||
/// # 数据库字段 级别:INFO / WARN / ERROR
|
||
level String @default("INFO")
|
||
readAt DateTime?
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([workspaceId, createdAt])
|
||
}
|
||
|
||
/// # 数据库表 certificates:TLS 证书统一模型(探针检测)
|
||
model Certificate {
|
||
id String @id @default(uuid())
|
||
workspaceId String
|
||
resourceId String @unique
|
||
/// # 数据库字段 证书主域名
|
||
domain String
|
||
domainId String?
|
||
/// # 数据库字段 状态:PENDING / ACTIVE / EXPIRED / ERROR
|
||
status String @default("PENDING")
|
||
issuer String?
|
||
notAfter DateTime?
|
||
lastCheckedAt DateTime?
|
||
createdAt DateTime @default(now())
|
||
updatedAt DateTime @updatedAt
|
||
|
||
resource Resource @relation(fields: [resourceId], references: [id], onDelete: Cascade)
|
||
|
||
@@index([workspaceId])
|
||
}
|
||
|
||
// ============ v2 Action Runtime ============
|
||
|
||
/// # 数据库表 devos_action_executions:v2 Action 执行记录(docs 03 §31)
|
||
model ActionExecution {
|
||
id String @id
|
||
actionId String
|
||
actorType String
|
||
actorId String?
|
||
resourceType String?
|
||
resourceId String?
|
||
status String
|
||
input Json?
|
||
output Json?
|
||
error Json?
|
||
requestId String?
|
||
rootExecutionId String?
|
||
parentExecutionId String?
|
||
durationMs Int?
|
||
startedAt DateTime?
|
||
completedAt DateTime?
|
||
createdAt DateTime @default(now())
|
||
|
||
@@index([actionId, createdAt])
|
||
@@index([status])
|
||
}
|