feat: harden tenant access and production operations
This commit is contained in:
@@ -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 竞态导致重复生成。
|
||||
|
||||
## 模型协议适配器
|
||||
|
||||
模型连接器在模型中台注册,密钥只保存为环境变量名,不保存密钥本身:
|
||||
|
||||
Reference in New Issue
Block a user