☰
Routa API契约实战:用api-contract.yaml让Web与桌面端永远保持一致
2026/10/11 18:30:41 网站建设 项目流程

【免费下载链接】routa

Workspace-first multi-agent coordination platform for AI development, with shared Specs, Kanban orchestration, and MCP/ACP/ A2A support across web and desktop.

项目地址:https://gitcode.com/gh_mirrors/ro/routa
点击查看免费下载

Routa 是一个 Workspace-first 的 AI 多智能体开发平台,它同时提供Web 端(Next.js)和桌面端(Tauri + Rust)两种运行形态。两种形态、两套后端,却必须对用户呈现完全一致的行为——靠什么保证?答案就在仓库根目录的那份 api-contract.yaml:一份 OpenAPI 3.1 契约文件,定义了 158 个 API 端点,是 Web 与桌面端 API 的单一事实来源(Single Source of Truth)。

这篇文章带你走一遍 Routa API 契约的实战流程:契约长什么样、如何自动验证双端一致性、以及新增接口时的标准动作。

为什么"双后端 API 一致性"这么难

想象一下:同一个看板界面,在浏览器里由 Next.js 服务(端口 3000)驱动,在桌面客户端里由 Rust/Axum 服务(端口 3210)驱动。

如果没有契约约束,时间一长两边必然"漂移":

  • Web 端加了PATCH /api/workspaces/{id},桌面端忘了同步,桌面用户更新工作区标题就 404
  • 两端返回的字段名不一致(一个叫taskId,一个叫task_id),前端组件时好时坏
  • 错误码一个返回 400、一个返回 500,用户看到的报错信息对不上

Routa 的解法写在架构决策记录 ADR-0001 双后端语义对等 中:Web 与桌面是一个产品的两个运行时形态,必须共享同一套领域词汇(workspace、session、task、kanban board),并暴露由api-contract.yaml统一治理的 API 形状。

api-contract.yaml 长什么样:契约的核心结构

打开 api-contract.yaml,头部声明就说明了它的地位:

Single source of truth for the Routa.js dual-backend API. Both the Next.js backend (src/app/api/) and the Rust backend (crates/routa-server/) MUST implement all endpoints defined here.

契约声明了两个服务地址(api-contract.yaml):

servers: - url: http://localhost:3000 description: Next.js backend (dev) - url: http://localhost:3210 description: Rust backend (desktop)

共享的领域枚举:两端"说同一种语言"

契约的components.schemas部分定义了共享数据模型。比如任务状态(api-contract.yaml):

TaskStatus: type: string enum: [PENDING, IN_PROGRESS, REVIEW_REQUIRED, COMPLETED, NEEDS_FIX, BLOCKED, CANCELLED]

无论 Next.js 还是 Rust,返回的任务状态都必须是这 7 个值之一。前端只需实现一次状态渲染,两端通用。

端点定义:路径、参数、响应一个不落

以健康检查为例(api-contract.yaml):

/api/health: get: operationId: getHealth responses: "200": schema: type: object required: [status, timestamp]

再看创建智能体(api-contract.yaml)——请求体明确要求name和role,role必须引用共享的AgentRole枚举(ROUTA / CRAFTER / GATE / DEVELOPER),成功返回201并包含agentId与agent对象。契约把"入参要求什么、成功返回什么、失败返回什么"全部写死,两个后端照着实现即可。

整个契约共覆盖 158 个端点,横跨 agents、tasks、kanban、notes、workspaces、sessions、shared-sessions、ACP、MCP、A2A、git、github、codebases 等模块,你可以直接通读 api-contract.yaml 的paths部分。

契约如何"自动守门":3 层验证命令

写契约只是第一步,Routa 的关键设计是:契约不是摆设,它被自动化验证反复执行。

第 1 层:静态 Schema 校验(不需要启动服务)

npm run api:schema:validate

对应脚本 validate-openapi-schema.ts 会做 7 项静态检查:所有$ref能否解析、operationId是否唯一、响应 Schema 能否被 AJV 编译、枚举是否非空等等。契约文件本身写得对不对,这一步就能拦住。

第 2 层:三端路由对账(Parity Check)

npm run api:check

这是最有意思的一步。check-api-parity.ts 会从三个来源提取路由清单并逐一比对:

  1. api-contract.yaml中声明的端点
  2. Next.js 文件系统路由:扫描src/app/api/下的route.ts(src/app/api/ 共 245 个文件)
  3. Rust 路由:扫描crates/routa-server/src/api/(crates/routa-server/src/api/)下的.rs文件

