Files
nexus/Project/fonrey/TECH_STACK/API_CONTRACT.md
2026-04-28 07:38:30 +08:00

7.6 KiB
Raw Blame History

For AI assistants: Read this entire file before designing or implementing any API. Contract rules here are mandatory. Do not invent per-module variants unless explicitly allowed.

Fonrey API 契约规范API_CONTRACT

版本: 1.0
适用范围: 全模块account / permission / property / client / complex / org / setting
关联总纲: TECH_STACK/TECH_STACK.md
最后更新: 2026-04-27


1. 文档定位与原则

本文件定义 Fonrey 全局 API 契约标准,解决跨模块接口风格漂移问题。模块技术方案中的 API 章节必须遵循本文件,不得各自定义冲突规则。

1.1 强制级别

  • MUST:必须遵守,违反视为缺陷
  • SHOULD:建议遵守,若不遵守需在模块文档注明原因
  • MAY:可选能力

1.2 适用接口类型

  • JSON API/api/**
  • HTMX 片段端点HTML response
  • 文件上传/下载端点

2. 请求 / 响应格式规范

2.1 请求体规范JSON API

  • Content-Type MUST 为 application/json
  • charset=utf-8 SHOULD 显式声明
  • 写操作POST/PUT/PATCHMUST 传业务 payload禁止空对象写入

推荐请求结构:

{
  "data": {
    "...": "业务字段"
  },
  "meta": {
    "request_id": "可选,客户端透传"
  }
}

兼容说明:历史端点已存在 filters/sort/pagination 平铺结构时可继续使用,但新接口 SHOULD 迁移到 data 容器。

2.2 成功响应规范JSON API

成功响应 MUST 使用统一 envelope

{
  "ok": true,
  "data": {},
  "meta": {
    "request_id": "uuid",
    "timestamp": "2026-04-27T16:30:00+08:00"
  }
}

说明:

  • ok MUST 为 true
  • data MUST 存在(可为空对象 {} 或空数组 []
  • meta SHOULD 包含 request_id 与服务端时间

2.3 失败响应规范JSON API

失败响应 MUST 使用统一 envelope

{
  "ok": false,
  "error": "权限不足",
  "code": "PROPERTY_PERMISSION_DENIED",
  "details": {},
  "meta": {
    "request_id": "uuid",
    "timestamp": "2026-04-27T16:30:00+08:00"
  }
}

说明:

  • error MUST 为面向用户/调用方可读消息
  • code MUST 为稳定机器可读码(大写下划线)
  • details MAY 提供字段级错误(如校验失败)

2.4 HTMX 响应规范

  • 成功:返回 HTML 片段;必要时通过 HX-Trigger 触发前端事件
  • 失败:
    • 状态码 MUST 正确4xx/5xx
    • SHOULD 在响应头返回 HX-Trigger,例如:
      • {"toast:error":"权限不足"}
      • {"toast:error":"请求失败,请重试"}

3. 错误码规范

3.1 命名规则

  • 错误码 MUST 为 UPPER_SNAKE_CASE
  • 推荐前缀:<MODULE>_(如 PROPERTY_ / CLIENT_ / ORG_

3.2 HTTP 状态码基线

HTTP 使用场景 示例 code
400 参数错误、业务前置条件不满足 PROPERTY_VALIDATION_ERROR
401 仅用于纯 API Token 鉴权失败(当前 Web 会话模式一般不用) AUTH_UNAUTHORIZED
403 已登录但无权限 *_PERMISSION_DENIED
404 资源不存在或不可见 *_NOT_FOUND
409 状态冲突、任务未就绪 *_STATE_CONFLICT / *_JOB_NOT_READY
422 字段级校验错误(可选) *_VALIDATION_FAILED
429 频控触发 RATE_LIMITED
500 未预期异常 INTERNAL_ERROR

3.3 稳定性要求

  • code MUST 可稳定依赖,不得频繁改名
  • 错误文案 error 可优化,但不应影响调用方流程判断

4. 分页规范

Fonrey 列表查询 MUST 使用 Keyset 分页;禁止 OFFSET 深分页。

4.1 请求格式

{
  "filters": {},
  "sort": {"field": "updated_at", "order": "desc"},
  "pagination": {"mode": "keyset", "cursor": null, "limit": 20}
}

4.2 响应格式

{
  "ok": true,
  "data": {
    "items": [],
    "next_cursor": "opaque_cursor_2"
  },
  "meta": {
    "pagination": {"mode": "keyset", "cursor": "opaque_cursor", "limit": 20}
  }
}

4.3 约束

  • limit MUST 有上限(建议 ≤ 100
  • cursor MUST 为不透明字符串,禁止暴露内部排序字段组合
  • 排序字段 MUST 来自白名单,防止 SQL 注入与慢查询

5. 搜索 / 筛选规范

5.1 推荐请求结构

{
  "filters": {
    "keyword": "保利",
    "status": ["active", "pending"],
    "district_id": "uuid"
  },
  "sort": {"field": "updated_at", "order": "desc"},
  "pagination": {"mode": "keyset", "cursor": null, "limit": 20}
}

5.2 语义规范

  • keyword:模糊检索词(服务端统一做 trim
  • 多选条件 MUST 使用数组(如 status: []
  • 空数组 [] 语义:不限制该条件
  • null 语义:由模块文档明确(默认建议等同“不传”)

5.3 安全与性能

  • 仅允许白名单字段参与筛选和排序
  • LIKE/全文检索字段 SHOULD 建立索引或搜索策略
  • 查询快照哈希(用于缓存/导出SHOULD 对 filters+sort+scope 进行规范化后计算

6. 上传规范

Fonrey 优先采用“预签名上传 + 回执提交commit”两段式。

6.1 标准流程

  1. 客户端请求 upload-token业务 API
  2. 客户端直传对象存储R2
  3. 客户端调用 commit API 回写元数据

6.2 合约要求

  • upload-token MUST 短时有效(建议 5~15 分钟)
  • commit MUST 幂等(建议支持 idempotency_key
  • 上传白名单与大小限制 MUST 在模块文档声明并在服务端校验
  • SHOULD 校验 content_typesize
  • MAY 增加 sha256 校验确保完整性

6.3 错误码建议

  • *_UPLOAD_TOKEN_EXPIRED (409/400)
  • *_UPLOAD_FILE_TOO_LARGE (400)
  • *_UPLOAD_FILE_TYPE_NOT_ALLOWED (400)
  • *_UPLOAD_COMMIT_CONFLICT (409)

7. 文件下载规范

下载统一采用“导出任务 + 状态查询 + download endpoint”。

7.1 标准流程

  1. 创建导出任务 POST /api/**/export/jobs/
  2. 轮询任务状态 GET /api/**/export/jobs/{job_id}/
  3. 下载结果 GET /api/**/export/jobs/{job_id}/download/

