DevOS v1 + Phase 2: unified resource model, infra ops, website deployment, AI chat ops
- Monorepo: NestJS API (Fastify) + React web (antd/ProComponents) + shared packages - PostgreSQL/Prisma (unified resources, relations graph, audit, events, jobs) - Auth/RBAC/workspace isolation, credential vault (AES-256-GCM) - Servers/SSH, Docker discovery & lifecycle, Job Center - Websites & deployments (git provider credential clone, env, health verification) - Domains/DNS (Cloudflare adapter), certificates (TLS probe), monitoring - Automation (cron/event/webhook HMAC + notifications), AI Gateway, MCP (29 tools) - AI chat window (LLM function-calling + rules fallback, SSE streaming, approvals) - Notes: Vditor WYSIWYG markdown editor, non-blocking autosave - Tests: 35 unit/security tests; UI audit clean (desktop+mobile, deep links)
This commit is contained in:
@@ -0,0 +1,734 @@
|
||||
// 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])
|
||||
}
|
||||
Reference in New Issue
Block a user