@voltro/database 0.85.0 → 0.87.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.
Files changed (173) hide show
  1. package/CHANGELOG.md +5987 -0
  2. package/THIRD-PARTY-NOTICES.md +5 -257
  3. package/dist/actorSnapshot.js +24 -0
  4. package/dist/arrayCodec.js +32 -0
  5. package/dist/branchExecute.js +92 -0
  6. package/dist/branching.js +106 -0
  7. package/dist/bulkInsertLimits.js +25 -0
  8. package/dist/cdcOffsetsTables.js +19 -0
  9. package/dist/changeEvent.js +41 -0
  10. package/dist/changeIdentity.js +65 -0
  11. package/dist/changeListenerCeiling.js +6 -0
  12. package/dist/columnReference.js +17 -0
  13. package/dist/columns.js +326 -0
  14. package/dist/committedChanges.js +12 -0
  15. package/dist/connectionIdentity.js +36 -0
  16. package/dist/coreTables.js +16 -0
  17. package/dist/coreTablesRegistry.js +10 -0
  18. package/dist/dataTransfers.js +23 -0
  19. package/dist/dbCause.js +222 -0
  20. package/dist/dbMetrics.js +65 -0
  21. package/dist/decimalComparison.js +27 -0
  22. package/dist/derivedRowId.js +5 -0
  23. package/dist/dialect.js +13 -0
  24. package/dist/enumRenames.js +14 -0
  25. package/dist/expiresMixin.js +10 -0
  26. package/dist/fieldEncryption.js +121 -0
  27. package/dist/frameworkTables.js +143 -0
  28. package/dist/ginIndex.js +10 -0
  29. package/dist/hybridSearch.js +32 -0
  30. package/dist/idGenerator.js +57 -0
  31. package/dist/identifierLimits.js +32 -0
  32. package/dist/index.d.ts +166 -22
  33. package/dist/index.js +82 -2183
  34. package/dist/indexAudit.js +61 -0
  35. package/dist/indexStorage.js +58 -0
  36. package/dist/joinCompiler.js +160 -0
  37. package/dist/jsonEagerCompiler.js +436 -0
  38. package/dist/jsonPatch.js +78 -0
  39. package/dist/jsonPatchAssignments.js +13 -0
  40. package/dist/jsonPath.js +31 -0
  41. package/dist/localFirstMixin.js +12 -0
  42. package/dist/migrate.js +644 -0
  43. package/dist/migration.js +18 -0
  44. package/dist/migrations/appliedAtValue.js +8 -0
  45. package/dist/migrations/applier.js +1100 -0
  46. package/dist/migrations/boot.js +196 -0
  47. package/dist/migrations/branchRehearsal.js +122 -0
  48. package/dist/migrations/columnEquivalence.js +85 -0
  49. package/dist/migrations/ddlError.js +63 -0
  50. package/dist/migrations/ddlStatements.js +9 -0
  51. package/dist/migrations/declaredSchema.js +162 -0
  52. package/dist/migrations/deployLedger.js +19 -0
  53. package/dist/migrations/fileBased.js +57 -0
  54. package/dist/migrations/fileContext.js +482 -0
  55. package/dist/migrations/fileDiscovery.js +332 -0
  56. package/dist/migrations/fileSkipProbes.js +117 -0
  57. package/dist/migrations/fingerprint.js +46 -0
  58. package/dist/migrations/fkCycles.js +13 -0
  59. package/dist/migrations/frameworkLiveTables.js +25 -0
  60. package/dist/migrations/idempotentDdl.js +37 -0
  61. package/dist/migrations/indexPredicate.js +50 -0
  62. package/dist/migrations/introspect.js +801 -0
  63. package/dist/migrations/ledgerRows.js +4 -0
  64. package/dist/migrations/lock.js +91 -0
  65. package/dist/migrations/migrationTableExists.js +9 -0
  66. package/dist/migrations/mssqlColumnDependencies.js +76 -0
  67. package/dist/migrations/mysqlEngine.js +11 -0
  68. package/dist/migrations/namespaceCharset.js +51 -0
  69. package/dist/migrations/planner.js +785 -0
  70. package/dist/migrations/postgresEnumCheck.js +22 -0
  71. package/dist/migrations/reactiveTriggerDrift.js +58 -0
  72. package/dist/migrations/reactiveTriggerName.js +7 -0
  73. package/dist/migrations/renameMssqlCheck.js +21 -0
  74. package/dist/migrations/restoreSnapshots.js +206 -0
  75. package/dist/migrations/resumeLedger.js +86 -0
  76. package/dist/migrations/rollingDeploy.js +106 -0
  77. package/dist/migrations/schemaOwner.js +46 -0
  78. package/dist/migrations/schemaOwnerTable.js +4 -0
  79. package/dist/migrations/softDropSnapshot.js +20 -0
  80. package/dist/migrations/sqlLimit.js +8 -0
  81. package/dist/migrations/sqliteCatalogName.js +13 -0
  82. package/dist/migrations/sqliteConstraintIdentity.js +97 -0
  83. package/dist/migrations/sqliteDecimalBoot.js +22 -0
  84. package/dist/migrations/sqliteDecimalPublication.js +257 -0
  85. package/dist/migrations/sqliteDecimalReview.js +30 -0
  86. package/dist/migrations/sqliteDecimalReviewStore.js +188 -0
  87. package/dist/migrations/sqliteDecimalReviewWitness.js +38 -0
  88. package/dist/migrations/sqliteDecimalSource.js +69 -0
  89. package/dist/migrations/sqliteDecimalStage.js +135 -0
  90. package/dist/migrations/sqliteForeignKeys.js +38 -0
  91. package/dist/migrations/sqliteMigrationBatch.js +37 -0
  92. package/dist/migrations/sqliteRetainedSource.js +106 -0
  93. package/dist/migrations/sqliteRowIdentity.js +63 -0
  94. package/dist/migrations/sqliteSchemaEpoch.js +12 -0
  95. package/dist/migrations/sqliteSnapshotGuard.js +10 -0
  96. package/dist/migrations/sqliteTableContents.js +34 -0
  97. package/dist/migrations/sqliteTableCopy.js +25 -0
  98. package/dist/migrations/sqliteTableSchema.js +19 -0
  99. package/dist/migrations/sqliteWitnessProtection.js +8 -0
  100. package/dist/migrations/squash.js +81 -0
  101. package/dist/migrations/storeCharset.js +66 -0
  102. package/dist/migrations/transactionCause.js +10 -0
  103. package/dist/migrations/undeclaredCharset.js +40 -0
  104. package/dist/migrations/uniqueActiveLowering.js +39 -0
  105. package/dist/mixins.js +22 -0
  106. package/dist/mssqlDecimalDistinct.js +51 -0
  107. package/dist/mssqlJsonValueCheck.js +42 -0
  108. package/dist/mssqlTextStorage.js +9 -0
  109. package/dist/namespace.js +21 -0
  110. package/dist/{wire-CG2j7J3f.js → optimisticVersion.js} +2 -2
  111. package/dist/pendingAttribution.js +79 -0
  112. package/dist/pluginRef.js +17 -0
  113. package/dist/predicate.js +273 -0
  114. package/dist/predicateCoercion.js +13 -0
  115. package/dist/projectedColumn.js +37 -0
  116. package/dist/queryBuilder.js +388 -0
  117. package/dist/rawSql.js +8 -0
  118. package/dist/relations.js +69 -0
  119. package/dist/relationsRegistry.js +38 -0
  120. package/dist/replaceInProgress.js +53 -0
  121. package/dist/requiredColumns.js +26 -0
  122. package/dist/residency.js +52 -0
  123. package/dist/retention.js +62 -0
  124. package/dist/rowDecoder.js +173 -0
  125. package/dist/rowKey.js +8 -0
  126. package/dist/rowSchema.js +31 -0
  127. package/dist/scopeKey.js +8 -0
  128. package/dist/seed.js +33 -0
  129. package/dist/snowflake.js +26 -0
  130. package/dist/sql.d.ts +2792 -3773
  131. package/dist/sql.js +42 -6905
  132. package/dist/sqlCompiler.js +360 -0
  133. package/dist/sqlError.js +8 -0
  134. package/dist/sqlMutation.js +55 -0
  135. package/dist/sqlPoolCapacity.js +12 -0
  136. package/dist/sqliteDecimal.js +22 -0
  137. package/dist/sqliteDecimalAggregateSql.js +61 -0
  138. package/dist/sqliteDecimalColumnSql.js +108 -0
  139. package/dist/sqliteDecimalConversion.js +15 -0
  140. package/dist/sqliteDecimalCte.js +154 -0
  141. package/dist/sqliteDecimalEncodeSql.js +32 -0
  142. package/dist/sqliteDecimalOutputs.js +74 -0
  143. package/dist/sqliteDecimalPredicate.js +66 -0
  144. package/dist/sqliteDecimalQuery.js +183 -0
  145. package/dist/sqliteDecimalQueryPlan.js +37 -0
  146. package/dist/sqliteDecimalResultSql.js +44 -0
  147. package/dist/sqliteDecimalRowQuery.js +63 -0
  148. package/dist/sqliteDecimalSetQuery.js +50 -0
  149. package/dist/sqliteDecimalSource.js +63 -0
  150. package/dist/sqliteDecimalStorage.js +29 -0
  151. package/dist/sqliteDecimalSubquery.js +19 -0
  152. package/dist/sqliteDecimalWindowQuery.js +196 -0
  153. package/dist/sqliteValueCoercion.js +4 -0
  154. package/dist/stampId.js +21 -0
  155. package/dist/storeErrors.js +9 -0
  156. package/dist/storeRefusal.js +20 -0
  157. package/dist/stream.js +36 -0
  158. package/dist/subjectGraph.js +175 -0
  159. package/dist/table.js +394 -0
  160. package/dist/tableRegistry.js +16 -0
  161. package/dist/tenantSelection.js +27 -0
  162. package/dist/transactionOutcome.js +100 -0
  163. package/dist/transientContention.js +36 -0
  164. package/dist/typeId.js +51 -0
  165. package/dist/typedStore.js +16 -0
  166. package/dist/upsertUpdate.js +20 -0
  167. package/dist/vectorEmbedding.js +31 -0
  168. package/dist/view.js +39 -0
  169. package/dist/wire.js +6 -2
  170. package/dist/writeAttribution.js +16 -0
  171. package/dist/writeRecorder.js +38 -0
  172. package/package.json +3 -4
  173. package/dist/replaceInProgress-DC88Pdiy.js +0 -3735
