Skip to content

Skip destructive scope checks for state-only hard deletion migrations - #53

Closed
sskyy wants to merge 1 commit into
mainfrom
codex/state-only-hard-delete-migration-guard
Closed

sskyy wants to merge 1 commit into
mainfrom
codex/state-only-hard-delete-migration-guard

Conversation

@sskyy

@sskyy sskyy commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Summary

The migration scheduler currently requires destructive-scope approval for every hard-deletion computation in the rebuild plan. A state-only plan resets bound state but does not rebuild output, so it cannot delete host rows and should not require that approval. The scheduler now applies the guard only when rebuildOutput is true.

The regression suite covers an empty new host whose _isDeleted_ StateMachine is state-only (rebuildState: true, rebuildOutput: false) and a changed output computation that would delete a stored host row. The first applies without a scope; the second remains rejected without one and preserves the row.

Validation

  • Red first: npx vitest run tests/runtime/stateOnlyHardDeletionMigration.spec.ts failed on the state-only case with the missing-scope guard before the fix.
  • npx vitest run tests/runtime/stateOnlyHardDeletionMigration.spec.ts tests/runtime/migration.spec.ts tests/runtime/migrationDestructiveFuzz.spec.ts passed after the fix.
  • npm run check:all passed.
  • npm run test:runtime passed: 122 files, 1,348 tests; 15 files and 63 tests skipped.
  • npm run test:postgres passed on a disposable PostgreSQL 18 container: 11 files, 53 tests.

@sskyy

sskyy commented Oct 10, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #56, released in v4.11.2.

This PR adds the rebuildOutput check to the MigrationScheduler hard-deletion guard only. The same applicability decision was also made by five other readers: the cascade-aware and analytic scope estimates, the migrate-time check, getRecomputeBlockingChanges, and the execution-time deletion audit. With this change alone, a migration that creates the host table of a HardDeletionProperty still demands an empty destructive-scope approval for changed, and a state-only decision approved with the diff's empty scope is still refused by the migrate-time check (#55).

#56 routes all six readers through one function, getDestructiveScopeRecordName. Its three conditions are: the item rebuilds output, the output can delete records, and the record exists in the source schema. #56 also fixes a scheduler path that the corrected guard would otherwise expose: a state-only decision on a computation without bound state fell through to a full output recompute. The state-only regression from this PR is covered by tests/runtime/migrationDestructiveScopeApplicability.spec.ts and by the hardDeletionStateOnly mutation in migrationDestructiveFuzz.

@sskyy sskyy closed this Oct 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant