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:
+117
@@ -0,0 +1,117 @@
|
||||
# DevOS v1 API 契约
|
||||
|
||||
基址:`/api/v1`。所有响应为 JSON;变更(mutation)契约:zod DTO 校验 → 工作区授权 → 风险判定 → 审计记录 → 事件(如适用)→ 响应头 `X-Request-Id`。
|
||||
|
||||
## 错误契约
|
||||
|
||||
```json
|
||||
{ "error": { "code": "RESOURCE_NOT_FOUND", "message": "Server not found", "requestId": "uuid" } }
|
||||
```
|
||||
|
||||
错误码:`VALIDATION_ERROR`(400) / `UNAUTHORIZED`(401) / `FORBIDDEN`(403) / `RESOURCE_NOT_FOUND`(404) / `CONFLICT`(409) / `UPSTREAM_FAILURE`(502) / `TIMEOUT`(504) / `INTERNAL_ERROR`(500)。
|
||||
|
||||
## 认证
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| POST | /auth/register | `{email,password,name?}` → `{token,user}`(自动创建 OWNER 工作区) |
|
||||
| POST | /auth/login | `{email,password}` → `{token,expiresIn,user}`(JWT HS256,12h) |
|
||||
| GET | /auth/me | 当前用户 + 工作区列表 |
|
||||
| POST | /auth/logout | 无状态登出(审计记录) |
|
||||
|
||||
鉴权:`Authorization: Bearer <jwt>`;工作区:`X-Workspace-Id` 头(缺省用 token `wid` 或第一个成员关系)。角色:VIEWER 只读,MEMBER 可操作,ADMIN 管理成员/凭据,OWNER 全权。
|
||||
|
||||
## 工作区
|
||||
|
||||
- `GET /workspaces` 我的列表
|
||||
- `POST /workspaces` `{name}` 创建(创建者 OWNER)
|
||||
- `GET /workspaces/:id` 详情(须为成员;路径参数越权返回 403)
|
||||
- `GET|POST /workspaces/:id/members`、`POST /workspaces/:id/members/:memberId`(改角色)、`DELETE .../:memberId`
|
||||
|
||||
## 资源(统一模型)
|
||||
|
||||
- `GET /resources?type=&status=&q=&page=&pageSize=`
|
||||
- `POST /resources`(通用类型:PROJECT/REPOSITORY/DATABASE/DOCUMENT/BACKUP/EMAIL_ACCOUNT/TASK/NOTE)
|
||||
- `GET|PATCH|DELETE /resources/:id`(DELETE 需 ADMIN)
|
||||
- `GET|POST /resources/:id/relations`、`DELETE /resources/:id/relations/:rid`
|
||||
|
||||
## 服务器
|
||||
|
||||
- `GET|POST /servers`;创建:`{name,host,port,username,provider:"ssh"|"local",authType,password|privateKey|credentialId}`
|
||||
- `provider:"local"`:通过本机 `/var/run/docker.sock` 管理(无需凭据)
|
||||
- `GET|DELETE /servers/:id`
|
||||
- `POST /servers/:id/connect` 连通性探测(刷新状态、发 server.online/offline 事件)
|
||||
- `GET /servers/:id/status` 含 docker 可用性
|
||||
- `POST /servers/:id/exec` `{command,timeoutMs}`(审计;危险命令风险 CRITICAL)
|
||||
- `POST /servers/:id/restart` `{confirm:true}`(ADMIN;HIGH)
|
||||
|
||||
## 容器
|
||||
|
||||
- `GET /containers` 全工作区
|
||||
- `POST /servers/:id/containers` 发现(docker ps → 入库/更新 + runs_container 关系)
|
||||
- `GET /servers/:id/containers`
|
||||
- `GET /containers/:id/inspect`(env 键脱敏)
|
||||
- `POST /containers/:id/restart` `{confirm:true}`
|
||||
|
||||
## 网站
|
||||
|
||||
- `GET|POST /websites`:`{name,primaryDomain?,serverId?,repositoryUrl?,deployType,port,healthPath,env?,domainId?}`
|
||||
- `GET|PATCH|DELETE /websites/:id`
|
||||
- `POST /websites/:id/deploy` → 创建部署(HIGH)
|
||||
- `GET /websites/:id/logs?limit=` 最近部署日志
|
||||
- `GET /websites/:id/health` 即时健康检查
|
||||
|
||||
## 部署
|
||||
|
||||
- `GET /deployments?websiteId=`;`GET /deployments/:id`(含 logs)
|
||||
- `POST /deployments` `{websiteId,branch?,trigger?}`
|
||||
- `POST /deployments/:id/cancel`(QUEUED 立即取消;RUNNING 步骤间生效)
|
||||
|
||||
## 域名
|
||||
|
||||
- `GET|POST /domains`:`{name,provider:"CLOUDFLARE"|"MANUAL",credentialId?}`
|
||||
- `GET|DELETE /domains/:id`
|
||||
- `GET /domains/:id/records`(CLOUDFLARE 实时拉取并同步本地)
|
||||
- `POST /domains/:id/records` `{type,name,value,ttl?,proxied?}`(upsert)
|
||||
- `POST /domains/:id/records/:localId/delete`
|
||||
|
||||
## 监控
|
||||
|
||||
- `GET|POST /monitors`:`{name,kind:"HTTP"|"TCP",target,intervalSec?,timeoutMs?,websiteId?,enabled?}`
|
||||
- `GET /monitors/:id`(含 50 条结果历史)
|
||||
- `PATCH /monitors/:id` `{enabled}`;`DELETE /monitors/:id`
|
||||
|
||||
## 自动化
|
||||
|
||||
- `GET|POST /automations`:`{name,triggerType,triggerConfig:{cron|eventType|secret},conditions:[{path,op,value}],actions:[{type,args,timeoutMs,retries}],enabled}`
|
||||
- `GET /automations/:id`(含 20 条执行历史)
|
||||
- `POST /automations/:id/enable|disable|run`
|
||||
- `POST /automations/:id/webhook`(公开;`X-Webhook-Secret` 头校验)
|
||||
- `DELETE /automations/:id`(ADMIN)
|
||||
|
||||
## AI
|
||||
|
||||
- `GET|POST /ai/runs`:`{objective}` → 创建后异步规划;HIGH/CRITICAL 停在 `AWAITING_APPROVAL`
|
||||
- `GET /ai/runs/:id`(plan/toolCalls/verification)
|
||||
- `POST /ai/runs/:id/approve|reject`(ADMIN)
|
||||
|
||||
## 凭据
|
||||
|
||||
- `GET|POST /credentials`(ADMIN):`{name,type,provider?,secret}` — 明文仅存在于请求瞬间,任何响应不含密文
|
||||
- `PATCH /credentials/:id`(轮换)、`DELETE /credentials/:id`(ADMIN)
|
||||
|
||||
## 审计与事件
|
||||
|
||||
- `GET /audit?page=&pageSize=&resourceType=&resourceId=&action=`
|
||||
- `GET /events?page=&pageSize=&eventType=`
|
||||
|
||||
## 系统
|
||||
|
||||
- `GET /health`(公开)
|
||||
- `GET /dashboard`(工作台统计)
|
||||
|
||||
## MCP
|
||||
|
||||
- `POST /api/v1/mcp` — Streamable HTTP(无状态)。请求头:`Authorization: Bearer <jwt>`、`Accept: application/json, text/event-stream`
|
||||
- 工具:`devos.server.list/status/exec/getDockerContainers`、`devos.website.list/deploy/logs/health`、`devos.deployment.get/list`、`devos.domain.list/records`、`devos.automation.list/run`
|
||||
- 所有调用经 ToolRegistry → 各模块 service(同授权/审计;actorType=MCP)
|
||||
@@ -0,0 +1,63 @@
|
||||
# DevOS v1 数据库文档
|
||||
|
||||
PostgreSQL 为系统记录源;Prisma 为 ORM。迁移位于 `prisma/migrations/`(基线 `20260908000000_init`)。
|
||||
表名统一 snake_case(`@@map`);列名为 camelCase(Prisma 默认)。
|
||||
|
||||
## 表清单
|
||||
|
||||
### 身份与租户
|
||||
| 表 | 说明 |
|
||||
| --- | --- |
|
||||
| `users` | 平台用户(argon2id/scrypt 密码哈希) |
|
||||
| `workspaces` | 租户/安全边界 |
|
||||
| `workspace_members` | 用户-工作区关系 + 角色(OWNER/ADMIN/MEMBER/VIEWER),UNIQUE(workspaceId,userId) |
|
||||
|
||||
### 统一资源模型
|
||||
| 表 | 说明 |
|
||||
| --- | --- |
|
||||
| `resources` | 资源身份/发现/状态公共字段(type/name/provider/status/metadata);领域表经 `resourceId` 一对一关联 |
|
||||
| `resource_relations` | 有向关系边(UNIQUE source+target+relationType),如 deployed_on / runs_container / has_domain / resolves_to / monitors / has_deployment |
|
||||
|
||||
索引:`workspaceId`、`(type,status)`、`(workspaceId,type)`、关系端点。
|
||||
|
||||
### 凭据与合规
|
||||
| 表 | 说明 |
|
||||
| --- | --- |
|
||||
| `credentials` | AES-256-GCM 密文(`encryptedData` JSON:iv/tag/data,base64;AAD=workspaceId) |
|
||||
| `audit_logs` | 每个变更一条:actorType/actorId/action/resource/riskLevel/status/requestId/ip/metadata(已脱敏)。索引 `(workspaceId,createdAt)`、`(resourceType,resourceId)` |
|
||||
| `events` | 领域事件:eventType/resourceId/payload/correlationId。索引 `(eventType,createdAt)` |
|
||||
| `jobs` | 异步任务状态机:PENDING→RUNNING→SUCCEEDED/FAILED/CANCELLED/DEAD;`attempts/maxAttempts/runAt`(指数退避),SKIP LOCKED 认领,15 分钟僵死回收。索引 `(status,runAt)` |
|
||||
|
||||
### 基础设施域
|
||||
| 表 | 说明 |
|
||||
| --- | --- |
|
||||
| `servers` | SSH 目标(host/port/username/authType/provider("ssh"\|"local")/credentialId/osInfo/lastSeenAt) |
|
||||
| `containers` | docker 发现结果(containerId/name/image/state/ports/labels)→ serverId |
|
||||
| `websites` | 可部署应用(primaryDomain/serverId/repositoryUrl/deployType/port/healthPath/env) |
|
||||
| `domains` | 域名 + provider(CLOUDFLARE/MANUAL)+ credentialId |
|
||||
| `domain_records` | DNS 记录(UNIQUE domain+type+name+value;providerRecordId 为云侧 ID) |
|
||||
| `deployments` | 部署执行(status QUEUED→RUNNING→…;trigger/progress/commit/config(branch、cancelRequested)/error)。索引 `(websiteId,createdAt)` |
|
||||
| `deployment_logs` | 步骤日志行(seq 顺序)。索引 `(deploymentId,seq)` |
|
||||
| `monitors` | 健康检查配置(kind/target/intervalSec/lastStatus/consecutiveFailures)。索引 `(enabled,lastCheckedAt)` |
|
||||
| `monitor_results` | 检查结果历史(ok/status/latencyMs/error)。索引 `(monitorId,createdAt)` |
|
||||
|
||||
### 自动化与 AI
|
||||
| 表 | 说明 |
|
||||
| --- | --- |
|
||||
| `automations` | Trigger(MANUAL/CRON/EVENT/WEBHOOK)+ triggerConfig + conditions + actions(JSON)+ lastTriggeredAt |
|
||||
| `automation_runs` | 执行历史(status/stepIndex/logs/error/correlationId) |
|
||||
| `ai_runs` | AI 运行:status(PLANNING→AWAITING_APPROVAL→RUNNING→SUCCEEDED/FAILED/REJECTED)、plan/toolCalls/verification JSON、riskLevel、approvedBy |
|
||||
|
||||
## 关键设计约束
|
||||
|
||||
1. **租户隔离**:所有领域表带 `workspaceId`;服务层查询一律带 workspace 谓词;守卫校验路径参数中的 workspaceId 成员资格。
|
||||
2. **资源 ↔ 领域表**:领域行创建与 resources 行在同一个事务中;删除走 `onDelete: Cascade`。
|
||||
3. **密文隔离**:明文机密只在内存短暂存在;`audit metadata` 与日志经 `maskSecrets()` 脱敏。
|
||||
4. **事件追溯**:events/audit_logs/jobs 均记录 correlationId / requestId,贯穿 HTTP 与 worker。
|
||||
|
||||
## 迁移与种子
|
||||
|
||||
```bash
|
||||
bunx prisma migrate deploy # 应用迁移
|
||||
bun run prisma/seed.ts # 幂等种子:管理员 + Main Workspace(OWNER)
|
||||
```
|
||||
Reference in New Issue
Block a user