用途
convex-verify 用于证明一个已构建的 Convex 功能确实按预期工作,而不仅仅是「代码能通过类型检查」。类型检查只能说明代码可解析,却无法证明非属主会被拒绝、查询返回了正确的行、或 mutation 产生了声称的效果。该技能通过「seed → drive → assert」的循环来弥补这一缺口,在进程内使用 convex-test 运行,因此无需部署。其最高价值的断言是那些「负向」断言——即本应被拒绝的调用者确实被拒绝——因为这类授权缺陷正是真实项目中最常见的一类 bug,也是 happy-path 演示永远无法捕捉到的。
主要能力
-
识别待证功能:明确用户刚构建/修改的具体导出 query/mutation/action 及其预期行为——谁应被允许、应返回什么数据、mutation 应改变什么。若意图未说明,会提出一个聚焦的问题而不是猜测契约。
-
设置 convex-test:确保 convex-test 与 vitest 为开发依赖,并确保 vitest.config.ts 设置了 test.environment: "edge-runtime" 和 server.deps.inline: ["convex-test"]。若缺少该配置,convexTest(schema) 会在运行时以 import.meta.glob is not a function 失败(已验证)。同时需安装 @edge-runtime/vm。配置后 convexTest(schema) 会提供 t 句柄。若项目已有测试设置,会复用而非另起分支。
-
播种数据:尽可能通过应用自身的函数播种真实数据,使播种过程经过与真实用户相同的校验器/mutation;对于公共 API 无法创建的固定数据,回退到 t.run(async (ctx) => ctx.db.insert(...))。至少播种调用者自己的行和第二个用户的行,以便测试跨用户访问。
-
多身份驱动:使用 t.withIdentity({ subject, tokenIdentifier, ... }) 以不同身份调用功能,包括 (a) 合法属主、(b) 不同的已认证用户、(c) 未认证用户(无身份的 t)。使用应用认证所用的真实身份结构(subject/tokenIdentifier)。
-
断言行为(正向与负向):
- 正向:属主获得预期行/mutation 产生预期变更。
- 负向(关键部分):不同用户调用同一函数应被拒绝,未认证调用者在需要认证处应被拒绝。只有「错误调用者被阻止」时功能才算被证明。
- 数据作用域:列表/查询只返回调用者自己的行,绝不返回第二个用户的行。
-
运行并报告:运行 npx vitest run,报告已证明的内容(每个通过的正向与负向断言),并特别报告任何失败的断言,因为失败的负向断言意味着上线前发现了一个真实的授权漏洞。对未按预期行为的情况,会在总线上发出发现项(规格 finding.schema.json,类别 authz/correctness,证据类型 probe-result,附带确切的失败调用)。
使用方式
- 该技能驱动的是某个具体已构建的功能;若请求是「一般性地搭建测试框架」,则应使用测试类能力。
- 需要确保 vitest.config.ts 已配置 environment 'edge-runtime' 并将 convex-test 内联,否则 convex-test 无法运行。
- 运行命令为 npx vitest run。
适用场景
适用于刚构建或修改了 Convex 的 query/mutation/action,并希望证明其行为正确(包括授权边界与数据作用域)的场景。尤其适合需要验证跨用户访问控制和负向授权路径的情况。
限制与规则
- 证明行为而非编译:每次验证至少包含一个负向断言,仅 happy path 不构成证明。
- 必须使用应用真实的 subject/tokenIdentifier 结构,以属主、其他用户、未认证三种身份驱动。
- 必须播种调用者与第二个用户双方的数据,跨用户访问与数据作用域才可测。
- 必须有正确配置的 vitest.config.ts(environment 'edge-runtime',convex-test 内联),不能只写测试文件。
- 使用 convex-test 进程内运行,无需部署;复用测试类能力的设置而不是另起分支。
- 绝不为了通过而弱化断言:失败的负向测试是真实缺陷,应交给 convex-authz/convex-expert 修复,而不是改测试直到变绿。
- 对任何失败的断言发出总线发现项(authz/correctness,证据为失败的探测调用),以便复合流程或自愈机制接手。
其他信息如具体版本、收费、价格、平台等暂未提供。