Skip to content

Commit cc73b80

Browse files
committed
chore(changeset): the OS_ARTIFACT_URL gate keeps warn-and-boot on a Turso remote primary
The maintainer's ruling on the contract review: say plainly that the boot migration gate does not judge a remote database. It warns and boots, applies nothing and refuses nothing, and decides that from the driver's declared driftReportCaveat. It stays that way until the remote sync honours storage.notNull and os migrate apply has a remedy on that transport. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lr3rg6qTp9r38exA5DHEEH
1 parent 040fbcc commit cc73b80

1 file changed

Lines changed: 4 additions & 1 deletion

File tree

‎.changeset/23816-turso-remote-ownership-ceremony.md‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@ Clause-②: yes (widening)
1313
- **`@objectstack/driver-turso`**, remote face:
1414
- `detectManagedDrift()` answers instead of refusing with `NOT_IMPLEMENTED` / 501. The verdict is the shared differ's, the one the local face runs; the physical schema it diffs is read from the remote catalog (`pragma_table_info`, `sqlite_master`, `pragma_index_list` / `pragma_index_info`, and the ADR-0120 D4 duplicate probe). The declarations it diffs against are recorded by every remote schema door and by the DDL-free `registerObjectMetadata`, so a boot that skipped schema sync is covered too.
1515
- `applyMigrationEntries()` applies `drop_index`, `create_index`, `recreate_index`, `replace_unique_index` and `drop_column` instead of refusing. Each entry runs as one libSQL `write` batch, so it lands whole or not at all: a `drop_column` drops the column's indexes with it in the same transaction, and a re-created index that fails to build leaves the old one in place. An entry is reported `applied` only once a read-back shows its target state. Every other column entry (nullability, width, a dropped DEFAULT) needs the SQLite table rebuild, which this transport does not run, so it is reported `skipped` and logged, as the in-place dialects report an op they cannot perform.
16+
- The remote face declares `driftReportCaveat`: a sentence saying its drift report is for reading only and naming the reason. The OS_ARTIFACT_URL boot gate reads it (below). The local and embedded-replica faces declare `null`.
1617
- The remote driver's `config` now carries its `url`, so the CLI labels a remote database by its URL (credential-free) instead of `better-sqlite3`. The ceremony writes that label into its plan and refuses an apply whose plan names another database; that refusal can now tell two remote databases apart.
1718
- **`@objectstack/cli`**: the ceremony's plan and apply boots skip schema sync, instead of arming deferred DDL, when the primary datasource is a Turso remote one. No DDL is attempted, so the plan stays read-only, and every other datasource the boot connects is still deferred. The environment's own boot has already run the additive sync the ceremony reads. Every other `os migrate` command keeps refusing on that transport: their dry runs list held-back schema work, which a boot that holds nothing back cannot list.
1819
- **`@objectstack/runtime`**: `createStandaloneStack` takes `skipSchemaSync`, passed to `ObjectQLPlugin` as the option `OS_SKIP_SCHEMA_SYNC=1` names. Unset, the plugin reads the variable as before.
1920

20-
One behaviour change outside the ceremony: on an `os serve` boot pinned with `OS_ARTIFACT_URL`, the boot's migration gate now judges a Turso remote database as it judges every other one. It applies safe drift and refuses the boot on destructive drift. Until now it printed that it could not check the schema and booted.
21+
On a Turso remote primary, the `OS_ARTIFACT_URL` boot migration gate on `os serve` keeps its earlier answer: cannot judge, warn and boot. It applies no drift and refuses no boot. Only its warning's wording changes, from `Could not check the physical schema` to `Did not check the physical schema against the artifact: …`, followed by the driver's reason. The gate now decides this from a capability the driver declares (`driftReportCaveat`, a string on the remote face and `null` on the local and embedded-replica faces), not from a refusal it catches. Two follow-ups have to land before that gate may act on a remote report:
22+
- the remote transport's schema sync honours `storage.notNull`, so the report stops naming a tightening its own sync produced;
23+
- `os migrate apply` gains a remedy on that transport for the destructive drift the gate would refuse on.

0 commit comments

Comments
 (0)