{
  "filename": "app/orders/actions.ts",
  "rule": "- name: action-write-authorization\n  where: \"app/orders/actions.ts\"\n  ensure: >-\n    cancelOrder must obtain a verified actor and constrain updateMany by that actor tenantId and ownerId before mutating the order.",
  "corrected": "\"use server\";\nimport { revalidatePath } from \"next/cache\";\nimport { requireActor } from \"@/lib/auth\";\nimport { prisma } from \"@/lib/db\";\n\nexport async function cancelOrder(orderId: string) {\n  const actor = await requireActor();\n  const result = await prisma.order.updateMany({\n    where: { id: orderId, tenantId: actor.tenantId,\n             ownerId: actor.id, status: \"pending\" },\n    data: { status: \"cancelled\" },\n  });\n  if (result.count !== 1) throw new Error(\"Order not available\");\n  revalidatePath(\"/orders\");\n  return { status: \"cancelled\" };\n}\n",
  "broken": "\"use server\";\nimport { revalidatePath } from \"next/cache\";\nimport { requireActor } from \"@/lib/auth\";\nimport { prisma } from \"@/lib/db\";\n\nexport async function cancelOrder(orderId: string) {\n  const actor = await requireActor();\n  const result = await prisma.order.updateMany({\n    where: { id: orderId, ownerId: actor.id, status: \"pending\" },\n    data: { status: \"cancelled\" },\n  });\n  if (result.count !== 1) throw new Error(\"Order not available\");\n  revalidatePath(\"/orders\");\n  return { status: \"cancelled\" };\n}\n",
  "regression": [
    "tenantId: actor.tenantId,\n             ",
    ""
  ],
  "test_scenarios": [
    [
      "Owned pending order",
      "One row changes and path revalidation runs"
    ],
    [
      "Signed-out invocation",
      "requireActor rejects before the query"
    ],
    [
      "Cross-tenant or cross-owner id",
      "Zero updates, action throws"
    ],
    [
      "Two invocations for one pending order",
      "At most one conditional update succeeds"
    ]
  ],
  "test_source": null,
  "test_command": "npx vitest run tests/cancel-order.test.ts"
}