Repository navigation
Commit f32d795
test(driver-sql): pin the NODE_ENV=production auto-migrate guard with a safe drift, beside a dev control (#24967)
Fixes #24903
Clause-②: no (test only: no product code, accept set or served shape
moves)
## What changed
One case in
`packages/drivers/driver-sql/src/sql-driver-schema-drift.test.ts` is
re-staged, and a development control is added beside it. Test only: no
product file moves.
- **Before:** "is force-disabled under NODE_ENV=production (warns, does
not alter)" staged `relax_not_null`. ADR-0113 made that `needs_confirm`,
and `reconcileAndWarnDrift` (`sql-driver.ts`) applies only `d.category
=== 'safe'`. So the column stayed NOT NULL with or without the
production guard, and the case asserted no warning.
- **After:** the case stages a `safe` drift: a `current_user` runtime
token written as the column DEFAULT by a pre-#4560 build, which
`detectManagedDrift` classes `drop_column_default` / `safe`. Under
`NODE_ENV=production` with `autoMigrate: 'safe'` it asserts:
- the DEFAULT is still on the column (`columnInfo().owner.defaultValue`
still carries `current_user`);
- the drift is still reported as `safe` / `drop_column_default`, so the
guard is the only thing that held it back;
- `logger.warn` received `[schema-drift] autoMigrate='safe' is ignored
under NODE_ENV=production`, matched on that stable prefix. The em-dash
tail is left unpinned.
- **Control:** "applies the safe drop_column_default drift outside
production (control for the guard below)". It is the same table and the
same boot with `NODE_ENV=development`. The DEFAULT is removed,
`detectManagedDrift()` answers `[]`, and no production warning is
logged. The pair cannot pass vacuously again.
- `NODE_ENV` is restored in `finally` in both cases. The logger is a
per-driver `vi.fn()` object (the file's own `makeDriver`), so no global
spy is left to restore.
## Why `drop_column_default`
The `safe` ops `detectManagedDrift` emits on `main` (`schema-drift.ts`)
are `drop_column_default`, `widen_varchar`, `replace_unique_index` and
`create_index`.
- `widen_varchar` is gated on `enforcesVarcharLength` (postgres / mysql
only), so it never fires on this file's SQLite driver.
- `create_index`: `syncTableIndexes` creates a missing declared index
additively during `initObjects`, whatever `autoMigrate` says. The guard
would not be the only reason it is absent.
- `replace_unique_index` works, but it needs a tenant-scoped unique
field, an organization column and an index read-back. It is already the
stage of `sql-driver-index-drift.test.ts`'s production case. PR #24893
is also rewriting the NULL-safe key part it compares.
- `drop_column_default` needs one column and one read-back, and stays in
this file's `biz_unit` fixture idiom. The SQLite rebuild path applies it
(`sql-driver-runtime-token-default.test.ts` measures that).
**PR #24893** (draft) edits `schema-drift.ts`. Its patch changes no
`category:` line, and it does not touch the runtime-token default
branch. It does not change which ops are `safe`.
## The guard, as read
`reconcileAndWarnDrift`: `autoOn = this.autoMigrate === 'safe' &&
this.schemaMode === 'managed'`, then `if (autoOn &&
this.isProductionEnv())`. `isProductionEnv()` is `(process.env.NODE_ENV
?? '').toLowerCase() === 'production'`, so the check is case-insensitive
and reads nothing else. The warning goes out once per drifting table
through `this.logger.warn`, not `console.warn`. The case spies on that
logger.
## Verification (head `41b3fdf86`, `origin/main` merged at `19e5338cc`)
- **Target file:** `pnpm --filter @objectstack/driver-sql exec vitest
run --maxWorkers=2 src/sql-driver-schema-drift.test.ts`: 15 passed (was
14).
- **Ablation:** `node scripts/ablation-replace.mjs --file
packages/drivers/driver-sql/src/sql-driver.ts --anchor 'if (autoOn &&
this.isProductionEnv()) {' --replacement 'if (false /* ABLATED-24903 */)
{' -- vitest run` on that file.
- Anchor hit x1 to x0, and the replacement landed x0 to x1. Blob
`b4393f25d41b` became `98a32996463a`.
- The production case went red: `AssertionError: expected 'null' to
contain 'current_user'`. The control stayed green: 1 failed / 14 passed.
- Restored: blob after restore = blob at HEAD = `b4393f25d41b`, and `git
diff HEAD` is empty.
- The test imports `SqlDriver` from `../src/index.js`, so no `dist/`
rebuild sits between the mutation and the run.
- **Package checks:** `pnpm --filter @objectstack/driver-sql typecheck`
exit 0, run before and after the merge. `tsc --listFiles` includes this
test file.
- **Full suite:** `pnpm --filter @objectstack/driver-sql test` exit 0
before and after the merge: 225 files passed and 12 skipped (the
live-dialect suites), 3692 tests passed.
- **Repo project:** `pnpm --filter @objectstack/core test:repo` exit 0:
6 files, 82 tests.
- **Derived gates:** `node scripts/pm/dispatch-gates.mjs --commands
--repo objectstack-ai/objectstack` gives 54 commands. All 54 were re-run
on the final head with exit codes captured before any pipe: 54 of 54
exit 0 (26 direct node, 28 pnpm).
- `check:dual-build-cjs-loads` and `check:lean-entry-closure` first
exited 3 (PREREQUISITE NOT MET). They were re-run after `pnpm build`
(76/76 tasks) and exited 0.
- `--ran` reconciliation: 54 derived, 54 run, 0 NOT-MEASURED (a derived
zero).
- **Changeset:** none. The test file is outside
`@objectstack/driver-sql`'s `files[]` (`dist`, `README.md`,
`CHANGELOG.md`). The built `dist/` has zero hits for the test file name,
and the positive control (the warning text) hits `dist/index.js`.
`skip-changeset` is declared in the same create.
## Acceptance notes
- **Pin sweep:** the warning text and the guard were swept across every
package, `qa/`, `docs/qa/platform-checklist/` and `content/docs/`.
- The only other pin of the driver-level guard is
`sql-driver-index-drift.test.ts`, "is force-disabled under
NODE_ENV=production — the index survives untouched". It stages
`replace_unique_index` (`safe`) beside a dev self-heal sibling, so it is
**not** vacuous. It does not assert the warning. Noted, not built.
- The CLI / runtime pins (`dev-self-heal-host-parity`,
`runtime/src/dev-auto-migrate`, `dev-standalone-self-heal`) pin a
different layer: the host does not pass `autoMigrate` in production.
They do not pin this driver branch.
- `docs/qa/platform-checklist/areas/cli.json` names the warning in a
live-boot step and carries this case as `knownGaps`. Re-adding the case
to `cli.dev-automigrate-policy`'s `automated.ref` is `domain:devx`'s,
and is not touched here.
- Built by the `os-dev` agent for `domain:engine` seat 1, under claim
6297759904 on #24903.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---
_Generated by [Claude
Code](https://claude.ai/code/session_01XrcLWFkToZjHv2DJDAHhz4)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 6440cf1 commit f32d795
1 file changed
Lines changed: 46 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
199 | 199 | | |
200 | 200 | | |
201 | 201 | | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
202 | 237 | | |
203 | 238 | | |
204 | 239 | | |
205 | 240 | | |
206 | 241 | | |
207 | | - | |
208 | | - | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
209 | 246 | | |
210 | | - | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
211 | 254 | | |
212 | 255 | | |
213 | 256 | | |
| |||
0 commit comments