qubu 0.6.2 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/mysql.d.mts +1 -1
  2. package/dist/postgres.d.mts +1 -1
  3. package/docs/dialects-and-execution.md +54 -25
  4. package/docs/getting-started.md +9 -9
  5. package/docs/guides/better-auth.md +16 -5
  6. package/docs/guides/compose-queries.md +21 -9
  7. package/docs/guides/drizzle.md +8 -3
  8. package/docs/guides/extensions/dialects.md +1 -1
  9. package/docs/guides/extensions/overview.md +1 -1
  10. package/docs/guides/extensions/sources-and-clauses.md +7 -3
  11. package/docs/guides/extensions/typed-expressions.md +25 -13
  12. package/docs/guides/extensions/unsafe-syntax.md +10 -6
  13. package/docs/guides/json.md +52 -27
  14. package/docs/guides/mutations.md +15 -6
  15. package/docs/guides/select/conditions.md +18 -11
  16. package/docs/guides/select/grouping-and-windows.md +5 -2
  17. package/docs/guides/select/ordering-and-pagination.md +5 -3
  18. package/docs/guides/select/overview.md +6 -3
  19. package/docs/guides/sql-templates.md +11 -5
  20. package/docs/guides/valtio-sync.md +11 -5
  21. package/docs/guides/vite-plugin.md +2 -2
  22. package/docs/index.md +24 -17
  23. package/docs/migrations/adapters.md +47 -19
  24. package/docs/migrations/artifacts-and-policy.md +49 -20
  25. package/docs/migrations/index.md +15 -8
  26. package/docs/migrations/lotta-adoption.md +16 -5
  27. package/docs/migrations/operations.md +29 -15
  28. package/docs/migrations/recovery.md +34 -17
  29. package/docs/query-model/fragments.md +13 -5
  30. package/docs/query-model/result-shapes.md +2 -2
  31. package/docs/query-model/source-scope.md +5 -3
  32. package/docs/reference/introspection-support.md +26 -19
  33. package/docs/reference/mysql-snapshot.md +19 -4
  34. package/docs/reference/postgres-snapshot.md +17 -4
  35. package/docs/reference/sqlite-snapshot.md +19 -2
  36. package/docs/reference/supported-surface.md +221 -85
  37. package/docs/schema/catalog-model.md +24 -7
  38. package/docs/schema/code-generation.md +40 -21
  39. package/docs/schema/columns-and-writes.md +21 -11
  40. package/docs/schema/constraints-and-indexes.md +12 -5
  41. package/docs/schema/ddl-emission.md +16 -5
  42. package/docs/schema/diff.md +12 -4
  43. package/docs/schema/introspection.md +47 -21
  44. package/docs/schema/migration-plans.md +18 -10
  45. package/docs/schema/snapshots.md +57 -29
  46. package/docs/schema/storage-and-schema-sql.md +10 -4
  47. package/docs/schema/tables-and-names.md +1 -1
  48. package/docs/sql-semantic-types.md +11 -8
  49. package/docs/troubleshooting.md +14 -6
  50. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  # Write mutations
2
2
 
3
- > Build typed `INSERT`, `UPDATE`, and `DELETE` statements from the same table metadata while keeping destructive operations explicit.
3
+ > Insert, update, and delete rows with typed inputs and explicit safeguards.
4
4
 
5
5
  ## Define write-time rules
6
6
 
