mcpField
C
convex-verify

convex-verify

github.com/get-convexテスト・品質6931.1k 回インストール1 日前に更新
リポジトリ

convex-verify について

convex-verifyは、Convexの機能を検証する開発者向けのテストスキルです。convex-testをプロセス内で使って複数のユーザーIDから実行し、デプロイせずに認可とデータ範囲を確認します。

主な機能

  1. 01convex-testによるプロセス内テスト
  2. 02複数のIDで関数を実行
  3. 03許可・拒否の動作を検証
  4. 04ユーザー間のデータ範囲を確認
  5. 05テストを実行して失敗を報告

活用シーン

  1. 01クエリが呼び出し元のデータだけを返すか検証
  2. 02他ユーザーによる制限対象の変更を確認
  3. 03デプロイ前に機能をテスト

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/get-convex/agent-skills --skill convex-verify

インストール後、Claude Code で/convex-verifyを入力して読み込まれたか確認します。

詳細

機能が動作することを証明する — シード、実行、アサート

型チェックが成功しても、コードが解析できることしか証明されません。所有者以外のユーザーが実際に拒否されること、クエリが正しい行を返すこと、ミューテーションが期待どおりの効果をもたらすことは証明されません。この機能は、フィールド全体で欠けているループ、つまりシード → 実行 → アサートによって、その隔たりを埋めます。convex-test を使ってプロセス内で実行するため、デプロイは不要です。最も価値の高いアサーションは NEGATIVE(拒否されるべき呼び出し元)です。30 アプリのコーパスが示すとおり、これらは実際に最も多いバグである認可の欠陥そのものであり、ハッピーパスのデモでは決して見つかりません。

ワークフロー

  1. 証明する機能を特定します。ユーザーが作成または変更した、具体的なエクスポート済みクエリ/ミューテーション/アクション(または少数のセット)と、その意図された動作(誰に許可されるべきか、どのデータが返されるべきか、ミューテーションで何が変更されるべきか)です。意図が示されていない場合は、契約を推測するのではなく、要点を絞って質問を 1 つしてください。
  2. 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 機能と組み合わせます)。
  3. 可能であればアプリ独自の関数を通じて現実的なデータをシードします(そうすることで、シードでも実際のユーザーと同じバリデーター/ミューテーションを利用できます)。公開 API では作成できないフィクスチャについては、t.run(async (ctx) => ctx.db.insert(...)) を使用します。少なくとも、呼び出し元自身の行と別のユーザーの行をシードし、ユーザー間のアクセスをテストできるようにします。
  4. t.withIdentity({ subject, tokenIdentifier, ... }) を使い、異なる ID として機能を実行します。関数を(a)正当な所有者、(b)別の認証済みユーザー、(c)未認証ユーザー(ID なしの t)として呼び出します。所有権の解決方法に合わせ、アプリの認証で使用されている実際の ID 形式(subject/tokenIdentifier)を使います。
  5. 動作を POSITIVE と NEGATIVE の両方でアサートします。
    • positive:所有者が期待される行を取得する、またはミューテーションが期待される変更を行うこと(expect(await t.withIdentity(owner).query(api.x.y, args)).toEqual(...))。
    • NEGATIVE(最も重要な部分):別のユーザーが同じ関数を呼び出すと拒否されること — await expect(t.withIdentity(other).mutation(api.x.cancel, {id})).rejects.toThrow(/forbidden|not authorized|403/) — また、認証が必要な箇所では未認証の呼び出し元も拒否されること。誤った呼び出し元がブロックされることを確認するまで、機能を証明したことにはなりません。
    • データ範囲:リスト/クエリが呼び出し元自身の行だけを返し、別のユーザーの行を決して返さないこと(別のユーザーの行が含まれないことをアサートします)。
  6. テスト(npx vitest run)を実行し、証明できた内容(成功した各 positive/negative アサーション)と、重要な点として、失敗したアサーションがあれば報告します。失敗した negative アサーションは、リリース前に見つかった実際の認可の穴です。期待どおりに動作しなかったものについては、バスに指摘を送信します(specs/finding.schema.json、class authz/correctness、evidence kind probe-result。失敗した呼び出しを正確に記載)。
  7. テストを通すために弱めてはいけません。所有者のみが使えるクエリが別のユーザーの行を返す場合、修正すべきなのはアサーションではなく関数です(convex-authz に引き継ぎます)。テストを変更してグリーンにしても、何の証明にもなりません。

ルール

  • コンパイルではなく動作を検証してください。すべての検証に、少なくとも1つの否定的アサーションを含めてください(拒否されるべき呼び出しが拒否されること)。成功パスだけでは証明になりません。
  • アプリが実際に使用する subject/tokenIdentifier の形式を使い、t.withIdentity で複数のユーザー(所有者、別のユーザー、未認証)として機能を実行してください。
  • 呼び出し元の行と、別ユーザーの行の両方をシードしてください。これにより、ユーザー間アクセスとデータスコープを実際に検証できます。
  • convex-test の実行には、環境が 'edge-runtime' で convex-test がインライン化された vitest.config.ts が必須です(import.meta.glob が必要とするため)。テストファイルだけでなく、設定ファイルも作成してください。
  • デプロイは不要です。convex-test を使ってプロセス内で実行してください。test 機能のセットアップと組み合わせ、独自に分岐させないでください。
  • アサーションを弱めて合格させないでください。否定的テストの失敗は実際の不具合です。修正を convex-authz/convex-expert に引き継ぎ、テストは合格するまで編集しないでください。
  • アサーションが失敗した場合は、失敗したプローブ呼び出しを証拠として、バスに検出結果(authz/correctness)を送信してください。これにより、複合パスまたはセルフヒーリングで検出結果を利用できます。
  • これは特定の構築済み機能を動作させるためのものです。一般的なテストフレームワークのセットアップ依頼は、通常 test 機能の対象です。

コメント