关于 convex-verify
convex-verify 是用于通过进程内测试验证 Convex 函数行为的技能,面向检查授权与数据范围的开发者。它特别强调确认无权访问的调用者会被拒绝。
主要功能
- 01为多个用户准备测试数据
- 02以不同身份调用函数
- 03断言正向与拒绝行为
- 04使用 convex-test 和 Vitest 运行测试
- 05将失败探测记录为发现
适用场景
- 01验证所有者能访问预期数据
- 02检查其他用户调用变更函数时会被拒绝
- 03测试查询是否排除其他用户的数据
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ convex/ agent-skills --skill convex-verify安装后在 Claude Code 中输入/convex-verify确认已加载。
详细介绍
验证功能是否有效 — 初始化数据、调用、断言
类型检查通过只能证明代码可以解析;它无法证明非所有者确实会被拒绝、查询返回了正确的行,或变更产生了其声称的效果。此能力通过整个领域都缺少的循环来弥合这一差距:初始化数据 → 调用 → 断言,并使用 convex-test 在进程内运行,无需部署。价值最高的断言是负向断言——针对理应被拒绝的调用者——因为 30 个应用的语料库显示,这类授权缺陷是最常见的真实 Bug,而顺利路径演示永远发现不了它们。
工作流
- 识别要验证的功能:用户刚刚构建或更改的具体导出查询/变更/操作(或少量此类功能),以及预期行为——谁应获准、应返回哪些数据、变更应做出什么改变。如果意图未说明,请针对契约提出一个聚焦的问题,而不要自行猜测。
- 配置
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句柄。如果项目已有测试配置,请复用它(与test` 能力组合使用,不要另起一套)。 - 尽可能通过应用自身的函数初始化真实数据(这样初始化过程也会经过真实用户使用的同一套验证器/变更),对于公开 API 无法创建的测试数据,则改用
t.run(async (ctx) => ctx.db.insert(...))。至少初始化调用者自己的行和另一位用户的行,以便测试跨用户访问。 - 使用
t.withIdentity({ subject, tokenIdentifier, ... }),以不同身份调用该功能:分别以(a)合法所有者、(b)另一位已通过身份验证的用户,以及(c)未经身份验证的身份(不带身份的t)调用函数。使用应用认证所采用的真实身份结构(subject/tokenIdentifier),与所有权的解析方式一致。 - 断言行为——包括正向和负向:
- 正向:所有者获得预期的行,或变更产生了预期的更改(
expect(await t.withIdentity(owner).query(api.x.y, args)).toEqual(...))。 - 负向(关键所在):另一位用户调用同一函数时会被拒绝——
await expect(t.withIdentity(other).mutation(api.x.cancel, {id})).rejects.toThrow(/forbidden|not authorized|403/)——需要身份验证的地方,未经身份验证的调用者也会被拒绝。只有证明错误的调用者会被拦截,功能才算得到验证。 - 数据范围:列表/查询只返回调用者自己的行,绝不返回另一位用户的行(断言另一位用户的行不存在)。
- 正向:所有者获得预期的行,或变更产生了预期的更改(
- 运行测试(
npx vitest run)并报告已验证的内容(每条通过的正向和负向断言),以及——至关重要的——任何失败的断言,因为负向断言失败意味着在发布前发现了真实的授权漏洞。对于任何行为不符的情况,在总线上发出发现报告(specs/finding.schema.json,class authz/correctness,evidence kind probe-result,并附上确切的失败调用)。 - 不要为了让测试通过而弱化测试:如果仅限所有者的查询返回了另一位用户的行,应该修复的是函数(交给 convex-authz),而不是断言。反复修改测试直到通过,毫无证明作用。
规则
- 验证行为,而非编译:每项验证都至少包含一个否定断言(应被拒绝的调用者确实遭到拒绝)——仅有成功路径不足以证明。
- 使用
t.withIdentity,以多个身份(所有者、其他用户、未认证用户)驱动功能,并采用应用实际的 subject/tokenIdentifier 结构。 - 同时为调用者和第二个用户填充数据行,确保确实能够测试跨用户访问和数据范围。
- 必须提供环境为
edge-runtime且内联convex-test的 vitest.config.ts,convex-test才能运行(它需要import.meta.glob);请编写该配置文件,不要只编写测试文件。 - 使用
convex-test在进程内运行——无需部署;与test能力的 setup 组合,而非另行创建。 - 绝不要为了让断言通过而放宽它:失败的否定测试代表真实缺陷 → 将修复工作交给 convex-authz/convex-expert,不要改动测试,直到测试变绿。
- 任何断言失败时,都要发出一条 bus finding(authz/correctness,证据:失败的探测调用),以便组合式通过检查或自动修复流程能够发现。
- 这是在驱动一项具体实现的功能;若请求是一般性地搭建测试框架,通常应使用
test能力。
评论
支持 Markdown