@@ -121,6 +121,8 @@ const query = update(
121
121
  The assignment expression is source-aware, so a column from an unrelated table
122
122
  cannot silently enter the update.
123
123
 
124
+ ### Update from another source
125
+
124
126
  PostgreSQL updates can introduce one or more typed sources with `updateFrom()`.
125
127
  Those sources are available to assignments, the predicate, and `RETURNING`:
126
128
 
@@ -153,6 +155,8 @@ with the default, SQLite, or MySQL dialect is rejected. Qubu still requires a
153
155
  predicate or an explicit `allowAll()` marker; introducing a source does not
154
156
  authorize an unrestricted update.
155
157
 
158
+ ### Omit an assignment at runtime
159
+
156
160
  Use `omit` for a runtime-conditional assignment. Qubu removes omitted fields
157
161
  before validating and rendering the effective assignment set:
158
162
 
@@ -171,7 +175,9 @@ const query = update(
171
175
 
172
176
  `omit` means that the column is absent from `SET`. It is distinct from `null`
173
177
  and explicit `undefined`, which remain bound assignment values, and it does not
174
- emit SQL `DEFAULT`. At least one assignment must remain; `update()` throws
178
+ emit SQL `DEFAULT`.
179
+
180
+ At least one assignment must remain; `update()` throws
175
181
  before rendering when every field is omitted. Possible expression branches
176
182
  remain source- and capability-aware even when their runtime alternative is
177
183
  `omit`.
@@ -237,11 +243,14 @@ unrestricted operation is intended.
237
243
 
238
244
  ## Return typed rows
239
245
 
240
- `returning()` uses the same named object projection as `SELECT`. Reserve
241
- `{ ...all(table) }` for the intentional contract of returning every table
242
- column. When present, the mutation's `row` type is inferred from that projection, so
246
+ `returning()` uses the same named object projection as `SELECT`. Use
247
+ `{ ...all(table) }` when you want every table column.
248
+
249
+ The mutation’s `row` type is inferred from that projection, so
243
250
  `(await db.execute(query)).rows` has the same shape as a read query when `db`
244
- comes from `qubu(adapter)`. The projection's SQL semantic domains are
251
+ comes from `qubu(adapter)`.
252
+
253
+ The projection’s SQL semantic domains are
245
254
  retained too, so a returned query used by typed composition does not collapse
246
255
  UUID, text, numeric, or other known fields to their JavaScript types alone.
247
256
 
@@ -1,7 +1,6 @@
1
1
  # Add optional conditions
2
2
 
3
- > Keep optional predicates, null checks, and empty-list behavior explicit while
4
- > the query keeps the same structural shape.
3
+ > Add or omit conditions at runtime, and handle NULL values and empty lists.
5
4
 
6
5
  The examples use the `users` table from [Build a `SELECT`](overview.md).
7
6
 
@@ -65,15 +64,23 @@ Here `omit` affects only whether `email` belongs to the projection. It does
65
64
  not make the expression nullable: a non-nullable expression would produce
66
65
  `email?: string`, while this nullable column produces `email?: string | null`.
67
66
 
68
- This support is specific to boolean operand lists, query-level ordering terms,
69
- and the complete clauses named above. Generic `sequence()` and
70
- `commaSeparated()` collections do not discard `omit`. Clauses that provide
71
- sources or change structural guarantees cannot be conditional. Pagination is
72
- the exception: `offset()`, `fetchFirst()`, and `fetchNext()` can be paired
73
- with `omit`, but a conditional row bound keeps the query's inferred
74
- cardinality at `many`. Qubu still rejects `omit` branches paired with
75
- `from()`, joins, `groupBy()`, correlation, CTEs, or custom clauses. Build
76
- separate queries when those structural parts differ at runtime.
67
+ ### Where omission is supported
68
+
69
+ Use `omit` in the clauses and expression lists shown above. Generic
70
+ `sequence()` and `commaSeparated()` collections do not discard it.
71
+
72
+ Pagination also supports `omit`: pair it with `offset()`, `fetchFirst()`, or
73
+ `fetchNext()`. A conditional limit keeps the inferred cardinality at `many`
74
+ because the limit may be absent.
75
+
76
+ Build separate queries when any of these parts differ at runtime. They cannot
77
+ be paired with `omit`:
78
+
79
+ - `from()` or joins.
80
+ - `groupBy()`.
81
+ - Correlation.
82
+ - CTEs.
83
+ - Custom clauses.
77
84
 
78
85
  ## Handle `NULL` and empty lists deliberately
79
86
 
@@ -1,6 +1,6 @@
1
1
  # Group and rank rows
2
2
 
3
- > Use aggregates, grouping, and window expressions while preserving the dependencies and result types that make each expression valid.
3
+ > Summarize rows with aggregates and rank them with window functions.
4
4
 
5
5
  The examples use the `users` and `posts` tables from [Build a
6
6
  `SELECT`](overview.md).
@@ -28,6 +28,7 @@ const counts = select(
28
28
 
29
29
  `users.name` is grouped, while `posts.id` is consumed by `COUNT()`. The
30
30
  same dependency rule applies to `HAVING` and grouped `ORDER BY` expressions.
31
+
31
32
  A projection such as `{ email: users.email, postCount: count(posts.id) }` is
32
33
  rejected unless `users.email` is grouped or is functionally determined by a
33
34
  grouped primary or unique key declared in the table schema. Qubu uses only
@@ -58,7 +59,9 @@ const rankedUsers = select(
58
59
  Window expressions remain ordinary expressions. They can be projected, aliased,
59
60
  and passed to `orderBy()`. Their source requirements and result types are
60
61
  retained through `over()`, and values rendered inside the window
61
- specification remain parameters. Named windows and frame clauses are outside
62
+ specification remain parameters.
63
+
64
+ Named windows and frame clauses are outside
62
65
  the initial inline scope.
63
66
 
64
67
  ## Read next
@@ -1,6 +1,6 @@
1
1
  # Order and paginate
2
2
 
3
- > Choose a stable order and apply optional row limits while keeping SQL clause order and query cardinality visible.
3
+ > Sort results and limit the rows a query returns.
4
4
 
5
5
  The examples use the `users` table from [Build a `SELECT`](overview.md).
6
6
 
@@ -34,10 +34,12 @@ const page = select(
34
34
  )
35
35
  ```
36
36
 
37
- The rendered clause order is still `FROM`, `WHERE`, `ORDER BY`, and
38
- pagination. The active dialect decides whether pagination uses standard
37
+ The rendered clauses follow SQL order: `FROM` comes before `WHERE`, followed
38
+ by `ORDER BY` and pagination. The active dialect decides whether pagination uses standard
39
39
  `FETCH` syntax or a driver-specific `LIMIT` form.
40
40
 
41
+ ### Make the limit optional
42
+
41
43
  Pair a pagination clause with `omit` when the row bound is optional at runtime:
42
44
 
43
45
  ```ts
@@ -1,6 +1,6 @@
1
1
  # Build a `SELECT`
2
2
 
3
- > Build a `SELECT` from typed tables, then inspect its sources, projection, joins, and result row.
3
+ > Choose fields, add a source, and join tables to build a typed SELECT query.
4
4
 
5
5
  ## Start with a projection and a source
6
6
 
@@ -24,8 +24,7 @@ render(query).text
24
24
  ```
25
25
 
26
26
  An object projection uses its keys as result names. Name the fields you intend
27
- to return in the usual case. Reserve `all(source)` for a result contract that
28
- intentionally returns every source column. It returns the source's columns as a
27
+ to return in the usual case. Use `all(source)` when you want every source column. It returns the source's columns as a
29
28
  named projection object, so it can still be spread alongside computed
30
29
  expressions:
31
30
 
@@ -79,6 +78,8 @@ Use `innerJoin`, `leftJoin`, `rightJoin`, or `fullJoin` with an `ON`
79
78
  condition. `crossJoin` and `naturalJoin` add a source without a condition;
80
79
  use them only when that SQL behavior is intentional.
81
80
 
81
+ ### Handle missing joined rows
82
+
82
83
  `leftJoin()` also carries nullability into the selected row. A column from the
83
84
  joined source is nullable because the row may be missing, while an expression
84
85
  with a deliberately non-nullable result such as `count()` remains non-null:
@@ -98,6 +99,8 @@ const summary = select(
98
99
  // { userName: string; postTitle: string | null; postCount: number }
99
100
  ```
100
101
 
102
+ ### Add conditions
103
+
101
104
  Compose boolean expressions explicitly:
102
105
 
103
106
  ```ts
@@ -1,6 +1,6 @@
1
1
  # Compose SQL templates
2
2
 
3
- > Use trusted SQL syntax with bound runtime values while retaining the Qubu metadata carried by interpolated expressions, fragments, and queries.
3
+ > Write SQL templates that bind values safely and preserve type information from Qubu expressions.
4
4
 
5
5
  ## Bind every runtime value
6
6
 
@@ -108,10 +108,16 @@ reaches `unsafeExpression()`.
108
108
 
109
109
  ## Preserve metadata through interpolated fragments
110
110
 
111
- The tag inherits source dependencies, conservative outer-join nullability,
112
- grouping facts, aggregate and window state, subquery state, and dialect
113
- capability requirements from Qubu fragment substitutions. It does not infer
114
- those facts from unchecked template text.
111
+ Qubu fragment substitutions pass these facts to the template:
112
+
113
+ - Required sources.
114
+ - Possible nulls from outer joins.
115
+ - Grouping dependencies.
116
+ - Aggregate and window state.
117
+ - Subquery state.
118
+ - Required dialect capabilities.
119
+
120
+ Qubu does not infer these facts from template text.
115
121
 
116
122
  Use a built-in expression as the substitution when its semantics matter:
117
123
 
@@ -102,11 +102,17 @@ const handlers = applyOpsWithQubu<SyncContext>({
102
102
  export const sync = valtioSync({ schema: { todos }, handlers })
103
103
  ```
104
104
 
105
- Authorization, conflict checks, the application mutation, and
106
- `syncEvents.write()` run in that order inside one Qubu transaction. If any step
107
- fails, the adapter rolls the transaction back. The event sequence becomes
108
- `serverVersion` unless the mutation handler returns an explicit version. Read
109
- handlers pass through unchanged.
105
+ Each mutation runs these steps in one Qubu transaction:
106
+
107
+ 1. Check authorization.
108
+ 2. Check conflicts.
109
+ 3. Apply the application mutation.
110
+ 4. Write the sync event with `syncEvents.write()`.
111
+
112
+ If any step fails, the adapter rolls the transaction back.
113
+
114
+ The event sequence becomes `serverVersion` unless the mutation handler returns
115
+ an explicit version. Read handlers pass through unchanged.
110
116
 
111
117
  The integration does not define persistence tables, import Drizzle, or execute
112
118
  driver APIs. The application owns table design, authorization, conflict policy,
@@ -1,6 +1,6 @@
1
1
  # Vite compiler hint
2
2
 
3
- > Opt a JavaScript or TypeScript module into Qubu's ambient query API while keeping the transform limited to explicit directive-bearing files.
3
+ > Use a "use qubu" directive to add the Qubu imports a module needs.
4
4
 
5
5
  The optional Vite plugin recognizes the `"use qubu"` directive and injects only
6
6
  the referenced named imports from the configured module.
@@ -33,7 +33,7 @@ ambient value and type declarations for the TypeScript compiler.
33
33
 
34
34
  ## Mark a module explicitly
35
35
 
36
- Put the directive in the module's initial directive prologue:
36
+ Put the directive at the start of the module, alongside any other directives:
37
37
 
38
38
  ```ts
39
39
  "use qubu"
package/docs/index.md CHANGED
@@ -1,11 +1,17 @@
1
1
  # Qubu
2
2
 
3
- > Build parameterized SQL from typed tables, expressions, and clauses.
3
+ > Build SQL queries from typed tables and reusable values.
4
4
 
5
- Qubu builds SQL from values. Tables, expressions, clauses, and complete queries
6
- compose without a mutable query builder. TypeScript tracks selected row shapes,
7
- source scope, and nullability, while rendering returns SQL text and ordered
8
- parameters.
5
+ Qubu builds SQL from reusable values. You can combine query parts without
6
+ changing a shared query-builder object.
7
+
8
+ TypeScript checks:
9
+
10
+ - Which fields the query returns and their types.
11
+ - Whether each column belongs to a source in the query.
12
+ - Whether a result can be `null`.
13
+
14
+ Render a query to inspect its SQL text and ordered parameters.
9
15
 
10
16
  The preferred source style names each projected field and writes the final
11
17
  `select()` clauses in SQL order. Clause values remain order-independent at
@@ -17,7 +23,7 @@ and placed in that final call where it reads best.
17
23
  If this is your first query, follow [Getting started](getting-started.md) to
18
24
  define a table, build a `SELECT`, and inspect its SQL and parameters.
19
25
 
20
- ## Choose a task
26
+ ## Build and run queries
21
27
 
22
28
  - [Build a `SELECT`](guides/select/overview.md) with projections, joins,
23
29
  predicates, ordering, and grouping.
@@ -36,18 +42,18 @@ define a table, build a `SELECT`, and inspect its SQL and parameters.
36
42
  - [Query nested JSON](guides/json.md) or read scalars from structured paths.
37
43
  - [Enable the Vite compiler hint](guides/vite-plugin.md) when query modules
38
44
  should opt into named imports through a directive.
39
- - [Inspect an existing database](schema/introspection.md) through the optional
40
- user-owned catalog boundary.
41
- - [Generate a schema module](schema/code-generation.md) from one complete,
42
- non-lossy Snapshot v1 introspection result.
45
+
46
+ ## Work with schemas and migrations
47
+
48
+ - [Inspect an existing database](schema/introspection.md) using a connection you provide.
49
+ - [Generate a schema module](schema/code-generation.md) from an introspection result without losing schema facts.
43
50
  - [Compare snapshots](schema/diff.md) with explicit rename hints and reviewable
44
51
  safety diagnostics.
45
52
  - [Build migration plans](schema/migration-plans.md) as reviewed, deterministic
46
53
  data before DDL emission.
47
54
  - [Emit DDL](schema/ddl-emission.md) from an approved migration plan without
48
55
  handing Qubu a database connection.
49
- - [Operate migrations](migrations/index.md) with versioned artifacts, verified
50
- adapter profiles, baselines, a portable executor, and explicit recovery.
56
+ - [Operate migrations](migrations/index.md) with reviewed migration files and a verified adapter.
51
57
 
52
58
  ## The query pipeline
53
59
 
@@ -106,8 +112,9 @@ render(query)
106
112
  The inferred row is `{ id: number; name: string }`. The value `7` stays out
107
113
  of the SQL text and appears in the `parameters` array in placeholder order.
108
114
 
109
- The [supported features](reference/supported-surface.md) page is the canonical
110
- package-entrypoint and ownership map. Applications may use Qubu's portable
111
- migration executor while retaining credentials, approval policy, custom SQL,
112
- and deployment lifecycle ownership. [Troubleshooting](troubleshooting.md)
113
- starts from common errors and points to the concept page behind each one.
115
+ ## Find support details
116
+
117
+ - [Supported features](reference/supported-surface.md) lists package imports and
118
+ explains which responsibilities stay with your application.
119
+ - [Troubleshooting](troubleshooting.md) starts from common errors and explains
120
+ how to fix them.
@@ -1,6 +1,6 @@
1
1
  # Adapter capability profiles
2
2
 
3
- > Select a migration adapter from capabilities proven by its driver and environment, not from dialect name alone.
3
+ > Choose a migration adapter based on what its driver and environment have been tested to support.
4
4
 
5
5
  Every executable migration adapter opens a migration session and
6
6
  advertises the exact behavior the executor may use:
@@ -25,12 +25,12 @@ executor never treats one as proof of the other.
25
25
 
26
26
  ## Trusted migration SQL
27
27
 
28
- Migration SQL, including SQL conditions, is trusted across all adapters. Qubu
29
- validates program structure and adapter capabilities, but does not parse SQL
30
- to enforce safety. Callers must preserve executor-owned transactions, connection
31
- settings, and migration journal state. For example, an explicit `COMMIT` can
32
- leave schema changes applied without their journal record; atomicity and recovery
33
- guarantees depend on respecting this contract.
28
+ Qubu validates program structure and adapter capabilities. It trusts the SQL
29
+ you supply, including SQL conditions, and does not parse it for safety.
30
+
31
+ Migration SQL must preserve the executor’s transactions, connection settings,
32
+ and journal state. For example, an explicit `COMMIT` can apply schema changes
33
+ without their journal record, breaking the executor’s recovery guarantees.
34
34
 
35
35
  ## Current profiles
36
36
 
@@ -44,11 +44,24 @@ The following stable profiles have live conformance coverage in this checkout:
44
44
  | `@qubu/adapter-postgresjs/migration` | PostgreSQL | required, optional, forbidden | none, exclusive | checkpointed | Reserves and releases one connection |
45
45
  | `@qubu/adapter-pglite/migration` | PostgreSQL | required, optional, forbidden | none, exclusive | checkpointed | Uses the database query queue as the pinned session |
46
46
 
47
- All five support every current tagged parameter kind (`null`, `boolean`,
48
- `string`, `number`, `bigint`, `bytes`, and `json`), a database journal and
49
- lease, atomic applied-record/head advancement, and recovery-required commit
50
- ambiguity classification. Support still depends on the artifact's server,
51
- feature, transaction, and lock constraints.
47
+ All five support:
48
+
49
+ - Every current tagged parameter kind.
50
+ - A journal and migrator lease stored in the database.
51
+ - An atomic update of the applied record and journal head.
52
+ - A recovery-required result when a commit’s outcome is uncertain.
53
+
54
+ Parameter kinds are:
55
+
56
+ - `null` and `boolean`.
57
+ - `string` and `number`.
58
+ - `bigint` and `bytes`.
59
+ - `json`.
60
+
61
+ The artifact’s server, feature, transaction, and lock requirements must still
62
+ match the adapter.
63
+
64
+ ### Unavailable profiles
52
65
 
53
66
  These exported profiles are unavailable and must not be passed to the
54
67
  executor:
@@ -62,6 +75,8 @@ executor:
62
75
  Unavailable profiles expose `reason` and `missingCapabilities`; they do not
63
76
  fall back to a generic executor.
64
77
 
78
+ ### Configure libSQL inspection
79
+
65
80
  For libSQL, let the migration entrypoint exclude all reserved journal objects
66
81
  during strict inspection:
67
82
 
@@ -84,7 +99,9 @@ Each executable artifact must contain exactly one phase and an embedded before
84
99
  snapshot. The adapter submits its statements, SQL assertions, applied-history
85
100
  record, head update, and terminal attempt state in one `client.migrate()` call.
86
101
  For example, creating a table and recording that migration either both commit
87
- or both roll back. Multiple artifacts are separate batches; earlier successful
102
+ or both roll back.
103
+
104
+ Multiple artifacts are separate batches; earlier successful
88
105
  artifacts remain applied if a later one fails.
89
106
 
90
107
  Preparation reads the schema in a read transaction. The submitted batch checks
@@ -92,13 +109,24 @@ that the catalog still matches that inspection, the lease is still owned, and
92
109
  the head still equals the expected parent. Foreign-key validation runs before
93
110
  commit because libSQL temporarily disables enforcement during `migrate()`.
94
111
 
112
+ ### Supported conditions
113
+
95
114
  Schema fingerprint and property preconditions are checked against the embedded
96
- before snapshot, whose physical facts are verified during preparation and
97
- guarded by the in-batch catalog assertion. Object-presence and scalar SQL checks
98
- run inside the batch. Postconditions must be object-presence/absence checks
99
- without fingerprints, or scalar SQL checks returning `1`. Unsupported conditions
100
- and multiple phases are rejected. SQL content is passed to the driver without
101
- safety validation; each program entry must follow the driver's statement contract.
115
+ before snapshot. Preparation verifies its physical facts, and the batch
116
+ asserts that the catalog still matches.
117
+
118
+ Object-presence and scalar SQL checks run inside the batch. Postconditions
119
+ must use either:
120
+
121
+ - Object-presence or absence checks without fingerprints.
122
+ - Scalar SQL checks returning `1`.
123
+
124
+ Unsupported conditions and multiple phases are rejected.
125
+
126
+ SQL is passed to the driver without safety validation. Each program entry
127
+ must follow the driver’s statement contract.
128
+
129
+ ### Crashes and uncertain outcomes
102
130
 
103
131
  The database-row lease has no expiry or heartbeat. A process crash can leave
104
132
  it held; ownership must be resolved before another runner can proceed. A lost
@@ -1,10 +1,12 @@
1
1
  # Artifacts and approval policy
2
2
 
3
- > Review exactly what is authenticated and executable before an artifact enters a repository.
3
+ > Review migration files and approve the exact operations they will run.
4
4
 
5
- Qubu has two strict artifact kinds. An executable migration contains a reviewed
6
- plan and authoritative program. A verified baseline records an observed schema
7
- without pretending that historical SQL ran.
5
+ An artifact is a versioned migration file. Qubu supports two kinds:
6
+
7
+ - An **executable migration** contains a reviewed plan and the program to run.
8
+ - A **verified baseline** records the observed schema as a starting point. It
9
+ does not claim that historical SQL ran through Qubu.
8
10
 
9
11
  ## Published formats
10
12
 
@@ -38,18 +40,30 @@ An executable artifact records:
38
40
  - operation-scoped approvals and custom-program provenance;
39
41
  - artifact provenance and `artifactDigest`.
40
42
 
41
- The program—not `emitMigrationPlan(...).sql` and not joined statement text—is
42
- the execution authority. Each phase declares its position, dependencies,
43
- transaction and lock requirements, preconditions, postconditions, and ordered
44
- statements. Each statement declares its operation ID, dependencies, SQL, and
45
- tagged parameters.
43
+ The executor runs the program stored in the artifact. The SQL preview from
44
+ `emitMigrationPlan(...).sql` is not an executable artifact.
45
+
46
+ Each phase declares:
47
+
48
+ - Its position and dependencies.
49
+ - Transaction and lock requirements.
50
+ - Preconditions and postconditions.
51
+ - Ordered statements.
52
+
53
+ Each statement declares its operation ID, dependencies, SQL, and tagged parameters.
46
54
 
47
55
  ### Baseline artifact schema
48
56
 
49
- A baseline records `id`, sequence and parent lineage, encoding descriptors,
50
- dialect and optional constraints, one verified snapshot descriptor,
51
- `verifiedAt`, provenance, optional operator metadata, and `artifactDigest`. It
52
- has no migration plan, program, or SQL digest.
57
+ A baseline records:
58
+
59
+ - `id`, sequence, and parent lineage.
60
+ - Encoding descriptors.
61
+ - Dialect and optional constraints.
62
+ - One verified snapshot descriptor and `verifiedAt`.
63
+ - Provenance and optional operator metadata.
64
+ - `artifactDigest`.
65
+
66
+ It has no migration plan, program, or SQL digest.
53
67
 
54
68
  Artifact IDs are stable identities, not repository order. Sequence and parent
55
69
  digest establish the linear chain. Renumbering therefore changes lineage and
@@ -57,21 +71,36 @@ the artifact digest.
57
71
 
58
72
  ## Canonical bytes and digest domains
59
73
 
60
- `encodeCanonical()` sorts object keys by Unicode code-point order, preserves
61
- array order, emits compact JSON as UTF-8, normalizes `-0` to `0`, rejects
62
- non-finite numbers, and adds one LF at EOF. `digestCanonical()` prefixes those
63
- bytes with the UTF-8 bytes for:
74
+ `encodeCanonical()` produces a repeatable byte representation:
75
+
76
+ - Sort object keys by Unicode code-point order.
77
+ - Preserve array order.
78
+ - Emit compact UTF-8 JSON.
79
+ - Normalize `-0` to `0` and reject non-finite numbers.
80
+ - End the file with one line feed.
81
+
82
+ `digestCanonical()` prefixes those bytes with the UTF-8 bytes for:
64
83
 
65
84
  ```text
66
85
  qubu:migrate:v1:<domain>\0
67
86
  ```
68
87
 
69
- The five domains are `artifact`, `baseline`, `migration-plan`,
70
- `migration-program`, and `schema-snapshot`. Domain separation prevents equal
71
- JSON values used for different purposes from sharing an integrity identity.
88
+ The digest identifies its purpose through one of five domains:
89
+
90
+ - `artifact`.
91
+ - `baseline`.
92
+ - `migration-plan`.
93
+ - `migration-program`.
94
+ - `schema-snapshot`.
95
+
96
+ The prefix ensures that identical JSON used for different purposes gets
97
+ different digests.
98
+
72
99
  Operational digests have the form `sha256:` plus 64 lowercase hexadecimal
73
100
  digits and are recomputed while sealing or decoding.
74
101
 
102
+ ### Fingerprints and integrity digests
103
+
75
104
  Snapshot and plan `fingerprint` APIs are deterministic FNV-1a64 change
76
105
  detectors. They remain useful for caches and fixture assertions, but they are
77
106
  not cryptographic integrity evidence and are never valid journal heads,
@@ -1,8 +1,8 @@
1
1
  # Migration operations
2
2
 
3
- > Choose the package entrypoint that owns each migration concern without pulling database or Node.js behavior into pure schema code.
3
+ > Find the packages and guides for planning, running, and recovering migrations.
4
4
 
5
- Qubu migrations are split across explicit ownership boundaries:
5
+ These packages handle different parts of a migration:
6
6
 
7
7
  | Owner | Imports | Responsibility |
8
8
  | --------------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
@@ -21,6 +21,8 @@ import { emitMigrationPlan } from "@qubu/migrate/ddl"
21
21
  import { compileMigrationProgram, sealExecutableArtifact } from "@qubu/migrate/artifact"
22
22
  ```
23
23
 
24
+ ## Choose an import
25
+
24
26
  The `@qubu/migrate` root intentionally exports only format/version constants
25
27
  and the central plan and artifact types. Import behavior from its focused
26
28
  entrypoint:
@@ -46,12 +48,17 @@ entrypoint:
46
48
  | `@qubu/migrate/bootstrap/sqlite` | Plan a fresh SQLite schema through the normal compiler |
47
49
  | `@qubu/migrate/testing` | Test adapter capabilities and deterministic failure boundaries |
48
50
 
49
- Start with [Artifacts and approval policy](artifacts-and-policy.md) when
50
- reviewing a migration format. Check [Adapter capability
51
- profiles](adapters.md), use [Command line operations](operations.md) to
52
- configure an application, then keep [Recovery and reconciliation](recovery.md)
53
- with the deployment runbook. [Lotta Games adoption](lotta-adoption.md) records
54
- the downstream cutover boundary and current combo-matrix blocker.
51
+ ## Choose a guide
52
+
53
+ - [Artifacts and approval policy](artifacts-and-policy.md): review migration
54
+ files and approve operations.
55
+ - [Adapter capability profiles](adapters.md): choose a supported driver.
56
+ - [Command line operations](operations.md): configure and use the CLI.
57
+ - [Recovery and reconciliation](recovery.md): handle interrupted migrations.
58
+ - [Lotta Games adoption](lotta-adoption.md): review the downstream cutover
59
+ plan and combo-matrix release blocker.
60
+
61
+ ## Select a built-in dialect
55
62
 
56
63
  Choose the dialect-specific bootstrap entrypoint when using a built-in dialect:
57
64
 
@@ -1,11 +1,13 @@
1
1
  # Lotta Games adoption
2
2
 
3
- > Replace Lotta's provisional runner with Qubu while preserving product-owned deployment policy and historical truth.
3
+ > Move Lotta to Qubu migrations while keeping deployment decisions in Lotta.
4
4
 
5
5
  Adopt the released `@qubu/migrate`, `@qubu/cli`, and libSQL migration entrypoint
6
6
  as a hard cutover. Do not add an upstream decoder for Lotta's provisional JSON,
7
7
  FNV artifact digests, journal, or broad unsafe flags.
8
8
 
9
+ ## Establish the starting state
10
+
9
11
  Before changing downstream state, inspect every environment for a provisional
10
12
  journal or baseline row. Regenerate unreleased migrations in the Qubu artifact
11
13
  format. For an existing database, create one standard baseline only after strict
@@ -13,6 +15,8 @@ live introspection matches the intended Qubu snapshot. That baseline records a
13
15
  verified starting state; it does not claim that old migrations ran through
14
16
  Qubu.
15
17
 
18
+ ## Keep deployment policy in Lotta
19
+
16
20
  Keep these concerns in Lotta:
17
21
 
18
22
  - Turso credentials and environment selection;
@@ -30,10 +34,17 @@ databases with `schema bootstrap`; keep connection PRAGMAs in the test harness.
30
34
  > Drizzle history. A verified baseline is the handoff from historical state to
31
35
  > Qubu lineage.
32
36
 
33
- The downstream verification set should cover a fresh bootstrap, an already
34
- baselined database, a no-op deploy, pending migrations in both deployment
35
- timing modes, drift refusal, concurrent invocation, rollback, and explicit
36
- recovery.
37
+ ## Verify the cutover
38
+
39
+ Cover these scenarios downstream:
40
+
41
+ - A fresh bootstrap.
42
+ - An already baselined database.
43
+ - A deploy with no pending migrations.
44
+ - Pending migrations in both deployment timing modes.
45
+ - Refusal when the schema has drifted.
46
+ - Concurrent migration attempts.
47
+ - Rollback and explicit recovery.
37
48
 
38
49
  ## Combo-matrix release blocker
39
50