@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
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Subject erasure inside a module's OWN tables (#2068) — the half of open question 17 that
3
+ * K-37 left named and unbuilt.
4
+ *
5
+ * `shredSubject` redacts the spine and destroys the key that seals the platform's copies. A
6
+ * module's rows were outside that, and §13.1 said so (limit 2). This file brings them in, two
7
+ * ways, both run by the kernel in the SAME transaction as the spine redaction and before the
8
+ * key is destroyed:
9
+ *
10
+ * - **Declared.** An entity names its subject columns beside its `erasable` fields
11
+ * (`erasure: { subjects }`, `subject-erasure.ts` in contracts), and the kernel blanks those
12
+ * fields — or deletes the row — wherever a subject column equals the id. No module code
13
+ * runs, so a vertical gets the right behaviour by declaring, and a declaration cannot forget
14
+ * a column the way a hand-written UPDATE can.
15
+ * - **A hook.** `onSubjectErased(ctx, { subjectId })` on the registration, for a link the row
16
+ * does not hold itself (a rating reached through its conversation). It is narrow on purpose:
17
+ * a `sql` that reaches the module's own tables and nothing else, and `now()`. No emit — an
18
+ * event about the erasure would be a new immutable copy of what is being erased — no
19
+ * check, grant, link or platform request, and no await: it is synchronous, so it runs inside
20
+ * the erasure's one transaction and nothing interleaves with it.
21
+ *
22
+ * **Failure is all or nothing.** A hook that throws rolls the whole scope-side unit back, the
23
+ * spine redaction with it, and the erasure throws before the key is touched or a receipt is
24
+ * written. Nothing claims an erasure that did not happen, and a re-run converges: a declared
25
+ * blank skips rows already blank, and a hook is idempotent by contract.
26
+ *
27
+ * **Derived stores.** A search index over an erased column is kept in step by its own triggers,
28
+ * but FTS5 keeps a deleted row's terms in older index segments until they merge — the words
29
+ * are still in the database file, findable by anyone reading the shadow tables. So the erasure
30
+ * runs with FTS5's `secure-delete` on for the indexes over the erasing modules' tables, which
31
+ * removes each entry where it sits rather than recording its deletion. A list index is an ordinary b-tree and loses the old value with the
32
+ * UPDATE. What neither reaches — free pages SQLite has not reused, and attachment text — is
33
+ * written down in kernel-design.md §13.1 rather than implied.
34
+ */
35
+ import { type ErasedEntityCount, type ErasureHookCount, type SubjectErasureDeclaration, type UnreachedEntity } from '@substrat-run/contracts';
36
+ import type { ModuleRegistration, ScopedSql } from './scope-host.js';
37
+ import type { SearchIndexPlan } from './search-index.js';
38
+ /** What a module's `onSubjectErased` hook is handed — and all it is handed. */
39
+ export interface SubjectErasureContext {
40
+ /**
41
+ * The module's own tables, and only those — the ones its migrations create: a statement
42
+ * naming any other table in the scope (another module's, a view, a TEMP object, the spine)
43
+ * is refused before it runs, reads included. Only `SELECT`, `UPDATE`, `DELETE`, `INSERT` and
44
+ * `REPLACE`; no `WITH`, no DDL, no `PRAGMA`. Revoked when the hook returns: a call after that
45
+ * throws and writes nothing.
46
+ */
47
+ readonly sql: ScopedSql;
48
+ /** The erasure's instant, the same one the spine's tombstones carry. Revoked with `sql`. */
49
+ now(): string;
50
+ }
51
+ /**
52
+ * A module's own erasure step (#2068). Synchronous and returning nothing — a promise, an
53
+ * iterator or any other returned value refuses the whole erasure — and
54
+ * idempotent: an erasure is re-run after any failure, so a second call for the same subject
55
+ * must find nothing left to do.
56
+ */
57
+ export type OnSubjectErased = (ctx: SubjectErasureContext, subject: {
58
+ readonly subjectId: string;
59
+ }) => void;
60
+ /** One registered module's erasure, validated once at registration. */
61
+ export interface ModuleErasurePlan {
62
+ readonly moduleId: string;
63
+ readonly declaration: SubjectErasureDeclaration;
64
+ readonly hook?: OnSubjectErased;
65
+ /**
66
+ * The tables this module's erasure may touch, lowercased: the declaration's, each one VERIFIED
67
+ * at registration to be created by the module's own migrations. The hook's whole reach.
68
+ */
69
+ readonly ownTables: ReadonlySet<string>;
70
+ }
71
+ /** What the module half of one erasure did — the receipt's three new lines. */
72
+ export interface ModuleErasureCounts {
73
+ verticalRows: ErasedEntityCount[];
74
+ hookRows: ErasureHookCount[];
75
+ unreachedEntities: UnreachedEntity[];
76
+ }
77
+ /**
78
+ * The tables a module's own migration TEXT creates, lowercased — read at registration, where no
79
+ * scope exists yet, as early feedback only: it can refuse a module whose erasure names a table it
80
+ * plainly never creates, and it never grants anything. `CREATE TABLE IF NOT EXISTS` on another
81
+ * module's table reads as a creation here and creates nothing in a scope, which is why the
82
+ * authority is the ownership each scope RECORDS as its migrations run (`table-ownership.ts`),
83
+ * checked by the erasure itself before it writes.
84
+ */
85
+ export declare function tablesCreatedBy(migrations: readonly {
86
+ readonly sql: string;
87
+ }[]): Set<string>;
88
+ /**
89
+ * The erasure plan for one registration, or undefined when it has nothing to erase. Throws,
90
+ * at registration, for every way a module can claim an erasure it cannot deliver, or one that
91
+ * would reach past itself:
92
+ *
93
+ * - a hook with no `manifest.erasure` — the hook's reach IS that block's `tables`, and a hook
94
+ * with no reach declared is refused rather than handed the whole scope;
95
+ * - an entity declared `custom` with no hook to reach it;
96
+ * - an entity the erasure would write (`blank`, `delete`, `custom`) on a table the module's own
97
+ * migrations do not create, and — when there is a hook — any table in its reach that they do
98
+ * not create. The declaration is a claim; the migrations are what the kernel ran. A misdeclared
99
+ * entity naming another module's table would otherwise have that table erased through the
100
+ * kernel's own handle. An `unreached` entity writes nothing and is not held to it.
101
+ */
102
+ export declare function moduleErasurePlan(registration: ModuleRegistration): ModuleErasurePlan | undefined;
103
+ /**
104
+ * Refuse a hook statement that reaches past the module's own tables (#2068).
105
+ *
106
+ * An ALLOWLIST, judged where a table can stand: every name in a table position — after `FROM`,
107
+ * `JOIN`, `INTO` and `UPDATE`, and each further name in a comma-joined `FROM` list, at any
108
+ * nesting depth — must be one of `own`, unqualified. Whatever else the scope holds — another
109
+ * module's table, a view, a TEMP object, the spine — is refused without having to be listed,
110
+ * so nothing the schema grows later widens the reach. Also refused: a qualified name
111
+ * (`main.x`, `temp.x`), a table-valued function other than `json_each`/`json_tree`, `WITH`
112
+ * (a CTE could shadow an own table's name), and any spine- or `sqlite_`-prefixed name
113
+ * anywhere. Every statement chained after a `;` starts with an allowed verb.
114
+ *
115
+ * It errs toward refusing: a name in a table position that is not a table at all
116
+ * (`a IS DISTINCT FROM b`) is held to the allowlist too, and fails closed with a message.
117
+ */
118
+ export declare function assertWithinErasureReach(moduleId: string, sql: string, own: ReadonlySet<string>): void;
119
+ /**
120
+ * The oldest SQLite that may run an erasure over a search index (#2068): FTS5 `secure-delete`
121
+ * arrived in 3.42.0, and an index deleted from under it is recorded at FTS5 format version 5,
122
+ * which no older SQLite can read. A dump never carries a search index (it is rebuilt on load),
123
+ * so the reader that matters is the runtime holding the scope's own file.
124
+ */
125
+ export declare const SECURE_DELETE_MIN_SQLITE = "3.42.0";
126
+ /**
127
+ * Run the module half of one erasure: every declared entity, then every hook, with FTS5's
128
+ * `secure-delete` on for the search indexes over those modules' tables. `sql` is the kernel's
129
+ * own handle on the scope — never module code's — and the caller holds it inside the
130
+ * transaction the spine redaction runs in, so a throw from here rolls both back.
131
+ *
132
+ * Order between the two halves: declared first, hooks after, so a hook reading a declared
133
+ * entity sees it already blank and a hook that deletes cannot strand a declared blank. Order
134
+ * between modules is registration order, which nothing here depends on: each touches its own
135
+ * tables only.
136
+ */
137
+ export declare function eraseSubjectFromModules(input: {
138
+ readonly sql: ScopedSql;
139
+ readonly plans: readonly ModuleErasurePlan[];
140
+ readonly searchPlans: Iterable<SearchIndexPlan>;
141
+ /** The module tables carrying archive/trash columns (#119), lowercased — `guardSpine`'s. */
142
+ readonly statefulTables?: ReadonlySet<string>;
143
+ readonly subjectId: string;
144
+ readonly at: string;
145
+ /** A registered module's migration text, for backfilling a scope migrated before ownership was recorded. */
146
+ readonly migrationSqlOf: (moduleId: string, version: string) => string | undefined;
147
+ }): ModuleErasureCounts;
148
+ /** Every row the module half changed — what the access log adds to "how much evidence this destroyed". */
149
+ export declare function moduleRowsErased(counts: ModuleErasureCounts): number;
150
+ /**
151
+ * Whether a host's reply carries the module half (#2068) in the shape this kernel wrote — what a
152
+ * coordinator checks before destroying the key, so a host built before the half existed is
153
+ * refused rather than read as having reached nothing.
154
+ */
155
+ export declare function isModuleErasureCounts(value: unknown): value is ModuleErasureCounts;
156
+ //# sourceMappingURL=module-erasure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-erasure.d.ts","sourceRoot":"","sources":["../src/module-erasure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EAKL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,EAC9B,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAY,MAAM,iBAAiB,CAAC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAKzD,+EAA+E;AAC/E,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC;IACxB,4FAA4F;IAC5F,GAAG,IAAI,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,qBAAqB,EAAE,OAAO,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,CAAC;AAE5G,uEAAuE;AACvE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,yBAAyB,CAAC;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACzC;AAED,+EAA+E;AAC/E,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,iBAAiB,EAAE,eAAe,EAAE,CAAC;CACtC;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,SAAS;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAW5F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,SAAS,CAyCjG;AAkBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAqEtG;AAoCD;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,WAAW,CAAC;AA0BjD;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE;IAC7C,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC7C,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IAChD,4FAA4F;IAC5F,QAAQ,CAAC,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,4GAA4G;IAC5G,QAAQ,CAAC,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CACpF,GAAG,mBAAmB,CAgJtB;AAED,0GAA0G;AAC1G,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CAIlF"}
@@ -0,0 +1,440 @@
1
+ /**
2
+ * Subject erasure inside a module's OWN tables (#2068) — the half of open question 17 that
3
+ * K-37 left named and unbuilt.
4
+ *
5
+ * `shredSubject` redacts the spine and destroys the key that seals the platform's copies. A
6
+ * module's rows were outside that, and §13.1 said so (limit 2). This file brings them in, two
7
+ * ways, both run by the kernel in the SAME transaction as the spine redaction and before the
8
+ * key is destroyed:
9
+ *
10
+ * - **Declared.** An entity names its subject columns beside its `erasable` fields
11
+ * (`erasure: { subjects }`, `subject-erasure.ts` in contracts), and the kernel blanks those
12
+ * fields — or deletes the row — wherever a subject column equals the id. No module code
13
+ * runs, so a vertical gets the right behaviour by declaring, and a declaration cannot forget
14
+ * a column the way a hand-written UPDATE can.
15
+ * - **A hook.** `onSubjectErased(ctx, { subjectId })` on the registration, for a link the row
16
+ * does not hold itself (a rating reached through its conversation). It is narrow on purpose:
17
+ * a `sql` that reaches the module's own tables and nothing else, and `now()`. No emit — an
18
+ * event about the erasure would be a new immutable copy of what is being erased — no
19
+ * check, grant, link or platform request, and no await: it is synchronous, so it runs inside
20
+ * the erasure's one transaction and nothing interleaves with it.
21
+ *
22
+ * **Failure is all or nothing.** A hook that throws rolls the whole scope-side unit back, the
23
+ * spine redaction with it, and the erasure throws before the key is touched or a receipt is
24
+ * written. Nothing claims an erasure that did not happen, and a re-run converges: a declared
25
+ * blank skips rows already blank, and a hook is idempotent by contract.
26
+ *
27
+ * **Derived stores.** A search index over an erased column is kept in step by its own triggers,
28
+ * but FTS5 keeps a deleted row's terms in older index segments until they merge — the words
29
+ * are still in the database file, findable by anyone reading the shadow tables. So the erasure
30
+ * runs with FTS5's `secure-delete` on for the indexes over the erasing modules' tables, which
31
+ * removes each entry where it sits rather than recording its deletion. A list index is an ordinary b-tree and loses the old value with the
32
+ * UPDATE. What neither reaches — free pages SQLite has not reused, and attachment text — is
33
+ * written down in kernel-design.md §13.1 rather than implied.
34
+ */
35
+ import { namesSpineTable, substratError, subjectErasureDeclaration, tokenizeSql, } from '@substrat-run/contracts';
36
+ import { guardSpine } from './spine-guard.js';
37
+ import { assertSqlIdentifier } from './sql-identifier.js';
38
+ import { assertTablesOwned, tableStatements } from './table-ownership.js';
39
+ /**
40
+ * The tables a module's own migration TEXT creates, lowercased — read at registration, where no
41
+ * scope exists yet, as early feedback only: it can refuse a module whose erasure names a table it
42
+ * plainly never creates, and it never grants anything. `CREATE TABLE IF NOT EXISTS` on another
43
+ * module's table reads as a creation here and creates nothing in a scope, which is why the
44
+ * authority is the ownership each scope RECORDS as its migrations run (`table-ownership.ts`),
45
+ * checked by the erasure itself before it writes.
46
+ */
47
+ export function tablesCreatedBy(migrations) {
48
+ const owned = new Set();
49
+ for (const migration of migrations) {
50
+ for (const st of tableStatements(migration.sql)) {
51
+ if (st.kind === 'create')
52
+ owned.add(st.table);
53
+ else if (st.kind === 'rename') {
54
+ if (owned.delete(st.from))
55
+ owned.add(st.to);
56
+ }
57
+ else
58
+ owned.delete(st.table);
59
+ }
60
+ }
61
+ return owned;
62
+ }
63
+ /**
64
+ * The erasure plan for one registration, or undefined when it has nothing to erase. Throws,
65
+ * at registration, for every way a module can claim an erasure it cannot deliver, or one that
66
+ * would reach past itself:
67
+ *
68
+ * - a hook with no `manifest.erasure` — the hook's reach IS that block's `tables`, and a hook
69
+ * with no reach declared is refused rather than handed the whole scope;
70
+ * - an entity declared `custom` with no hook to reach it;
71
+ * - an entity the erasure would write (`blank`, `delete`, `custom`) on a table the module's own
72
+ * migrations do not create, and — when there is a hook — any table in its reach that they do
73
+ * not create. The declaration is a claim; the migrations are what the kernel ran. A misdeclared
74
+ * entity naming another module's table would otherwise have that table erased through the
75
+ * kernel's own handle. An `unreached` entity writes nothing and is not held to it.
76
+ */
77
+ export function moduleErasurePlan(registration) {
78
+ const { manifest, onSubjectErased: hook } = registration;
79
+ if (hook !== undefined && typeof hook !== 'function') {
80
+ throw new Error(`${manifest.id}: onSubjectErased must be a function`);
81
+ }
82
+ if (!manifest.erasure) {
83
+ if (hook) {
84
+ throw new Error(`${manifest.id}: onSubjectErased is registered but the manifest declares no \`erasure\` — the ` +
85
+ "hook's reach is that block's `tables`. Spread `manifestEntities(...)` into the manifest");
86
+ }
87
+ return undefined;
88
+ }
89
+ const declaration = subjectErasureDeclaration.parse(manifest.erasure);
90
+ const custom = declaration.entities.filter((e) => e.mode === 'custom');
91
+ if (custom.length && !hook) {
92
+ throw new Error(`${manifest.id}: ${custom.map((e) => e.entityType).join(', ')} declare${custom.length === 1 ? 's' : ''} ` +
93
+ "`erasure: { mode: 'custom' }` but the module registers no onSubjectErased hook to reach them");
94
+ }
95
+ const created = tablesCreatedBy(registration.migrations ?? []);
96
+ const claimed = [
97
+ ...declaration.entities.filter((e) => e.mode !== 'unreached').map((e) => e.table),
98
+ ...(hook ? declaration.tables : []),
99
+ ];
100
+ const foreign = [...new Set(claimed.filter((t) => !created.has(t.toLowerCase())))];
101
+ if (foreign.length) {
102
+ throw new Error(`${manifest.id}: its erasure names ${foreign.map((t) => `'${t}'`).join(', ')}, which its own migrations ` +
103
+ 'do not create — an erasure reaches only the tables a module owns. Create the table in this ' +
104
+ "module's migrations, or leave the entity without an `erasure`");
105
+ }
106
+ return {
107
+ moduleId: manifest.id,
108
+ declaration,
109
+ ...(hook ? { hook } : {}),
110
+ ownTables: new Set(claimed.map((t) => t.toLowerCase())),
111
+ };
112
+ }
113
+ /** The statements a hook may run. Everything else — DDL, PRAGMA, ATTACH, VACUUM, WITH — is refused. */
114
+ const HOOK_VERBS = new Set(['select', 'update', 'delete', 'insert', 'replace']);
115
+ /** The only table-valued functions a hook may name in a FROM: they read the row's own JSON. */
116
+ const TABLE_FUNCTIONS = new Set(['json_each', 'json_tree']);
117
+ /** Words that end a FROM list (or an UPDATE / INTO target) — what follows them is no table. */
118
+ const ENDS_TABLE_LIST = new Set([
119
+ 'set', 'where', 'on', 'using', 'group', 'order', 'limit', 'values', 'select', 'returning',
120
+ 'union', 'except', 'intersect', 'default', 'having', 'window', 'left', 'right', 'full',
121
+ 'inner', 'cross', 'natural', 'outer',
122
+ ]);
123
+ /** The conflict clause words between `UPDATE` and its table: `UPDATE OR IGNORE t`. */
124
+ const CONFLICT_WORDS = new Set(['or', 'rollback', 'abort', 'replace', 'fail', 'ignore']);
125
+ /**
126
+ * Refuse a hook statement that reaches past the module's own tables (#2068).
127
+ *
128
+ * An ALLOWLIST, judged where a table can stand: every name in a table position — after `FROM`,
129
+ * `JOIN`, `INTO` and `UPDATE`, and each further name in a comma-joined `FROM` list, at any
130
+ * nesting depth — must be one of `own`, unqualified. Whatever else the scope holds — another
131
+ * module's table, a view, a TEMP object, the spine — is refused without having to be listed,
132
+ * so nothing the schema grows later widens the reach. Also refused: a qualified name
133
+ * (`main.x`, `temp.x`), a table-valued function other than `json_each`/`json_tree`, `WITH`
134
+ * (a CTE could shadow an own table's name), and any spine- or `sqlite_`-prefixed name
135
+ * anywhere. Every statement chained after a `;` starts with an allowed verb.
136
+ *
137
+ * It errs toward refusing: a name in a table position that is not a table at all
138
+ * (`a IS DISTINCT FROM b`) is held to the allowlist too, and fails closed with a message.
139
+ */
140
+ export function assertWithinErasureReach(moduleId, sql, own) {
141
+ const refuse = (what) => {
142
+ throw substratError('forbidden', `${moduleId}: onSubjectErased reaches its own module's tables only — refused ${what}`, { reason: 'erasure_reach' });
143
+ };
144
+ const tokens = tokenizeSql(sql, { punctuation: true });
145
+ const stack = [];
146
+ let f = { expect: false, clause: null, inList: false };
147
+ let start = true;
148
+ let prev = '';
149
+ for (let i = 0; i < tokens.length; i += 1) {
150
+ const token = tokens[i];
151
+ if (token.punct) {
152
+ if (token.text === ';') {
153
+ start = true;
154
+ stack.length = 0;
155
+ f = { expect: false, clause: null, inList: false };
156
+ }
157
+ else if (token.text === '(') {
158
+ // A subquery in a FROM position stands where a table would: once it closes, the outer
159
+ // list continues after it, so a `, other` that follows is still judged.
160
+ stack.push(f.expect ? { expect: false, clause: f.clause, inList: true } : { ...f, expect: false });
161
+ f = { expect: false, clause: null, inList: false };
162
+ }
163
+ else if (token.text === ')') {
164
+ f = stack.pop() ?? { expect: false, clause: null, inList: false };
165
+ }
166
+ else if (token.text === ',' && f.inList && f.clause === 'from') {
167
+ f = { ...f, expect: true, inList: false };
168
+ }
169
+ continue;
170
+ }
171
+ const word = token.quoted ? '' : token.text.toLowerCase();
172
+ for (const part of token.text.split('.')) {
173
+ const name = part.toLowerCase();
174
+ if (namesSpineTable(name) || name.startsWith('sqlite_'))
175
+ refuse(`'${part}'`);
176
+ }
177
+ if (start) {
178
+ start = false;
179
+ if (!HOOK_VERBS.has(word))
180
+ refuse(`the statement: ${sql.slice(0, 60)}`);
181
+ }
182
+ if (word === 'with')
183
+ refuse('WITH — a common table expression could shadow a table name');
184
+ if (f.expect) {
185
+ if (f.clause === 'update' && CONFLICT_WORDS.has(word))
186
+ continue;
187
+ const next = tokens[i + 1];
188
+ if (f.clause === 'from' && next?.punct && next.text === '(') {
189
+ if (!TABLE_FUNCTIONS.has(word))
190
+ refuse(`the table-valued function '${token.text}'`);
191
+ }
192
+ else if (token.text.includes('.')) {
193
+ refuse(`the qualified name '${token.text}'`);
194
+ }
195
+ else if (!own.has(token.text.toLowerCase())) {
196
+ refuse(`'${token.text}', which is not one of its tables`);
197
+ }
198
+ f = { ...f, expect: false, inList: true };
199
+ }
200
+ else if (word === 'from' || word === 'join') {
201
+ f = { expect: true, clause: 'from', inList: false };
202
+ }
203
+ else if (word === 'into') {
204
+ f = { expect: true, clause: 'into', inList: false };
205
+ }
206
+ else if (word === 'update' && prev !== 'do') {
207
+ f = { expect: true, clause: 'update', inList: false };
208
+ }
209
+ else if (f.inList && ENDS_TABLE_LIST.has(word)) {
210
+ f = { ...f, inList: false };
211
+ }
212
+ prev = word;
213
+ }
214
+ }
215
+ /**
216
+ * Refuse the erasure when a TEMP object carries the name of a table it is about to touch: an
217
+ * unqualified name resolves to the temp schema first, so the declared write or the hook would
218
+ * land on the shadow. A host whose SQLite will not show its temp schema (a Durable Object) has
219
+ * none for anything to have made.
220
+ */
221
+ function assertNoTempShadow(sql, tables) {
222
+ let temp;
223
+ try {
224
+ temp = sql.query('SELECT name FROM temp.sqlite_master');
225
+ }
226
+ catch {
227
+ return;
228
+ }
229
+ const shadow = temp.map((r) => r.name).find((n) => tables.has(n.toLowerCase()));
230
+ if (shadow) {
231
+ throw substratError('precondition_failed', `erasure: a TEMP object '${shadow}' shadows a module table this erasure would touch — nothing was erased`);
232
+ }
233
+ }
234
+ /**
235
+ * What the statement just run changed, as SQLite counts it: `changes()` is that statement's own
236
+ * rows and never a trigger's; `total_changes()` is the connection's running count, compared and
237
+ * never reported. Read rather than taken from the handle's exec result because the two adapters
238
+ * disagree there — a Durable Object's `rowsWritten` counts every index and FTS trigger write
239
+ * too — and a receipt must say the same number whichever host erased.
240
+ */
241
+ function changeCounts(sql) {
242
+ const row = sql.query('SELECT changes() AS c, total_changes() AS t')[0];
243
+ return { changes: row?.c ?? 0, total: row?.t ?? 0 };
244
+ }
245
+ /**
246
+ * The oldest SQLite that may run an erasure over a search index (#2068): FTS5 `secure-delete`
247
+ * arrived in 3.42.0, and an index deleted from under it is recorded at FTS5 format version 5,
248
+ * which no older SQLite can read. A dump never carries a search index (it is rebuilt on load),
249
+ * so the reader that matters is the runtime holding the scope's own file.
250
+ */
251
+ export const SECURE_DELETE_MIN_SQLITE = '3.42.0';
252
+ /**
253
+ * Switch `secure-delete` on for one index, or refuse the erasure if this SQLite cannot.
254
+ *
255
+ * A capability probe rather than a version check, because a Durable Object will not run
256
+ * `sqlite_version()`. The probe is exact anyway: an FTS5 older than 3.42.0 has no
257
+ * `secure-delete` command and rejects it, and that rejection comes before anything is written
258
+ * to the index's table, so the erasure fails closed — nothing erased, and no index left at a
259
+ * format the runtime holding it could not read back.
260
+ */
261
+ function enableSecureDelete(sql, idx) {
262
+ try {
263
+ sql.exec(`INSERT INTO ${idx}(${idx}, rank) VALUES('secure-delete', 1)`);
264
+ }
265
+ catch (err) {
266
+ throw substratError('precondition_failed', `erasure: erasing from a search index needs FTS5 secure-delete (SQLite ${SECURE_DELETE_MIN_SQLITE}+), ` +
267
+ `which this host's SQLite refused (${err instanceof Error ? err.message : String(err)}) — nothing was erased`);
268
+ }
269
+ }
270
+ /** A name the kernel interpolates — re-checked here, never trusted from a manifest. */
271
+ const ident = (name) => assertSqlIdentifier('erasure', 'an identifier', name, 'a module erasure');
272
+ /**
273
+ * Run the module half of one erasure: every declared entity, then every hook, with FTS5's
274
+ * `secure-delete` on for the search indexes over those modules' tables. `sql` is the kernel's
275
+ * own handle on the scope — never module code's — and the caller holds it inside the
276
+ * transaction the spine redaction runs in, so a throw from here rolls both back.
277
+ *
278
+ * Order between the two halves: declared first, hooks after, so a hook reading a declared
279
+ * entity sees it already blank and a hook that deletes cannot strand a declared blank. Order
280
+ * between modules is registration order, which nothing here depends on: each touches its own
281
+ * tables only.
282
+ */
283
+ export function eraseSubjectFromModules(input) {
284
+ const { sql, plans, subjectId, at } = input;
285
+ const out = { verticalRows: [], hookRows: [], unreachedEntities: [] };
286
+ // Before anything is written: every table this erasure would touch must be recorded, in THIS
287
+ // scope, as created by the erasing module's own migrations.
288
+ for (const plan of plans)
289
+ assertTablesOwned(sql, plan.moduleId, plan.ownTables, input.migrationSqlOf, at);
290
+ if (plans.some((p) => p.ownTables.size > 0)) {
291
+ assertNoTempShadow(sql, new Set(plans.flatMap((p) => [...p.ownTables])));
292
+ }
293
+ // FTS5 keeps a deleted row's terms in the older index segments until they merge, so an
294
+ // erased word stays in the database file after search stops finding it. `secure-delete`
295
+ // makes a delete remove the entry from the segment it sits in instead — at the cost of that
296
+ // one entry, where a full merge ('optimize') rewrites the whole index (0.5 s at 100k rows,
297
+ // measured). It is switched on lazily, for an index whose table this erasure is about to
298
+ // change and no other, and off again at the end; a throw rolls the switch back with
299
+ // everything else. Lazily because the switch leaves a row in the index's own config, which
300
+ // SQLite will not let anyone remove: an erasure that holds nothing for the subject — the
301
+ // common case, every scope it is not about — leaves every index exactly as it found it.
302
+ const indexesOf = new Map();
303
+ for (const p of input.searchPlans) {
304
+ const key = p.table.toLowerCase();
305
+ const list = indexesOf.get(key) ?? [];
306
+ list.push(ident(p.indexTable));
307
+ indexesOf.set(key, list);
308
+ }
309
+ const secured = new Set();
310
+ const secure = (table) => {
311
+ for (const idx of indexesOf.get(table.toLowerCase()) ?? []) {
312
+ if (secured.has(idx))
313
+ continue;
314
+ enableSecureDelete(sql, idx);
315
+ secured.add(idx);
316
+ }
317
+ };
318
+ for (const plan of plans) {
319
+ for (const entity of plan.declaration.entities) {
320
+ if (entity.mode === 'unreached') {
321
+ out.unreachedEntities.push({ module: plan.moduleId, entityType: entity.entityType });
322
+ continue;
323
+ }
324
+ if (entity.mode === 'custom')
325
+ continue;
326
+ const table = ident(entity.table);
327
+ const subjects = (entity.subjects ?? []).map(ident);
328
+ const match = `(${subjects.map((s) => `${s} = ?`).join(' OR ')})`;
329
+ const subjectParams = subjects.map(() => subjectId);
330
+ // Only rows still holding something: a re-run changes nothing and counts zero.
331
+ const cols = entity.fields.map((f) => ident(f.name));
332
+ const blanks = entity.fields.map((f) => f.blank);
333
+ const isDelete = entity.mode === 'delete';
334
+ const filter = isDelete ? match : `${match} AND (${cols.map((c) => `${c} IS NOT ?`).join(' OR ')})`;
335
+ const params = isDelete ? subjectParams : [...subjectParams, ...blanks];
336
+ // The probe exists only to switch an index's secure-delete on lazily; a table no index
337
+ // covers goes straight to its write.
338
+ const indexed = indexesOf.has(table.toLowerCase());
339
+ let rows = 0;
340
+ if (!indexed || sql.query(`SELECT 1 FROM ${table} WHERE ${filter} LIMIT 1`, params).length > 0) {
341
+ secure(table);
342
+ if (isDelete) {
343
+ sql.exec(`DELETE FROM ${table} WHERE ${filter}`, params);
344
+ }
345
+ else {
346
+ sql.exec(`UPDATE ${table} SET ${cols.map((c) => `${c} = ?`).join(', ')} WHERE ${filter}`, [...blanks, ...params]);
347
+ }
348
+ rows = changeCounts(sql).changes;
349
+ }
350
+ out.verticalRows.push({ module: plan.moduleId, entityType: entity.entityType, mode: entity.mode, rows });
351
+ }
352
+ }
353
+ const guarded = guardSpine(sql, input.statefulTables);
354
+ for (const plan of plans) {
355
+ if (!plan.hook)
356
+ continue;
357
+ const own = plan.ownTables;
358
+ let rows = 0;
359
+ // The hook's capability lives exactly as long as its synchronous run. A hook that kept
360
+ // `ctx` — an async continuation, a handle stored on a global — and used it later would
361
+ // write outside the erasure's transaction, after a refusal had rolled it back; revoked,
362
+ // every later call throws and writes nothing.
363
+ let live = true;
364
+ const alive = () => {
365
+ if (!live) {
366
+ throw substratError('forbidden', `${plan.moduleId}: onSubjectErased's ctx was used after the hook returned — it is valid only while the hook runs`, { reason: 'erasure_revoked' });
367
+ }
368
+ };
369
+ // `changes()` is the last WRITE's count, so a read run through `exec` would repeat the
370
+ // previous one; `total_changes()` moving at all is what says a statement wrote.
371
+ let total = changeCounts(sql).total;
372
+ const hookSql = {
373
+ query: (statement, params) => {
374
+ alive();
375
+ assertWithinErasureReach(plan.moduleId, statement, own);
376
+ return guarded.query(statement, params);
377
+ },
378
+ exec: (statement, params) => {
379
+ alive();
380
+ assertWithinErasureReach(plan.moduleId, statement, own);
381
+ // Any statement the hook runs may change any of its tables; secure their indexes first.
382
+ for (const t of own)
383
+ secure(t);
384
+ guarded.exec(statement, params);
385
+ const after = changeCounts(sql);
386
+ const changes = after.total === total ? 0 : after.changes;
387
+ total = after.total;
388
+ rows += changes;
389
+ return { changes };
390
+ },
391
+ };
392
+ const ctx = {
393
+ sql: hookSql,
394
+ now: () => {
395
+ alive();
396
+ return at;
397
+ },
398
+ };
399
+ let returned;
400
+ try {
401
+ returned = plan.hook(ctx, { subjectId });
402
+ }
403
+ finally {
404
+ live = false;
405
+ }
406
+ if (returned !== undefined) {
407
+ // Anything but `undefined` is a hook that did not finish in its synchronous run: a promise
408
+ // (an async hook), an iterator (a generator hook, whose body has not even started), or a
409
+ // value it meant as a result. Each refuses the whole erasure, before the key. A promise's
410
+ // rejection is the module's — swallowed so it does not surface unhandled after the erasure
411
+ // it belonged to has been refused and rolled back; its continuation can do nothing, `ctx`
412
+ // being revoked above.
413
+ if (returned !== null && typeof returned.then === 'function') {
414
+ returned.then(undefined, () => undefined);
415
+ }
416
+ throw substratError('precondition_failed', `${plan.moduleId}: onSubjectErased returned a value — it must run to completion synchronously and ` +
417
+ "return nothing (no async, no generator), so it runs inside the erasure's one transaction");
418
+ }
419
+ out.hookRows.push({ module: plan.moduleId, rows });
420
+ }
421
+ for (const idx of secured)
422
+ sql.exec(`INSERT INTO ${idx}(${idx}, rank) VALUES('secure-delete', 0)`);
423
+ return out;
424
+ }
425
+ /** Every row the module half changed — what the access log adds to "how much evidence this destroyed". */
426
+ export function moduleRowsErased(counts) {
427
+ return [...counts.verticalRows, ...counts.hookRows].reduce((n, c) => n + c.rows, 0);
428
+ }
429
+ /**
430
+ * Whether a host's reply carries the module half (#2068) in the shape this kernel wrote — what a
431
+ * coordinator checks before destroying the key, so a host built before the half existed is
432
+ * refused rather than read as having reached nothing.
433
+ */
434
+ export function isModuleErasureCounts(value) {
435
+ if (typeof value !== 'object' || value === null)
436
+ return false;
437
+ const v = value;
438
+ return Array.isArray(v.verticalRows) && Array.isArray(v.hookRows) && Array.isArray(v.unreachedEntities);
439
+ }
440
+ //# sourceMappingURL=module-erasure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-erasure.js","sourceRoot":"","sources":["../src/module-erasure.ts"],"names":[],"mappings":"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"}