|
| 1 | +--- |
| 2 | +'@objectstack/objectql': patch |
| 3 | +'@objectstack/platform-objects': minor |
| 4 | +'@objectstack/metadata-protocol': minor |
| 5 | +--- |
| 6 | + |
| 7 | +fix(objectql,platform-objects,metadata-protocol)!: the platform's `sys_migration` primary-key lookups go through `findOne`, so an existing deployment no longer prints "Paged read of 'sys_migration' is NOT deterministic" on every boot and every `os migrate plan` (#20648) |
| 8 | + |
| 9 | +Clause-②: no (narrowing) |
| 10 | + |
| 11 | +<!-- adr-0087: not-required (runtime-interface-only packages/platform-objects/src/system/migration-flag.ts#MigrationFlagEngine, packages/metadata-protocol/src/migrations/seed-tenancy-backfill.ts#SeedTenancyLedger) two duck-typed engine interfaces, each the parameter type of a published helper, whose one read method moves from `find` to `findOne`. Neither is a Zod schema, a `packages/spec` declaration or an object definition, neither is a projection of a schema, and no metadata surface references either, so `objectstack migrate meta` has nothing to rewrite. The body carries no migration prescription. The only party affected is the TypeScript author of a hand-written stand-in, and that author's fix is carried by the compiler at their own call site, which names the missing `findOne`. The other categories are closed on facts: both packages publish (not `unpublished`); no ADR-0087 id covers an engine interface's method set, and this diff adds none (not `registered` / `already-registered`); and both interfaces were concretely typed at the merge base, not erased (not `type-surface-only`). This category, not the broader `no-migration-prescription`, because the positive reading it verifies is available here: the named symbols have no metadata surface. --> |
| 12 | + |
| 13 | +The deployment ledger is read one row at a time, by primary key. Five readers |
| 14 | +spelled that read as `find(sys_migration, { where: { id }, limit: 1 })`: the |
| 15 | +engine's migration-gate read (`readMigrationFlagVerified`, behind |
| 16 | +`haveFileColumnsMoved`, `isFileReferencesMigrationVerified` and |
| 17 | +`isValueShapesMigrationVerified`), the engine's deviation marker and |
| 18 | +creation-attestation revocation, `readDataMigrationFlag` in |
| 19 | +`@objectstack/platform-objects/system`, and the seed-tenancy repair's receipt. |
| 20 | +The SQL driver cannot tell that read from page one of a walk. The engine's gate |
| 21 | +read runs at boot before the schema pass registers `sys_migration` with the |
| 22 | +driver, and on a table the driver has not registered an unsorted paged read |
| 23 | +warns that its pages may repeat or skip rows. Measured on a SQLite database |
| 24 | +created by 17.4.0: every 17.5.0 boot and every `os migrate plan` printed that |
| 25 | +warning once, for a lookup that cannot return two rows. All five readers now use |
| 26 | +`findOne`, the single-row route the driver already exempts. The driver's check is |
| 27 | +unchanged: an unsorted `limit` read on a table the driver did not create still |
| 28 | +warns. |
| 29 | + |
| 30 | +**BREAKING**: this narrows what two published engine interfaces accept. The |
| 31 | +first is `MigrationFlagEngine` in `@objectstack/platform-objects/system`. It is |
| 32 | +the parameter type of `readDataMigrationFlag`, `isDataMigrationVerified`, |
| 33 | +`mayActIrreversibly`, `recordDataMigrationRun`, `recordFileColumnMove` and |
| 34 | +`attestFreshDatastore`, and part of `FilesToReferencesEngine` in |
| 35 | +`@objectstack/service-storage`. The second is `SeedTenancyLedger` in |
| 36 | +`@objectstack/metadata-protocol`, the type of a `SeedTenancySeam`'s `ledger`. |
| 37 | +Each now requires `findOne` where it required `find`, so a hand-written stand-in |
| 38 | +that provides only `find` no longer satisfies either type. It ships as `minor` |
| 39 | +under the launch-window convention for accept-set narrowings. The ObjectQL engine |
| 40 | +has both methods, so a host that passes the engine needs no change. |
| 41 | + |
| 42 | +**Your fix:** a stand-in that implemented `find` for these helpers implements |
| 43 | +`findOne(object, options)` instead, answering the row whose `where.id` matches, |
| 44 | +or `null`. |
| 45 | + |
| 46 | +At run time, a stand-in that still provides only `find` fails the read. |
| 47 | +`readDataMigrationFlag` then answers `null`, the same answer as a missing row, so |
| 48 | +the gates it feeds stay closed. `resolveSeedTenancySeam` now attaches a `ledger` |
| 49 | +only for a host that has `getObject`, `findOne`, `insert` and `update`. For a |
| 50 | +find-only host the seam's `ledger` is `undefined`, and when the seed-tenancy |
| 51 | +repair applies, it says at `warn` that it could not record its receipt. |
0 commit comments