@@ -0,0 +1,57 @@
1
+ import { validateTypeIdPrefix as e } from "./identifierLimits.js";
2
+ import { typeId as t } from "./typeId.js";
3
+ import { generateSnowflake as n } from "./snowflake.js";
4
+ import { ulid as r } from "ulid";
5
+ //#region src/idGenerator.ts
6
+ var i = (t) => {
7
+ let n = t.toLowerCase();
8
+ if (n.startsWith("_")) throw Error(`cannot derive a typeid prefix for table '${t}' (table names starting with '_' are not valid typeid prefixes). Pick an explicit prefix via id({ prefix: '...' }) or use a different scheme like id({ scheme: 'numeric' }) for internal tables.`);
9
+ if (!/^[a-z][a-z0-9_]*$/.test(n)) throw Error(`cannot derive a typeid prefix from table name '${t}' (must match [a-z][a-z0-9_]*). Pick an explicit prefix via id({ prefix: '...' }).`);
10
+ let r = n.endsWith("ies") && n.length > 3 ? n.slice(0, -3) + "y" : n.endsWith("ses") || n.endsWith("xes") || n.endsWith("zes") || n.endsWith("shes") || n.endsWith("ches") ? n.slice(0, -2) : n.endsWith("s") && n.length > 1 ? n.slice(0, -1) : n;
11
+ return e(r, {
12
+ kind: "derived",
13
+ tableName: t
14
+ }), r;
15
+ }, a = (t, n) => {
16
+ if (t === void 0) return {
17
+ kind: "typeid",
18
+ prefix: i(n)
19
+ };
20
+ if ("prefix" in t && !("scheme" in t)) return e(t.prefix, {
21
+ kind: "explicit",
22
+ tableName: n
23
+ }), {
24
+ kind: "typeid",
25
+ prefix: t.prefix
26
+ };
27
+ if (!("scheme" in t)) throw Error("invalid id() options: no scheme or prefix");
28
+ switch (t.scheme) {
29
+ case "typeid": {
30
+ let r = t.prefix ?? i(n);
31
+ return t.prefix !== void 0 && e(t.prefix, {
32
+ kind: "explicit",
33
+ tableName: n
34
+ }), {
35
+ kind: "typeid",
36
+ prefix: r
37
+ };
38
+ }
39
+ case "ulid": return { kind: "ulid" };
40
+ case "numeric": return { kind: "numeric" };
41
+ case "snowflake": return { kind: "snowflake" };
42
+ case "custom": return {
43
+ kind: "custom",
44
+ generate: t.generate
45
+ };
46
+ }
47
+ }, o = (e, i) => {
48
+ switch (e.kind) {
49
+ case "typeid": return t(e.prefix);
50
+ case "ulid": return r();
51
+ case "numeric": return null;
52
+ case "snowflake": return n();
53
+ case "custom": return e.generate(i);
54
+ }
55
+ };
56
+ //#endregion
57
+ export { i as deriveTypeIdPrefix, o as generateId, a as resolveIdScheme };
@@ -0,0 +1,32 @@
1
+ //#region src/identifierLimits.ts
2
+ var e = 63, t = 60, n = /* @__PURE__ */ new Set(), r = (e) => {
3
+ n.add(e);
4
+ }, i = () => {
5
+ let e = [...n];
6
+ return n.clear(), e;
7
+ }, a = /^[a-zA-Z_][a-zA-Z0-9_]*$/, o = (e, t) => {
8
+ if (t.length === 0) throw Error(`${e} cannot be empty.`);
9
+ if (!a.test(t)) throw Error(`${e} '${t}' contains characters outside [A-Za-z0-9_] or starts with a digit. Dialect-portable identifiers must match /^[a-zA-Z_][a-zA-Z0-9_]*$/.`);
10
+ }, s = (e) => {
11
+ if (o("table name", e), e.length > 63) throw Error(`table name '${e}' is ${e.length} chars — exceeds the 63-byte cross-dialect limit (Postgres floor). Shorten the name; long table names also cascade into auto-named indexes and FK constraints that would themselves exceed the limit.`);
12
+ e.length > 60 && r(`table name '${e}' is ${e.length} chars — ${63 - e.length} from the Postgres 63-byte limit. Auto-named indexes on this table will run out of room fast.`);
13
+ }, c = (e, t) => {
14
+ if (o("column name", t), t.length > 63) throw Error(`column '${t}' on table '${e}' is ${t.length} chars — exceeds the 63-byte cross-dialect limit (Postgres floor). Rename it.`);
15
+ t.length > 60 && r(`column '${t}' on table '${e}' is ${t.length} chars — close to the 63-byte limit.`);
16
+ }, l = (e, t, n, i) => {
17
+ if (o("index name", t), t.length > 63) throw Error(n ? `auto-named index '${t}' on table '${e}' is ${t.length} chars — exceeds the 63-byte cross-dialect limit (Postgres floor). Supply an explicit short name: .index('<shortName>', ${JSON.stringify([...i])}).` : `index name '${t}' on table '${e}' is ${t.length} chars — exceeds the 63-byte cross-dialect limit (Postgres floor). Shorten it.`);
18
+ t.length > 60 && r(`index '${t}' on table '${e}' is ${t.length} chars — ${63 - t.length} from the 63-byte limit. ${n ? `Consider .index('<shortName>', ${JSON.stringify([...i])}) before it grows.` : ""}`);
19
+ }, u = (e, t) => {
20
+ if (e.length === 0) throw Error(`typeid prefix on table '${t.tableName}' cannot be empty.`);
21
+ if (!/^[a-z][a-z0-9_]*$/.test(e)) {
22
+ let n = t.kind === "derived" ? "the derived prefix doesn't match typeid's required shape — supply an explicit one via id({ prefix: '...' })." : "the prefix must match typeid's required shape /^[a-z][a-z0-9_]*$/.";
23
+ throw Error(`typeid prefix '${e}' on table '${t.tableName}' is invalid — ${n}`);
24
+ }
25
+ if (e.length > 63) {
26
+ let n = t.kind === "derived" ? "shorten the table name, or supply an explicit short prefix via id({ prefix: '...' })." : "pick a shorter prefix.";
27
+ throw Error(`typeid prefix '${e}' on table '${t.tableName}' is ${e.length} chars — exceeds the 63-byte limit; ${n}`);
28
+ }
29
+ e.length > 60 && r(`typeid prefix '${e}' on table '${t.tableName}' is ${e.length} chars — close to the 63-byte limit. Generated ids will be even longer (prefix + '_' + 26).`);
30
+ };
31
+ //#endregion
32
+ export { e as MAX_IDENTIFIER_LENGTH, t as WARN_IDENTIFIER_LENGTH, i as drainIdentifierWarnings, c as validateColumnName, l as validateIndexName, s as validateTableName, u as validateTypeIdPrefix };
package/dist/index.d.ts CHANGED
@@ -17,7 +17,7 @@ import { YieldableError } from 'effect/Cause';
17
17
 