7.2 合约要求

  • 任务未完成下载 MUST 返回 409 + *_EXPORT_JOB_NOT_READY
  • 下载链接 SHOULD 为一次性或短时有效 URL
  • 响应 SHOULD 设置 Content-Disposition(附件下载)
  • 文件名 SHOULD 带模块与日期,便于审计

8. 权限拒绝返回规范

8.1 JSON API

  • 未登录MUST 返回 302Web Session 场景)或 401(纯 API 场景)
  • 已登录无权限MUST 返回 403
  • 失败体 MUST 使用统一错误 envelopecode*_PERMISSION_DENIED

8.2 页面路由SSR/HTMX

  • 未登录302 跳转登录页
  • 已登录无权限403 页面(或 HTMX 403 片段)
  • HTMX 拒绝 SHOULD 触发 HX-Trigger toast 事件

8.3 测试强约束

每个受保护端点 MUST 覆盖三态:

  • 200有权限
  • 403已登录无权限
  • 302/401未登录视端点类型

9. 与模块文档的衔接规则

  • 各模块技术方案中的“四、API 设计原则”“六、关键 API 规范”“十二、错误码建议”必须引用本文件
  • 模块文档可补充模块特有 code 与字段,但不得与本规范冲突
  • 冲突时以本文件为准;若需例外,必须在模块文档显式记录 ADR 链接

10. 落地检查清单Review Checklist

  • 是否使用统一成功/失败 envelope
  • 错误码是否为稳定 UPPER_SNAKE_CASE
  • 列表接口是否全部 Keyset 分页
  • filters/sort 字段是否白名单化
  • 上传是否采用 token+commit 且具备幂等保障
  • 下载是否采用 job 流程并处理未就绪 409
  • 权限拒绝是否遵循 200/403/302(401) 三态
  • 测试是否覆盖契约关键路径