Test the tripwire refusal's rollback and unwrapped-error guarantee - #1546
Conversation
…antee Closes #1209. A refusal mid-write (UnmarkedQueryError, raised by originTripwire in beforeCompile) now has a test proving it rolls back the write's implicit transaction and reaches the caller unwrapped, checked by prototype identity rather than message matching. Verified falsifiable against both the pre-#1205 no-transaction regression and a hypothetical error-wrapping regression in normalizeDatabaseError. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LFqWbBhZwZyqBUzLmvbcgs
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
🦋 Changeset detectedLatest commit: 910fb36 The changes in this PR will be included in the next version bump. This PR includes changesets to release 9 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Deployment failed for project stack-docs with the following error: Learn More: https://vercel.com/open-saas?upgradeToPro=build-rate-limit |
Code review —
|
- Assert failure is an Error before checking its prototype, so a tripwire
regression fails cleanly instead of crashing on
Object.getPrototypeOf(undefined).
- Extract writeAuditRow(context, note, { marked }) so the marked and
unmarked raw-write tests share one helper instead of two near-identical
copies.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LFqWbBhZwZyqBUzLmvbcgs
|
Thanks for the review — both findings addressed in 910fb36:
Generated by Claude Code |
|
The Generated by Claude Code |
Coverage Report for Core Package Coverage (./packages/core)
File CoverageNo changed files found. |
Coverage Report for UI Package Coverage (./packages/ui)
File CoverageNo changed files found. |
Coverage Report for CLI Package Coverage (./packages/cli)
File CoverageNo changed files found. |
Coverage Report for Auth Package Coverage (./packages/auth)
File CoverageNo changed files found. |
Coverage Report for Storage Package Coverage (./packages/storage)
File CoverageNo changed files found. |
Coverage Report for RAG Package Coverage (./packages/rag)
File CoverageNo changed files found. |
Coverage Report for Storage S3 Package Coverage (./packages/storage-s3)
File CoverageNo changed files found. |
Coverage Report for Storage Vercel Package Coverage (./packages/storage-vercel)
File CoverageNo changed files found. |
Summary
packages/core/src/context/write-transaction.test.tsproving that a tripwire refusal (UnmarkedQueryError, raised byoriginTripwireinbeforeCompile) mid-write rolls back the write's implicit transaction and reaches the caller unwrapped.afterOperationhook issue a raw statement directly againstcontext.ormHandlewithout entering an origin scope (nowithOriginwrap) — hooks run outside the engine's origin scope by construction (ADR-0059), so an unmarked statement issued from one is exactly what the tripwire is designed to refuse.Object.getPrototypeOf(failure) === UnmarkedQueryError.prototype(prototype identity, not message matching, per the issue's acceptance criteria) and that the error is not aDatabaseError(i.e., not re-classified/wrapped bynormalizeDatabaseError).JobandAudittables are left empty, proving the whole write (not just the refused statement) rolled back.Why this test design
Since
context.dbwrites now open a real implicit transaction (#1205), and the tripwire fires on any statement compiled with no origin in scope (ADR-0059), the cleanest way to reproduce "the second of several statements is refused by the tripwire" without fabricating middleware internals is to have a hook perform a second, real statement through the raw ORM handle with no origin entered — the same technique the existing"a hook's own write through ormHandle rolls back with the write"test uses, but omitting thewithOriginwrap that test relies on to avoid the refusal.I verified the test is falsifiable against both regressions it guards:
runInTransactionto skip opening a transaction (simulating the pre-Every write on prisma-8 runs without a transaction: the rollback probe tests the Prisma 7 $transaction name #1205 defect) makes the rollback assertion fail (rows survive).normalizeDatabaseErrorunconditionally wrap errors makes the prototype-identity assertion fail (the error is no longerUnmarkedQueryError).Both were confirmed locally, then reverted before committing.
Test plan
a tripwire refusal mid-write rolls back and reaches the caller unwrappedpnpm --filter @opensaas/stack-core test— 1758 passed, 7 skipped (no regressions)pnpm lintpassespnpm format/pnpm manypkg fix— no changes needed beyond the new files@opensaas/stack-core, patch)Closes #1209
🤖 Generated with Claude Code
https://claude.ai/code/session_01LFqWbBhZwZyqBUzLmvbcgs
Generated by Claude Code