18
18
  /** The store shape this needs — a read, nothing more. */
19
19
  export declare interface ActorLookupStore {
20
- query: (descriptor: unknown) => Promise<ReadonlyArray<Record<string, unknown>>>;
20
+ query: (descriptor: QueryDescriptor) => Promise<ReadonlyArray<Record<string, unknown>>>;
21
21
  }
22
22
 
23
23
  /** The framework's built-in `actors` core table. */
@@ -293,7 +293,8 @@ export declare const AUTO_FILLED_COLUMNS: readonly ["id", "tenantId", "createdAt
293
293
 
294
294
  declare type AutoFilledColumn = (typeof AUTO_FILLED_COLUMNS)[number];
295
295
 
296
- export declare const avg: (column: string, alias?: string) => AggregateColumn;
296
+ /** `AVG(column)` — always a `number` (a mean is not exact), `null` over no rows. */
297
+ export declare const avg: (column: string, alias?: string) => AggregateColumn<number | null>;
297
298
 
298
299
  export declare const avgOver: (column: string, alias?: string) => WindowBuilder;
299
300
 
@@ -905,6 +906,24 @@ export declare const changeUpdate: (table: string, before: Row, after: Row, meta
905
906
  */
906
907
  export declare const chunkRowsForInsert: <T extends Record<string, unknown>>(rows: ReadonlyArray<T>, limits: BulkInsertLimits | undefined) => ReadonlyArray<ReadonlyArray<T>>;
907
908
 
909
+ /**
910
+ * The id of the key a ciphertext names, read off the value without any key —
911
+ * what lets a status count values per key instead of decrypting each one.
912
+ *
913
+ * The id is the LAST `:`-separated part of the envelope
914
+ * (`enc:v2:<r|c>:<iv>:<tag>:<ct>:<kid>`, `enc:v1:<iv>:<tag>:<ct>:<kid>`), after
915
+ * everything a release without key ids reads. That placement is deliberate:
916
+ * such a release takes the first parts and ignores the rest, so during a
917
+ * rolling deploy, and after a rollback, it still reads what the keyring wrote.
918
+ * The id is a lookup hint, not an authenticated field: a value whose id was
919
+ * altered still has to pass GCM under some key of the keyring, and a reader
920
+ * that verifies (the retire gate) decrypts rather than trusts it.
921
+ *
922
+ * `undefined` for a value written before ids, and for anything that is not a
923
+ * ciphertext.
924
+ */
925
+ export declare const ciphertextKeyId: (value: unknown) => string | undefined;
926
+
908
927
  /**
909
928
  * Claim the attribution for an echo, or `undefined` if this write did not
910
929
  * originate here.
@@ -2562,6 +2581,14 @@ export declare interface DataStore {
2562
2581
  * up, on `FluentStore.query`, which is what handlers actually call.
2563
2582
  */
2564
2583
  query(descriptor: QueryDescriptor): Promise<ReadonlyArray<Row>>;
2584
+ /** Server-internal constraint/integrity read on this exact store view.
2585
+ * Bypasses request row visibility only; preserves tenant, deletion/expiry
2586
+ * scopes, codecs, physical namespace and in-flight transaction writes.
2587
+ * Never use its rows as an application response or mutation authorization.
2588
+ * Optional for custom stores: a consumer requiring complete coverage must
2589
+ * refuse when absent, never fall back to an ordinary filtered query.
2590
+ */
2591
+ integrityQuery?(descriptor: QueryDescriptor): Promise<ReadonlyArray<Row>>;
2565
2592
  /** Insert a row. Emits an insert ChangeEvent (deferred if inside `transactional()`). */
2566
2593
  insert(table: string, row: Row): Promise<Row>;
2567
2594
  /**
@@ -2581,8 +2608,14 @@ export declare interface DataStore {
2581
2608
  * - memory store: loop + per-row emit
2582
2609
  *
2583
2610
  * An empty `rows` array is a no-op that returns `[]` (no statement, no events).
2611
+ *
2612
+ * `{ returning: 'none' }` is for a caller that does not read the result: it
2613
+ * resolves to `[]`. The rows are written, and their change events emitted,
2614
+ * exactly as without it; the store reads the inserted rows back only when
2615
+ * change events or an in-transaction recorder need them
2616
+ * (`writeImagesObserved`). A wrapper store forwards `options` unchanged.
2584
2617
  */
2585
- insertMany(table: string, rows: ReadonlyArray<Row>): Promise<ReadonlyArray<Row>>;
2618
+ insertMany(table: string, rows: ReadonlyArray<Row>, options?: InsertManyOptions): Promise<ReadonlyArray<Row>>;
2586
2619
  /**
2587
2620
  * In-place JSON merge: set `value` at `path` inside the JSON column
2588
2621
  * (`path` is the column name, optionally with a nested dot-path, e.g.
@@ -2978,12 +3011,13 @@ export declare interface DataStore {
2978
3011
  * not. Without a savepoint the two are incompatible, so `--atomic` simply
2979
3012
  * could not import such a bundle on those engines.
2980
3013
  *
2981
- * Only the TRANSACTIONAL views implement it, and only for the engines that
2982
- * need it: the mysql family and sqlite leave a transaction usable after a
2983
- * failed statement, so wrapping every row there would buy nothing and cost a
2984
- * round trip per row. Callers guard with `if (store.savepoint)` and run `fn`
2985
- * directly otherwise — which is also correct outside a transaction, where
2986
- * there is nothing to protect.
3014
+ * Every shipped memory and SQL TRANSACTIONAL view implements it. Besides
3015
+ * statement-abort recovery, it isolates a compound operation whose typed
3016
+ * application error may be handled inside the outer transaction. Rollback
3017
+ * discards that operation's buffered committed-change events as well as rows;
3018
+ * earlier events and successful nesting remain intact. Root stores have no
3019
+ * savepoint. Custom stores may omit it; operations requiring local atomicity
3020
+ * must refuse rather than run without protection.
2987
3021
  *
2988
3022
  * Failures propagate: the savepoint is rolled back and the error rethrown, so
2989
3023
  * the caller's own error handling is unchanged.
@@ -3192,6 +3226,9 @@ export declare interface DbOpSample {
3192
3226
  */
3193
3227
  export declare const decimal: (precision: number, scale?: number) => ColumnBuilder<string, "decimal">;
3194
3228
 
3229
+ /** Equality key for exact fixed-point decimal strings; null for invalid input. */
3230
+ export declare const decimalEqualityKey: (value: unknown) => string | null;
3231
+
3195
3232
  /**
3196
3233
  * Declare that an enum value was renamed. Place this NEXT TO the
3197
3234
  * `dbEnum(...)` declaration whose value array now carries the new label:
@@ -3276,6 +3313,12 @@ export declare const decodeRowsForTable: <T extends Record<string, unknown>>(row
3276
3313
  */
3277
3314
  export declare const decodeRowsFromSchema: <T extends Record<string, unknown>>(rows: ReadonlyArray<T>, tableName: string, dialect: DecoderDialectId, query?: QueryDescriptor) => ReadonlyArray<T>;
3278
3315
 
3316
+ /**
3317
+ * Decode the rows of a SELECT: by the query's aggregations when it has them,
3318
+ * by the table's columns otherwise. Every dialect store's read path calls this.
3319
+ */
3320
+ export declare const decodeSelectRows: <T extends Record<string, unknown>>(rows: ReadonlyArray<T>, query: QueryDescriptor, dialect: DecoderDialectId) => ReadonlyArray<T>;
3321
+
3279
3322
  /**
3280
3323
  * Decrypt every `.encrypted()` column's value on read. A value that
3281
3324
  * isn't a framework ciphertext (legacy plaintext, `null`) passes
@@ -3816,6 +3859,9 @@ export declare const encodeFieldValue: (cipher: FieldCipher, value: unknown, bin
3816
3859
  */
3817
3860
  export declare const encodeRowForSchema: <T extends Record<string, unknown>>(row: T, tableName: string, types?: ReadonlyArray<ColumnType>) => T;
3818
3861
 
3862
+ /** 16 bytes → the 26-character lowercase Crockford-base32 suffix of the spec. */
3863
+ export declare const encodeTypeIdSuffix: (src: Uint8Array) => string;
3864
+
3819
3865
  /** The UNBOUND envelope: `enc:v1:<iv>:<tag>:<ct>`. */
3820
3866
  export declare const ENCRYPTED_PREFIX = "enc:v1:";
3821
3867
 
@@ -3975,6 +4021,13 @@ export declare interface FallbackLogger {
3975
4021
  readonly debug: (message: string, fields?: Record<string, unknown>) => void;
3976
4022
  }
3977
4023
 
4024
+ /**
4025
+ * A key id: a short slug, so it can ride inside every envelope. Explicit ids
4026
+ * are chosen by the operator (`VOLTRO_FIELD_ENCRYPTION_KEYS`); derived ids are
4027
+ * `k` + 10 hex characters of a fingerprint that is not the key.
4028
+ */
4029
+ export declare const FIELD_KEY_ID_PATTERN: RegExp;
4030
+
3978
4031
  /**
3979
4032
  * Where a ciphertext BELONGS — the table, the column and, when the row's
3980
4033
  * identity is known at write time, the row. Fed to AES-GCM as additional
@@ -4008,6 +4061,16 @@ export declare interface FieldBinding {
4008
4061
  * its string form and a read of the numeric column agree. */
4009
4062
  export declare const fieldBinding: (table: string, column: string, rowId?: unknown) => FieldBinding;
4010
4063
 
4064
+ /**
4065
+ * Every address a column's values may have been sealed under: its own, and the
4066
+ * names a DECLARED rename says it had — `table('new').renamedFrom('old')`, a
4067
+ * column's `.renamedFrom('old')`. A rename is catalog-only, so the rows keep the
4068
+ * bytes bound to the old name; without this every value of a renamed column
4069
+ * stopped opening. Only declared names are added: a value moved anywhere else
4070
+ * still refuses. The own address comes first — a re-key seals under it.
4071
+ */
4072
+ export declare const fieldBindingsOf: (table: TableLike, column: string, rowId?: unknown) => ReadonlyArray<FieldBinding>;
4073
+
4011
4074
  /** The cipher the store middleware injects. Operates on opaque strings. */
4012
4075
  export declare interface FieldCipher {
4013
4076
  /**
@@ -4030,6 +4093,15 @@ export declare interface FieldCipher {
4030
4093
  * a cipher with one key.
4031
4094
  */
4032
4095
  readonly sealedWithPreviousKey?: (ciphertext: string, binding?: FieldBinding) => boolean;
4096
+ /** The id of the key new values are sealed under — a keyring's active key. */
4097
+ readonly activeKeyId?: string;
4098
+ /**
4099
+ * The id of the key that opens this value: the one the value names when that
4100
+ * key opens it, otherwise the key of the keyring that does (a value written
4101
+ * before ciphertexts carried an id). `undefined` when no key of the keyring
4102
+ * opens it.
4103
+ */
4104
+ readonly keyIdOf?: (ciphertext: string, binding?: FieldBinding) => string | undefined;
4033
4105
  }
4034
4106
 
4035
4107
  /**
@@ -4567,11 +4639,17 @@ export declare type IndexField = string | {
4567
4639
  export declare type IndexKind = 'btree' | 'gist' | 'gin' | 'brin' | 'hnsw';
4568
4640
 
4569
4641
  /**
4570
- * Per-kind tuning options. Today only `hnsw` carries knobs (the pgvector
4571
- * build-time params). `m` controls graph connectivity (default 16),
4642
+ * Per-kind tuning options. GIN supports a single-column operator class;
4643
+ * HNSW supports pgvector build-time parameters. `m` controls graph connectivity (default 16),
4572
4644
  * `efConstruction` the build-time candidate-list size (default 64).
4573
4645
  */
4574
4646
  export declare interface IndexKindOptions {
4647
+ /** PostgreSQL GIN operator class for a single plain column.
4648
+ * `gin_trgm_ops` installs pg_trgm and accelerates contains/ILIKE searches.
4649
+ */
4650
+ readonly gin?: {
4651
+ readonly opclass: string;
4652
+ };
4575
4653
  readonly hnsw?: {
4576
4654
  readonly m?: number;
4577
4655
  readonly efConstruction?: number;
@@ -4708,6 +4786,17 @@ export declare const insertIgnoreRowOutcome: <T extends AnyTable>(store: TypedIn
4708
4786
  readonly outcome: "inserted" | "ignored";
4709
4787
  }>;
4710
4788
 
4789
+ /** Options of {@link DataStore.insertMany}. */
4790
+ export declare interface InsertManyOptions {
4791
+ /**
4792
+ * `'rows'` (the default) resolves to the inserted rows as stored. `'none'`
4793
+ * resolves to `[]`, so a store need not send the rows back: a bulk insert
4794
+ * into a table no change event or recorder observes then costs one
4795
+ * statement per chunk and no result rows.
4796
+ */
4797
+ readonly returning?: 'rows' | 'none';
4798
+ }
4799
+
4711
4800
  /**
4712
4801
  * Insert MANY rows, typed against the table — `insertRow`'s batch, and nothing
4713
4802
  * else: it forwards to `store.insertMany` unchanged, so the chunking, the
@@ -4728,8 +4817,9 @@ export declare const insertIgnoreRowOutcome: <T extends AnyTable>(store: TypedIn
4728
4817
  *
4729
4818
  * An empty array is a legal no-op, so a caller does not have to guard the call
4730
4819
  * — `store.insertMany` decides what that means, and it means "insert nothing".
4820
+ * `{ returning: 'none' }` is forwarded as well: it resolves to `[]`.
4731
4821
  */
4732
- export declare const insertManyRows: <T extends AnyTable>(store: TypedInsertManyStore, table: T, rows: ReadonlyArray<InferInsertRow<T>>) => Promise<ReadonlyArray<InferRow<T>>>;
4822
+ export declare const insertManyRows: <T extends AnyTable>(store: TypedInsertManyStore, table: T, rows: ReadonlyArray<InferInsertRow<T>>, options?: InsertManyOptions) => Promise<ReadonlyArray<InferRow<T>>>;
4733
4823
 
4734
4824
  /**
4735
4825
  * Insert a row, typed against the table: the payload must carry every required
@@ -6175,6 +6265,10 @@ Joins extends JoinsMap = {}> {
6175
6265
  * on sqlite (its writers are serialised already).
6176
6266
  */
6177
6267
  forUpdate: () => Query<RowOf, IxNames, Joins>;
6268
+ /** Hold a shared SQL row lock until transaction end; concurrent readers may
6269
+ * proceed. SQLite-family stores retain their transaction isolation without
6270
+ * row-lock SQL, and memory retains optimistic validation. */
6271
+ forShare: () => Query<RowOf, IxNames, Joins>;
6178
6272
  /**
6179
6273
  * Cross-tenant: opt OUT of the runtime's automatic
6180
6274
  * `tenantId = <subject.tenantId>` scope on `tenant()` tables. Use for
@@ -6534,6 +6628,11 @@ Joins extends JoinsMap = {}> {
6534
6628
  export declare interface QueryDescriptor<R = Row> {
6535
6629
  readonly table: string;
6536
6630
  readonly predicate: Predicate | undefined;
6631
+ /** Additional reactive invalidation sources, independent of SQL row selection.
6632
+ * The runtime merges a query handler's declared `source` tables here. Changes
6633
+ * to these tables recheck subscription authority even when SQL rows do not
6634
+ * change. They add no joins, predicates or cross-tenant access. */
6635
+ readonly dependentTables?: ReadonlyArray<string>;
6537
6636
  /** Phantom — carries the row type through to `store.query()`. Never set at
6538
6637
  * runtime; erased entirely by the compiler. */
6539
6638
  readonly __row?: R;
@@ -6550,13 +6649,14 @@ export declare interface QueryDescriptor<R = Row> {
6550
6649
  readonly includeExpired?: boolean;
6551
6650
  /**
6552
6651
  * Lock the matched rows for the rest of the enclosing transaction — set by
6553
- * `.forUpdate()`. `SELECT … FOR UPDATE` on postgres / mysql / mariadb,
6554
- * `WITH (UPDLOCK, ROWLOCK)` on mssql; sqlite serialises writers already and
6652
+ * `.forUpdate()` for exclusive intent, `.forShare()` for concurrent readers
6653
+ * that must fence writers. SQL dialects retain the lock until transaction end;
6654
+ * sqlite serialises writers already and
6555
6655
  * emits nothing. Outside a transaction the lock is released as the statement
6556
6656
  * ends, which is harmless and useless — the point is a read-modify-write
6557
6657
  * whose read and write share one transaction.
6558
6658
  */
6559
- readonly lock?: 'update';
6659
+ readonly lock?: 'update' | 'share';
6560
6660
  /**
6561
6661
  * Opt OUT of the runtime's automatic tenant scope on `tenant()` tables.
6562
6662
  * Set by `.unscoped()`. Honored by the runtime, same as `includeDeleted`.
@@ -7052,6 +7152,15 @@ export declare interface ReferenceOptions {
7052
7152
  readonly column?: string;
7053
7153
  }
7054
7154
 
7155
+ /**
7156
+ * Refuse an UPDATE that changes the id of a row with `.encrypted()` columns.
7157
+ * Each sealed value is bound to its row's id: an update that moved the row to a
7158
+ * new id left every sealed value in it bound to the old one, reported success,
7159
+ * and from then on every read of the row failed. Move such a row by writing it
7160
+ * under the new id (insert, then delete the old one) — the store seals it there.
7161
+ */
7162
+ export declare const refuseIdChangeOfSealedRow: (patch: Row, table: TableLike | undefined, rowId: unknown) => void;
7163
+
7055
7164
  /**
7056
7165
  * Build the error a dialect store throws when the framework refuses a write.
7057
7166
  *
@@ -7275,7 +7384,10 @@ export declare const resolveActorSnapshot: (store: ActorLookupStore, subjectId:
7275
7384
  export declare type ResolveAggregateResult<A, RowOf, Joins extends JoinsMap> = A extends {
7276
7385
  readonly op: 'min' | 'max';
7277
7386
  readonly column: infer C extends string;
7278
- } ? ResolveJoinedSource<C, RowOf, Joins> | null : A extends AggregateColumn<infer T> ? T : never;
7387
+ } ? ResolveJoinedSource<C, RowOf, Joins> | null : A extends {
7388
+ readonly op: 'sum';
7389
+ readonly column: infer C extends string;
7390
+ } ? [NonNullable<ResolveJoinedSource<C, RowOf, Joins>>] extends [string] ? string | null : number | null : A extends AggregateColumn<infer T> ? T : never;
7279
7391
 
7280
7392
  /**
7281
7393
  * Pick the branch mechanism. Prioritises the Neon copy-on-write fast-path when
@@ -7470,12 +7582,12 @@ declare type Row_2 = Readonly<Record<string, unknown>>;
7470
7582
  declare type Row_3 = Readonly<Record<string, unknown>>;
7471
7583
 
7472
7584
  /** Addresses one row: its `id`, or the columns of an explicit primary key. */
7473
- export declare type RowKey = string | Readonly<Record<string, unknown>>;
7585
+ export declare type RowKey = string | number | Readonly<Record<string, unknown>>;
7474
7586
 
7475
7587
  /**
7476
7588
  * The `(column, value)` pairs a key addresses, in declaration order.
7477
7589
  *
7478
- * A string is the `id` column — that is the contract every existing caller
7590
+ * A scalar is the `id` column — that is the contract every existing caller
7479
7591
  * relies on, and widening it must not change what a string means.
7480
7592
  */
7481
7593
  export declare const rowKeyColumns: (key: RowKey) => ReadonlyArray<readonly [string, unknown]>;
@@ -8374,7 +8486,13 @@ export declare interface SubqueryInPredicate {
8374
8486
  */
8375
8487
  export declare type SubqueryResults = Map< QueryDescriptor, Set<unknown> | number>;
8376
8488
 
8377
- export declare const sum: (column: string, alias?: string) => AggregateColumn;
8489
+ /** `SUM(column)` — a `number` over `integer()` / `real()`, the exact decimal
8490
+ * STRING over `decimal()` / `bigint()` (the column's own type), `null` over no
8491
+ * rows. On a typed query the result type follows the column. */
8492
+ export declare const sum: <C extends string>(column: C, alias?: string) => AggregateColumn<number | null> & {
8493
+ readonly op: "sum";
8494
+ readonly column: C;
8495
+ };
8378
8496
 
8379
8497
  export declare const sumOver: (column: string, alias?: string) => WindowBuilder;
8380
8498
 
@@ -8914,8 +9032,8 @@ export declare interface TableIndex {
8914
9032
  */
8915
9033
  readonly kind?: IndexKind;
8916
9034
  /**
8917
- * Per-kind tuning knobs. Today only `hnsw` (`kindOptions.hnsw.{m,
8918
- * efConstruction, opclass}`). Ignored for kinds that don't read it.
9035
+ * Per-kind tuning: `gin.opclass` or `hnsw.{m, efConstruction, opclass}`.
9036
+ * Ignored for kinds that do not read the corresponding options.
8919
9037
  */
8920
9038
  readonly kindOptions?: IndexKindOptions;
8921
9039
  /**
@@ -9266,7 +9384,7 @@ export declare interface TypedInsertIgnoreOutcomeStore {
9266
9384
 
9267
9385
  /** The minimal store surface `insertManyRows` needs. */
9268
9386
  export declare interface TypedInsertManyStore {
9269
- readonly insertMany: (table: string, rows: ReadonlyArray<Row>) => Promise<ReadonlyArray<Row>>;
9387
+ readonly insertMany: (table: string, rows: ReadonlyArray<Row>, options?: InsertManyOptions) => Promise<ReadonlyArray<Row>>;
9270
9388
  }
9271
9389
 
9272
9390
  /** The minimal store surface `insertRow` needs — satisfied by `ctx.store`. */
@@ -9294,6 +9412,14 @@ export declare interface TypedUpsertStore {
9294
9412
  readonly upsert: (table: string, row: Row, options: UpsertOptions) => Promise<Row>;
9295
9413
  }
9296
9414
 
9415
+ /**
9416
+ * A fresh TypeID for `prefix`: `user_01h455vb4pex5vsknk084sn02q`. This is what
9417
+ * the `typeid` id scheme writes on insert; call it yourself when a row's id
9418
+ * has to exist before the insert (a self-referencing `createdBy`, a child row
9419
+ * written in the same flow).
9420
+ */
9421
+ export declare const typeId: (prefix: string) => string;
9422
+
9297
9423
  /**
9298
9424
  * `(SELECT ...) UNION (SELECT ...) ...` — dedup-merge. Q6.
9299
9425
  *
@@ -9449,6 +9575,9 @@ export declare const upsertUpdatePatch: (row: Row, existing: Row, options: Upser
9449
9575
  /** Shared driver lowering: omit undefined values and refuse identity rewrites. */
9450
9576
  export declare const upsertUpdateValues: (options: UpsertOptions) => Record<string, unknown>;
9451
9577
 
9578
+ /** The 16 bytes of a fresh UUIDv7 (RFC 9562), monotonic within this process. */
9579
+ export declare const uuidV7Bytes: (now?: number) => Uint8Array;
9580
+
9452
9581
  /**
9453
9582
  * Validate one column-name key on a table's fields map. Throws on
9454
9583
  * empty / invalid characters / > 63 bytes. Records a WARN above 50.
@@ -9695,6 +9824,9 @@ export declare const VOLTRO_LOCAL_FIRST_MIXIN_ID: "voltro/localFirst";
9695
9824
  */
9696
9825
  export declare const _voltroApiKeysTable: SchemaTable;
9697
9826
 
9827
+ /** Finalized role-observation history survives graceful replica shutdown. */
9828
+ export declare const _voltroApiRoleWorkloadBucketsTable: SchemaTable;
9829
+
9698
9830
  export declare const _voltroCdcOffsetsTable: TableLike;
9699
9831
 
9700
9832
  /**
@@ -9990,6 +10122,18 @@ export declare interface WriteAttribution {
9990
10122
  readonly via?: 'agent';
9991
10123
  }
9992
10124
 
10125
+ /**
10126
+ * Does anything read the row images of a write to `table`? A set-based write
10127
+ * (`updateMany` / `deleteMany`) answers with a count; the stores fetch its rows
10128
+ * back — `RETURNING *`, `OUTPUT`, a SELECT first — only to hand them to change
10129
+ * events and in-transaction recorders. A `.nonReactive()` table that no
10130
+ * recorder watches has neither, and the rows then crossed the wire for nobody:
10131
+ * every retired aggregate generation, `rowData` included, on every refresh.
10132
+ *
10133
+ * Asked per statement, not cached: recorders register and suspend at runtime.
10134
+ */
10135
+ export declare const writeImagesObserved: (table: string) => boolean;
10136
+
9993
10137
  export declare type WriteRecorder = (port: TxnRecorderPort, write: RecordedWrite) => Promise<void>;
9994
10138
 
9995
10139
  /** Are recorders suspended right here? Exported so a caller can SAY so. */