feat: harden tenant access and production operations

This commit is contained in:
xz
2026-08-24 22:02:22 +08:00
parent ffb27d845b
commit 9811469a64
18 changed files with 709 additions and 36 deletions
+20
View File
@@ -23,6 +23,7 @@ user → organization → workspace → project → permission
| 认证与会话 | `/api/auth/login`、`/api/auth/session`、`/api/auth/logout`、`/api/auth/password`、`/api/auth/sessions/*` | 登录用户 |
| MFA 与企业身份 | `/api/auth/login/mfa`、`/api/auth/mfa/*`、`/api/auth/sso/*`、`/api/system/identity/*` | MFA 管理或 `system:settings:*` |
| 租户上下文 | `/api/context`、`/api/organizations/*`、`/api/workspaces/*`、`/api/projects/*` | 按组织 / 工作区 / 项目角色 |
| 全局生产搜索 | `/api/search?q=&scope=workspace|project` | 登录用户,结果严格受当前作用域限制 |
| 用户通知中心 | `/api/notifications`、`/api/notifications/:id`、`/api/notifications/read-all`、`/api/notification-preferences` | 登录用户 / 当前组织 |
| 内容生产 | `/api/production/catalog`、`/api/production/graph`、`/api/production/script/*`、`/api/production/bible`、`/api/production/shots/*` | `script:edit`、`asset:edit`、`job:create` |
| 资产与声音 | `/api/assets/*`、`/api/assets/:assetId/versions/upload`、`/api/assets/:assetId/verify`、`/api/assets/:assetId/versions/:versionId/restore` | `asset:edit`、`voice:edit` |
@@ -35,6 +36,17 @@ user → organization → workspace → project → permission
未登录返回 `401`;已登录但没有作用域或权限返回 `403`。接口不会因为前端菜单隐藏就跳过后端检查。
### 全局生产搜索
```http
GET /api/search?q=雷雨&scope=workspace&limit=40
GET /api/search?q=雷雨&scope=project&limit=40
```
搜索接口只在当前登录会话的组织、工作区和可访问项目集合内查询,支持项目、分集、剧本、镜头、资产、协作任务、生成任务和交付记录。`scope=workspace` 搜索当前工作区内可访问项目;`scope=project` 只搜索当前项目。返回结果包含 `type`、`typeLabel`、`title`、`subtitle`、`status`、`targetTab` 和目标作用域 ID,前端命令面板可以据此直接切换项目并跳转到对应生产页面。空查询返回空结果,不会返回未经筛选的目录数据。
搜索不会把连接器 endpoint、API key、客户交付令牌或本地存储绝对路径作为可搜索字段返回;跨组织、跨工作区或无项目访问权的关键词不会出现在结果中。
### 审计与合规中心
```http
@@ -94,11 +106,15 @@ POST /api/projects/:projectId/lifecycle
系统管理员可读取部署边界和当前运行时状态:
```text
GET /api/system/health
GET /api/system/worker
GET /api/system/readiness
GET /api/system/backups
POST /api/system/backups
```
`/api/system/health` 返回数据库中的服务探针、Runner 状态、队列深度和最近心跳;`/api/system/worker` 返回本地 Worker 的租约、并发、心跳年龄和队列告警。管理概览直接使用这些服务端结果,组织管理员只能看到后端允许的健康范围,不能通过前端隐藏绕过权限。
`/api/system/readiness` 会明确区分当前激活运行时与目标 provider:业务数据库当前返回 `node:sqlite`,PostgreSQL、Redis、S3-compatible 对象存储只有在对应 `PLATFORM_*` 环境变量存在时标记为“已配置”,不会把 compose 注入误报成已经完成业务迁移。`POST /api/system/backups` 使用 SQLite `VACUUM INTO` 创建 `data/backups/` 下的快照,并写入 `system.database.backup_created` 审计事件;接口不提供在线恢复,恢复必须经过停机审查和人工确认。
### 商业运营、席位与配额
@@ -161,6 +177,8 @@ POST /api/auth/register
创建或重发邀请时,服务端只在当前响应返回一次性 `inviteToken` 和 `acceptUrl`;数据库保存的是令牌哈希和短提示,不保存明文令牌。邀请默认 7 天过期,过期邀请不会继续占用席位。重发会替换令牌哈希,使旧注册链接立即返回 `404 invitation_not_found`;撤销会清空令牌哈希、返回 `revoked`,并释放待入组席位。未登录预览仍可读取邀请范围,但注册时会再次校验令牌、邮箱和有效期。
邀请角色必须匹配目标层级:不传 `workspaceId` 时只能使用组织角色 `org_member` / `org_admin`;传 `workspaceId` 时只能使用工作区角色 `producer` / `writer` / `art_director` / `voice_editor` / `reviewer`;同时传 `workspaceId` 与 `projectId` 时只能使用项目角色 `project_editor` / `project_viewer`。项目级邀请接受后会自动建立 `project_guest` 工作区成员身份和 `access_mode=project-only`,不会把项目角色升级为工作区制片,也不会展示工作区其他项目;组织所有者不能通过普通邀请授予。
普通成员调用组织邀请接口返回 `403 permission_denied`;重复邀请同一邮箱返回 `409 invitation_already_pending`,已是组织成员的邮箱返回 `409 invitation_recipient_already_member`。
### MFA
@@ -259,6 +277,8 @@ AI_DRAMA_WORKER_STALE_MS=30000
如果设置 `AI_DRAMA_WORKER_ENABLED=0`,任务不会自动执行,后台仍会显示 Worker 已暂停。
`POST /api/jobs/:jobId/run` 允许管理员或拥有 `job:create` 的角色手动执行任务;如果请求到达时任务已经被本地 Worker 完成,服务端返回现有结果并带 `idempotent: true`,避免手动按钮与自动 Worker 竞态导致重复生成。
## 模型协议适配器
模型连接器在模型中台注册,密钥只保存为环境变量名,不保存密钥本身:
+3 -2
View File
@@ -22,7 +22,7 @@
└── 模型连接器、Runner、资产存储策略
```
组织解决客户和计费隔离,工作区解决团队协作隔离,项目解决内容访问和交付隔离。一个用户可以加入多个组织,在同一组织中进入多个工作区;项目默认继承工作区成员,但敏感项目可以额外配置 project member。
组织解决客户和计费隔离,工作区解决团队协作隔离,项目解决内容访问和交付隔离。一个用户可以加入多个组织,在同一组织中进入多个工作区;普通工作区成员默认可以访问工作区项目,项目级邀请则使用 `workspace_members.access_mode = project-only` 和 `project_guest` 角色,只能进入显式授权的项目。
## 角色模型
@@ -35,6 +35,7 @@
| 工作区 | `art_director` | 角色/场景/道具锁、参考图、prompt、连续性 |
| 工作区 | `voice_editor` | 声线锁、TTS、字幕、ASR 对齐 |
| 工作区 | `reviewer` | QA、审片意见、通过/驳回 |
| 工作区 | `project_guest` | 只进入被授权项目,不继承工作区其他项目和生成权限 |
| 项目 | `project_editor` | 指定项目内容编辑 |
| 项目 | `project_viewer` | 只读查看、下载被授权的交付物 |
@@ -48,7 +49,7 @@
- `organizations`:租户、slug、部署模式、所有者。
- `organization_members`:用户加入组织的角色、邀请状态。
- `workspaces`:组织下的生产空间。
- `workspace_members`:工作区角色。
- `workspace_members`:工作区角色和访问范围;`access_mode=project-only` 只允许显式 `project_members` 项目。
- `projects`:工作区下的系列、模板或客户项目。
- `project_members`:项目级额外授权。
- `invitations`:待接受邀请,不把邀请误当作已加入成员。