@substrat-run/kernel 0.138.0 → 0.140.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 (164) hide show
  1. package/dist/admin-log-ddl.d.ts +21 -0
  2. package/dist/admin-log-ddl.d.ts.map +1 -0
  3. package/dist/admin-log-ddl.js +32 -0
  4. package/dist/admin-log-ddl.js.map +1 -0
  5. package/dist/attachment-extractor.d.ts +21 -2
  6. package/dist/attachment-extractor.d.ts.map +1 -1
  7. package/dist/attachment-extractor.js +31 -6
  8. package/dist/attachment-extractor.js.map +1 -1
  9. package/dist/attachment-text.d.ts +64 -0
  10. package/dist/attachment-text.d.ts.map +1 -1
  11. package/dist/attachment-text.js +87 -16
  12. package/dist/attachment-text.js.map +1 -1
  13. package/dist/attribution.d.ts +36 -3
  14. package/dist/attribution.d.ts.map +1 -1
  15. package/dist/attribution.js +21 -8
  16. package/dist/attribution.js.map +1 -1
  17. package/dist/audit-outcome.d.ts +149 -0
  18. package/dist/audit-outcome.d.ts.map +1 -0
  19. package/dist/audit-outcome.js +233 -0
  20. package/dist/audit-outcome.js.map +1 -0
  21. package/dist/connect-links.d.ts +91 -0
  22. package/dist/connect-links.d.ts.map +1 -0
  23. package/dist/connect-links.js +189 -0
  24. package/dist/connect-links.js.map +1 -0
  25. package/dist/connect-state.d.ts +12 -3
  26. package/dist/connect-state.d.ts.map +1 -1
  27. package/dist/connect-state.js +8 -3
  28. package/dist/connect-state.js.map +1 -1
  29. package/dist/derived-object.d.ts +14 -0
  30. package/dist/derived-object.d.ts.map +1 -0
  31. package/dist/derived-object.js +2 -0
  32. package/dist/derived-object.js.map +1 -0
  33. package/dist/derived-objects.d.ts +108 -0
  34. package/dist/derived-objects.d.ts.map +1 -0
  35. package/dist/derived-objects.js +199 -0
  36. package/dist/derived-objects.js.map +1 -0
  37. package/dist/email-intent.d.ts +56 -0
  38. package/dist/email-intent.d.ts.map +1 -0
  39. package/dist/email-intent.js +71 -0
  40. package/dist/email-intent.js.map +1 -0
  41. package/dist/entity-edges.d.ts +6 -1
  42. package/dist/entity-edges.d.ts.map +1 -1
  43. package/dist/entity-edges.js +13 -0
  44. package/dist/entity-edges.js.map +1 -1
  45. package/dist/entity-grant-shape.d.ts +94 -0
  46. package/dist/entity-grant-shape.d.ts.map +1 -0
  47. package/dist/entity-grant-shape.js +329 -0
  48. package/dist/entity-grant-shape.js.map +1 -0
  49. package/dist/entity-grant.d.ts +45 -0
  50. package/dist/entity-grant.d.ts.map +1 -0
  51. package/dist/entity-grant.js +71 -0
  52. package/dist/entity-grant.js.map +1 -0
  53. package/dist/entity-state-reads.d.ts +40 -0
  54. package/dist/entity-state-reads.d.ts.map +1 -0
  55. package/dist/entity-state-reads.js +91 -0
  56. package/dist/entity-state-reads.js.map +1 -0
  57. package/dist/entity-state.d.ts +204 -0
  58. package/dist/entity-state.d.ts.map +1 -0
  59. package/dist/entity-state.js +356 -0
  60. package/dist/entity-state.js.map +1 -0
  61. package/dist/entity-trash.d.ts +245 -0
  62. package/dist/entity-trash.d.ts.map +1 -0
  63. package/dist/entity-trash.js +380 -0
  64. package/dist/entity-trash.js.map +1 -0
  65. package/dist/findings.d.ts +143 -0
  66. package/dist/findings.d.ts.map +1 -0
  67. package/dist/findings.js +463 -0
  68. package/dist/findings.js.map +1 -0
  69. package/dist/grant-scoped-read.d.ts +41 -0
  70. package/dist/grant-scoped-read.d.ts.map +1 -0
  71. package/dist/grant-scoped-read.js +100 -0
  72. package/dist/grant-scoped-read.js.map +1 -0
  73. package/dist/index.d.ts +40 -8
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +26 -6
  76. package/dist/index.js.map +1 -1
  77. package/dist/kernel-outbox.d.ts +14 -0
  78. package/dist/kernel-outbox.d.ts.map +1 -0
  79. package/dist/kernel-outbox.js +37 -0
  80. package/dist/kernel-outbox.js.map +1 -0
  81. package/dist/list-index.d.ts +34 -3
  82. package/dist/list-index.d.ts.map +1 -1
  83. package/dist/list-index.js +83 -31
  84. package/dist/list-index.js.map +1 -1
  85. package/dist/mail-sender.d.ts +78 -0
  86. package/dist/mail-sender.d.ts.map +1 -0
  87. package/dist/mail-sender.js +2 -0
  88. package/dist/mail-sender.js.map +1 -0
  89. package/dist/membership-executor.d.ts +7 -47
  90. package/dist/membership-executor.d.ts.map +1 -1
  91. package/dist/membership-executor.js +28 -53
  92. package/dist/membership-executor.js.map +1 -1
  93. package/dist/migration-digest.d.ts +161 -0
  94. package/dist/migration-digest.d.ts.map +1 -0
  95. package/dist/migration-digest.js +237 -0
  96. package/dist/migration-digest.js.map +1 -0
  97. package/dist/module-erasure.d.ts +156 -0
  98. package/dist/module-erasure.d.ts.map +1 -0
  99. package/dist/module-erasure.js +440 -0
  100. package/dist/module-erasure.js.map +1 -0
  101. package/dist/module-migrations.d.ts +6 -3
  102. package/dist/module-migrations.d.ts.map +1 -1
  103. package/dist/module-migrations.js +12 -5
  104. package/dist/module-migrations.js.map +1 -1
  105. package/dist/peer.d.ts +9 -1
  106. package/dist/peer.d.ts.map +1 -1
  107. package/dist/peer.js +29 -0
  108. package/dist/peer.js.map +1 -1
  109. package/dist/permission-checker.d.ts +6 -0
  110. package/dist/permission-checker.d.ts.map +1 -1
  111. package/dist/permission-checker.js.map +1 -1
  112. package/dist/permission-eval.d.ts +51 -1
  113. package/dist/permission-eval.d.ts.map +1 -1
  114. package/dist/permission-eval.js +104 -2
  115. package/dist/permission-eval.js.map +1 -1
  116. package/dist/platform-sweep.d.ts +8 -2
  117. package/dist/platform-sweep.d.ts.map +1 -1
  118. package/dist/platform-sweep.js +17 -0
  119. package/dist/platform-sweep.js.map +1 -1
  120. package/dist/scope-host.d.ts +479 -24
  121. package/dist/scope-host.d.ts.map +1 -1
  122. package/dist/scope-host.js +82 -7
  123. package/dist/scope-host.js.map +1 -1
  124. package/dist/scope-role-admin.d.ts +68 -0
  125. package/dist/scope-role-admin.d.ts.map +1 -0
  126. package/dist/scope-role-admin.js +80 -0
  127. package/dist/scope-role-admin.js.map +1 -0
  128. package/dist/search-index.d.ts +21 -1
  129. package/dist/search-index.d.ts.map +1 -1
  130. package/dist/search-index.js +60 -37
  131. package/dist/search-index.js.map +1 -1
  132. package/dist/spine-guard.d.ts +71 -2
  133. package/dist/spine-guard.d.ts.map +1 -1
  134. package/dist/spine-guard.js +393 -10
  135. package/dist/spine-guard.js.map +1 -1
  136. package/dist/spine-restore.d.ts.map +1 -1
  137. package/dist/spine-restore.js +5 -0
  138. package/dist/spine-restore.js.map +1 -1
  139. package/dist/sql-identifier.d.ts +12 -0
  140. package/dist/sql-identifier.d.ts.map +1 -0
  141. package/dist/sql-identifier.js +17 -0
  142. package/dist/sql-identifier.js.map +1 -0
  143. package/dist/sql-statements.d.ts +71 -0
  144. package/dist/sql-statements.d.ts.map +1 -0
  145. package/dist/sql-statements.js +191 -0
  146. package/dist/sql-statements.js.map +1 -0
  147. package/dist/subject-redaction.d.ts +9 -1
  148. package/dist/subject-redaction.d.ts.map +1 -1
  149. package/dist/subject-redaction.js.map +1 -1
  150. package/dist/system-switch-record.d.ts +3 -0
  151. package/dist/system-switch-record.d.ts.map +1 -1
  152. package/dist/system-switch-record.js +2 -0
  153. package/dist/system-switch-record.js.map +1 -1
  154. package/dist/table-ownership.d.ts +103 -0
  155. package/dist/table-ownership.d.ts.map +1 -0
  156. package/dist/table-ownership.js +285 -0
  157. package/dist/table-ownership.js.map +1 -0
  158. package/dist/timeline.d.ts +4 -4
  159. package/dist/timeline.js +4 -4
  160. package/dist/visible-continuation.d.ts +38 -0
  161. package/dist/visible-continuation.d.ts.map +1 -0
  162. package/dist/visible-continuation.js +162 -0
  163. package/dist/visible-continuation.js.map +1 -0
  164. package/package.json +2 -2
