门禁兼容修复

This commit is contained in:
andy committed 2026-09-05 17:36:23 +08:00
1 parent f60b416949
commit 801c0af692
18 files changed
+257 -87

No files matched your search

+8 -3
View File
@@ -17,7 +17,7 @@
## 2. 目标
- 新增默认关闭的 `POST /api/chat`。
- 使用独立静态 Bearer Token 保护首版测试入口,不复用 SuperAgent Key 或 MCP Token。
- 使用独立静态 Bearer Token 保护首版测试入口,不复用 SuperAgent Key 或 MCP Token;默认要求至少 32 个可打印 ASCII 字符。
- 首轮创建随机本地 `conversation_id` 和 SuperAgent Session;后续轮次复用映射。
- 同一 `conversation_id` 同时只允许一个活动 Run,冲突时返回 `409`。
- 通过 SSE 返回对话 ID、安全进度、严格完成后的最终回答和完成事件。
@@ -119,7 +119,8 @@ SSE 开始后的 Provider 失败使用终止 `error` 事件,不返回部分回
| 环境变量 | 默认值 | 说明 |
| --- | --- | --- |
| `FIRE_SAFETY_CHAT_ENABLED` | `false` | 对话 API 总开关;启用时要求 SuperAgent 同时启用 |
| `FIRE_SAFETY_CHAT_AUTH_TOKEN` | 空 | 独立高熵静态 Bearer,至少 32 个可打印 ASCII 字符 |
| `FIRE_SAFETY_CHAT_AUTH_TOKEN` | 空 | 独立静态 Bearer;默认至少 32 个可打印 ASCII 字符,兼容开关开启时允许已交付的旧短凭证 |
| `FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN` | `false` | 仅为已交付旧客户端短凭证的受控测试/迁移临时兼容开关;新环境不得开启 |
| `FIRE_SAFETY_CHAT_SUBJECT_ID` | `fire-safety-ymd-chat-test-subject` | 服务端固定测试主体,不使用真实用户标识 |
| `FIRE_SAFETY_CHAT_ALLOWED_ORIGINS` | 空 | 逗号分隔的精确 HTTP(S) Origin;空值只允许无 Origin 的服务端/CLI 调用 |
| `FIRE_SAFETY_CHAT_MAX_BODY_BYTES` | `131072` | HTTP JSON 请求体上限,最大 1 MiB |
@@ -129,13 +130,15 @@ SSE 开始后的 Provider 失败使用终止 `error` 事件,不返回部分回
`FIRE_SAFETY_CHAT_AUTH_TOKEN` 必须分别不同于 `FIRE_SAFETY_SUPERAGENT_OPEN_API_KEY` 和 `FIRE_SAFETY_MCP_AUTH_TOKEN`。
`FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN` 默认为 `false`。只有在旧客户端已经拿到、且无法立即更换的短凭证时,才可在受控测试或迁移窗口显式设置为 `true`。无论开关取值如何,`FIRE_SAFETY_CHAT_AUTH_TOKEN` 都必须非空、不超过 4096 字节,并且每个字符都在 ASCII `0x21-0x7e` 范围内(不得包含空格、控制字符或 Unicode);开关只影响 Chat 原生 Bearer 和兼容入口的 `xtoken`,不放宽 MCP Token 至少 32 个可打印 ASCII 字符的门禁。三种凭证仍必须使用不同值。凭证轮换完成后必须恢复 `false`;新环境不得以该开关绕过默认门禁。开关启用时,服务启动日志会记录不含 Secret 的安全 warning,便于后续清理。
## 7. CORS 与鉴权边界
- 无 `Origin` 的 CLI/服务端请求可以进入 Bearer 校验。
- 带 `Origin` 的浏览器请求必须精确匹配配置列表;不支持 `*`。
- 预检只允许 `POST` 以及 `Authorization`、`Content-Type` Header。
- 不启用 Cookie 身份或 CORS credentials。
- 静态 Bearer 只适合首版受控联调;公网最终用户入口必须接入真实身份认证、速率限制和动态授权。
- 静态 Bearer 只适合首版受控联调;legacy 短凭证开关只适合明确的迁移窗口,公网最终用户入口必须接入真实身份认证、速率限制和动态授权。
## 8. 日志与数据边界
@@ -153,6 +156,8 @@ SSE 开始后的 Provider 失败使用终止 `error` 事件,不返回部分回
- Given 同一会话已有活动 Run,When 再次发送,Then 返回 `409` 且不发第二个上游请求。
- Given Provider 流不完整或 Run 失败,When 处理结束,Then 不发送 `message` 或 `done`,只返回安全错误。
- Given 服务重启、会话过期或随机 ID 不存在,When 继续对话,Then 返回 `404` 而不把客户端值当作 Provider Session。
- Given `FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN` 未开启,When Chat Token 少于 32 个字符,Then 服务启动配置校验失败。
- Given `FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN=true`,When 旧短凭证用于受控测试/迁移,Then 原生 Bearer 和兼容 `xtoken` 均可校验,但非空、4096 字节上限和 ASCII `0x21-0x7e` 约束仍生效,且启动日志只记录不含 Secret 的安全 warning。
- Given 无真实网络和 Secret,When 执行自动化测试,Then 使用本地 fake/模拟 Provider 并全部通过。
## 10. Definition of Done
@@ -36,10 +36,13 @@
| 环境变量 | 默认值 | 说明 |
| --- | --- | --- |
| `FIRE_SAFETY_CHAT_COMPAT_APP_ID` | 空 | 非空时注册兼容路径;1 至 128 个 ASCII 字母、数字、下划线或连字符 |
| `FIRE_SAFETY_CHAT_AUTH_TOKEN` | 空 | 兼容路径期望的 `xtoken`,仍必须与 SuperAgent Key、MCP Token 不同 |
| `FIRE_SAFETY_CHAT_AUTH_TOKEN` | 空 | 兼容路径期望的 `xtoken`;默认至少 32 个可打印 ASCII 字符,兼容开关开启时允许已交付的旧短凭证 |
| `FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN` | `false` | 仅为已交付旧客户端短凭证的受控测试/迁移临时兼容开关;新环境不得开启 |
兼容路径只有在 `FIRE_SAFETY_CHAT_ENABLED=true` 且 App ID 非空时注册。App ID 是用于路径匹配的公开标识,不是 Secret;不匹配的路径返回 404。
`FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN` 默认为 `false`。只有在旧客户端已经拿到、且无法立即更换的短 `xtoken` 时,才可在受控测试或迁移窗口显式设置为 `true`。无论开关取值如何,Chat 凭证都必须非空、不超过 4096 字节,并且每个字符都在 ASCII `0x21-0x7e` 范围内(不得包含空格、控制字符或 Unicode);开关同时适用于原生 `/api/chat` 的 Bearer 和本兼容路径的 `xtoken`,不放宽 MCP Token 至少 32 个可打印 ASCII 字符的门禁。Chat、SuperAgent Open API 和 MCP 三种凭证仍必须使用不同值。凭证轮换完成后必须恢复 `false`,新环境不得开启该开关。开关启用时,服务启动日志会记录不含 Secret 的安全 warning,便于后续清理。
## 5. 请求契约
```http
@@ -130,6 +133,8 @@ SSE 开始后的失败发送 `event: error`,只包含稳定 code、通用 mess
- Given App ID 未配置,When 请求兼容路径,Then 路由返回 404,原生 `/api/chat` 行为不变。
- Given App ID 或 `xtoken` 错误,When 请求,Then 在读取问题和调用 SuperAgent 前拒绝。
- Given `FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN` 未开启,When 已交付的旧 `xtoken` 少于 32 个字符,Then 服务启动配置校验失败。
- Given `FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN=true`,When 旧短 `xtoken` 用于受控测试/迁移,Then 兼容入口允许该凭证但仍执行非空、4096 字节上限和 ASCII `0x21-0x7e` 校验,并记录不含 Secret 的安全 warning;MCP Token 的至少 32 字符门禁不变。
- Given 首轮请求成功,When 读取 SSE,Then 先收到字符串 `"null"` 会话事件,再收到同会话 `"stop"` 最终正文。
- Given 后续请求携带成功返回的 `session_id`,When 调用,Then 复用同一服务端会话映射。
- Given Provider 流失败,When SSE 已开始,Then 收到安全 `error`,不收到部分正文或 `stop`。