@voltro/database 0.79.1 → 0.81.0

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.
@@ -2132,7 +2132,13 @@ var Qt = (e, t, n) => $t(e, "id", t, n), $t = (e, t, n, r, i = "asc") => {
2132
2132
  workflowRunId: p().nullable(),
2133
2133
  createdAt: _().default("now"),
2134
2134
  updatedAt: _().default("now").onUpdate("now")
2135
- }).index(["lifecycle"]).index(["nextRunAt"]), Xr = I("_voltro_migration_plans", {
2135
+ }).index(["lifecycle"]).index(["nextRunAt"]), Xr = I("_voltro_schema_owner", {
2136
+ id: f({ prefix: "own" }),
2137
+ appName: p(),
2138
+ projectName: p().nullable(),
2139
+ frameworkVersion: p().nullable(),
2140
+ claimedAt: _().default("now")
2141
+ }), Zr = I("_voltro_migration_plans", {
2136
2142
  id: f({ prefix: "plan" }),
2137
2143
  fingerprint: p(),
2138
2144
  liveFingerprint: p().nullable(),
@@ -2148,14 +2154,14 @@ var Qt = (e, t, n) => $t(e, "id", t, n), $t = (e, t, n, r, i = "asc") => {
2148
2154
  appliedAt: _().default("now"),
2149
2155
  createdAt: _().default("now"),
2150
2156
  updatedAt: _().default("now").onUpdate("now")
2151
- }).index(["fingerprint"]).index(["environment"]), Zr = I("_voltro_idempotency", {
2157
+ }).index(["fingerprint"]).index(["environment"]), Qr = I("_voltro_idempotency", {
2152
2158
  id: f({ prefix: "idem" }),
2153
2159
  scope: p(),
2154
2160
  key: p(),
2155
2161
  status: p(),
2156
2162
  response: v().nullable(),
2157
2163
  createdAt: _().default("now")
2158
- }).unique(["scope", "key"]).index(["createdAt"]), Qr = I("_voltro_devices", {
2164
+ }).unique(["scope", "key"]).index(["createdAt"]), $r = I("_voltro_devices", {
2159
2165
  id: f({ prefix: "device" }),
2160
2166
  tenantId: p(),
2161
2167
  name: p(),
@@ -2175,20 +2181,20 @@ var Qt = (e, t, n) => $t(e, "id", t, n), $t = (e, t, n, r, i = "asc") => {
2175
2181
  createdBy: p().nullable(),
2176
2182
  metadata: v().nullable(),
2177
2183
  createdAt: _()
2178
- }).index(["tenantId"]).index(["pairingHash"]).index(["accessHash"]).index(["refreshHash"]).index(["previousRefreshHash"]), $r = I("_voltro_tenant_selections", {
2184
+ }).index(["tenantId"]).index(["pairingHash"]).index(["accessHash"]).index(["refreshHash"]).index(["previousRefreshHash"]), ei = I("_voltro_tenant_selections", {
2179
2185
  id: f({ prefix: "tsel" }),
2180
2186
  subjectType: p().maxLength(32),
2181
2187
  subjectId: p(),
2182
2188
  tenantId: p(),
2183
2189
  selectedAt: _()
2184
- }).primaryKey(["id"]).nonReactive(), ei = I("_voltro_kv", {
2190
+ }).primaryKey(["id"]).nonReactive(), ti = I("_voltro_kv", {
2185
2191
  id: f({ prefix: "kv" }),
2186
2192
  key: p().unique(),
2187
2193
  value: p().nullable(),
2188
2194
  expiresAt: _().nullable(),
2189
2195
  createdAt: _().default("now"),
2190
2196
  updatedAt: _().default("now").onUpdate("now")
2191
- }).index(["expiresAt"]), ti = I("_voltro_api_keys", {
2197
+ }).index(["expiresAt"]), ni = I("_voltro_api_keys", {
2192
2198
  id: f({ prefix: "apikey" }),
2193
2199
  tenantId: p().nullable(),
2194
2200
  name: p(),
@@ -2203,7 +2209,7 @@ var Qt = (e, t, n) => $t(e, "id", t, n), $t = (e, t, n, r, i = "asc") => {
2203
2209
  onBehalfOf: p().nullable(),
2204
2210
  metadata: v().nullable(),
2205
2211
  createdAt: _().default("now")
2206
- }).index("byApiKeyTenant", ["tenantId"]), ni = I("_voltro_replica_observations", {
2212
+ }).index("byApiKeyTenant", ["tenantId"]), ri = I("_voltro_replica_observations", {
2207
2213
  id: f({ prefix: "robs" }),
2208
2214
  replicaId: p().maxLength(191),
2209
2215
  startedAt: _(),
@@ -2212,11 +2218,11 @@ var Qt = (e, t, n) => $t(e, "id", t, n), $t = (e, t, n, r, i = "asc") => {
2212
2218
  payload: p().nullable(),
2213
2219
  reachableAt: p().maxLength(255).nullable(),
2214
2220
  writtenAt: _().default("now").onUpdate("now")
2215
- }).unique(["replicaId", "kind"]).index(["kind"]), ri = [
2221
+ }).unique(["replicaId", "kind"]).index(["kind"]), ii = [
2216
2222
  Jr,
2217
2223
  Yr,
2218
- Xr
2219
- ], ii = "_voltro_replace_in_progress", ai = I(ii, {
2224
+ Zr
2225
+ ], ai = "_voltro_replace_in_progress", oi = I(ai, {
2220
2226
  id: f({ prefix: "repl" }),
2221
2227
  startedAt: _().default("now"),
2222
2228
  kind: p().default("replace"),
@@ -2226,10 +2232,10 @@ var Qt = (e, t, n) => $t(e, "id", t, n), $t = (e, t, n, r, i = "asc") => {
2226
2232
  staging: p().nullable(),
2227
2233
  heartbeatAt: _().nullable(),
2228
2234
  resumable: g().nullable()
2229
- }), oi = 30, si = (e, t) => {
2235
+ }), si = 30, ci = (e, t) => {
2230
2236
  let n = typeof t == "number" && Number.isFinite(t) && t > 0 ? t : 30, r = Number(e.VOLTRO_STAGING_STALE_MINUTES);
2231
2237
  return (Number.isFinite(r) && r > 0 ? r : n) * 6e4;
2232
- }, ci = (e) => e == null || String(e).length === 0 ? [] : String(e).split(",").map((e) => e.trim()).filter((e) => e.length > 0), li = (e) => {
2238
+ }, li = (e) => e == null || String(e).length === 0 ? [] : String(e).split(",").map((e) => e.trim()).filter((e) => e.length > 0), ui = (e) => {
2233
2239
  let t = e.filter((e) => e.kind !== "staging");
2234
2240
  if (t.length !== 0) return `refusing to start: a destructive data operation did not finish.
2235
2241
  ${t.map((e) => {
@@ -2244,7 +2250,7 @@ ${t.map((e) => {
2244
2250
 
2245
2251
  When the data is back, or you have decided the current state is correct, clear the marker:
2246
2252
  voltro data clear-replace-marker --yes`;
2247
- }, ui = (e, t, n) => {
2253
+ }, di = (e, t, n) => {
2248
2254
  let r = e.filter((e) => e.kind === "staging");
2249
2255
  return {
2250
2256
  all: r,
@@ -2254,7 +2260,7 @@ ${t.map((e) => {
2254
2260
  return Number.isFinite(r) ? t - r >= n : !1;
2255
2261
  })
2256
2262
  };
2257
- }, di = (e, t) => {
2263
+ }, fi = (e, t) => {
2258
2264
  if (e.all.length === 0) return;
2259
2265
  let n = new Set(e.droppable.map((e) => e.id));
2260
2266
  return `staged data-import leftovers:
@@ -2265,4 +2271,4 @@ ${e.all.map((e) => {
2265
2271
  a reason to refuse the boot — it is a reason to know the disk is holding a copy of a bundle.`;
2266
2272
  };
2267
2273
  //#endregion
2268
- export { qn as $, Ee as $n, Lt as $t, Dr as A, dt as An, ee as Ar, G as At, Tr as B, M as Bn, nn as Bt, Kr as C, L as Cn, m as Cr, On as Ct, qr as D, pt as Dn, te as Dr, Dn as Dt, Br as E, I as En, S as Er, En as Et, Pr as F, nt as Fn, _ as Fr, fn as Ft, xr as G, w as Gn, Mt as Gt, Cr as H, N as Hn, Ft as Ht, Mr as I, Ve as In, le as Ir, dn as It, nr as J, Re as Jn, Gt as Jt, br as K, Pe as Kn, Nt as Kt, Or as L, He as Ln, mn as Lt, jr as M, ct as Mn, oe as Mr, Sn as Mt, Nr as N, st as Nn, o as Nr, W as Nt, Wr as O, ut as On, me as Or, yn as Ot, Ar as P, at as Pn, p as Pr, un as Pt, Q, Ie as Qn, qt as Qt, kr as R, Ue as Rn, tn as Rt, Gr as S, bt as Sn, f as Sr, q as St, Hr as T, ft as Tn, v as Tr, K as Tt, Sr as U, T as Un, Yt as Ut, gr as V, A as Vn, an as Vt, _r as W, Oe as Wn, Rt as Wt, Zn as X, Te as Xn, Vt as Xt, Yn as Y, ze as Yn, Ht as Yt, Xn as Z, Fe as Zn, Kt as Zt, $r as _, Tt as _n, re as _r, rr as _t, di as a, Wt as an, ge as ar, Gn as at, Lr as b, St as bn, fe as br, $ as bt, si as c, Pt as cn, ue as cr, $n as ct, Zr as d, Bt as dn, y as dr, Wn as dt, It as en, be as er, zn as et, ei as f, Ot as fn, ae as fr, Bn as ft, Yr as g, jt as gn, ie as gr, sr as gt, ni as h, z as hn, b as hr, Kn as ht, li as i, Zt as in, _e as ir, Hn as it, wr as j, ot as jn, se as jr, Cn as jt, Fr as k, lt as kn, c as kr, vn as kt, ti as l, Jt as ln, ne as lr, ar as lt, Jr as m, Et as mn, s as mr, lr as mt, oi as n, $t as nn, ve as nr, cr as nt, ui as o, Xt as on, u as or, or as ot, Xr as p, At as pn, l as pr, ir as pt, Qn as q, Le as qn, en as qt, ai as r, Qt as rn, ye as rr, Vn as rt, ci as s, Ut as sn, x as sr, er as st, ii as t, B as tn, xe as tr, Z as tt, Qr as u, zt as un, g as ur, Un as ut, ri as v, Dt as vn, h as vr, tr as vt, Rr as w, mt as wn, de as wr, J as wt, zr as x, xt as xn, pe as xr, Y as xt, Ur as y, kt as yn, ce as yr, Jn as yt, Ir as z, j as zn, rn as zt };
2274
+ export { Q as $, Ie as $n, qt as $t, Fr as A, lt as An, c as Ar, vn as At, Ir as B, j as Bn, rn as Bt, Gr as C, bt as Cn, f as Cr, q as Ct, Br as D, I as Dn, S as Dr, En as Dt, Hr as E, ft as En, v as Er, K as Et, Ar as F, at as Fn, p as Fr, un as Ft, _r as G, Oe as Gn, Rt as Gt, gr as H, A as Hn, an as Ht, Pr as I, nt as In, _ as Ir, fn as It, Qn as J, Le as Jn, en as Jt, xr as K, w as Kn, Mt as Kt, Mr as L, Ve as Ln, le as Lr, dn as Lt, wr as M, ot as Mn, se as Mr, Cn as Mt, jr as N, ct as Nn, oe as Nr, Sn as Nt, qr as O, pt as On, te as Or, Dn as Ot, Nr as P, st as Pn, o as Pr, W as Pt, Xn as Q, Fe as Qn, Kt as Qt, Or as R, He as Rn, mn as Rt, zr as S, xt as Sn, pe as Sr, Y as St, Rr as T, mt as Tn, de as Tr, J as Tt, Cr as U, N as Un, Ft as Ut, Tr as V, M as Vn, nn as Vt, Sr as W, T as Wn, Yt as Wt, Yn as X, ze as Xn, Ht as Xt, nr as Y, Re as Yn, Gt as Yt, Zn as Z, Te as Zn, Vt as Zt, Yr as _, jt as _n, ie as _r, sr as _t, fi as a, Zt as an, _e as ar, Hn as at, Ur as b, kt as bn, ce as br, Jn as bt, ci as c, Ut as cn, x as cr, er as ct, Qr as d, zt as dn, g as dr, Un as dt, Lt as en, Ee as er, qn as et, ti as f, Bt as fn, y as fr, Wn as ft, Xr as g, z as gn, b as gr, Kn as gt, ri as h, Et as hn, s as hr, lr as ht, ui as i, Qt as in, ye as ir, Vn as it, Dr as j, dt as jn, ee as jr, G as jt, Wr as k, ut as kn, me as kr, yn as kt, ni as l, Pt as ln, ue as lr, $n as lt, Jr as m, At as mn, l as mr, ir as mt, si as n, B as nn, xe as nr, Z as nt, di as o, Wt as on, ge as or, Gn as ot, Zr as p, Ot as pn, ae as pr, Bn as pt, br as q, Pe as qn, Nt as qt, oi as r, $t as rn, ve as rr, cr as rt, li as s, Xt as sn, u as sr, or as st, ai as t, It as tn, be as tr, zn as tt, $r as u, Jt as un, ne as ur, ar as ut, ei as v, Tt as vn, re as vr, rr as vt, Kr as w, L as wn, m as wr, On as wt, Lr as x, St as xn, fe as xr, $ as xt, ii as y, Dt as yn, h as yr, tr as yt, kr as z, Ue as zn, tn as zt };
package/dist/sql.d.ts CHANGED
@@ -320,6 +320,12 @@ export declare interface ApplyPlanCtx {
320
320
  * releases while `voltro dev`'s boot diff, which uses this parameter, did not.
321
321
  */
322
322
  readonly replan: (sql: SqlClient.SqlClient) => Effect.Effect<MigrationPlan, SqlError_2, SqlClient.SqlClient>;
323
+ /**
324
+ * The declared store charset — the one `replan` plans with. Here only for
325
+ * the resume ledger this creates before the first statement: nothing declares
326
+ * it, so without this it is created in the database default.
327
+ */
328
+ readonly charset?: MysqlCharset | undefined;
323
329
  }
324
330
 
325
331
  export declare const applySchema: (tables: ReadonlyArray<AnyTable>, dialect?: DialectId,
@@ -330,6 +336,14 @@ export declare const applySchema: (tables: ReadonlyArray<AnyTable>, dialect?: Di
330
336
  * raised nothing. */
331
337
  cdcChannel?: string, options?: SchemaApplyOptions) => Effect.Effect<void, never, SqlClient.SqlClient>;
332
338
 
339
+ /**
340
+ * Run the work. No lock of its own — the caller holds the one that fits:
341
+ * `convergeUndeclaredCharset` the migration lock, the cluster gate its own.
342
+ * `.unprepared`, the text protocol, like every DDL statement a prepared
343
+ * protocol may refuse on one of the two engines.
344
+ */
345
+ export declare const applyUndeclaredCharsetWork: (sql: SqlClient.SqlClient, work: UndeclaredCharsetWork) => Effect.Effect<void, SqlError_2>;
346
+
333
347
  /**
334
348
  * The OPT-IN refuse gate over the advisory. By default (`VOLTRO_ROLLING_DEPLOY`
335
349
  * unset) this never fires — the classifier stays a `db plan` advisory, because
@@ -609,6 +623,21 @@ export declare const charsetColumnsOf: (table: TableSnapshot) => ReadonlyArray<{
609
623
  readonly charset: string;
610
624
  }>;
611
625
 
626
+ /**
627
+ * Check — and, when `mayWrite`, establish — which app owns this schema.
628
+ *
629
+ * With `mayWrite` the owner table is bootstrapped and an unclaimed schema is
630
+ * claimed for `claim.appName`. Two apps racing for an unclaimed database both
631
+ * try the INSERT; the loser's fails on the primary key and it re-reads, so
632
+ * exactly one of them owns it and the other is told so.
633
+ *
634
+ * Without `mayWrite` nothing is created or written: a missing table or row is
635
+ * `unclaimed`, and only an existing FOREIGN claim is reported.
636
+ */
637
+ export declare const checkSchemaOwner: (sql: SqlClient.SqlClient, claim: SchemaOwnerClaim, options: {
638
+ readonly mayWrite: boolean;
639
+ }) => Effect.Effect<SchemaOwnership, SqlError_2>;
640
+
612
641
  /** Partition into ≤`n`-sized chunks (disjoint, complete). Exported for the
613
642
  * batching regression test — the introspection's correctness reduces to this
614
643
  * producing a complete, non-overlapping partition of the table list. */
@@ -1504,6 +1533,28 @@ export declare type ColumnInput = {
1504
1533
  __definition(): ColumnDefinition<unknown>;
1505
1534
  } | ColumnDefinition<unknown>;
1506
1535
 
1536
+ /**
1537
+ * A table's COLUMN-level CHECKs on MariaDB, by column — what a `MODIFY COLUMN`
1538
+ * has to restate so that it keeps them.
1539
+ *
1540
+ * MariaDB records a CHECK written inline on a column (the bring-up path writes
1541
+ * every enum CHECK that way) as part of the column definition
1542
+ * (`check_constraints.level = 'Column'`, named after the column), and `MODIFY
1543
+ * COLUMN` REDEFINES the column: a definition without the CHECK removes it.
1544
+ * Measured on 11.8 — plain MODIFY: gone; MODIFY with the CHECK inline: kept,
1545
+ * still column-level. A table-level CHECK (what `add-check` writes) survives
1546
+ * either way, and MySQL has no column-level constraints in its catalog, so this
1547
+ * is empty there.
1548
+ *
1549
+ * Without it every operation that renders MODIFY — a character-set conversion,
1550
+ * a nullability or type change — removed the CHECK as a side effect, the re-plan
1551
+ * proposed `add-check`, and the apply refused as "did not converge". A declared
1552
+ * charset over a real schema produced 67 of them at once. The planner's own
1553
+ * `drop-check` still removes a CHECK the declaration no longer has: it runs
1554
+ * after the column changes and reads the catalog again.
1555
+ */
1556
+ export declare const columnLevelChecksMysql: (sql: SqlClient.SqlClient, table: string) => Effect.Effect<ReadonlyMap<string, string>, SqlError_2>;
1557
+
1507
1558
  /**
1508
1559
  * A column as seen by the planner: either declared in code (extracted
1509
1560
  * from `ColumnDefinition`) or live in the DB (extracted via introspection).
@@ -1764,6 +1815,17 @@ declare type ColumnType = 'id' | 'text' | 'integer' | 'real' | 'decimal' | 'bigi
1764
1815
 
1765
1816
  declare type ColumnType_2 = 'id' | 'text' | 'integer' | 'real' | 'decimal' | 'bigint' | 'boolean' | 'timestamp' | 'date' | 'json' | 'bytes' | 'reference' | 'vector' | 'enum' | 'array' | 'interval' | 'raw';
1766
1817
 
1818
+ /**
1819
+ * Carry a `utf8mb4` declaration to the undeclared framework tables that
1820
+ * already exist, under the migration lock. Idempotent: a second run reads a
1821
+ * converged catalog and does nothing.
1822
+ */
1823
+ export declare const convergeUndeclaredCharset: (sql: SqlClient.SqlClient, options: {
1824
+ readonly declaredNames: ReadonlySet<string>;
1825
+ readonly charset: MysqlCharset | undefined;
1826
+ readonly lockSchema?: string | undefined;
1827
+ }) => Effect.Effect<UndeclaredCharsetWork, SqlError_2>;
1828
+
1767
1829
  /** A live foreign key a charset conversion has to carry across the rewrite. */
1768
1830
  export declare interface ConvertCharsetForeignKey {
1769
1831
  /** Catalog name of the constraint. */
@@ -2393,6 +2455,9 @@ export declare const describeProbe: (probe: SchemaProbe) => string;
2393
2455
  /** One line per finding, for the CLI and the doctor. */
2394
2456
  export declare const describeStoreCharsetFinding: (f: StoreCharsetFinding) => string;
2395
2457
 
2458
+ /** The lines `db plan` prints and `db apply` logs — one per table. */
2459
+ export declare const describeUndeclaredCharsetWork: (w: UndeclaredCharsetWork) => ReadonlyArray<string>;
2460
+
2396
2461
  /**
2397
2462
  * Parse `VOLTRO_DESTRUCTIVE_OK`.
2398
2463
  *
@@ -2746,7 +2811,7 @@ declare type EmptyMerge = unknown;
2746
2811
  export declare const engineFromVersion: (version: string) => MysqlEngine;
2747
2812
 
2748
2813
  /** The deploy ledger (`_voltro_deploys`) — same bootstrap, same reason: it has to exist before the first plan. */
2749
- export declare const ensureDeployLedgerTable: (sql: SqlClient.SqlClient, dialect: DialectId) => Effect.Effect<void, SqlError_2>;
2814
+ export declare const ensureDeployLedgerTable: (sql: SqlClient.SqlClient, dialect: DialectId, charset?: MysqlCharset) => Effect.Effect<void, SqlError_2>;
2750
2815
 
2751
2816
  /**
2752
2817
  * Create `_voltro_migration_ops` if it isn't there yet.
@@ -2761,7 +2826,7 @@ export declare const ensureDeployLedgerTable: (sql: SqlClient.SqlClient, dialect
2761
2826
  * framework-table set because it has to exist before the FIRST plan — and the
2762
2827
  * first plan is the one that creates the framework tables.
2763
2828
  */
2764
- export declare const ensureLedgerTable: (sql: SqlClient.SqlClient, dialect: DialectId) => Effect.Effect<void, SqlError_2>;
2829
+ export declare const ensureLedgerTable: (sql: SqlClient.SqlClient, dialect: DialectId, charset?: MysqlCharset) => Effect.Effect<void, SqlError_2>;
2765
2830
 
2766
2831
  /**
2767
2832
  * The PLAN ledger (`_voltro_migration_plans`) — same bootstrap, one caller.
@@ -2794,6 +2859,10 @@ export declare const ensurePlanLedgerTable: (sql: SqlClient.SqlClient, dialect:
2794
2859
  */
2795
2860
  export declare const ensureReplaceMarkerTable: (sql: SqlClient.SqlClient, dialect: DialectId) => Effect.Effect<void, SqlError_2>;
2796
2861
 
2862
+ /** The schema-owner row's table (`_voltro_schema_owner`) — bootstrapped so the
2863
+ * ownership check can run BEFORE the first plan, which is the plan it guards. */
2864
+ export declare const ensureSchemaOwnerTable: (sql: SqlClient.SqlClient, dialect: DialectId) => Effect.Effect<void, SqlError_2>;
2865
+
2797
2866
  /** Exported for the same reason as {@link enumTypeBlocks}, and it MUST run
2798
2867
  * before it — see that function's note on ordering. */
2799
2868
  export declare const enumRenameBlocks: (tables: ReadonlyArray<AnyTable>, dialect: DialectId) => string;
@@ -3144,6 +3213,9 @@ export declare const fingerprintSchema: (snapshot: SchemaSnapshot) => string;
3144
3213
 
3145
3214
  export declare const fnv1a64: (input: string) => bigint;
3146
3215
 
3216
+ /** The refusal a foreign claim produces — one sentence for both boot paths. */
3217
+ export declare const foreignOwnerMessage: (self: string, owner: string, claimedAt: string | undefined) => string;
3218
+
3147
3219
  /** Human/PR-comment rendering. Markdown-free on purpose — the CI job that posts
3148
3220
  * it to a PR wraps it, and a terminal reader gets the same text. */
3149
3221
  export declare const formatBranchRehearsal: (report: BranchRehearsalReport) => string;
@@ -3433,6 +3505,16 @@ export declare const isRawSqlFragment: (value: unknown) => value is RawSqlFragme
3433
3505
  */
3434
3506
  export declare const isReRunSafeDdl: (statement: string, dialect: DialectId) => boolean;
3435
3507
 
3508
+ /**
3509
+ * The tables this step owns: created by the framework or its engines, not
3510
+ * declared by the app. A soft-drop snapshot and a `--mode replace` staging copy
3511
+ * are data the operator is handling, and `_cloud_*` / `__turso_internal_*`
3512
+ * belong to another product and another engine.
3513
+ */
3514
+ export declare const isUndeclaredCharsetTable: (name: string, declaredNames: ReadonlySet<string>) => boolean;
3515
+
3516
+ export declare const isUndeclaredCharsetWorkEmpty: (w: UndeclaredCharsetWork) => boolean;
3517
+
3436
3518
  /**
3437
3519
  * A json-path index entry, produced by {@link jsonIndex}. Unlike a plain
3438
3520
  * `{ expr }` (verbatim, dialect-specific) this carries the column + path
@@ -5114,6 +5196,9 @@ export declare const reactiveTriggerRepairSql: (input: {
5114
5196
  readonly channel?: string;
5115
5197
  }) => ReadonlyArray<string>;
5116
5198
 
5199
+ /** Every string column of a base table in the connected database. */
5200
+ export declare const readUndeclaredCharsetColumns: (sql: SqlClient.SqlClient) => Effect.Effect<ReadonlyArray<UndeclaredCharsetColumn>, SqlError_2>;
5201
+
5117
5202
  /**
5118
5203
  * Record that a schema was applied even though there was nothing to DO.
5119
5204
  *
@@ -5463,6 +5548,8 @@ export declare const runSchemaOp: (sql: SqlClient.SqlClient, op: MigrationSchema
5463
5548
  /** Runs one Effect over the connection — the shape `ManagedRuntime.runPromise` and a store's `run` share. */
5464
5549
  export declare type RunSql = <A>(effect: Effect.Effect<A, SqlError_2, SqlClient.SqlClient>) => Promise<A>;
5465
5550
 
5551
+ export declare const SCHEMA_OWNER_TABLE = "_voltro_schema_owner";
5552
+
5466
5553
  /**
5467
5554
  * Effect that applies the emitted DDL to the provided SqlClient. Splits
5468
5555
  * on `;` only outside dollar-quoted blocks (the postgres NOTIFY trigger
@@ -5507,6 +5594,34 @@ export declare interface SchemaEmitOptions {
5507
5594
  /** What a schema operation on the migration context found to do. */
5508
5595
  export declare type SchemaOpOutcome = 'applied' | 'already-absent' | 'already-present';
5509
5596
 
5597
+ /** Who is claiming the schema. */
5598
+ export declare interface SchemaOwnerClaim {
5599
+ /** The app's `name` — the identity compared on every boot. */
5600
+ readonly appName: string;
5601
+ readonly projectName?: string;
5602
+ readonly frameworkVersion?: string;
5603
+ }
5604
+
5605
+ export declare type SchemaOwnership =
5606
+ /** This app already owned the schema. */
5607
+ {
5608
+ readonly kind: 'owned';
5609
+ }
5610
+ /** Unclaimed until now; this app's claim was written. */
5611
+ | {
5612
+ readonly kind: 'claimed';
5613
+ }
5614
+ /** ANOTHER app owns it — the boot must refuse. */
5615
+ | {
5616
+ readonly kind: 'foreign';
5617
+ readonly owner: string;
5618
+ readonly claimedAt: string | undefined;
5619
+ }
5620
+ /** Read-only mode found no claim (or no table) to compare against. */
5621
+ | {
5622
+ readonly kind: 'unclaimed';
5623
+ };
5624
+
5510
5625
  /** A schema object a body asked about, in the vocabulary a user writes. */
5511
5626
  export declare type SchemaProbe = {
5512
5627
  readonly kind: 'table';
@@ -5645,6 +5760,8 @@ declare interface SpatialClause_2 {
5645
5760
  */
5646
5761
  export declare const sql: (strings: TemplateStringsArray, ...values: ReadonlyArray<unknown>) => RawSqlFragment;
5647
5762
 
5763
+ /* Excluded from this release type: sqlPoolCapacity */
5764
+
5648
5765
  /**
5649
5766
  * Map a logical column type to its dialect-specific DDL keyword.
5650
5767
  *
@@ -6418,8 +6535,52 @@ export declare class TransactionBrokenByBodyError extends Error {
6418
6535
  constructor(migrationId: string, dialect: DialectId);
6419
6536
  }
6420
6537
 
6538
+ /**
6539
+ * Hand the schema to a different app name — `voltro db claim`. The one
6540
+ * deliberate way to change the owner: an app was RENAMED, not replaced.
6541
+ */
6542
+ export declare const transferSchemaOwner: (sql: SqlClient.SqlClient, claim: SchemaOwnerClaim) => Effect.Effect<{
6543
+ readonly previous: string | undefined;
6544
+ }, SqlError_2>;
6545
+
6421
6546
  export declare const unblockLossy: (plan: MigrationPlan, scope?: ReturnType<typeof destructiveScope>) => MigrationPlan;
6422
6547
 
6548
+ /** One string column of an undeclared framework table, as the catalog reports it. */
6549
+ export declare interface UndeclaredCharsetColumn {
6550
+ readonly table: string;
6551
+ readonly column: string;
6552
+ readonly charset: string;
6553
+ /** `information_schema.columns.column_type`, e.g. `varchar(255)`, `text`. */
6554
+ readonly columnType: string;
6555
+ readonly nullable: boolean;
6556
+ /** Raw `column_default`; `null` (or the text `NULL` on MariaDB) when there is none. */
6557
+ readonly columnDefault: string | null;
6558
+ readonly generated: boolean;
6559
+ }
6560
+
6561
+ /**
6562
+ * One `ALTER TABLE` per table of the work. `checks` is each table's
6563
+ * column-level CHECKs (`columnLevelChecksMysql`): MariaDB stores such a CHECK
6564
+ * in the column definition, and a MODIFY that does not restate it deletes it.
6565
+ */
6566
+ export declare const undeclaredCharsetStatements: (w: UndeclaredCharsetWork, checks?: ReadonlyMap<string, ReadonlyMap<string, string>>) => ReadonlyArray<string>;
6567
+
6568
+ export declare interface UndeclaredCharsetWork {
6569
+ readonly tables: ReadonlyArray<{
6570
+ readonly table: string;
6571
+ readonly columns: ReadonlyArray<UndeclaredCharsetColumn>;
6572
+ }>;
6573
+ /** Columns that are off but carry a default or a generation expression — named, not rewritten. */
6574
+ readonly left: ReadonlyArray<UndeclaredCharsetColumn>;
6575
+ }
6576
+
6577
+ /**
6578
+ * What a declaration asks of the undeclared framework tables. Pure, so `db
6579
+ * plan` can print it and `db apply` can do it from the same reading. `only`
6580
+ * narrows it to named tables — the ones the cluster gate has just created.
6581
+ */
6582
+ export declare const undeclaredCharsetWork: (columns: ReadonlyArray<UndeclaredCharsetColumn>, declaredNames: ReadonlySet<string>, charset: MysqlCharset | undefined, only?: ReadonlySet<string>) => UndeclaredCharsetWork;
6583
+
6423
6584
  /** Every deploy that did not finish — `running` (the process died) or `failed` (its undo did not complete). An absent table is an empty ledger. */
6424
6585
  export declare const unfinishedDeploys: (sql: SqlClient.SqlClient) => Effect.Effect<ReadonlyArray<DeployLedgerRow>, never>;
6425
6586