@@ -33,7 +33,9 @@
33
33
  * registry the fields are checked against. So there is no second description of
34
34
  * where a customer lives — the model already said it.
35
35
  */
36
+ import type { DerivedObject } from './derived-object.js';
36
37
  import type { SqlMigration } from './scope-host.js';
38
+ import type { EntityStateName } from '@substrat-run/contracts';
37
39
  /** How a declared searchable is matched. `prefix` unless it says otherwise. */
38
40
  export type SearchTokenizer = 'prefix' | 'substring';
39
41
  /**
@@ -71,6 +73,12 @@ export interface SearchHit {
71
73
  export interface SearchOptions {
72
74
  /** Defaults to `DEFAULT_SEARCH_LIMIT`, capped at `MAX_SEARCH_LIMIT`. */
73
75
  readonly limit?: number;
76
+ /**
77
+ * Which rows (#119): `active` when unset, so an archived or trashed row never surfaces in a
78
+ * picker nobody asked to show it in. `archived` asks for the archive. The bin is not here —
79
+ * `ctx.searchTrashed` reads it, checking the declared trash key per hit.
80
+ */
81
+ readonly view?: Exclude<EntityStateName, 'trashed'>;
74
82
  }
75
83
  /**
76
84
  * A typeahead wants ten rows, not ten thousand. The cap is the design: a ranked
@@ -148,6 +156,11 @@ export declare function searchIndexPlans(moduleId: string, searchables: readonly
148
156
  * rebuild at the end reconstructs it from rows that never moved.
149
157
  */
