--- reviewStatus: pending reviewedAt: null replacedBy: null --- # 第一阶段工程基线接口与页面契约设计 ## 1. 设计范围 第一阶段不采用 Django REST Framework,也不提供公开 JSON API 或 OpenAPI 契约。本设计只定义浏览器访问的服务端页面 HTTP 契约,以及页面、Admin、Agent SDK 适配器调用的内部服务契约。 如果后续出现前后端分离、第三方调用或移动端需求,应重新执行正式 API 设计,不直接把本阶段内部服务暴露为外部 API。 关联设计: - [后端落地设计](backend-design.md) - [前端落地设计](frontend-design.md) - [数据库设计](database-design.md) ## 2. 通用 HTTP 规则 - 用户认证使用 Django Session。 - 所有状态修改请求使用 POST 并验证 CSRF。 - GET 请求不得产生业务状态变更。 - 成功写入后使用 POST/Redirect/GET。 - 未登录访问受保护页面时跳转登录页,并携带安全的站内返回地址。 - 普通用户访问其他用户资源时返回 404,不暴露资源存在性。 - 表单输入错误返回原页面和字段错误,响应状态按 Django 页面约定实现。 - 意外异常返回通用错误页面,日志使用请求关联标识定位。 - 响应不得包含堆栈、数据库错误、密钥、Cookie 或未脱敏工具参数。 ## 3. 页面端点 ### 3.1 登录 `GET /accounts/login/` - 返回登录表单。 - 已登录用户可重定向到运行列表。 `POST /accounts/login/` - 输入:用户名、密码、可选站内 `next`。 - 成功:建立 Session,重定向到安全 `next` 或运行列表。 - 失败:返回登录页和统一认证错误,不区分用户名或密码错误。 ### 3.2 退出 `POST /accounts/logout/` - 前置条件:已登录。 - 成功:清除 Session,重定向登录页。 - 不提供 GET 退出。 ### 3.3 个人资料 `GET /accounts/profile/` - 前置条件:已登录。 - 返回当前用户的用户名、显示名和时区。 - 不接受目标用户编号参数。 `POST /accounts/profile/` - 前置条件:已登录、CSRF 有效。 - 输入:显示名、时区。 - 成功:保存当前用户资料并重定向到资料页。 - 失败:原页显示字段错误,不保存部分数据。 ### 3.4 Agent Run 列表 `GET /runs/` - 前置条件:已登录。 - 查询参数:`page`,其他未知参数忽略或按统一规则拒绝。 - 返回当前用户拥有的 Run,按创建时间倒序分页。 - 管理员在普通站点页面仍默认只看自己的 Run;跨用户管理使用 Admin。 ### 3.5 Agent Run 详情 `GET /runs//` - 前置条件:已登录。 - 返回 Run 概览、有序事件、工具调用摘要和人工确认状态。 - 目标不存在或不属于当前用户时返回相同的 404。 - 页面端点不提供状态更新能力。 ### 3.6 管理后台 `/admin/` 沿用 Django Admin 的认证和权限体系。 - 用户资料和 Run 主记录按配置开放管理能力。 - 事件和完成的工具调用设置为只读或限制修改。 - 人工确认处理必须调用领域服务,不能只修改单个状态字段。 ### 3.7 模型服务商配置 `GET /runs/providers/` - 返回内置服务商目录、当前用户连接状态、搜索和分类结果。 - 不返回密文 API Key,已配置密钥只显示末四位提示。 `POST /runs/providers//configure/` - 输入:API Key、可选默认模型、是否设为默认服务商。 - 服务端按固定预设端点请求模型目录;验证成功后才加密保存。 - 验证失败返回安全错误说明,不透传上游正文,不覆盖旧密钥。 `POST /runs/providers//disconnect/` - 只删除当前用户对应配置;删除默认配置后自动选择一个剩余可用配置。 - GET 请求不得删除或修改配置。 ## 4. 表单契约 ### 4.1 登录表单 | 字段 | 必填 | 规则 | | --- | --- | --- | | `username` | 是 | 使用 Django 认证表单规则 | | `password` | 是 | 不回显、不写日志 | | `next` | 否 | 只允许站内安全路径 | ### 4.2 用户资料表单 | 字段 | 必填 | 规则 | | --- | --- | --- | | `display_name` | 否 | 去除首尾空白,长度上限由模型统一定义 | | `timezone` | 是 | 必须来自服务端受控候选 | 模型约束、表单约束和服务校验必须保持一致,不能只依赖浏览器端校验。 ## 5. 内部服务契约 内部服务只接受明确的操作者和标识,不接受未经限定的 QuerySet。 ### 5.1 账户服务 | 操作 | 输入 | 输出 | 失败语义 | | --- | --- | --- | --- | | 获取资料 | 当前用户 | `UserProfile` | 用户无效 | | 更新资料 | 当前用户、已校验数据 | 更新后资料 | 校验失败、并发冲突 | | 停用用户 | 管理员、目标用户 | 停用结果 | 无权限、目标不存在 | ### 5.2 Run 查询服务 | 操作 | 输入 | 输出 | 权限规则 | | --- | --- | --- | --- | | 查询列表 | 当前用户、分页参数 | 分页 Run | 强制用户归属过滤 | | 查询详情 | 当前用户、Run UUID | Run 详情视图模型 | 越权与不存在统一处理 | ### 5.3 Run 命令服务 | 操作 | 关键输入 | 关键输出 | | --- | --- | --- | | 创建 Run | 所属用户、脱敏输入摘要、版本 | 新 Run 和创建事件 | | 开始 Run | Run 标识、期望版本 | `running` Run 和开始事件 | | 完成 Run | Run 标识、脱敏输出、用量 | `succeeded` Run 和完成事件 | | 失败 Run | Run 标识、错误码、脱敏摘要 | `failed` Run 和失败事件 | | 取消 Run | 操作者、Run 标识 | `cancelled` Run 和取消事件 | | 请求确认 | Run、请求键、类型、摘要 | 待处理确认和暂停事件 | | 处理确认 | 操作者、确认标识、决定 | 确认结果及 Run 状态变更 | 命令服务必须显式返回更新后的领域对象或结果对象,不依赖调用方猜测数据库状态。 ## 6. SDK Gateway 契约 ### 6.1 请求模型 `AgentExecutionRequest` 至少包含: - `agent_run_id` - `user_id` - `agent_name` - `agent_version` - `instruction_version` - `toolset_version` - 脱敏运行输入 - 最大轮次、时间和工具调用预算 不包含 API Key、网站密码和 Cookie。 ### 6.2 结果模型 `AgentExecutionResult` 至少包含: - 结果状态。 - 脱敏结构化输出摘要。 - trace 标识。 - 输入和输出 token。 - 估算费用。 - 稳定错误码和脱敏错误摘要。 ### 6.3 失败分类 - 配置缺失:调用真实 Gateway 前失败,不影响其他页面。 - 输入无效:不发起外部请求。 - 外部超时或服务失败:记录工具或 Run 失败事件。 - 输出校验失败:保留安全摘要并将 Run 标记失败。 - 取消:停止后续调用并记录取消事件。 第一阶段测试使用 Stub Gateway,禁止自动化测试发起真实付费调用。 ## 7. 幂等、并发和重试 - 页面资料提交使用 POST/Redirect/GET,重复刷新不重复写入。 - Run 命令携带期望的 `lock_version` 或在服务内锁定记录。 - 工具调用使用 `(run_id, call_id)` 和幂等键防止重复记录。 - 人工确认使用 `(run_id, request_key)` 防止重复请求。 - 第一阶段不实现自动重试;失败结果保持终态。 - 外部调用开始和完成分别写入短事务,调用方可根据已有状态安全恢复记录。 ## 8. 错误映射 | 领域错误 | 页面语义 | 外部 API 预留语义 | | --- | --- | --- | | 资源不存在或无权访问 | 404 页面 | 404 | | 输入校验失败 | 表单错误 | 400 或 422,后续 API 设计确定 | | 状态转换冲突 | 操作失败提示 | 409 | | 重复或幂等冲突 | 操作失败提示 | 409 | | SDK 配置缺失 | 功能不可用提示 | 503 | | 外部服务失败 | 通用失败提示和关联编号 | 502 或 503,后续确定 | 表中外部 API 状态只作为未来语义预留,不代表第一阶段已经提供 JSON API。 ## 9. 安全测试清单 - 登录失败信息不泄露账户存在性。 - `next` 参数不能跳转到站外地址。 - GET 退出请求不能改变 Session。 - 缺失或错误 CSRF 的写请求被拒绝。 - 用户 A 无法通过修改 URL 访问用户 B 的 Run。 - UUID 格式错误和不存在资源均安全处理。 - 表单和摘要输出经过 HTML 转义。 - 密码、Cookie、API Key 和完整敏感参数不出现在响应或日志。 - Admin 人工确认操作经过领域服务和权限检查。 ## 10. 兼容与演进 - 页面 URL 使用命名空间和反向解析,避免模板硬编码路径。 - 第一阶段不承诺外部 API 兼容性。 - 后续新增 JSON API 时复用领域服务,不复用 HTML 视图作为接口层。 - 引入 DRF 或 OpenAPI 前必须确认调用方、认证方式、版本策略和错误模型。 - Celery 接入后通过同一 Run 命令服务记录状态,不改变页面查询契约。 ## 11. 待确认项 - 页面表单错误是否统一使用 200 还是采用更严格的 4xx 状态,实施时按项目测试约定确定。 - 是否允许管理员在普通运行页面跨用户查询;当前设计仅允许 Admin。 - 第二阶段是否向普通用户开放人工确认处理页面。 - 是否存在未来外部调用方;确认前不创建 OpenAPI 文档。