feat: harden V2 identity security and release readiness
Build and Test Quality Gate / Contract Web typecheck and build (pull_request) Successful in 7m4s
Build and Test Quality Gate / Python tests and Contract API migration (pull_request) Failing after 10m0s
Security Quality Gate / npm audit, Bandit, pip-audit, detect-secrets (pull_request) Failing after 10m6s

This commit is contained in:
2026-08-02 14:18:12 +08:00
parent 45608f436f
commit 96e456abcc
123 changed files with 14159 additions and 777 deletions
@@ -0,0 +1,583 @@
# AI 合同平台 V2 数据安全与反爬虫方案
日期:2026-07-21
适用范围:AI 合同平台 V2 的 Contract Web、Contract API、AI Platform API、worker、Nginx/WAF、PostgreSQL、文件仓库、审计与发布质量门。
## 1. 背景和目标
V2 已经具备合同台账、模板起草、审查结果、条款推荐、法律全文库、知识库、AI Trace、文件仓库和报告下载等能力。上线后真正的数据安全风险不只是匿名爬虫访问公开页面,而是合法账号、被盗 Cookie、内部人员、多账号轮换或代理池持续抓取数据库中的高价值数据。
本方案目标:
- 降低合同、附件、审查报告、模板、条款规则、Prompt、知识库、AI Trace 被批量抓取和下载的概率。
- 让列表接口默认只暴露摘要,正文和敏感内容走详情接口并计量。
- 对搜索、详情、预览、下载、批量导出建立多维限流和每日出站预算。
- 对异常行为及时告警、冻结、审计,并提供管理员解封和临时放宽配额流程。
- 把反爬和数据出站控制纳入上线前 schema-check、smoke、安全扫描和接口压测。
非目标:
- 不承诺阻止用户截图、拍照或人工逐条复制。
- 不把 `robots.txt`、UA 黑名单或验证码作为核心防线。
- 不在本方案阶段直接删除既有业务字段或大改数据库;数据库变更需单独迁移评审。
## 2. 当前能力
已经具备:
- Contract Web 到 Contract API 有 proxy shared secret。
- AI Platform 有 service shared secret。
- 已有租户字段,合同、文件、知识库、AI Trace、质量动作等多数持久化查询具备租户过滤基础。
- Contract Web 使用 HMAC 签名 Cookie,HttpOnly,SameSite=Lax。
- 身份接口已有邮箱、IP、租户维度限流,主要覆盖登录、验证码、邀请。
- 合同、附件、批量附件、审查报告下载已有审计事件基础。
- 合同、文件、搜索等分页接口通常限制 `page_size <= 100`。
- 生产 Nginx 已有 IP 级限流、连接限制、HTTPS 和安全响应头。
- AI Trace 已有脱敏、保留、归档治理字段和 worker 基础。
## 3. 关键缺口
P0 缺口:
- 业务接口缺统一后端 RBAC 和对象级授权门,不能仅依赖前端菜单隐藏。
- 部分接口仍存在从请求参数传 `role` 的兼容习惯,生产不能信任客户端角色。
- 后端需要使用可信身份上下文,不能裸信任外部传入的 `X-Tenant-Id`、`X-User-Id`。
- 缺统一业务 API 限流,当前 Nginx IP 限流只能挡粗暴洪泛,不能挡已登录慢速搬运。
- 缺按记录数、文件数、字节数计量的数据出站预算。
- 批量下载缺文件数和总字节硬限制。
- 模板、标准条款、审查规则、Prompt、知识库 chunk、法律全文等高价值资产需要摘要列表和详情计量。
- AI Trace、Prompt、知识库、审查规则属于管理资产,需要严格角色授权和低频配额。
- 下载审计需要补齐真实 user_id、tenant_id、IP 哈希、UA 哈希、字节数、trace id、数据分级。
- runtime/schema-check 尚未检查反滥用配置是否启用。
P1 缺口:
- 缺服务端 session 表、会话撤销、并发会话限制和风险会话冻结。
- 缺统一安全事件表、行为风险评分、管理员“数据安全中心”。
- Word/PDF 下载缺用户、租户、时间、trace id 水印。
- 缺异常访问告警、配额临时放宽和解封闭环。
P2 缺口:
- 可接入阿里云 WAF/Bot Management。
- 可引入设备指纹作为辅助风险信号。
- 可加入高风险导出审批、蜜罐资源标识、DLP 和泄露追踪。
## 4. 数据分级
| 等级 | 数据 | 访问原则 |
| --- | --- | --- |
| S4 极高敏感 | 合同正文、附件、审查报告、签署证据、AI Trace 原始输入输出 | 详情和下载必须授权、计量、审计、限流 |
| S3 高敏感 | 模板正文、变量 schema、标准条款、审查规则、Prompt、知识库 chunk | 列表只返回摘要,正文走详情并计量 |
| S2 内部资产 | 法律全文、法规影响扫描、全局审计、质量动作 | 分页、角色限制、搜索和详情计量 |
| S1 普通元数据 | 标题、状态、分类、摘要、创建时间、负责人 | 可列表展示,但仍分页和限流 |
| S0 公开信息 | 健康检查、公开宣传内容 | 可公开,但仍走基础 WAF 和速率限制 |
原则:列表接口默认返回 S1 摘要;S3/S4 正文、完整 prompt、chunk、文件内容、报告内容都必须通过详情、预览、下载或导出接口单独授权和计量。
## 5. 威胁模型
重点防护对象:
- 匿名爬虫扫描公开路径。
- 已登录普通用户持续翻页下载。
- 被盗 Cookie 或共享账号批量导出合同、附件、报告。
- 同一租户多个账号轮换抓取。
- 多 IP 或代理池绕过单 IP 限流。
- 内部管理员批量导出 Prompt、AI Trace、知识库、审查规则。
- 直接调用 BFF/API 绕过前端按钮和菜单。
核心结论:只靠 Nginx IP 限流不够。必须在应用层按租户、用户、会话、IP、接口风险等级、数据分级和出站量做统一控制。
## 6. 高风险接口清单
Contract API:
- `GET /api/v1/contracts`
- `GET /api/v1/contracts/{contract_id}`
- `GET /api/v1/contracts/{contract_id}/download`
- `GET /api/v1/contracts/{contract_id}/review-report`
- `GET /api/v1/files`
- `GET /api/v1/files/{file_id}/preview`
- `GET /api/v1/files/{file_id}/download`
- `POST /api/v1/files/batch-download`
- `GET /api/v1/search`
- `GET /api/v1/templates/tree`
- `GET /api/v1/templates/{template_id}`
- `POST /api/v1/templates/{template_id}/draft`
- `GET /api/v1/legal-assets/*`
- `GET /api/v1/legal-fulltext/*`
- `POST /api/v1/legal-change-impacts/scan`
- `POST /api/v1/legal/qa`
- `GET /api/v1/audit/*`
AI Platform API:
- `GET /api/v1/audit/ai-runs`
- `GET /api/v1/audit/ai-runs/{run_id}`
- `GET /api/v1/prompt-templates`
- `GET /api/v1/prompt-templates/{name}`
- `GET /api/v1/knowledge-documents`
- `GET /api/v1/knowledge-documents/search`
- `GET /api/v1/knowledge-import-batches/{batch_id}/documents`
- `GET /api/v1/knowledge-import-batches/{batch_id}/chunks`
- `GET /api/v1/audit/quality-improvement-actions`
- `GET /api/v1/runtime/trace-governance/*`
Contract Web BFF:
- `/api/contract-platform/*`
- `/api/ai-platform/*`
BFF 必须传递可信 session 上下文,不允许浏览器直接伪造用户、租户、角色。
## 7. 控制架构
建议采用十层防护:
1. 可信身份上下文:Contract Web 从 HttpOnly session 解出 tenant/user/role,后端只接受 BFF 签名后的上下文。
2. 后端 RBAC:每个 endpoint 绑定最小角色集合。
3. 对象级授权:合同、文件、审查结果、模板草稿、AI Trace 必须检查 tenant_id 和权限关系。
4. Endpoint risk policy:按接口定义数据等级、记录计量、字节计量、限流桶和默认动作。
5. Redis 多维限流:按 user、tenant、session、IP 哈希、route、risk class 组合限流。
6. 数据出站预算:按日统计记录数、文件数、字节数、S3/S4 详情次数。
7. 下载授权:下载前创建短时 download grant,限制 jti、文件、用户、租户、过期时间和一次性使用。
8. 审计和风险评分:每次 S3/S4 访问、搜索、导出、下载、429、403 都写安全事件。
9. 告警与冻结:达到阈值后自动通知管理员,严重时临时冻结用户、会话或 IP 哈希。
10. 水印与追踪:报告和 Word/PDF 下载增加用户、租户、时间、trace id 标记。
## 8. RBAC 和对象授权矩阵
| 能力 | admin | legal | business | approver | observer | 说明 |
| --- | --- | --- | --- | --- | --- | --- |
| 合同列表摘要 | 是 | 是 | 是 | 是 | 只读 | 只能本租户 |
| 合同详情正文 | 是 | 是 | 相关合同 | 审批相关 | 可配置 | S4 计量 |
| 合同下载 | 是 | 是 | 相关合同 | 审批相关 | 默认否 | S4 计量和水印 |
| 附件预览下载 | 是 | 是 | 相关合同 | 审批相关 | 默认否 | S4 字节预算 |
| 批量下载 | 是 | 是 | 默认否 | 默认否 | 否 | 单次硬限制 |
| 模板正文 | 是 | 是 | 起草可用模板 | 否 | 只读摘要 | S3 计量 |
| 条款规则管理 | 是 | 是 | 否 | 否 | 只读摘要 | 发布下线审计 |
| 法律全文 | 是 | 是 | 是 | 是 | 只读 | S2,可较宽松 |
| Prompt | admin | 否 | 否 | 否 | 否 | S3 管理资产 |
| AI Trace 详情 | admin | 指定审计员 | 否 | 否 | 否 | S4,强脱敏 |
| 全局审计 | admin | 指定审计员 | 否 | 否 | 否 | S2 |
| 用户租户管理 | admin | 否 | 否 | 否 | 否 | 超管另行区分 |
生产环境禁止客户端通过 query/body 指定自己的 role。兼容字段如需保留,应仅用于日志观测或被后端忽略。
## 9. 限流和出站预算初值
以下为可配置默认值,不应写死:
| 类型 | 用户级 | 租户级 | 说明 |
| --- | --- | --- | --- |
| 普通列表 | 60 次/分钟 | 600 次/分钟 | S1 摘要 |
| 搜索 | 20 次/分钟 | 200 次/分钟 | 统一搜索、知识库检索 |
| S3/S4 详情 | 30 次/分钟 | 300 次/分钟 | 计入每日记录预算 |
| 单文件下载 | 10 次/分钟 | 100 次/分钟 | 计入字节预算 |
| 批量下载 | 2 次/小时 | 20 次/小时 | 单次最多 20 个文件、100 MB |
| 合同报告下载 | 10 次/小时 | 100 次/小时 | 计入报告预算 |
| Prompt/AI Trace 详情 | 10 次/分钟 | 100 次/分钟 | 仅管理角色 |
| 法律全文详情 | 60 次/分钟 | 600 次/分钟 | S2,可较宽松 |
| 法律问答 | 10 次/分钟 | 100 次/分钟 | 同时受 AI 成本预算约束 |
每日预算建议:
- S3/S4 详情记录:普通用户 1000 条/天,法务 3000 条/天,管理员可配置。
- 下载文件数:普通用户 50 个/天,法务 200 个/天。
- 下载字节数:普通用户 500 MB/天,法务 2 GB/天。
- 批量下载:普通用户默认关闭,法务 5 次/天,管理员 10 次/天。
- 达到 70% 提示,90% 告警,100% 阻断或要求管理员放行。
429 响应必须带 `Retry-After`。高风险异常可以返回 403 并写安全事件。
## 10. 数据库设计建议
后续迁移建议新增:
### security_access_events
记录每次高风险访问。
关键字段:
- `id`
- `tenant_id`
- `user_id`
- `session_id_hash`
- `ip_hash`
- `ua_hash`
- `route_key`
- `http_method`
- `resource_type`
- `resource_id`
- `data_class`
- `records_count`
- `bytes_count`
- `decision`
- `reason_code`
- `trace_id`
- `created_at`
### data_egress_ledger
记录每日出站预算消耗。
关键字段:
- `tenant_id`
- `user_id`
- `date`
- `data_class`
- `records_count`
- `files_count`
- `bytes_count`
- `reports_count`
- `updated_at`
### security_incidents
记录风险评分后的事件。
关键字段:
- `id`
- `tenant_id`
- `user_id`
- `severity`
- `incident_type`
- `signals`
- `status`
- `assigned_to`
- `created_at`
- `resolved_at`
### security_blocks
记录临时冻结。
关键字段:
- `id`
- `dimension`
- `subject_hash`
- `tenant_id`
- `user_id`
- `reason`
- `starts_at`
- `expires_at`
- `created_by`
- `released_by`
- `release_reason`
### tenant_security_policies
租户级安全策略。
关键字段:
- `tenant_id`
- `policy_json`
- `risk_mode`
- `download_watermark_enabled`
- `batch_download_enabled`
- `updated_by`
- `updated_at`
### download_grants
短时下载授权。
关键字段:
- `jti`
- `tenant_id`
- `user_id`
- `resource_type`
- `resource_id`
- `scope`
- `expires_at`
- `used_at`
- `bytes_limit`
- `created_at`
可选:
- `user_sessions`:服务端会话、撤销、并发限制、设备信息、风险状态。
原始 IP 和 UA 不入库,统一使用独立 security secret 做 HMAC 哈希。
## 11. Redis key 设计
建议 key:
- `abuse:rate:{tenant}:{user}:{route}:{window}`
- `abuse:tenant:{tenant}:{route}:{window}`
- `abuse:ip:{ip_hash}:{route}:{window}`
- `abuse:session:{session_hash}:{route}:{window}`
- `egress:records:{tenant}:{user}:{date}:{data_class}`
- `egress:files:{tenant}:{user}:{date}`
- `egress:bytes:{tenant}:{user}:{date}`
- `abuse:block:{dimension}:{subject_hash}`
- `download:grant:{jti}`
Redis 不可用时的策略:
- production 默认 fail closed 或 degrade strict,即高风险下载、批量下载、AI Trace、Prompt 详情不可用。
- smoke/local 可 fail open 并记录 warning,方便开发。
## 12. Nginx 和 WAF 建议
Nginx 不只做全站一个限流区,应按风险分区:
- `read_low`:普通页面、摘要列表。
- `read_search`:搜索、法律全文检索、知识库检索。
- `read_sensitive`:合同详情、模板详情、Prompt 详情、AI Trace 详情。
- `download_single`:单文件、合同 Word/PDF、审查报告。
- `download_batch`:批量打包下载。
- `auth`:登录、验证码、邀请、密码重置。
建议:
- 生产只对外暴露 Contract Web 和 HTTPS edge。
- Contract API、AI Platform API 绑定内网或 loopback,经 BFF/网关访问。
- 高风险路径设置更低 `rate` 和更小 `burst`。
- 下载路径限制并发连接数和最大请求体。
- 记录 request id、upstream time、status、bytes_sent、user agent 哈希所需原始信号。
- 阿里云 WAF/Bot Management 可作为 P2 叠加层,拦截已知恶意 IP、代理、异常 UA 和自动化特征。
## 13. 下载授权和水印
下载流程:
1. 用户点击下载。
2. BFF 带可信 session 请求 Contract API 创建 download grant。
3. Contract API 做 RBAC、对象授权、限流、预算、冻结状态检查。
4. 通过后生成短时 grant,记录审计。
5. 实际下载必须携带 grant jti,且一次性使用或短期有效。
6. 下载完成写入 `bytes_count` 和结果状态。
水印:
- Word/PDF 页脚或末尾加入租户名、用户邮箱脱敏、下载时间、trace id。
- 审查报告和合同导出默认启用水印。
- 原始附件如不能修改内容,至少文件名、压缩包清单、下载审计中保留 trace id。
## 14. 行为风险评分
风险信号:
- 短时间翻页过快。
- 合同详情命中率异常高。
- 下载量或字节数快速增长。
- 搜索关键字枚举特征明显。
- 多账号同租户同 IP 或同 UA 轮换访问。
- 同账号多 IP 快速切换。
- 访问被隐藏菜单或无 UI 入口的管理 API。
- 重复触发 429 后继续请求。
- 夜间或非工作时间大量下载。
动作:
- 低风险:提示或降低速率。
- 中风险:写 incident、通知管理员、要求重新登录。
- 高风险:冻结 session 或用户,阻断 S3/S4 接口。
- 严重风险:冻结租户批量下载、通知超级管理员。
管理员需要能查看、解封、临时放宽配额,所有操作写审计。
## 15. 分阶段实施计划
### P0:公开 SaaS 上线前必须完成
1. 建立 endpoint risk policy 注册表,覆盖 Contract API、AI Platform API 和 BFF 高风险路由。
2. Contract API 和 AI Platform API 增加统一 anti-abuse middleware。
3. 统一可信身份上下文,生产禁止信任客户端 role。
4. 接入 Redis 多维限流,支持 user、tenant、session、IP 哈希、route。
5. 建立数据出站预算,先在 Redis 计量,再落库审计。
6. 文件、合同、报告、批量下载增加硬限制、预算和安全审计。
7. 模板、条款、规则、Prompt、知识库 chunk、法律全文列表改为摘要优先,正文走详情。
8. AI Trace、Prompt、知识库管理接口收紧到 admin/legal 指定角色。
9. runtime/schema-check 增加反滥用配置检查:Redis、security secret、risk policy、download limits。
10. Nginx 分风险路径限流。
11. 安全测试覆盖租户隔离、越权、批量下载、配额阻断和 429。
### P1:上线后第一阶段增强
1. 服务端 session 表、撤销和并发会话限制。
2. 数据安全中心管理页。
3. Word/PDF 水印和下载 trace id。
4. 安全事件、incident、block、解封流程落库。
5. 告警接入邮件、企业微信或钉钉。
6. 租户级安全策略配置。
### P2:商业化和高安全客户增强
1. 阿里云 WAF/Bot Management。
2. 设备指纹风险信号。
3. 高风险导出审批。
4. 蜜罐资源标识和泄露追踪。
5. DLP、字段级脱敏策略、客户自定义配额。
## 16. 灰度和回滚
灰度策略:
- `ANTI_ABUSE_ENABLED=false|observe|enforce`
- `DATA_EGRESS_BUDGET_ENABLED=false|observe|enforce`
- `DOWNLOAD_GRANT_REQUIRED=false|true`
- `SENSITIVE_LIST_SUMMARY_ONLY=false|true`
推荐顺序:
1. 本地和 smoke 开 `observe`,只记录不阻断。
2. smoke 压测确认 429 比例、误伤率和 Redis 性能。
3. production 先对下载和 AI Trace 开 enforce。
4. 再对搜索、详情、Prompt、知识库开 enforce。
回滚:
- middleware 支持环境变量快速退回 observe。
- Redis 限流异常时可临时关闭高风险接口或切 strict fallback。
- 数据库迁移只新增表和字段,不影响老业务读写。
- Nginx 分区限流可单独回滚到旧配置。
## 17. 验收测试
安全测试:
- A 租户用户无法访问 B 租户合同、文件、审查结果、AI Trace。
- 普通用户不能访问 Prompt、AI Trace、全局审计、规则管理详情。
- 修改 URL/ID 访问他人文件返回 403 或 404。
- 批量下载超过文件数或字节数返回 429/403。
- 达到每日预算后详情、下载被阻断,列表摘要仍可用。
- 客户端传 `role=admin` 不影响后端授权。
- Redis 不可用时 production 高风险接口按策略阻断。
性能测试:
- 普通列表 p95 < 800ms。
- 搜索和模板树 p95 < 1200ms。
- anti-abuse middleware 单请求额外开销 p95 < 30ms。
- Redis 连接池无耗尽。
- 30 分钟压测无内存持续上涨。
误封测试:
- 正常法务连续处理 50 份合同不触发冻结。
- 正常下载 10 个附件不触发冻结。
- 达到 70%/90% 预算时只提示和告警,不提前阻断。
- 管理员临时放宽配额后立即生效且有审计。
## 18. 与当前上线计划关系
当前 V2 可以继续内部 UAT 或受控 smoke 验证,但如果目标是公开多租户 SaaS 或承载真实客户合同数据,不建议只靠现有 Nginx 限流直接上线。
生产上线建议门槛:
- 至少完成 P0。
- 跑安全扫描、接口压测、Docker smoke、schema-check。
- 完成租户隔离和越权测试。
- 下载、搜索、AI Trace、Prompt、知识库路径全部纳入 risk policy。
- 形成数据安全回归报告。
最建议的第一片实现:
1. `endpoint risk policy` + `anti-abuse middleware`。
2. Redis 多维限流。
3. 下载和批量下载出站预算。
4. Prompt、AI Trace、知识库、模板正文等 S3/S4 详情计量。
5. runtime/schema-check 增加反滥用配置检查。
这片能最快把“可被批量抓取”变成“可计量、可阻断、可审计、可告警”。
## 19. P0 第一片落地记录
日期:2026-07-22
已完成:
- Contract API 新增 endpoint risk policy 和 anti-abuse middleware。
- AI Platform API 新增 endpoint risk policy 和 anti-abuse middleware。
- 支持 `disabled / observe / enforce` 三种模式。
- 命中高风险接口时返回 `X-Anti-Abuse-Mode`、`X-Anti-Abuse-Decision`、`X-Anti-Abuse-Policy`、`X-Data-Class` 响应头。
- `enforce` 模式下超过当前策略阈值返回 429,并带 `Retry-After`。
- 当前第一片使用进程内滑动窗口限流,适合本地、测试和 smoke 验证行为;生产长期稳定运行仍需接 Redis。
- Contract API runtime config-check 和 schema-check 已输出 `anti_abuse` / `anti_abuse_runtime`。
- AI Platform schema-check 已输出 `anti_abuse_runtime`,即使 memory repository 模式也会报告该安全门。
- `.env.example` 和 production compose env 示例已增加反滥用配置。
本片覆盖的高风险路径:
- Contract API:合同列表、合同详情、合同下载、审查报告、文件列表、文件详情、文件预览、文件下载、批量下载、统一搜索、模板树、模板详情、条款规则、法律全文、法律问答、审计路径。
- AI Platform API:AI Trace 列表/详情、质量动作、Prompt 列表/变更、知识库文档、知识库文档 chunk、知识库搜索、知识库批次文档/chunk、Trace governance。
下一片建议:
- 将 `InMemorySlidingWindowLimiter` 替换为 Redis 多维限流实现,支持 user、tenant、session、IP hash、route 维度。
- 建立 `security_access_events` 和 `data_egress_ledger`,把当前内存事件落库。
- 给文件下载、合同 Word/报告下载、批量下载接入文件数和字节预算。
- BFF 透传可信 user/session 上下文,逐步禁止后端信任客户端传入的 role。
## 20. P0 第二片落地记录
日期:2026-07-22
已完成:
- Contract API 和 AI Platform API 的 anti-abuse guard 支持 Redis 滑动窗口限流。
- Redis 不可用或未配置时自动回退到进程内滑动窗口,local/test 不阻断开发;staging/production 的 runtime check 会要求反滥用配置启用并配置 Redis。
- 两个服务均新增 `security_access_events` 和 `data_egress_ledger` 模型与 Alembic 迁移。
- middleware 命中高风险路径后会写入安全访问事件;S3/S4 访问会累计每日数据出站账本。
- Contract API schema-check 已将两张安全表纳入核心表检查。
- AI Platform schema-check 已将两张安全表纳入核心表和 tenant 列检查。
- Python 依赖增加 `redis>=5.0`。
新增迁移:
- Contract API:`20260722_0032_add_security_access_events.py`
- AI Platform API:`20260722_0022_add_security_access_events.py`
当前边界:
- 本片已经做到“可计量、可审计、可 Redis 限流”。
- 数据出站预算目前先累计,不直接按每日预算阻断;预算阈值阻断应作为下一片实现。
- 安全事件查询/管理页还未做,后续可进入“数据安全中心”。
下一片建议:
- 增加每日记录数、文件数、字节数预算检查,超过阈值时返回 429/403。
- 批量下载增加单次文件数和总字节硬限制。
- BFF 透传 session id hash,安全事件补 `session_id_hash`。
- 增加管理端安全事件列表和租户安全策略配置。
## 21. P0 第三片落地记录
日期:2026-07-23
已完成:
- Contract API 与 AI Platform API 的 `check_egress_budget(...)` 从“只看既有账本是否已达阈值”升级为“既有账本 + 本次请求投影”判断,超过每日预算时返回 403。
- S3/S4 records 预算开始按 `page_size` / `limit` 估算本次出站记录数,避免分页列表、知识库检索、AI Trace 列表按 1 次请求低估爬取量。
- Contract API 文件下载、合同 Word 下载、审查报告下载接入 `reserve_egress_budget(...)`,在返回内容前累计每日文件数与字节数。
- 批量下载保持仓储层单次硬限制:
- `CONTRACT_API_BATCH_DOWNLOAD_MAX_FILES`,默认 20。
- `CONTRACT_API_BATCH_DOWNLOAD_MAX_BYTES`,默认 100 MiB。
- 配置示例补齐每日 records/files/bytes 预算和批量下载硬上限:
- Contract API `.env.example`
- AI Platform `.env.example`
- compose `.env.example`
- compose `.env.production.example`
- 回归测试覆盖:
- S4 详情路径达到每日记录预算后返回 403。
- 文件下载成功后累计 `files_count` 与 `bytes_count`。
- 文件下载超过每日字节预算返回 403。
- 批量下载超过单次文件数硬上限返回 409。
- AI Platform 知识库列表按 `limit` 投影每日记录预算。
当前边界:
- 批量下载的单次硬上限已经在仓储层前置执行;每日预算按生成后的 zip 实际字节数入账。
- 列表类 records 预算采用请求参数估算,属于偏保守策略:空页也可能计入请求额度,但能更有效阻断枚举式爬取。
- 下一片建议补“安全事件/出站账本管理页 + 租户级安全策略配置”,让运营可以查看、调整、临时放宽或封禁。
@@ -0,0 +1,451 @@
# 钰麒合同 V2 产品审计与开发 Backlog
日期:2026-08-01
角色:产品经理、运营质量负责人、测试复核负责人
## 一、审计结论
当前 V2 的合同业务骨架已接近企业 UAT 水平,但尚不具备“面向个人、团队与企业的公开 SaaS”发布条件。主要阻断项不是模板或审查能力,而是:
1. 服务端角色授权没有真正落到合同写接口。
2. 未登录页面展示管理员导航和模拟业务数据。
3. 产品承诺包含个人用户,但身份模型只闭环了“公司租户”。
4. 平台超级管理员并非独立身份,而是依靠默认租户和固定用户 ID 推断。
5. 真实 AI、内容签批、服务协议和运营交付仍是既有文档明确记录的 No-Go 项。
现有实现已经覆盖:30 个模板、模板起草、合同编辑、审批退回重提、异步 AI 审查、结构化风险与引用、条款修复、PDF 审查报告、Word 下载、文件仓库、版本、签署证据、履约和归档。
## 二、三类用户模型与关键旅程
### 2.1 个人用户
目标定义:独立自然人账号,默认拥有一个个人工作空间,不要求提供公司信息。
关键旅程:
1. 注册账号并验证身份。
2. 系统自动创建个人工作空间。
3. 选择模板起草,或上传已有合同。
4. 发起 AI 审阅,查看风险、依据和修改建议。
5. 下载合同或审阅报告。
6. 查看个人用量、订阅与历史记录。
当前状态:产品定位明确包含个人用户,但没有个人注册或个人空间创建路径。
### 2.2 企业租户用户
目标定义:组织工作空间中的成员,按管理员、法务、业务、审批人、观察者角色协作。
关键旅程:
1. 平台管理员或自助流程创建组织工作空间。
2. 组织管理员邀请成员。
3. 员工通过邀请设置密码并登录。
4. 业务人员起草或上传合同。
5. 法务发起审查和修订,审批人处理审批。
6. 合同完成签署、履约和归档,保留审计证据。
当前状态:流程基本闭环,但角色授权主要停留在展示层,登录多空间体验较差。
### 2.3 平台超级管理员
目标定义:平台级主体,负责租户、套餐、全局安全、AI 质量、运营和交付管理;默认不得参与客户合同流程或查看客户正文。
关键旅程:
1. 安全 bootstrap 或受控邀请创建平台管理员。
2. 创建、停用和审计工作空间。
3. 管理 Provider、Prompt、全局知识资产和质量门。
4. 监控安全事件、容量、失败任务和交付状态。
5. 通过显式授权和完整审计执行租户支持操作。
当前状态:没有显式平台角色;依靠 `default` 租户和固定用户 ID 判断。
## 三、P0 问题与验收标准
### P0-1 服务端合同角色授权缺失
问题:详情和工作台接受客户端 `role` 参数,合同编辑、审批、审查、归档等写接口没有统一按照当前会话用户角色复核。
验收标准:
- 角色必须由服务端根据当前 `tenant_id`、`user_id` 查询,不信任 URL、请求体或公开环境变量。
- 业务用户直接调用审批、归档、规则发布等接口返回 `403`。
- 审批人不能编辑合同,观察者不能修改或发起审查。
- 客户端传入 `role=admin` 不影响服务端权限。
- 所有读写权限边界都有 API 级回归测试。
### P0-2 未登录页面展示管理员工作台
问题:前端角色默认 `admin`,无会话时页面请求失败后回退模拟合同和待办,登录只表现为可选入口。
验收标准:
- 未登录访问业务页和管理页统一跳转登录,API 返回 `401`。
- 登录、注册、密码重置和邀请页使用独立认证布局,不展示业务和后台导航。
- 实际会话角色驱动导航和页面守卫。
- 未登录、接口故障、真实空数据三种状态严格分离。
### P0-3 真实空待办被替换成模拟待办
问题:只要 `pending_tasks` 为空就回退到模拟任务,真实零待办会显示虚假业务数据。
验收标准:
- 合法的零待办显示空状态。
- 接口超时或失败显示明确错误和重试入口。
- 模拟数据只能在显式 demo 模式出现,并带清楚的演示标识。
### P0-4 平台超级管理员身份不可治理
问题:平台管理员由默认租户和固定用户 ID 推断,无法规范支持多人、停用、轮换和审计。
验收标准:
- 增加显式平台权限声明或平台角色。
- 支持多名平台管理员、停用、凭据轮换和完整审计。
- 平台权限不依赖固定字符串 ID。
- 企业管理员不能访问跨工作空间数据和平台级配置。
### P0-5 AI 与内容交付不满足公开生产承诺
验收标准:
- 真实 Provider 启用,生产 fallback 关闭。
- 审查、法律问答、生成和条款推荐黄金样本通过。
- 高风险模板完成具名法务签批。
- 引用准确率、无依据响应、幻觉和低置信度结果有明确门禁。
### P0-6 公开产品缺法定信任页面
验收标准:
- 上线用户协议、隐私政策、服务协议、数据处理规则和 AI 免责声明。
- 注册、上传、AI 问答和报告交付可访问相关协议。
- 用户同意记录包含协议版本、时间和主体。
## 四、P1 Backlog
### P1-1 将租户产品语义统一为工作空间
- 普通页面不再出现“租户 ID”。
- “公司”只用于组织类型工作空间。
- 平台运维页面可以保留租户技术字段。
### P1-2 建立个人工作空间
- 个人注册后原子创建账号、个人空间和 owner 成员。
- 个人用户可以立即起草、上传、审查和下载报告。
- 个人空间隐藏成员邀请、SSO 和复杂企业治理能力。
### P1-3 增加工作空间切换器
- 同一账号加入多个空间时无需手填工作空间 ID。
- 登录后可以查看并切换有权访问的空间。
- 切换后会话、权限、缓存和导航同步刷新。
### P1-4 分离平台后台与企业管理区
- 企业管理员只见成员、审批、企业资产和企业审计。
- 平台管理员才见跨租户、安全、Provider、全局 AI 质量和运行配置。
- 平台支持进入租户数据时需要显式授权并记录审计。
### P1-5 修正身份页和导航
- 登录页标题和品牌口径统一为“登录钰麒合同”。
- 未登录不显示后台导航。
- SSO 实际登录闭环完成前不得包装为可用能力。
- 公开注册关闭时提供清晰的申请试用或联系服务入口。
### P1-6 收口主流程语义
- “起草新合同”进入模板起草,不进入合同台账。
- 文件上传后提供“创建合同并发起审查”。
- 去除用户可见的“V1/V2”等工程文案。
- 合同状态、生命周期、下一步动作使用统一中文口径。
### P1-7 AI 结果风险沟通
- 问答页和合同审查结果页常驻人工复核提示。
- 低置信度结果不得使用成功色。
- 无引用或依据不足时不得包装成可靠结论。
- 普通用户不能进入平台 AI Trace 管理页。
### P1-8 账号恢复与邀请运营
- 明确邀请到期、重发、撤销和可信渠道交付。
- 覆盖员工离职、管理员转移和唯一管理员保护。
- 无邮箱模式提供明确账号支持 SLA。
## 五、P2 Backlog
- 套餐、配额与用量:个人、试用、团队、企业套餐,审查量、存储、成员、报告水印和超限提示。
- 运营与客户成功:试点周期、负责人、活跃用户、起草/审查/报告转化、失败任务和续费风险。
- 通知中心:审批、审查、履约、邀请和安全提醒形成可到达的入口与已读闭环。
- 文档治理:功能状态、RC 结论、测试证据和运行环境保持一致,废止陈旧结论。
## 六、个人工作空间兼容方案
### 6.1 第一阶段:保持现有 tenant_id 边界
将现有 `TenantModel` 解释为通用工作空间,在现有 `settings` 或后续显式字段中加入:
```text
workspace_type: system | personal | organization
owner_user_id: string | null
legal_name: string | null
```
迁移规则:
- 现有客户租户默认标记为 `organization`。
- `default` 标记为 `system`。
- 个人注册创建 `personal` 空间。
- 继续复用合同、文件、审查、知识库和审计表中的 `tenant_id`,不重写业务外键。
- 个人空间中的 `admin` 在产品上显示为“所有者”。
### 6.2 第二阶段:全局账号与成员关系
引入:
- `accounts`:全局唯一账号和凭据。
- `workspace_memberships`:账号与工作空间的成员关系、角色和状态。
- 现有 `tenant_users` 通过 `account_id` 兼容迁移,或逐步演化为 membership 表。
目标:解决同一邮箱在多个租户中拥有多套凭据、登录时必须输入空间 ID、密码策略不一致等问题。
## 七、回归测试清单
### 身份与会话
- 未登录访问全部业务与管理路由。
- 个人注册、企业邀请、密码设置和登录。
- 多空间查看和切换。
- 停用用户、停用空间、邀请过期和管理员转移。
- 平台管理员 bootstrap、停用和轮换。
### 权限与隔离
- 五类企业角色逐项验证读取、编辑、上传、审查、审批、下载、归档和规则发布。
- 同时覆盖 UI、同源代理和直接 API 绕过。
- 个人与企业、两个企业、平台后台三组交叉访问合同、文件、报告、搜索、审计和 AI Trace。
### 模板与合同
- 30 个模板全量生成。
- 必填项、可选项、特殊字符、长文本和重复提交。
- 草稿、审查、提交审批、退回、重提、签署、履约和归档的合法与非法状态转换。
### AI 审查与报告
- 上传后建合同、排队、运行、失败和重试。
- 结构化风险、引用、条款修复、报告生成下载及旧版本一致性。
- 无依据、低置信度、Provider 不可用和 fallback 禁用场景。
### 空态与故障
- 零合同、零待办、零文件和零通知。
- API `401/403/500`、超时和服务不可用。
- 任何故障都不得出现模拟业务数据或虚假成功。
### 运营交付
- 试用额度、报告水印和超限行为。
- 协议版本、用户同意记录、数据导出和删除。
- 客服升级、人工复核和交付审计证据。
## 八、开发执行顺序
1. P0 服务端授权与未登录边界。
2. 移除隐式模拟数据和客户端角色来源。
3. 引入工作空间类型和显式平台权限。
4. 打通个人工作空间注册与多空间会话。
5. 收口导航、身份文案和主流程入口。
6. 补齐协议、运营、套餐和客户成功能力。
7. 运行全量回归、真实 Provider 质量验收和生产发布门禁。
## 九、自动化开发阶段状态(2026-08-01)
本轮已启动三个智能 Agent,分别负责服务端授权、前端身份边界和个人工作空间后端;随后追加个人/组织注册前端接入。所有改动保留在当前工作树,尚未提交、部署或应用到生产数据库。
### 9.1 已完成
- **P0-1 服务端角色授权**:新增统一 capability 授权层。代理认证开启时,角色只从当前 `tenant_id`、`user_id` 对应的活跃成员关系解析;客户端 `role=admin` 不再影响权限。合同、审批、审查、报告、下载、文件、归档、签署、履约、备份、模板、法务资产和审批规则接口已接入授权守卫。
- **P0-2 未登录边界**:Next.js 请求代理验签会话 cookie;未登录访问业务路由跳转 `/login`,无权访问管理路由跳转 `/workspace`。认证页、邀请页、密码重置页和政策页使用独立外壳,不再显示业务后台导航。
- **P0-3 隐式模拟数据**:合同列表、合同详情和工作台待办已移除生产路径中的模拟回退;合法零待办返回空列表,接口失败抛出错误,不再显示虚假合同或待办。
- **P0-4 显式平台权限第一阶段**:`tenant_users.platform_permissions` 支持显式 `platform_admin`,运行时判断不再比较固定用户 ID。历史 `default/user-current-admin` 仅在迁移和 bootstrap 中用于给既有记录回填显式权限。
- **P1-1/P1-2 工作空间与个人注册第一阶段**:保留全部 `tenant_id` 外键,新增 `workspace_type`、`owner_user_id`、`legal_name`;个人注册原子创建 `personal` 工作空间、owner/admin 成员、账户设置和密码凭据;组织注册继续创建 `organization` 工作空间。
- **个人/组织注册入口**:注册页默认提供个人模式,并可切换组织模式;个人模式不要求公司名称或技术空间 ID。成功注册复用现有签名会话进入工作台。
- **P1-5/P1-6/P1-7 部分项**:导航使用会话角色;“起草新合同”进入模板起草;用户可见的 V1/V2 工程文案已移除;法律问答和合同审查增加人工复核边界;低、中、高置信度使用警告、主色和成功色分级。
- **法定信任页面载体**:已增加用户协议、隐私政策、服务协议和 AI 使用说明入口,并明确标注为产品草案、正式发布前需具名法务审核。
### 9.2 验证证据
- Contract API 按四个隔离数据库分片执行 182 个测试用例;发现 2 个本地兼容模式回归后已修复,相关防滥用、代理认证和越权测试 16 项复跑通过。
- 服务端越权测试覆盖业务用户审批/归档、审批人编辑、观察者上传/审查以及 `role=admin` 伪造,均返回预期 `403`;缺少身份上下文返回 `401`。
- 身份定向测试覆盖个人空间 owner、密码登录、企业/个人同邮箱多空间、重复注册冲突、事务回滚和显式平台权限。
- AI Platform API 全量 93 项测试通过,包含新增生产发布就绪门禁测试。
- `npm run web:typecheck` 通过;`npm run web:build` 通过,共生成 94 个路由并识别 Next.js Proxy。
- Playwright 真实浏览器验证:未登录 `/workspace` 跳转 `/login`;登录页无业务侧栏且含四类政策链接;注册页个人/组织分段可切换;政策页显示草案和法务审核状态。
- 新版 Contract API 临时实例完成一次真实个人注册和指定工作空间登录:返回 `workspace_type=personal`、owner 与用户一致、成员角色为 `admin`、认证方式为 `password`。
- 迁移 `20260801_0033` 已由开发 Agent 在全新 SQLite 上完成 upgrade、downgrade、re-upgrade 验证。
### 9.3 仍未完成或不得作为上线完成项
- **P0-5** 的真实 AI Provider 单场景联网验收已通过:当前 Codex Provider/模型在隔离内存实例中完成法律问答端到端运行,未使用 fallback,质量与引用门禁均通过。该运行尚未持久化到共享或生产数据库,且审查、生成、条款推荐等完整黄金套件仍待执行,因此不得据此将 P0-5 整体标记为生产交付完成。
- 协议版本与同意记录已持久化,但四份协议仍是产品草案,尚未经过具名法务审核和正式生效;草案留痕不得被解释为正式法律文本已发布。
- 平台管理员的多人开通、停用、轮换和支持访问审计仍需补齐运营管理入口;当前完成的是显式权限数据和运行时识别。
- 多工作空间兼容层与可视化切换器已完成,登录页不再要求填写工作空间 ID;但当前仍复用各 `tenant_user` 的历史凭据进行候选校验,尚未完成统一全局凭据、已验证邮箱归并和账号合并/拆分治理,因此不得把兼容层解释为最终账号体系。
- 个人空间的套餐、配额、用量、支付、成员功能隐藏和数据退出仍属于后续 P1/P2。
- 本地验收预览已使用隔离 SQLite 在 `8100` 重启当前 Contract API,并在 `3011` 启动当前 Web;这不代表生产或共享数据库已迁移。生产/共享环境启用前必须备份数据库、依次执行 Alembic `0033`、`0034` 与 `0035`、配置代理认证并重启服务。
### 9.4 第二阶段已完成
- **AI 生产发布门禁**:新增 `GET /api/v1/quality/release-readiness` 和可供 CI 调用的 `python -m yuqei_ai_platform_api.release_readiness_gate`。生产环境必须启用非占位 Provider、可解析 URL 与凭据、关闭 fallback、通过黄金资产和引用策略检查,并提供指定的真实 `acceptance_run_id`。离线黄金资产结果明确标记为不验证 Provider 输出。
- **协议版本与同意留痕**:新增公开协议目录和受控同意记录查询接口。个人与组织注册必须逐项提交服务端目录中的当前精确版本;缺失、重复、额外或客户端自定义版本均被拒绝。
- **注册事务一致性**:工作空间、owner/admin、账户、凭据和四条同意记录在同一事务中创建,任一写入失败整体回滚。`20260801_0034` 新增 `identity_agreement_consents`,记录工作空间、用户、协议类型、版本、服务端同意时间、注册来源、客户端 IP 和 User-Agent。
- **注册前端闭环**:个人与组织模式均从同源协议目录加载必签项,逐项展示政策链接、精确版本和“草案未生效”状态;未全部勾选时提交禁用,模式切换清空已有同意。
- **扩展角色权限矩阵**:补充法务备份、内部 review worker、业务用户管理审批规则、审批人创建合同、观察者发布模板等直接 API 越权场景,均要求返回 `403`。
### 9.5 第二阶段验证证据
- Contract API 当前完整 185 项按四个隔离数据库分片通过:合同工作流 78 项、核心治理 36 项、领域模块 40 项、身份/权限/迁移 31 项。
- Contract API 身份管理 9 项通过;身份安全、代理权限和角色授权组合 21 项通过;`0034` 升级/降级自动化测试 1 项通过,共 31 项定向回归通过。
- `0034` 在完整 SQLite 迁移链执行 upgrade、downgrade、re-upgrade 通过;表结构、唯一约束及新增请求来源字段均有断言。
- AI Platform API 全量 93 项通过;生产默认 mock/fallback 配置被门禁判定为 `blocked`,CLI 返回退出码 `1`。
- Web 类型检查和生产构建通过,构建包含 `/api/auth/agreements/current`、个人注册和组织注册路由,共生成 94 个路由。
- 隔离实例真实注册验证返回 `workspace_type=personal`、角色 `admin`、4 条同意记录;版本、注册来源、服务端采集的 IP 和 User-Agent 均与请求上下文一致。
- Playwright 在无网络 mock 的本地预览验证:四项协议和政策链接可见;未勾选时提交禁用;全部勾选后启用;切换到组织模式后全部恢复未选;稳定页面控制台无错误。
### 9.6 下一阶段优先项
1. 将真实 Provider 验收扩展到审查、生成、条款推荐等完整黄金套件,并在共享预发布环境持久化通过的审计运行 ID;单场景隔离验收不得替代完整发布证据。
2. 完成四份政策的具名法务审核、正式版本号、生效时间、历史版本查询和再次同意策略。
3. 在现有全局账号兼容层上收口统一凭据、已验证邮箱归并、账号合并/拆分和成员关系恢复流程,避免仅凭相同邮箱长期承担跨空间身份绑定语义。
4. 补齐平台管理员多人治理、支持访问授权审计,以及个人套餐、配额、用量和数据退出能力。
### 9.7 真实 AI Provider 联网验收证据(2026-08-01)
- 参数来源:仅在单次验收子进程中读取 Codex 当前 Provider 配置和凭据;Provider、模型和端点按运行时配置解析,不作为固定产品参数写入仓库、`.env`、数据库或日志。验收期间未输出任何密钥值。
- 协议兼容性:当前 Provider 的 `/v1/responses` 与 `/v1/chat/completions` 均完成真实联网调用;项目现有 Chat Completions 适配器可正常调用当前 Provider,无需为本次验收改写协议。
- 端到端用例:向隔离内存知识库加入《中华人民共和国劳动合同法》第十九条和第二十条,询问三年以上固定期限劳动合同的试用期上限及试用期工资下限。模型准确返回“六个月”“80%(百分之八十)”和“当地最低工资标准”,并正确列出对应法条。
- 审计证据:运行 ID `run-06172b83f530`;Provider `ccswitch`;模型 `gpt-5.6-sol`;Provider 与运行状态均为 `succeeded`;fallback 未使用;响应引用 4 条;检索来源 2 个;总 token 4855;延迟 6258 ms;质量状态 `passed`,质量分 100。
- 门禁结果:以该运行 ID 调用生产规则 `GET /api/v1/quality/release-readiness`,返回 `ready`、`release_allowed=true`、`provider_acceptance_verified=true`,无失败检查。
- 证据边界:该运行 ID 属于验收进程内的隔离内存仓库,进程退出后不会出现在共享或生产数据库。它证明当前动态 Provider 参数、项目适配器、检索引用、质量评估和发布门禁能够端到端工作,但不构成生产部署、生产数据迁移、完整黄金套件通过或具名法务签批的证据。
### 9.8 第三阶段自动化开发结果(2026-08-01)
- **全局账号兼容层**:新增 `identity_accounts` 与 `workspace_memberships`,保持合同、文件、审查和审计等业务表继续使用 `tenant_id`。同一标准化邮箱可关联个人与组织工作空间,每个成员关系保留目标空间中的 `tenant_user_id`、角色、状态和 owner 标记。
- **迁移与旧数据回填**:新增 `20260801_0035`,从现有有效 `tenants` 与 `tenant_users` 回填全局账号和成员关系,不读取或搬运密码凭据;迁移支持 upgrade、downgrade、re-upgrade,并断言同邮箱只生成一个全局账号及多个空间成员关系。
- **登录与空间切换**:登录页只提交邮箱与密码,不再暴露工作空间 ID。服务端在同邮箱多空间候选中校验实际匹配凭据后建立会话;登录后通过 `GET /api/v1/identity/workspaces` 获取有效成员空间,通过 `POST /api/v1/identity/workspaces/switch` 切换。目标空间必须属于同一有效全局账号,且工作空间、成员和用户均为有效状态,否则统一返回 `403`。
- **前端会话闭环**:新增同源 workspace 列表和切换代理,均要求有效签名会话;切换成功后重新签发包含目标 `tenant_id`、`user_id` 和角色的前端会话。顶栏单空间保持紧凑展示,多空间显示选择器;失败时保留当前会话和当前空间。
- **Provider 验收工具加固**:`run-ai-provider-acceptance.py` 默认将证据写入 `.runtime`,持久化字段限制为 Provider、模型、状态、计数和问题代码;不写入完整模型响应、合同内容、问题文本、引用 ID、审计 ID、tenant 或法务姓名。工具同时限制 URL、header、密钥文件大小、超时、用例数量和响应体,并显式使用 UTF-8。
- **离线完整用例准备**:隔离 HTTP 服务已跑通 Phase13 的 10 条法律问答与 8 条合同审查,18/18 技术通过,法律状态均保持 `needs_legal_review`;该结果仅验证验收工具和样本编排,不代表真实 Provider 完整黄金套件通过。
### 9.9 第三阶段验证证据
- Contract API 186 项按四个独立 SQLite 分片全部通过:合同工作流 92 项、核心治理 45 项、领域模块 21 项、身份/权限/迁移 28 项。
- 身份定向覆盖:同邮箱个人/组织空间归并、免工作空间 ID 的凭据匹配登录、空间列表、合法切换、跨账号/系统空间拒绝、成员状态过滤、注册事务回滚,以及 `0035` 升级/降级/再升级与旧数据回填。
- Web 类型检查和生产构建通过,共生成 96 个路由,新增 `/api/auth/workspaces` 与 `/api/auth/workspaces/switch`;切换器状态测试 2/2 通过。
- Provider 验收及 Bandit 相关测试 7 项通过;中文请求 UTF-8、证据脱敏、参数安全和 18 条隔离黄金用例均有自动化断言。
- `git diff --check` 通过,仅存在 Windows 工作树 LF/CRLF 转换提示;未提交、未部署、未执行共享或生产数据库迁移。
### 9.10 第四阶段自动化开发结果(2026-08-02)
- **统一全局凭据与邮箱验证**:新增迁移 `20260802_0036`、`identity_account_credentials` 和 `identity_accounts.email_verified_at`。一个全局账号最多保留一条全局密码凭据;同邮箱使用不同密码重复注册返回 `409` 并完整回滚,同一密码可继续创建或关联个人、组织工作空间。
- **旧账号渐进兼容**:仅对“单成员、单凭据”的无歧义旧账号回填全局密码;历史 `tenant_user_credentials.email_verified_at` 不直接提升为全局邮箱验证。多空间、多凭据旧账号继续走兼容登录,完成邮箱验证或密码重置后再归并,避免迁移阶段错误合并账号。
- **跨空间安全边界**:未验证全局邮箱只允许访问当前工作空间;验证后才开放同账号的有效工作空间列表与切换。全局密码登录只选择 `active` 用户,邀请未接受成员不能提前登录。密码重置旋转唯一全局密码后,新密码可登录全部成员空间,旧密码失效。
- **动态 Provider 协议兼容**:AI Platform 新增 `responses` 与 `chat_completions` 可配置 wire API。Responses 适配支持 `/responses`、`output_text`/`output` 以及 `input_tokens`/`output_tokens`,HTTP 错误信息执行脱敏;当前参数仍从 Codex 运行时动态读取,不固定写入产品配置。
- **多工作空间浏览器闭环**:个人/组织注册、四份协议、免工作空间 ID 登录、同邮箱候选凭据匹配、顶栏空间切换、非法切换、退出和并行会话隔离均通过真实浏览器验证。前端增加 `127.0.0.1` 开发资源允许来源,并将登录 `401/429` 稳定映射为不泄露账号状态的中文提示。
### 9.11 第四阶段真实 Provider 与回归证据
- 当前动态 Provider 摘要为 `ccswitch / gpt-5.6-sol / responses`。Key 只注入 `8123` 隔离内存进程,验收后进程和一次性服务密钥均已清理;安全扫描中 Provider Key、真实网关 URL、运行时 Authorization 均为 0 命中。
- 真实法律问答和合同审查各执行 1 条,外部调用、运行审计和 Provider 状态均为 `succeeded`,无 Provider 错误,共计 3357 tokens。这证明当前鉴权、Responses 协议、模型和联网链路可用。
- 黄金产品门禁结果为 `failed`、技术门禁 `0/2`:两条均出现 `expected_source_not_retrieved`,合同审查另有 `missing_citations` 与 `severity_below_expected`。根因是隔离内存知识文档使用随机 `doc-*`,未保留清单要求的 `LAW-*` 稳定 source ID;同时合同审查结构化 `risk_items` 仍由规则函数生成,Provider 目前只替换摘要。该结果不得表述为完整真实 Provider 验收通过。
- 脱敏证据位于 `.runtime/v2-ai-provider-acceptance/2026-08-02-codex-current-full/ai-provider-acceptance-summary.json`,仅保留 Provider、模型、状态、计数和问题代码。
- Contract API 最终 `186/186` 通过:工作流 97、治理 52、领域 5、身份/权限/迁移 32。`0036` 已在隔离 SQLite 完成 upgrade、downgrade、re-upgrade;未在共享或生产数据库执行迁移。
- AI Platform API `94/94` 通过;Provider/发布工具定向 `7/7` 通过。生产预检仍因仓库示例配置包含 `placeholders` 而失败,这是有效发布阻断项,不能绕过。
- Web workspace 状态测试 `2/2`、TypeScript 类型检查、生产构建均通过,共生成 96 个路由。重启后的 Playwright 复核显示登录页和注册页 `ready=complete`、注册策略已加载、控制台 0 error。
- 本地服务已使用当前代码重启:Contract API `http://127.0.0.1:8110`、AI Platform `http://127.0.0.1:8111`、Web `http://127.0.0.1:3021/login`,均返回 200。后端 schema-check 的 `warning` 来自本地 SQLite、内存仓库和 Provider disabled,符合隔离开发运行边界。
### 9.12 下一阶段优先项(2026-08-02 更新)
1. **P0 AI 黄金门禁**:为 Phase13 知识资产建立稳定 `LAW-*` source ID 装载;让 Provider 结构化输出参与合同审查 `risk_items`、严重度和引用生成;先通过 10 条法律问答与 8 条合同审查,再扩展合同生成和条款推荐,最后在共享预发布环境持久化验收运行 ID。
2. **P1 账号治理**:增加账号合并、拆分、争议恢复、成员关系恢复的运营 API/UI;历史多密码账号需要明确的邮箱验证/密码重置引导;正式定义全局登录邮箱变更,避免与工作空间 `AccountSettings.email` 混淆。
3. **P1 邀请与恢复**:已有全局账号接受邀请时要求已认证会话或显式恢复确认,避免邀请 token 被解释为无条件密码轮换授权。
4. **P1 发布与法务**:完成四份政策的具名法务审核、正式版本、生效时间、历史版本和再次同意策略;清除生产示例占位符后重新执行严格预检。
5. **P2 运营能力**:补齐平台管理员多人治理、支持访问审计、个人套餐/配额/用量/支付、成员功能隐藏和数据退出。
### 9.13 第五阶段自动化开发结果(2026-08-02)
- **P0 AI 黄金技术门禁通过**:`LegalCitation` 从知识文档 `reference` 提取稳定 `LAW-*` 外部 source ID,memory/SQLite 内部仍使用原有随机 `doc-*` 主键,不改表、不迁移。Phase13 的 10 张知识卡以幂等方式装载到固定 `phase13-golden` 知识库,并明确标注为待法务复核材料、不是法条原文或法律批准。
- **Provider 结构化合同审查**:合同审查提示词要求严格 JSON;服务端以 `extra=forbid` 模型校验摘要、总体风险、风险项、严重度、建议和 `citation_source_ids`。每个风险项至少引用一个本次实际检索 source ID,总体风险必须等于最高风险项严重度;自由文本、未知引用和严重度不一致均不进入业务风险对象,而是按现有 fallback/failed 策略处理并留痕。
- **普通用户自助邮箱验证闭环**:普通有效成员只能为当前会话邮箱和当前工作空间发送、确认验证码;越权确认在消费验证码前被拒绝,不消耗失败次数。租户管理员保留本工作空间成员管理能力,平台管理员保留全局能力。确认成功返回刷新后的全局账号会话。
- **Web 邮箱验证与会话刷新**:新增 `/verify-email`、`/api/auth/email-verification/send` 和 `/api/auth/email-verification/confirm`。同源代理强制使用签名会话中的邮箱,只有返回会话与当前工作空间、用户完全一致时才重写 cookie。所有登录、注册、邀请、密码重置和工作空间切换入口统一携带 `email_verified_at`;旧 cookie 兼容为未验证状态。
- **账号设置权威边界收口**:个人设置 PATCH 只接受显示名、语言、时区、通知和偏好;`tenant_id`、`user_id`、登录邮箱、成员角色和审计操作者均由服务端上下文决定,客户端越权字段返回 `422`。读取设置时以全局账号邮箱和当前成员角色覆盖设置表中的历史副本,保持现有表结构兼容,不新增迁移。
- **密码与邀请语义**:组织注册、邀请接受和密码重置统一要求 12-128 位密码;密码重置不再要求技术工作空间 ID。已有全局账号接受邀请时必须输入当前密码,不能借邀请 token 轮换全局凭据;邀请页同步区分“新用户设置密码”和“已有账号输入当前密码”,并提供密码重置入口。
### 9.14 第五阶段验证证据
- Contract API 使用全新隔离 SQLite 执行全量 `189/189` 通过;账号设置定向回归中身份管理 `11/11`、代理权限 `6/6` 通过。未执行共享或生产数据库迁移。
- AI Platform API 全量 `99/99` 通过;Provider/发布工具全量 `13/13` 通过。Phase13 专项覆盖 memory/SQLite source ID 兼容、虚构引用拒绝、结构化输出失败策略和 Provider URL 日志脱敏。
- 当前动态 Codex Provider 为 `ccswitch / gpt-5.6-sol / responses`。隔离内存实例执行法律问答 10 条、合同审查 8 条,技术门禁 `18/18`、问题数 `0`;状态为 `needs_legal_review`,法律批准 `0/18`。脱敏摘要位于 `.runtime/v2-ai-provider-acceptance/2026-08-02-phase13-structured-full/ai-provider-acceptance-summary.json`,不包含密钥、真实端点、完整提示词或完整响应。
- Web 会话映射测试 `2/2`、工作空间状态测试 `2/2`、TypeScript 类型检查和生产构建通过;构建生成 99 个页面/路由,包含新的邮箱验证页面和代理入口。
- Provider 验收临时端口和一次性服务密钥已清理;Provider Key 与真实 Provider URL 在修改代码和验收证据中均为 0 命中。常驻开发 AI 服务继续使用 Provider disabled,避免把真实凭据持久化到开发运行态。
- 最终运行态已重启:Contract API `http://127.0.0.1:8110`、AI Platform `http://127.0.0.1:8111`、Web `http://127.0.0.1:3021/login` 均返回 200。
### 9.15 后续优先项(取代 9.12 的当前执行顺序)
1. **P0 法律与预发布交付**:由具名法务复核 10 张知识卡及 18 条黄金结果,建立权威法条原文库、正式版本和生效记录;在共享预发布数据库持久化通过的验收运行 ID。当前隔离 memory 证据只能证明技术链路,不代表法律正确性或生产发布批准。
2. **P1 邮件与账号恢复运营**:接入真实 SMTP/邮件服务并执行浏览器端到端验收;定义全局登录邮箱变更的旧邮箱确认、新邮箱验证、冲突检查和恢复流程。当前仅完成开发挑战码与 API/UI 闭环,尚未验收真实邮件投递。
3. **P1 账号争议治理**:先建设 platform-only 只读冲突诊断列表和详情,再设计带 preview、幂等 operation ID、双人审批和完整审计的账号合并、拆分及成员关系恢复;不得直接以破坏性写接口起步。
4. **P1 平台管理员治理**:增加平台管理员只读名册和“不得停用最后一名有效平台管理员”保护;随后补充授予/撤销、支持访问时限与原因、双人审批和专用 before/after 审计。
5. **P2 运营能力**:补齐个人套餐、配额、用量、支付、成员功能隐藏、数据导出/删除和客户成功指标;四份公开政策仍需具名法务审核、正式版本、生效时间、历史版本与再次同意策略。
### 9.16 第六阶段自动化开发结果(2026-08-02)
- **平台管理员只读名册**:新增 `GET /api/v1/identity/platform-administrators`,只返回管理员身份、工作空间、状态和最近登录等非凭据信息。后端以显式 `platform_admin` 权限为唯一跨空间边界;企业工作空间管理员返回 `403`,不能依赖固定用户 ID 或前端角色判断。
- **最后有效管理员保护**:内存和 SQL 仓储均在成员状态更新时阻止停用最后一名有效平台管理员,API 返回 `409`。SQL 路径在同一事务内使用 `SELECT ... FOR UPDATE` 锁定有效管理员集合;Web 对该冲突显示中文运营提示。两名管理员时可停用其中一名,停用后其平台权限立即失效,独立凭据轮换不影响另一名管理员。
- **平台专属账号冲突诊断**:新增 `GET /api/v1/identity/account-conflicts` 和详情路由。诊断复用现有全局账号、工作空间成员、租户用户和凭据表,不新增迁移、不写身份数据;支持严重度、冲突码、精确规范化邮箱和分页筛选。稳定 `diagnostic_id` 只由实体 ID 哈希生成,不把邮箱写入 URL 资源 ID。
- **冲突分类与最小披露**:首期覆盖重复全局账号、缺失/孤立/重复成员关系、身份或状态漂移、所有者漂移、停用账号仍有有效成员、凭据身份/算法异常、有效身份无凭据和历史多凭据未归并。响应仅包含凭据作用域、状态、算法、更新时间和是否需要重置,禁止返回密码哈希、token、验证码或会话数据。相关访问纳入 `identity.account_conflicts`、`S3`、`sensitive=true` 的反滥用与访问留痕策略。
- **Web 运营入口**:新增 `/admin/identity/conflicts` 只读列表与详情工具页。只有平台名册请求成功时,身份管理页才显示诊断入口;企业管理员直接访问时不渲染跨空间统计或邮箱。页面提供严重度、冲突类型和精确邮箱筛选,不提供合并、拆分或恢复写操作。
- **工作空间语义收口**:身份管理、管理首页和侧栏的面向用户文案从“用户与租户/公司租户”改为“用户与工作空间/组织工作空间”;技术 `tenant_id` 继续保留在内部 API 和平台治理详情,兼容现有数据模型和个人工作空间方案。
### 9.17 第六阶段验证证据
- 平台管理员治理定向用例 `8/8`、身份管理/安全/代理鉴权组合回归 `31/31` 通过;加入账号冲突诊断后,身份域组合回归为 `35/35`。
- Contract API 从仓库根目录首次执行全量时为 `191/193`,两项失败均因 Alembic 相对路径把 `migrations` 解析到仓库根目录,属于测试命令工作目录错误,不是业务断言失败。随后从 `services/contract-api` 目录、使用全新隔离 SQLite `.test-runtime/contract-full-phase6-20260802-1332.sqlite3` 重新执行,最终 `195/195` 通过,退出码为 0。未执行共享或生产数据库迁移。
- 账号冲突专项 `4/4` 通过:健康身份零误报;平台管理员 `200`、企业管理员 `403`、缺代理凭据 `401`;重复账号、状态/所有者漂移、异常算法和缺失成员关系可稳定定位;未知详情 `404`、`page_size=101` 为 `422`;响应递归扫描不含密码哈希、token 或验证码字段。
- Web 会话映射 `2/2`、工作空间状态 `2/2`、TypeScript 类型检查和生产构建通过;构建生成 100 个页面/路由,包含 `/admin/identity/conflicts`。
- `git diff --check` 通过,仅有工作区既有 CRLF 提示。Contract API、AI Platform 和 Web 已重启并分别在 `8110`、`8111`、`3021` 返回 200。
- 重启前在已登录 Codex 内置浏览器检查 `/legal-documents`、`/workspace`、`/verify-email`、`/admin/identity` 和 `/admin`,数据加载成功且控制台无 error;发现已登录访问 `/login` 仍显示登录表单,以及平台管理界面仍存在“租户”历史文案。后者本阶段已收口。Web 运行脚本每次启动随机生成会话签名密钥,因此重启后既有 cookie 失效;新诊断页的登录态可视化复核需用户重新登录后继续,不能把未完成的浏览器复核写成通过。
### 9.18 后续优先项(取代 9.15 的当前执行顺序)
1. **P0 法律与预发布交付**:仍需具名法务复核 10 张知识卡和 18 条黄金结果,并在共享预发布环境持久化批准记录;当前技术门禁不代表法律正确性或生产批准。
2. **P1 邮件与账号恢复运营**:接入真实 SMTP,完成发送、退信、限流、旧邮箱确认、新邮箱验证、冲突检查和恢复流程的浏览器端到端验收。
3. **P1 账号争议写操作**:以本阶段只读诊断为入口,设计账号合并、拆分和成员恢复的 preview、幂等 operation ID、双人审批、回滚策略和完整 before/after 审计;不得直接增加破坏性写接口。SQL 诊断当前按需聚合全表,进入大规模预发布前应增加候选集查询和性能基线。
4. **P1 平台管理员完整治理**:补充受控授予/撤销、支持访问原因和时限、双人审批及专用审计;最后管理员并发保护仍需真实 PostgreSQL 双请求集成验收。
5. **P1 产品语义与会话体验**:将开发环境的“默认租户”种子名称改为系统工作空间口径;明确已登录访问 `/login` 时是重定向工作台还是提供显式“切换账号”,避免当前重复登录表单语义。
6. **P2 运营与测试效率**:补齐个人套餐、配额、用量、支付、数据导出/删除和客户成功指标;在不降低密码哈希参数的前提下并行化身份测试夹具,缩短当前约 6 分钟的 Contract API 全量回归。
### 9.19 平台管理员登录态浏览器实测与修复复核(2026-08-02)
- 使用已登录平台管理员 `admin@example.com` 的 Codex 内置浏览器会话实测,`/workspace`、`/admin/identity`、`/admin/identity/conflicts` 和 `/verify-email` 均正常加载;本轮未伪造会话、未绕过服务端权限,也未执行账号合并、拆分、恢复或其他争议身份写操作。
- 身份管理页的平台管理员名册显示共 `1` 人、有效 `1` 人,平台专属账号冲突诊断入口可见;这与当前单管理员开发数据一致,但不替代多人治理、授权审批或并发保护验收。
- 账号冲突列表显示严重冲突 `0`、提醒 `2`。精确邮箱筛选以包含大写字母和首尾空格的输入执行,服务端按既有规则规范化后只返回目标项;切换到“严重”筛选时显示明确的零结果空状态,没有把提醒误计为严重冲突。
- 冲突详情可查看全局账号、租户用户、工作空间成员和凭据元数据。对页面返回对象执行递归字段扫描,未发现 `password_hash`、`credential_hash`、`verification_code`、`access_token` 或 `refresh_token`;该证据证明当前页面和 API 响应满足本阶段最小披露要求,不代表底层数据库不存在受控凭据字段。
- 全程浏览器控制台 error 和 warning 均为 `0`,仅出现开发环境 HMR 信息;未观察到页面加载、筛选、详情请求或权限请求错误。
- 首次实测发现三项产品质量问题:顶栏和管理员名册仍显示“默认租户”、组织注册按钮仍写“创建公司”、管理员初始密码被浏览器自动填入。另一开发 Agent 已将前两项统一为“系统工作空间”和“创建组织工作空间”,并将密码输入保持空值、设置为 `new-password` 自动填充语义,避免展示或复用已有凭据。
- 已登录访问 `/login` 的语义确定为自动返回 `/workspace`。真实浏览器复核确认最终 URL 为 `/workspace`、工作台标题存在且登录表单不再渲染,控制台 error/warning 为 `0`;未登录 `/login` 及注册、密码重置、邀请和政策页继续保持公开访问。
- 修复后 Web 路由测试 `4/4`、工作空间状态测试 `3/3`、身份页敏感默认值源码测试 `1/1`、会话映射测试 `2/2` 均通过,TypeScript 类型检查通过;浏览器刷新复核确认“系统工作空间”“创建组织工作空间”、密码空值和登录重定向均已生效。该复核只覆盖当前开发登录态和可见交互,不等同于真实 SMTP、共享预发布数据库或生产环境验收。
### 9.20 后续优先项(取代 9.18 的当前执行顺序)
1. **P0 法律签批与共享预发布交付**:仍需具名法务复核 10 张知识卡和 18 条黄金结果,建立权威法条原文、正式版本、生效记录和批准责任人,并在共享预发布环境持久化验收运行 ID。当前技术门禁和浏览器实测均不能替代法律正确性确认或生产发布批准。
2. **P1 真实邮件与账号恢复运营**:接入真实 SMTP/邮件服务,完成发送、退信、重试、限流、旧邮箱确认、新邮箱验证、冲突检查和恢复流程的浏览器端到端验收;当前开发挑战码闭环不得表述为真实邮件交付完成。
3. **P1 账号争议写操作设计**:以已通过登录态实测的只读冲突列表和详情为入口,设计账号合并、拆分及成员关系恢复的 preview、幂等 operation ID、双人审批、回滚策略和完整 before/after 审计;在方案和验收标准明确前不得直接增加破坏性写接口。SQL 诊断进入大规模预发布前仍需候选集查询和性能基线。
4. **P1 平台管理员完整治理与并发验收**:继续补充受控授予/撤销、支持访问原因和时限、双人审批及专用审计。最后有效管理员保护虽已通过本地定向回归,但仍需在真实 PostgreSQL 上执行双请求并发集成验收,不能以 SQLite 或单请求结果替代。
5. **原 9.18 第 5 项已完成并移出阻断**:开发环境工作空间口径、组织创建命令和管理员密码输入语义已修正;已登录访问 `/login` 自动返回工作台,未登录及其他公开身份入口保持原行为。Web 路由 `4/4`、工作空间状态 `3/3`、身份页源码 `1/1`、会话映射 `2/2`、TypeScript 和登录态浏览器刷新复核均通过;后续如改变登录或切换账号策略,应作为独立会话需求重新评审,不回退本次已验收语义。
6. **P2 运营与测试效率**:补齐个人套餐、配额、用量、支付、数据导出/删除和客户成功指标;在不降低密码哈希参数的前提下并行化身份测试夹具,并建立账号冲突诊断的规模化查询和回归性能基线。