150
158
  export declare function searchIndexDdl(plan: SearchIndexPlan): string;
159
+ /**
160
+ * What `searchIndexDdl` creates, each with its CREATE statement: the FTS table, then the three
161
+ * triggers that keep it in step (insert, delete, update).
162
+ */
163
+ export declare function searchIndexObjects(plan: SearchIndexPlan): DerivedObject[];
151
164
  /**
152
165
  * The migrations that provision a module's declared indexes, journaled like any
153
166
  * other so a scope applies them once and a changed declaration re-applies.
@@ -162,6 +175,8 @@ export declare function searchIndexDdl(plan: SearchIndexPlan): string;
162
175
  * the content table exist by the time the trigger references it.
163
176
  */
164
177
  export declare function searchIndexMigrations(moduleId: string, searchables: readonly SearchableDeclaration[] | undefined): SqlMigration[];
178
+ /** One plan's migration version — the declaration itself, as above. */
179
+ export declare const searchIndexVersion: (plan: SearchIndexPlan) => string;
165
180
  /**
166
181
  * Index the plans by entity type for a whole scope, refusing an ambiguity.
167
182
  *
@@ -213,7 +228,12 @@ export declare function searchMatchExpression(term: string, tokenizer: SearchTok
213
228
  * aliasing it to `idx` and writing `WHERE idx MATCH ?` fails at prepare time with
214
229
  * "no such column: idx". Found by running the emitted SQL rather than reading it.
215
230
  */