任何一端缺失契约里定义的端点,或私自带了一个契约里没有的端点,都会被精确报出——"契约里有、Rust 里没有"和"Next.js 多写了一个"是两种不同的漂移,都会失败。

第 3 层:行为测试(同一套测试打两个后端)

前两层是静态的,第三层是真枪实弹。tests/api-contract/run.ts 实现了一套与后端无关的测试套件,覆盖 workspaces、agents、tasks、notes、sessions、skills、schema-validation 七大场景:

npm run api:test:nextjs # 打到 http://localhost:3000 npm run api:test:rust # 打到 http://localhost:3210

同一套断言、两个 BASE_URL。如果 Rust 端的行为和 Next.js 端出现任何偏差(响应结构、状态码、负向路径的报错),测试就会在其中一个后端上失败。其中 test-schema-validation.ts 更进一步:对真实响应用契约里声明的 JSON Schema 做逐字段校验,覆盖 create → read → delete 全链路。

验证命令验证什么需要启动服务
npm run api:schema:validate契约文件自身合法性❌
npm run api:check契约 vs Next.js vs Rust 路由一致性❌
npm run api:test:nextjs/api:test:rust双端真实行为对等✅

新增一个 API 端点:4 步标准流程

Routa 遵循**契约优先(Contract First)**原则:先改契约,再写代码。docs/fitness/api-contract.md 中规定的新端点流程:

  1. 📝 在 api-contract.yaml 中定义端点(路径、方法、参数、请求/响应 Schema)
  2. 🟦 在 Next.js 中实现:src/app/api/下新建路由
  3. 🦀 在 Rust 中实现:crates/routa-server/src/api/下新增对应 handler
  4. ✅ 运行npm run api:check验证一致性,并在 rust-api-test.md 端点矩阵中登记测试条目

修改现有端点更严格:必须先评估是否为breaking change,若是,则需要版本化或废弃旧端点、提供迁移文档、并在 PR 中明确标注——契约原则里写着"Breaking Changes 禁止:除非有迁移计划"(docs/fitness/api-contract.md)。

契约被破坏时会发生什么:Fitness 门禁自动拦截

Routa 把 API 契约检查纳入了 fitness(工程适应度)体系,作为硬门禁(hard gate):

  • docs/fitness/api-contract.md:openapi_schema_valid与api_parity_check两个指标均为hard_gate: true,通过阈值 100 分——也就是说,Schema 校验或路由对账任何一处不过,整个检查直接失败
  • docs/fitness/rust-api-test.md:api_contract维度权重 10,除npm run api:check外还挂了 Rust 侧的端到端测试cargo test -p routa-server --test rust_api_end_to_end,并按"端点 × 方法 × 成功/负向/回归路径"三层逐条登记 VERIFIED 证据

换句话说:没有契约覆盖的 API 进不了主干。CI 里api:schema:validate+api:check两道闸门跑不过,代码就无法合并。

动手看看:克隆仓库跑一遍

git clone https://gitcode.com/gh_mirrors/ro/routa cd routa npm install npm run api:schema:validate # 静态校验契约 npm run api:check # 三端路由对账

前两条命令无需启动任何服务,几秒钟就能看到契约与两个后端的对账结果。想体验行为层测试,再分别启动 Next.js(npm run dev)或 Rust(cargo run -p routa-server),执行对应的npm run api:test:*即可。

小结:3 个值得借鉴的设计

  • 单一事实来源:158 个端点全部声明在 api-contract.yaml 中,两个后端是"契约的实现者",不是"契约的作者"
  • 分层验证:静态 Schema → 路由对账 → 行为测试,成本递增、可信度递增,且前两层零依赖即可运行
  • 门禁化:契约检查不是"建议",而是 fitness 体系里的硬门槛,破坏契约的代码过不了 CI

对多形态产品(Web / 桌面 / CLI)来说,API 契约文件 + 自动化对账,是把"永远保持一致"从一句口号变成一条npm run api:check命令的最实际路径。

【免费下载链接】routa

Workspace-first multi-agent coordination platform for AI development, with shared Specs, Kanban orchestration, and MCP/ACP/ A2A support across web and desktop.

项目地址:https://gitcode.com/gh_mirrors/ro/routa
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询