216
- export declare function searchQuery(plan: SearchIndexPlan, match: string, limit: number): {
231
+ export declare function searchQuery(plan: SearchIndexPlan, match: string, limit: number,
232
+ /**
233
+ * A further predicate over the source row, aliased `src` — the archive/trash view (#119).
234
+ * Applied BEFORE the limit, so hiding rows never shortens a ranked top-N.
235
+ */
236
+ where?: string): {
217
237
  sql: string;
218
238
  params: [string, number];
219
239
  };
@@ -1 +1 @@
1
- {"version":3,"file":"search-index.d.ts","sourceRoot":"","sources":["../src/search-index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search-index.d.ts","sourceRoot":"","sources":["../src/search-index.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { assertSqlIdentifier } from './sql-identifier.js';
1
2
  /**
2
3
  * A typeahead wants ten rows, not ten thousand. The cap is the design: a ranked
3
4
  * result set has no stable sort key, so it has no honest cursor either — Stripe
@@ -36,20 +37,7 @@ export class NotSearchable extends Error {
36
37
  this.name = 'NotSearchable';
37
38
  }
38
39
  }
39
- /**
40
- * SQL identifiers reach the DDL by interpolation — there is no parameter form for
41
- * a table or column name — so every one of them is checked against this first.
42
- * The inputs are declarations rather than user input, but a declaration is still
43
- * a string somebody typed, and "it came from the manifest" is exactly the
44
- * reasoning that makes an injection a surprise.
45
- */
46
- const IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
47
- function assertIdentifier(kind, value, where) {
48
- if (!IDENTIFIER.test(value)) {
49
- throw new Error(`search: ${where} names ${kind} '${value}', which is not a plain SQL identifier`);
50
- }
51
- return value;
52
- }
40
+ const assertIdentifier = (kind, value, where) => assertSqlIdentifier('search', kind, value, where);
53
41
  /** `@acme/vertical` → `acme_vertical`: an id is not an identifier, and the index table needs one. */
54
42
  function slug(value) {
55
43
  return value.replace(/[^A-Za-z0-9]+/g, '_').replace(/^_+|_+$/g, '').toLowerCase();
@@ -147,31 +135,59 @@ function tokenizeClause(tokenizer) {
147
135
  * rebuild at the end reconstructs it from rows that never moved.
148
136
  */
149
137
  export function searchIndexDdl(plan) {
138
+ const [table, ...triggers] = searchIndexObjects(plan);
139
+ return [
140
+ ...triggers.map((t) => `DROP TRIGGER IF EXISTS ${t.name};`),
141
+ `DROP TABLE IF EXISTS ${table.name};`,
142
+ `${table.sql};`,
143
+ ...triggers.map((t) => `${t.sql};`),
144
+ `INSERT INTO ${plan.indexTable}(${plan.indexTable}) VALUES('rebuild');`,
145
+ ].join('\n');
146
+ }
147
+ /**
148
+ * What `searchIndexDdl` creates, each with its CREATE statement: the FTS table, then the three
149
+ * triggers that keep it in step (insert, delete, update).
150
+ */
151
+ export function searchIndexObjects(plan) {
150
152
  const idx = plan.indexTable;
151
153
  const cols = plan.fields.join(', ');
152
154
  const newCols = plan.fields.map((f) => `new.${f}`).join(', ');
153
155
  const oldCols = plan.fields.map((f) => `old.${f}`).join(', ');
156
+ const trigger = (suffix, lines) => ({
157
+ name: `${idx}_${suffix}`,
158
+ type: 'trigger',
159
+ table: plan.table,
160
+ sql: lines.join('\n'),
161
+ });
154
162
  return [
155
- `DROP TRIGGER IF EXISTS ${idx}_ai;`,
156
- `DROP TRIGGER IF EXISTS ${idx}_ad;`,
157
- `DROP TRIGGER IF EXISTS ${idx}_au;`,
158
- `DROP TABLE IF EXISTS ${idx};`,
159
- `CREATE VIRTUAL TABLE ${idx} USING fts5(`,
160
- ` ${cols},`,
161
- ` content='${plan.table}', content_rowid='rowid', ${tokenizeClause(plan.tokenizer)}`,
162
- `);`,
163
- `CREATE TRIGGER ${idx}_ai AFTER INSERT ON ${plan.table} BEGIN`,
164
- ` INSERT INTO ${idx}(rowid, ${cols}) VALUES (new.rowid, ${newCols});`,
165
- `END;`,
166
- `CREATE TRIGGER ${idx}_ad AFTER DELETE ON ${plan.table} BEGIN`,
167
- ` INSERT INTO ${idx}(${idx}, rowid, ${cols}) VALUES('delete', old.rowid, ${oldCols});`,
168
- `END;`,
169
- `CREATE TRIGGER ${idx}_au AFTER UPDATE ON ${plan.table} BEGIN`,
170
- ` INSERT INTO ${idx}(${idx}, rowid, ${cols}) VALUES('delete', old.rowid, ${oldCols});`,
171
- ` INSERT INTO ${idx}(rowid, ${cols}) VALUES (new.rowid, ${newCols});`,
172
- `END;`,
173
- `INSERT INTO ${idx}(${idx}) VALUES('rebuild');`,
174
- ].join('\n');
163
+ {
164
+ name: idx,
165
+ type: 'table',
166
+ table: idx,
167
+ sql: [
168
+ `CREATE VIRTUAL TABLE ${idx} USING fts5(`,
169
+ ` ${cols},`,
170
+ ` content='${plan.table}', content_rowid='rowid', ${tokenizeClause(plan.tokenizer)}`,
171
+ `)`,
172
+ ].join('\n'),
173
+ },
174
+ trigger('ai', [
175
+ `CREATE TRIGGER ${idx}_ai AFTER INSERT ON ${plan.table} BEGIN`,
176
+ ` INSERT INTO ${idx}(rowid, ${cols}) VALUES (new.rowid, ${newCols});`,
177
+ `END`,
178
+ ]),
179
+ trigger('ad', [
180
+ `CREATE TRIGGER ${idx}_ad AFTER DELETE ON ${plan.table} BEGIN`,
181
+ ` INSERT INTO ${idx}(${idx}, rowid, ${cols}) VALUES('delete', old.rowid, ${oldCols});`,
182
+ `END`,
183
+ ]),
184
+ trigger('au', [
185
+ `CREATE TRIGGER ${idx}_au AFTER UPDATE ON ${plan.table} BEGIN`,
186
+ ` INSERT INTO ${idx}(${idx}, rowid, ${cols}) VALUES('delete', old.rowid, ${oldCols});`,
187
+ ` INSERT INTO ${idx}(rowid, ${cols}) VALUES (new.rowid, ${newCols});`,
188
+ `END`,
189
+ ]),
190
+ ];
175
191
  }
176
192
  /**
177
193
  * The migrations that provision a module's declared indexes, journaled like any
@@ -188,10 +204,12 @@ export function searchIndexDdl(plan) {
188
204
  */
189
205
  export function searchIndexMigrations(moduleId, searchables) {
190
206
  return searchIndexPlans(moduleId, searchables).map((plan) => ({
191
- version: `search/${plan.entityType}:${plan.tokenizer}:${plan.fields.join('+')}`,
207
+ version: searchIndexVersion(plan),
192
208
  sql: searchIndexDdl(plan),
193
209
  }));
194
210
  }
211
+ /** One plan's migration version — the declaration itself, as above. */
212
+ export const searchIndexVersion = (plan) => `search/${plan.entityType}:${plan.tokenizer}:${plan.fields.join('+')}`;
195
213
  /**
196
214
  * Index the plans by entity type for a whole scope, refusing an ambiguity.
197
215
  *
@@ -271,12 +289,17 @@ export function searchMatchExpression(term, tokenizer) {
271
289
  * aliasing it to `idx` and writing `WHERE idx MATCH ?` fails at prepare time with
272
290
  * "no such column: idx". Found by running the emitted SQL rather than reading it.
273
291
  */
274
- export function searchQuery(plan, match, limit) {
292
+ export function searchQuery(plan, match, limit,
293
+ /**
294
+ * A further predicate over the source row, aliased `src` — the archive/trash view (#119).
295
+ * Applied BEFORE the limit, so hiding rows never shortens a ranked top-N.
296
+ */
297
+ where) {
275
298
  const idx = plan.indexTable;
276
299
  return {
277
300
  sql: `SELECT src.${plan.idColumn} AS id, bm25(${idx}) AS rank ` +
278
301
  `FROM ${idx} JOIN ${plan.table} src ON src.rowid = ${idx}.rowid ` +
279
- `WHERE ${idx} MATCH ? ORDER BY rank LIMIT ?`,
302
+ `WHERE ${idx} MATCH ?${where ? ` AND ${where}` : ''} ORDER BY rank LIMIT ?`,
280
303
  params: [match, limit],
281
304
  };
282
305
  }
@@ -1 +1 @@
1
- {"version":3,"file":"search-index.js","sourceRoot":"","sources":["../src/search-index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search-index.js","sourceRoot":"","sources":["../src/search-index.ts"],"names":[],"mappings":"AAqCA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAoD1D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAEpC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAoC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;AAE5F,2FAA2F;AAC3F,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACtB,OAAO;IAA5B,YAAqB,OAAe;QAClC,KAAK,CAAC,oCAAoC,OAAO,4CAA4C,CAAC,CAAC;uBAD5E,OAAO;QAE1B,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,0EAA0E;AAC1E,MAAM,OAAO,aAAc,SAAQ,KAAK;IACjB,UAAU;IAA/B,YAAqB,UAAkB;QACrC,KAAK,CACH,YAAY,UAAU,2DAA2D;YAC/E,4DAA4D,CAC/D,CAAC;0BAJiB,UAAU;QAK7B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAE,KAAa,EAAE,KAAa,EAAU,EAAE,CAC9E,mBAAmB,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAEpD,qGAAqG;AACrG,SAAS,IAAI,CAAC,KAAa;IACzB,OAAO,KAAK,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AACpF,CAAC;AAED,8EAA8E;AAC9E,MAAM,CAAC,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,OAAO,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,QAAgB,EAChB,WAAyD;IAEzD,IAAI,CAAC,WAAW,EAAE,MAAM;QAAE,OAAO,EAAE,CAAC;IACpC,MAAM,KAAK,GAAsB,EAAE,CAAC;IACpC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,GAAG,QAAQ,iBAAiB,IAAI,CAAC,UAAU,IAAI,CAAC;QAC9D,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACb,WAAW,KAAK,yEAAyE;gBACvF,yDAAyD,CAC5D,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,WAAW,KAAK,qBAAqB,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC7D,MAAM,QAAQ,GAAG,gBAAgB,CAAC,cAAc,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,KAAK,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QAC7E,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,WAAW,KAAK,uBAAuB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/E,CAAC;QACD,KAAK,CAAC,IAAI,CAAC;YACT,QAAQ;YACR,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,KAAK;YACL,QAAQ;YACR,MAAM;YACN,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,QAAQ;YACrC,UAAU,EAAE,oBAAoB,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;SAC1E,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,cAAc,CAAC,SAA0B;IAChD,OAAO,SAAS,KAAK,WAAW;QAC9B,CAAC,CAAC,oBAAoB;QACtB,CAAC,CAAC,oCAAoC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAAC,IAAqB;IAClD,MAAM,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACtD,OAAO;QACL,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,0BAA0B,CAAC,CAAC,IAAI,GAAG,CAAC;QAC3D,wBAAwB,KAAM,CAAC,IAAI,GAAG;QACtC,GAAG,KAAM,CAAC,GAAG,GAAG;QAChB,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;QACnC,eAAe,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,sBAAsB;KACxE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAqB;IACtD,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,CAAC,MAAc,EAAE,KAAe,EAAiB,EAAE,CAAC,CAAC;QACnE,IAAI,EAAE,GAAG,GAAG,IAAI,MAAM,EAAE;QACxB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;KACtB,CAAC,CAAC;IACH,OAAO;QACL;YACE,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,GAAG;YACV,GAAG,EAAE;gBACH,wBAAwB,GAAG,cAAc;gBACzC,KAAK,IAAI,GAAG;gBACZ,cAAc,IAAI,CAAC,KAAK,6BAA6B,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;gBACrF,GAAG;aACJ,CAAC,IAAI,CAAC,IAAI,CAAC;SACb;QACD,OAAO,CAAC,IAAI,EAAE;YACZ,kBAAkB,GAAG,uBAAuB,IAAI,CAAC,KAAK,QAAQ;YAC9D,iBAAiB,GAAG,WAAW,IAAI,wBAAwB,OAAO,IAAI;YACtE,KAAK;SACN,CAAC;QACF,OAAO,CAAC,IAAI,EAAE;YACZ,kBAAkB,GAAG,uBAAuB,IAAI,CAAC,KAAK,QAAQ;YAC9D,iBAAiB,GAAG,IAAI,GAAG,YAAY,IAAI,iCAAiC,OAAO,IAAI;YACvF,KAAK;SACN,CAAC;QACF,OAAO,CAAC,IAAI,EAAE;YACZ,kBAAkB,GAAG,uBAAuB,IAAI,CAAC,KAAK,QAAQ;YAC9D,iBAAiB,GAAG,IAAI,GAAG,YAAY,IAAI,iCAAiC,OAAO,IAAI;YACvF,iBAAiB,GAAG,WAAW,IAAI,wBAAwB,OAAO,IAAI;YACtE,KAAK;SACN,CAAC;KACH,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAgB,EAChB,WAAyD;IAEzD,OAAO,gBAAgB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC5D,OAAO,EAAE,kBAAkB,CAAC,IAAI,CAAC;QACjC,GAAG,EAAE,cAAc,CAAC,IAAI,CAAC;KAC1B,CAAC,CAAC,CAAC;AACN,CAAC;AAED,uEAAuE;AACvE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,IAAqB,EAAU,EAAE,CAClE,UAAU,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAGzE;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAAoG;IAEpG,MAAM,MAAM,GAAG,IAAI,GAAG,EAA2B,CAAC;IAClD,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,KAAK,MAAM,IAAI,IAAI,gBAAgB,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7D,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC7C,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CACb,YAAY,IAAI,CAAC,UAAU,qCAAqC,QAAQ,CAAC,QAAQ,QAAQ;oBACvF,IAAI,IAAI,CAAC,QAAQ,4CAA4C,CAChE,CAAC;YACJ,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY,EAAE,SAA0B;IAC5E,MAAM,OAAO,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvE,+EAA+E;IAC/E,oEAAoE;IACpE,MAAM,KAAK,GAAG,SAAS,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACvF,6EAA6E;IAC7E,+EAA+E;IAC/E,qCAAqC;IACrC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC;QAAE,MAAM,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACnF,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;QAC7C,4EAA4E;QAC5E,4DAA4D;QAC5D,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;IAC3E,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CACzB,IAAqB,EACrB,KAAa,EACb,KAAa;AACb;;;GAGG;AACH,KAAc;IAEd,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC;IAC5B,OAAO;QACL,GAAG,EACD,cAAc,IAAI,CAAC,QAAQ,gBAAgB,GAAG,YAAY;YAC1D,QAAQ,GAAG,SAAS,IAAI,CAAC,KAAK,uBAAuB,GAAG,SAAS;YACjE,SAAS,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,wBAAwB;QAC7E,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC;KACvB,CAAC;AACJ,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,WAAW,CAAC,SAA6B;IACvD,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,oBAAoB,CAAC;IACzD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC;QAAE,OAAO,oBAAoB,CAAC;IAC9E,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC,CAAC;AAC3D,CAAC"}
@@ -6,7 +6,68 @@ import type { ScopedSql } from './scope-host.js';
6
6
  * is a fault in the module, not in the caller's permissions, and the message names
7
7
  * the table so the author sees which line to delete.
8
8
  */
9
- export declare function assertNoSpineWrite(sql: string): void;
9
+ export declare function assertNoSpineWrite(sql: string, statefulTables?: ReadonlySet<string>): void;
10
+ /**
11
+ * Refuse runtime DDL that would take a stateful table's guarantees away (#119, Codex r3).
12
+ *
13
+ * #1811 made a module's own DDL through `ctx.sql` a supported path, and it stays one. But a table
14
+ * that carries archive/trash state is guarded by derived triggers ON THAT TABLE, and DDL can move
15
+ * the rows out from under them: `ALTER TABLE docs RENAME TO x; CREATE TABLE docs AS SELECT …,
16
+ * NULL AS _substrat_trashed_at FROM x` un-trashes everything with no move and no event. So, for a
17
+ * stateful table, in any spelling — quoted, any case, `main.`/`temp.`-qualified:
18
+ *
19
+ * - `ALTER TABLE <it>` that renames the table or a column, or drops a column; and `RENAME TO <it>`
20
+ * from another table;
21
+ * - `DROP TABLE <it>`;
22
+ * - `CREATE [TEMP] TABLE|VIEW <it>` — a temp object of the same name SHADOWS the real table in
23
+ * every unqualified reference, the kernel's own included;
24
+ * - `CREATE [TEMP] TRIGGER … ON <it>`.
25
+ *
26
+ * Plus, for any table, a trigger, index or view carrying the reserved prefix (the kernel's derived
27
+ * objects), and `ATTACH`/`DETACH` outright: nothing in module code needs a second database, and an
28
+ * attached one is a second place a stateful name can resolve. Ordinary runtime DDL — a module's own
29
+ * unrelated tables, an index on a stateful table, an added column — is untouched.
30
+ */
31
+ export declare function assertNoStatefulDdl(sql: string, statefulTables: ReadonlySet<string>): void;
32
+ /**
33
+ * Whether `pieces` — `splitSqlStatements(sql)` — are the whole of `sql`: each found, in order, as
34
+ * an unaltered substring, and nothing left between or after them but whitespace, `;` and
35
+ * comments. The splitter never rewrites text, so this holds by construction; it is the check a
36
+ * multi-statement call is refused on rather than run in pieces nobody can account for.
37
+ */
38
+ export declare function piecesReproduce(sql: string, pieces: readonly string[]): boolean;
39
+ /** Does this SQL change the schema — any statement in it a CREATE, ALTER or DROP? */
40
+ export declare function changesSchema(sql: string): boolean;
41
+ /**
42
+ * Refuse a statement that WRITES a `_substrat_*` column of a module's own table (#119).
43
+ *
44
+ * The kernel keeps state on module rows — `_substrat_archived_at`, `_substrat_trashed_at` —
45
+ * and a row's way into or out of the trash must be `ctx.trash`/`ctx.restore`, which check the
46
+ * declared key and emit the event. A module that could `UPDATE todo_lists SET
47
+ * _substrat_trashed_at = NULL` would restore without the key and without a record, which is
48
+ * the forgery the table rule above exists to stop, one level down.
49
+ *
50
+ * Judged by POSITION, so reading the columns stays allowed — in a `SELECT`, and in the `WHERE`
51
+ * of a write (`UPDATE … SET done = 1 WHERE _substrat_trashed_at IS NULL`). Refused:
52
+ *
53
+ * - an assignment target after `SET` — `UPDATE … SET`, an upsert's `DO UPDATE SET`, and a
54
+ * trigger body's `UPDATE`, row-value targets `SET (a, b) = …` included;
55
+ * - a name in an `INSERT`/`REPLACE` column list;
56
+ * - any reserved name in an `ALTER TABLE` (add, rename or drop the column itself);
57
+ * - into a table that CARRIES the columns (`statefulTables`, lowercased names): an `INSERT`
58
+ * with no column list — `VALUES (…)` and `SELECT …` fill the columns by position, the
59
+ * reserved ones included, without ever naming them — and any `REPLACE` / `INSERT OR
60
+ * REPLACE`, which deletes the existing row and writes a new one with the columns NULL, so
61
+ * it un-archives and un-trashes without the key. An `INSERT … (columns) SELECT` and an
62
+ * upsert's `DO UPDATE SET` are judged by the rules above.
63
+ *
64
+ * Below this sits a trigger on each such table that refuses a row born archived or trashed
65
+ * (`entityStateMigrations`), so a form this scan misses still cannot set the state.
66
+ *
67
+ * The prefix is reserved whole, not the two names: the next kernel-owned column is covered
68
+ * without anyone remembering to list it here.
69
+ */
70
+ export declare function assertNoReservedColumnWrite(sql: string, statefulTables?: ReadonlySet<string>): void;
10
71
  /**
11
72
  * Refuse a statement whose `REFERENCES` clause names a `_substrat_*` table (#1898), for the
12
73
  * same reason `CREATE TRIGGER … ON` is refused above: the spine's rows become the parent of a
@@ -24,5 +85,13 @@ export declare function assertNoSpineReference(sql: string, what: string): void;
24
85
  * first. `query` is guarded too: SQLite runs `INSERT … RETURNING` perfectly well
25
86
  * through a `.all()`, so guarding only `exec` would leave the door open.
26
87
  */
27
- export declare function guardSpine(inner: ScopedSql): ScopedSql;
88
+ export declare function guardSpine(inner: ScopedSql,
89
+ /** The module tables that carry archive/trash columns (#119), lowercased — see `assertNoReservedColumnWrite`. */
90
+ statefulTables?: ReadonlySet<string>,
91
+ /**
92
+ * Run after any statement that changed the schema passed (#119, Codex r3): the kernel's own
93
+ * check that every stateful table still carries what it derived. It throws to fail closed —
94
+ * the operation, and the DDL with it, roll back.
95
+ */
96
+ afterDdl?: () => void): ScopedSql;
28
97
  //# sourceMappingURL=spine-guard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spine-guard.d.ts","sourceRoot":"","sources":["../src/spine-guard.ts"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,iBAAiB,CAAC;AAsD3D;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAsBpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAEtE;AAcD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAWtD"}
1
+ {"version":3,"file":"spine-guard.d.ts","sourceRoot":"","sources":["../src/spine-guard.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,iBAAiB,CAAC;AAsD3D;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAwB1F;AAYD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CA+E1F;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAS/E;AAED,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAelD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAgJnG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAEtE;AAcD;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,SAAS;AAChB,iHAAiH;AACjH,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC;AACpC;;;;GAIG;AACH,QAAQ,CAAC,EAAE,MAAM,IAAI,GACpB,SAAS,CAyCX"}