@hraness/oh 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +598 -0
  3. package/dist/canonical.d.ts +32 -0
  4. package/dist/canonical.d.ts.map +1 -0
  5. package/dist/cli.d.ts +4 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +3419 -0
  8. package/dist/contract.d.ts +33 -0
  9. package/dist/contract.d.ts.map +1 -0
  10. package/dist/graph.d.ts +67 -0
  11. package/dist/graph.d.ts.map +1 -0
  12. package/dist/index.d.ts +9 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +1988 -0
  15. package/dist/libsql.d.ts +57 -0
  16. package/dist/libsql.d.ts.map +1 -0
  17. package/dist/libsql.js +2662 -0
  18. package/dist/memory.d.ts +366 -0
  19. package/dist/memory.d.ts.map +1 -0
  20. package/dist/memory.js +3650 -0
  21. package/dist/ontology.d.ts +242 -0
  22. package/dist/ontology.d.ts.map +1 -0
  23. package/dist/operation.d.ts +24 -0
  24. package/dist/operation.d.ts.map +1 -0
  25. package/dist/projection-public.d.ts +59 -0
  26. package/dist/projection-public.d.ts.map +1 -0
  27. package/dist/projection-public.js +1682 -0
  28. package/dist/projection-suss.d.ts +17 -0
  29. package/dist/projection-suss.d.ts.map +1 -0
  30. package/dist/projection-suss.js +1721 -0
  31. package/dist/projection.d.ts +315 -0
  32. package/dist/projection.d.ts.map +1 -0
  33. package/dist/schema.d.ts +45 -0
  34. package/dist/schema.d.ts.map +1 -0
  35. package/dist/sdk.d.ts +51 -0
  36. package/dist/sdk.d.ts.map +1 -0
  37. package/dist/sdk.js +3072 -0
  38. package/dist/search.d.ts +34 -0
  39. package/dist/search.d.ts.map +1 -0
  40. package/dist/semantic.d.ts +83 -0
  41. package/dist/semantic.d.ts.map +1 -0
  42. package/dist/semantic.js +706 -0
  43. package/dist/sqlite/driver.d.ts +6 -0
  44. package/dist/sqlite/driver.d.ts.map +1 -0
  45. package/dist/sqlite/index.d.ts +5 -0
  46. package/dist/sqlite/index.d.ts.map +1 -0
  47. package/dist/sqlite/index.js +2840 -0
  48. package/dist/sqlite/migrations.d.ts +10 -0
  49. package/dist/sqlite/migrations.d.ts.map +1 -0
  50. package/dist/sqlite/port.d.ts +40 -0
  51. package/dist/sqlite/port.d.ts.map +1 -0
  52. package/dist/sqlite/runtime.d.ts +23 -0
  53. package/dist/sqlite/runtime.d.ts.map +1 -0
  54. package/dist/sqlite/store.d.ts +85 -0
  55. package/dist/sqlite/store.d.ts.map +1 -0
  56. package/dist/store.d.ts +236 -0
  57. package/dist/store.d.ts.map +1 -0
  58. package/dist/store.js +996 -0
  59. package/dist/sync.d.ts +57 -0
  60. package/dist/sync.d.ts.map +1 -0
  61. package/dist/sync.js +1328 -0
  62. package/package.json +121 -0
  63. package/skills/oh/SKILL.md +206 -0
  64. package/skills/oh/agents/openai.yaml +4 -0
  65. package/spec/README.md +74 -0
  66. package/spec/manifest.json +41 -0
  67. package/spec/v1/canonical-json.md +59 -0
  68. package/spec/v1/contract.json +28 -0
  69. package/spec/v1/contract.schema.json +58 -0
  70. package/spec/v1/embedding-profile.json +11 -0
  71. package/spec/v1/embedding.md +56 -0
  72. package/spec/v1/graph.md +87 -0
  73. package/spec/v1/memory.md +193 -0
  74. package/spec/v1/migration.md +92 -0
  75. package/spec/v1/ontology.json +55 -0
  76. package/spec/v1/ontology.md +80 -0
  77. package/spec/v1/operation.schema.json +138 -0
  78. package/spec/v1/projection-identity.schema.json +58 -0
  79. package/spec/v1/projection-query.schema.json +60 -0
  80. package/spec/v1/projection-result.schema.json +452 -0
  81. package/spec/v1/projection-rule-pack.schema.json +182 -0
  82. package/spec/v1/projection.md +165 -0
  83. package/spec/v1/record.schema.json +95 -0
  84. package/spec/v1/schema-evolution.md +51 -0
  85. package/spec/v1/schema-revision.schema.json +178 -0
  86. package/spec/v1/storage.md +88 -0
  87. package/spec/v1/store.md +131 -0
  88. package/spec/v1/sync-bundle.schema.json +51 -0
  89. package/spec/v1/sync.md +67 -0
  90. package/src/canonical.test.ts +46 -0
  91. package/src/canonical.ts +203 -0
  92. package/src/cli.test.ts +103 -0
  93. package/src/cli.ts +308 -0
  94. package/src/contract.ts +87 -0
  95. package/src/contracts.test.ts +147 -0
  96. package/src/graph.ts +248 -0
  97. package/src/index.ts +8 -0
  98. package/src/libsql.test.ts +657 -0
  99. package/src/libsql.ts +1687 -0
  100. package/src/memory.test.ts +783 -0
  101. package/src/memory.ts +1684 -0
  102. package/src/ontology.ts +573 -0
  103. package/src/operation.ts +80 -0
  104. package/src/projection-public.ts +53 -0
  105. package/src/projection-suss.ts +129 -0
  106. package/src/projection.test.ts +418 -0
  107. package/src/projection.ts +1457 -0
  108. package/src/schema.ts +156 -0
  109. package/src/sdk.ts +96 -0
  110. package/src/search.ts +66 -0
  111. package/src/semantic.test.ts +480 -0
  112. package/src/semantic.ts +333 -0
  113. package/src/sqlite/driver.ts +47 -0
  114. package/src/sqlite/index.ts +4 -0
  115. package/src/sqlite/migrations.test.ts +44 -0
  116. package/src/sqlite/migrations.ts +178 -0
  117. package/src/sqlite/port.test.ts +127 -0
  118. package/src/sqlite/port.ts +120 -0
  119. package/src/sqlite/runtime.test.ts +68 -0
  120. package/src/sqlite/runtime.ts +53 -0
  121. package/src/sqlite/store.test.ts +295 -0
  122. package/src/sqlite/store.ts +988 -0
  123. package/src/store.test.ts +121 -0
  124. package/src/store.ts +701 -0
  125. package/src/sync.test.ts +117 -0
  126. package/src/sync.ts +227 -0
package/src/libsql.ts ADDED
@@ -0,0 +1,1687 @@
1
+ import {
2
+ canonicalJson,
3
+ canonicalNow,
4
+ canonicalSha256,
5
+ parseSha256Hex,
6
+ safeCode,
7
+ utf8ByteLength,
8
+ type Sha256Hex,
9
+ } from "./canonical";
10
+ import { OH_CONTRACT_MANIFEST_V1 } from "./contract";
11
+ import { canonicalKnowledgeGraphChangesV1, knowledgeGraphRecordRefV1, OH_GRAPH_LIMITS_V1,
12
+ parseKnowledgeGraphRecordV1,
13
+ type KnowledgeGraphRecordV1 } from "./graph";
14
+ import { parseOhOperationV1, type OhOperationV1 } from "./operation";
15
+ import {
16
+ createOhDependencyClosureV1,
17
+ createOhSpacePurgeReceiptV1,
18
+ createOhStoreBindingV1,
19
+ emptyOhHeadV1,
20
+ OH_CANONICAL_STORE_PROFILE_V1,
21
+ OH_WORKING_STORE_PROFILE_V1,
22
+ OhConflictError,
23
+ OhIntegrityError,
24
+ OhProfileError,
25
+ OhPurgedSpaceError,
26
+ parseOhHeadRefV1,
27
+ parseOhSpacePurgeReceiptV1,
28
+ parseOhStoreBindingV1,
29
+ parseOhStoreProfileV1,
30
+ replayOhOperationsV1,
31
+ transitionOhSnapshotV1,
32
+ type OhChangesPageV1,
33
+ type OhCommitInputV1,
34
+ type OhDependencyClosureV1,
35
+ type OhHeadRefV1,
36
+ type OhHeadV1,
37
+ type OhSnapshotV1,
38
+ type OhSpacePurgeReceiptV1,
39
+ type OhStoreAuthorityV1,
40
+ type OhStoreBindingV1,
41
+ type OhStoreHostControlV1,
42
+ type OhStoreProfileV1,
43
+ type OhStoreV1,
44
+ type OhStoreVerificationV1,
45
+ } from "./store";
46
+
47
+ export type OhLibSqlValueV1 = ArrayBuffer | Date | Uint8Array | bigint | boolean | null | number | string;
48
+ export type OhLibSqlStatementV1 = Readonly<{ args?: readonly OhLibSqlValueV1[]; sql: string }>;
49
+ export type OhLibSqlResultV1 = Readonly<{
50
+ rows: readonly (Readonly<Record<string, unknown>> | readonly unknown[])[];
51
+ rowsAffected?: number;
52
+ }>;
53
+
54
+ /** Structural subset implemented by `@libsql/client` clients. */
55
+ export interface OhLibSqlClientV1 {
56
+ batch(
57
+ statements: readonly OhLibSqlStatementV1[],
58
+ mode?: "deferred" | "read" | "write",
59
+ ): Promise<readonly OhLibSqlResultV1[]>;
60
+ close?(): void;
61
+ execute(statement: OhLibSqlStatementV1 | string): Promise<OhLibSqlResultV1>;
62
+ }
63
+
64
+ export type OhLibSqlStoreAuthorityOptionsV1 = Readonly<{
65
+ closeClient?: boolean;
66
+ profile?: OhStoreProfileV1;
67
+ realmId?: string;
68
+ spaceId?: string;
69
+ }>;
70
+
71
+ export const OH_LIBSQL_STORE_LIMITS_V1 = Object.freeze({
72
+ changesPerCommit: 64,
73
+ changeFeedLimit: 7,
74
+ dependenciesPerCommit: 512,
75
+ historyBytes: 4 * 1024 * 1024,
76
+ historyOperations: 16_384,
77
+ operationBytes: 512 * 1024,
78
+ providerResponseBytes: 9_000_000,
79
+ snapshotComponentBytes: 6 * 1024 * 1024,
80
+ });
81
+
82
+ const AUTHORITY_SCHEMA_NAME = "oh.libsql-authority.v1";
83
+ const AUTHORITY_SCHEMA_VERSION = 1;
84
+ const EMPTY_RECORDS_SHA256 = canonicalSha256([]);
85
+ const PURGE_ROW_SELECT = `SELECT space_id, binding_sha256, prior_operation_sha256,
86
+ prior_sequence, purged_at, receipt_sha256, receipt_json
87
+ FROM oh_authority_purges WHERE space_id = ?`;
88
+ const BINDING_ROW_SELECT = `SELECT space_id, realm_id, profile_id, profile_kind,
89
+ profile_sha256, binding_sha256, binding_json FROM oh_authority_bindings WHERE space_id = ?`;
90
+ const SPACE_PURGE_PROOF_SELECT = `SELECT generation, graph_revision_sha256, head_operation_sha256,
91
+ records_sha256, sequence, contract_id FROM oh_authority_spaces WHERE space_id = ?`;
92
+ const OPERATION_ROW_COLUMNS = `operation_sha256, space_id, sequence, operation_id,
93
+ parent_operation_sha256, graph_revision_sha256, records_sha256, operation_json, instant`;
94
+ // libSQL serializes text again in its JSON response. Twice the UTF-8 text plus all
95
+ // duplicated columns and a fixed row reserve is a conservative upper bound for
96
+ // canonical JSON, whose own escapes can only be escaped once more by transport.
97
+ const OPERATION_RESPONSE_BYTES = `2 * length(CAST(operation.operation_json AS BLOB))
98
+ + 2 * (length(operation.operation_sha256) + length(operation.space_id)
99
+ + length(operation.operation_id) + coalesce(length(operation.parent_operation_sha256), 0)
100
+ + length(operation.graph_revision_sha256) + length(operation.records_sha256)
101
+ + length(operation.instant)) + 512`;
102
+ const RECORD_RESPONSE_BYTES = `2 * length(CAST(record.record_json AS BLOB))
103
+ + 2 * (length(record.record_key) + length(record.kind) + length(record.record_sha256)
104
+ + length(record.operation_sha256)) + 384`;
105
+ const DEPENDENCY_RESPONSE_BYTES = `2 * (length(dependency.record_key)
106
+ + length(dependency.dependency_key)) + 192`;
107
+ const OPERATION_RECORD_RESPONSE_BYTES = `2 * (length(materialized.space_id)
108
+ + length(materialized.operation_sha256) + length(materialized.record_key)
109
+ + length(materialized.change_kind) + length(materialized.record_sha256)) + 320`;
110
+
111
+ const AUTHORITY_SCHEMA_TABLE_STATEMENT = `CREATE TABLE IF NOT EXISTS oh_authority_schemas (
112
+ version INTEGER PRIMARY KEY,
113
+ name TEXT NOT NULL UNIQUE,
114
+ schema_sha256 TEXT NOT NULL,
115
+ applied_at TEXT NOT NULL
116
+ ) STRICT`;
117
+
118
+ const AUTHORITY_SCHEMA_STATEMENTS = Object.freeze([
119
+ `CREATE TABLE IF NOT EXISTS oh_authority_contracts (
120
+ contract_id TEXT PRIMARY KEY,
121
+ contract_sha256 TEXT NOT NULL,
122
+ manifest_json TEXT NOT NULL
123
+ ) STRICT`,
124
+ `CREATE TABLE IF NOT EXISTS oh_authority_spaces (
125
+ space_id TEXT PRIMARY KEY,
126
+ contract_id TEXT NOT NULL,
127
+ generation INTEGER NOT NULL CHECK(generation >= 0),
128
+ head_operation_sha256 TEXT,
129
+ graph_revision_sha256 TEXT,
130
+ records_sha256 TEXT NOT NULL,
131
+ sequence INTEGER NOT NULL CHECK(sequence >= 0),
132
+ created_at TEXT NOT NULL,
133
+ updated_at TEXT NOT NULL,
134
+ CHECK(generation = sequence)
135
+ ) STRICT`,
136
+ `CREATE TABLE IF NOT EXISTS oh_authority_operations (
137
+ operation_sha256 TEXT PRIMARY KEY,
138
+ space_id TEXT NOT NULL,
139
+ sequence INTEGER NOT NULL CHECK(sequence > 0),
140
+ operation_id TEXT NOT NULL,
141
+ parent_operation_sha256 TEXT,
142
+ graph_revision_sha256 TEXT NOT NULL,
143
+ records_sha256 TEXT NOT NULL,
144
+ operation_json TEXT NOT NULL,
145
+ instant TEXT NOT NULL,
146
+ UNIQUE(space_id, sequence),
147
+ UNIQUE(space_id, operation_id)
148
+ ) STRICT`,
149
+ `CREATE TABLE IF NOT EXISTS oh_authority_operation_records (
150
+ space_id TEXT NOT NULL,
151
+ operation_sha256 TEXT NOT NULL,
152
+ ordinal INTEGER NOT NULL CHECK(ordinal >= 0),
153
+ record_key TEXT NOT NULL,
154
+ change_kind TEXT NOT NULL CHECK(change_kind IN ('put', 'tombstone')),
155
+ record_sha256 TEXT NOT NULL,
156
+ PRIMARY KEY(operation_sha256, ordinal),
157
+ UNIQUE(operation_sha256, record_key)
158
+ ) STRICT`,
159
+ `CREATE TABLE IF NOT EXISTS oh_authority_records (
160
+ space_id TEXT NOT NULL,
161
+ record_key TEXT NOT NULL,
162
+ kind TEXT NOT NULL,
163
+ record_sha256 TEXT NOT NULL,
164
+ record_json TEXT NOT NULL,
165
+ operation_sha256 TEXT NOT NULL,
166
+ sequence INTEGER NOT NULL CHECK(sequence > 0),
167
+ PRIMARY KEY(space_id, record_key)
168
+ ) STRICT`,
169
+ `CREATE TABLE IF NOT EXISTS oh_authority_dependencies (
170
+ space_id TEXT NOT NULL,
171
+ record_key TEXT NOT NULL,
172
+ dependency_key TEXT NOT NULL,
173
+ PRIMARY KEY(space_id, record_key, dependency_key)
174
+ ) STRICT`,
175
+ `CREATE TABLE IF NOT EXISTS oh_authority_bindings (
176
+ space_id TEXT PRIMARY KEY,
177
+ realm_id TEXT NOT NULL,
178
+ profile_id TEXT NOT NULL,
179
+ profile_kind TEXT NOT NULL CHECK(profile_kind IN ('canonical', 'working')),
180
+ profile_sha256 TEXT NOT NULL,
181
+ binding_sha256 TEXT NOT NULL UNIQUE,
182
+ binding_json TEXT NOT NULL,
183
+ created_at TEXT NOT NULL
184
+ ) STRICT`,
185
+ `CREATE TABLE IF NOT EXISTS oh_authority_purges (
186
+ space_id TEXT PRIMARY KEY,
187
+ binding_sha256 TEXT NOT NULL,
188
+ prior_operation_sha256 TEXT,
189
+ prior_sequence INTEGER NOT NULL CHECK(prior_sequence >= 0),
190
+ purged_at TEXT NOT NULL,
191
+ receipt_sha256 TEXT NOT NULL UNIQUE,
192
+ receipt_json TEXT NOT NULL
193
+ ) STRICT`,
194
+ `CREATE TABLE IF NOT EXISTS oh_authority_commit_guards (
195
+ value TEXT NOT NULL CHECK(value = 'ok')
196
+ ) STRICT`,
197
+ "CREATE INDEX IF NOT EXISTS oh_authority_operations_space_sequence ON oh_authority_operations(space_id, sequence)",
198
+ "CREATE INDEX IF NOT EXISTS oh_authority_records_space_kind ON oh_authority_records(space_id, kind, record_key)",
199
+ "CREATE INDEX IF NOT EXISTS oh_authority_dependencies_dependency ON oh_authority_dependencies(space_id, dependency_key)",
200
+ `CREATE TRIGGER IF NOT EXISTS oh_authority_operations_no_update
201
+ BEFORE UPDATE ON oh_authority_operations
202
+ BEGIN SELECT RAISE(ABORT, 'Oh authority operations are immutable'); END`,
203
+ `CREATE TRIGGER IF NOT EXISTS oh_authority_operations_guard_delete
204
+ BEFORE DELETE ON oh_authority_operations
205
+ WHEN NOT EXISTS (SELECT 1 FROM oh_authority_purges WHERE space_id = OLD.space_id)
206
+ BEGIN SELECT RAISE(ABORT, 'Oh authority operations require a purge receipt'); END`,
207
+ `CREATE TRIGGER IF NOT EXISTS oh_authority_operation_records_no_update
208
+ BEFORE UPDATE ON oh_authority_operation_records
209
+ BEGIN SELECT RAISE(ABORT, 'Oh authority operation records are immutable'); END`,
210
+ `CREATE TRIGGER IF NOT EXISTS oh_authority_operation_records_guard_insert
211
+ BEFORE INSERT ON oh_authority_operation_records
212
+ WHEN NOT EXISTS (SELECT 1 FROM oh_authority_operations
213
+ WHERE operation_sha256 = NEW.operation_sha256 AND space_id = NEW.space_id)
214
+ BEGIN SELECT RAISE(ABORT, 'Oh authority operation record has no owning operation'); END`,
215
+ `CREATE TRIGGER IF NOT EXISTS oh_authority_operation_records_guard_delete
216
+ BEFORE DELETE ON oh_authority_operation_records
217
+ WHEN NOT EXISTS (SELECT 1 FROM oh_authority_operations AS operation
218
+ JOIN oh_authority_purges AS purge ON purge.space_id = operation.space_id
219
+ WHERE operation.operation_sha256 = OLD.operation_sha256)
220
+ BEGIN SELECT RAISE(ABORT, 'Oh authority operation records require a purge receipt'); END`,
221
+ `CREATE TRIGGER IF NOT EXISTS oh_authority_purges_immutable_update
222
+ BEFORE UPDATE ON oh_authority_purges
223
+ BEGIN SELECT RAISE(ABORT, 'Oh authority purge receipts are immutable'); END`,
224
+ `CREATE TRIGGER IF NOT EXISTS oh_authority_purges_immutable_delete
225
+ BEFORE DELETE ON oh_authority_purges
226
+ BEGIN SELECT RAISE(ABORT, 'Oh authority purge receipts are immutable'); END`,
227
+ ]);
228
+
229
+ function normalizedSchemaSql(sql: string): string {
230
+ return sql.replace(/\bIF\s+NOT\s+EXISTS\b/giu, "").replace(/\s+/gu, " ").trim();
231
+ }
232
+
233
+ function expectedSchemaObject(statement: string): Readonly<{
234
+ name: string;
235
+ sql: string;
236
+ tableName: string;
237
+ type: "index" | "table" | "trigger";
238
+ }> {
239
+ const match = /^CREATE\s+(TABLE|INDEX|TRIGGER)(?:\s+IF\s+NOT\s+EXISTS)?\s+([a-z0-9_]+)/iu.exec(statement.trim());
240
+ if (match === null) throw new Error("Invalid compiled authority schema statement.");
241
+ const declaredType = match[1]?.toLowerCase();
242
+ const type = declaredType === "index" ? "index" as const
243
+ : declaredType === "trigger" ? "trigger" as const : "table" as const;
244
+ const name = match[2] as string;
245
+ const tableMatch = type === "index" || type === "trigger" ? /\bON\s+([a-z0-9_]+)/iu.exec(statement) : null;
246
+ const tableName = type === "table" ? name : tableMatch?.[1];
247
+ if (tableName === undefined) throw new Error("Invalid compiled authority index statement.");
248
+ return { name, sql: normalizedSchemaSql(statement), tableName, type };
249
+ }
250
+
251
+ const AUTHORITY_SCHEMA_OBJECTS = Object.freeze(
252
+ [AUTHORITY_SCHEMA_TABLE_STATEMENT, ...AUTHORITY_SCHEMA_STATEMENTS]
253
+ .map(expectedSchemaObject)
254
+ .sort((left, right) => canonicalJson([left.type, left.name])
255
+ .localeCompare(canonicalJson([right.type, right.name]))),
256
+ );
257
+ const AUTHORITY_SCHEMA_SHA256 = canonicalSha256(AUTHORITY_SCHEMA_OBJECTS);
258
+
259
+ function rowValue(
260
+ row: Readonly<Record<string, unknown>> | readonly unknown[],
261
+ key: string,
262
+ index: number,
263
+ ): unknown {
264
+ return Array.isArray(row) ? row[index] : (row as Readonly<Record<string, unknown>>)[key];
265
+ }
266
+
267
+ function integer(value: unknown): number | null {
268
+ if (typeof value === "number") return Number.isSafeInteger(value) ? value : null;
269
+ if (typeof value === "bigint") {
270
+ const parsed = Number(value);
271
+ return Number.isSafeInteger(parsed) ? parsed : null;
272
+ }
273
+ return null;
274
+ }
275
+
276
+ function normalizeLimit(value: number | undefined, fallback = 100, maximum = 1000): number {
277
+ const limit = value ?? fallback;
278
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > maximum) {
279
+ throw new RangeError(`limit must be an integer from 1 through ${maximum}.`);
280
+ }
281
+ return limit;
282
+ }
283
+
284
+ function parseOperationJson(value: unknown): OhOperationV1 {
285
+ if (typeof value !== "string") throw new OhIntegrityError("A stored operation is not JSON text.");
286
+ let parsedValue: unknown;
287
+ try { parsedValue = JSON.parse(value); } catch { throw new OhIntegrityError("A stored operation is not JSON."); }
288
+ const operation = parseOhOperationV1(parsedValue);
289
+ if (operation === null || canonicalJson(operation) !== value) {
290
+ throw new OhIntegrityError("A stored operation is invalid.");
291
+ }
292
+ return operation;
293
+ }
294
+
295
+ function parseOperationRow(
296
+ row: Readonly<Record<string, unknown>> | readonly unknown[],
297
+ expected: Readonly<{ operationId?: string; operationSha256?: string; spaceId?: string }> = {},
298
+ ): OhOperationV1 {
299
+ const operation = parseOperationJson(rowValue(row, "operation_json", 7));
300
+ if (rowValue(row, "operation_sha256", 0) !== operation.operationSha256
301
+ || rowValue(row, "space_id", 1) !== operation.spaceId
302
+ || integer(rowValue(row, "sequence", 2)) !== operation.sequence
303
+ || rowValue(row, "operation_id", 3) !== operation.operationId
304
+ || rowValue(row, "parent_operation_sha256", 4) !== operation.parentOperationSha256
305
+ || rowValue(row, "graph_revision_sha256", 5) !== operation.graphRevisionSha256
306
+ || rowValue(row, "records_sha256", 6) !== operation.recordsSha256
307
+ || rowValue(row, "instant", 8) !== operation.instant
308
+ || (expected.spaceId !== undefined && operation.spaceId !== expected.spaceId)
309
+ || (expected.operationId !== undefined && operation.operationId !== expected.operationId)
310
+ || (expected.operationSha256 !== undefined && operation.operationSha256 !== expected.operationSha256)) {
311
+ throw new OhIntegrityError("Remote operation columns do not match their canonical envelope.");
312
+ }
313
+ return operation;
314
+ }
315
+
316
+ function parseBindingRow(
317
+ row: Readonly<Record<string, unknown>> | readonly unknown[],
318
+ expectedSpaceId: string,
319
+ ): OhStoreBindingV1 {
320
+ const json = rowValue(row, "binding_json", 6);
321
+ if (typeof json !== "string") throw new OhIntegrityError("A remote store binding is not JSON text.");
322
+ let value: unknown;
323
+ try { value = JSON.parse(json); } catch { throw new OhIntegrityError("A remote store binding is not JSON."); }
324
+ const binding = parseOhStoreBindingV1(value);
325
+ if (binding === null || canonicalJson(binding) !== json || binding.spaceId !== expectedSpaceId
326
+ || rowValue(row, "space_id", 0) !== binding.spaceId
327
+ || rowValue(row, "realm_id", 1) !== binding.realmId
328
+ || rowValue(row, "profile_id", 2) !== binding.profile.profileId
329
+ || rowValue(row, "profile_kind", 3) !== binding.profile.profileKind
330
+ || rowValue(row, "profile_sha256", 4) !== binding.profile.profileSha256
331
+ || rowValue(row, "binding_sha256", 5) !== binding.bindingSha256) {
332
+ throw new OhIntegrityError("Remote binding columns do not match their canonical envelope.");
333
+ }
334
+ return binding;
335
+ }
336
+
337
+ function parsePurgeReceiptRow(
338
+ row: Readonly<Record<string, unknown>> | readonly unknown[],
339
+ expectedSpaceId: string,
340
+ expectedBindingSha256?: Sha256Hex,
341
+ ): OhSpacePurgeReceiptV1 {
342
+ const json = rowValue(row, "receipt_json", 6);
343
+ if (typeof json !== "string") throw new OhIntegrityError("A remote purge receipt is invalid.");
344
+ let value: unknown;
345
+ try { value = JSON.parse(json); } catch { throw new OhIntegrityError("A remote purge receipt is invalid."); }
346
+ const receipt = parseOhSpacePurgeReceiptV1(value);
347
+ if (receipt === null || canonicalJson(receipt) !== json) {
348
+ throw new OhIntegrityError("A remote purge receipt is invalid.");
349
+ }
350
+ if (receipt.spaceId !== expectedSpaceId
351
+ || (expectedBindingSha256 !== undefined && receipt.bindingSha256 !== expectedBindingSha256)
352
+ || rowValue(row, "space_id", 0) !== receipt.spaceId
353
+ || rowValue(row, "binding_sha256", 1) !== receipt.bindingSha256
354
+ || rowValue(row, "prior_operation_sha256", 2) !== receipt.priorHead.operationSha256
355
+ || integer(rowValue(row, "prior_sequence", 3)) !== receipt.priorHead.sequence
356
+ || rowValue(row, "purged_at", 4) !== receipt.purgedAt
357
+ || rowValue(row, "receipt_sha256", 5) !== receipt.receiptSha256) {
358
+ throw new OhIntegrityError("Remote purge columns do not match their canonical receipt.");
359
+ }
360
+ return receipt;
361
+ }
362
+
363
+ function parseHeadRow(row: Readonly<Record<string, unknown>> | readonly unknown[]): OhHeadV1 {
364
+ const generation = integer(rowValue(row, "generation", 0));
365
+ const graphValue = rowValue(row, "graph_revision_sha256", 1);
366
+ const operationValue = rowValue(row, "head_operation_sha256", 2);
367
+ const recordsSha256 = parseSha256Hex(rowValue(row, "records_sha256", 3));
368
+ const sequence = integer(rowValue(row, "sequence", 4));
369
+ const graphRevisionSha256 = graphValue === null ? null : parseSha256Hex(graphValue);
370
+ const operationSha256 = operationValue === null ? null : parseSha256Hex(operationValue);
371
+ if (generation === null || sequence === null || generation !== sequence || recordsSha256 === null
372
+ || (graphValue !== null && graphRevisionSha256 === null)
373
+ || (operationValue !== null && operationSha256 === null)
374
+ || ((sequence === 0) !== (operationSha256 === null))
375
+ || ((sequence === 0) !== (graphRevisionSha256 === null))) {
376
+ throw new OhIntegrityError("The remote authority contains an invalid head.");
377
+ }
378
+ return { generation, graphRevisionSha256, operationSha256, recordsSha256, sequence, v: 1 };
379
+ }
380
+
381
+ async function queryOne(
382
+ client: OhLibSqlClientV1,
383
+ statement: OhLibSqlStatementV1,
384
+ ): Promise<Readonly<Record<string, unknown>> | readonly unknown[] | null> {
385
+ return (await client.execute(statement)).rows[0] ?? null;
386
+ }
387
+
388
+ async function verifyAuthoritySchemaObjects(client: OhLibSqlClientV1): Promise<void> {
389
+ const rows = (await client.execute({ sql: `SELECT type, name, tbl_name, sql FROM sqlite_schema
390
+ WHERE sql IS NOT NULL AND (name = 'oh_authority_schemas' OR name GLOB 'oh_authority_*'
391
+ OR tbl_name GLOB 'oh_authority_*')
392
+ ORDER BY type, name` })).rows;
393
+ const actual = rows.map((row) => {
394
+ const type = rowValue(row, "type", 0);
395
+ const name = rowValue(row, "name", 1);
396
+ const tableName = rowValue(row, "tbl_name", 2);
397
+ const sql = rowValue(row, "sql", 3);
398
+ if ((type !== "table" && type !== "index" && type !== "trigger") || typeof name !== "string"
399
+ || typeof tableName !== "string" || typeof sql !== "string") {
400
+ throw new OhIntegrityError("The installed libSQL authority has an invalid schema object.");
401
+ }
402
+ return { name, sql: normalizedSchemaSql(sql), tableName, type };
403
+ });
404
+ if (canonicalJson(actual) !== canonicalJson(AUTHORITY_SCHEMA_OBJECTS)) {
405
+ throw new OhIntegrityError("The installed libSQL authority objects differ from this runtime.");
406
+ }
407
+ }
408
+
409
+ async function verifyAuthoritySchema(client: OhLibSqlClientV1): Promise<void> {
410
+ const installed = await queryOne(client, { sql: `SELECT name, schema_sha256
411
+ FROM oh_authority_schemas WHERE version = ?`, args: [AUTHORITY_SCHEMA_VERSION] });
412
+ if (installed === null || rowValue(installed, "name", 0) !== AUTHORITY_SCHEMA_NAME
413
+ || rowValue(installed, "schema_sha256", 1) !== AUTHORITY_SCHEMA_SHA256) {
414
+ throw new OhIntegrityError("The installed libSQL authority schema differs from this runtime.");
415
+ }
416
+ const contract = await queryOne(client, { sql: `SELECT contract_sha256, manifest_json
417
+ FROM oh_authority_contracts WHERE contract_id = ?`, args: [OH_CONTRACT_MANIFEST_V1.contractId] });
418
+ if (contract === null || rowValue(contract, "contract_sha256", 0) !== OH_CONTRACT_MANIFEST_V1.contractSha256
419
+ || rowValue(contract, "manifest_json", 1) !== canonicalJson(OH_CONTRACT_MANIFEST_V1)) {
420
+ throw new OhIntegrityError("The remote authority contract differs from this runtime.");
421
+ }
422
+ await verifyAuthoritySchemaObjects(client);
423
+ }
424
+
425
+ /** One-time schema operation for a client authorized to create authority tables. */
426
+ export async function bootstrapOhLibSqlAuthorityV1(
427
+ client: OhLibSqlClientV1,
428
+ ): Promise<Readonly<{ schemaSha256: Sha256Hex; schemaVersion: 1; v: 1 }>> {
429
+ const existingObjects = (await client.execute({ sql: `SELECT name FROM sqlite_schema
430
+ WHERE sql IS NOT NULL AND (name = 'oh_authority_schemas' OR name GLOB 'oh_authority_*'
431
+ OR tbl_name GLOB 'oh_authority_*')` })).rows;
432
+ if (existingObjects.length > 0) {
433
+ if (!existingObjects.some((row) => rowValue(row, "name", 0) === "oh_authority_schemas")) {
434
+ throw new OhIntegrityError("Refusing to bootstrap over preexisting Oh authority objects.");
435
+ }
436
+ await verifyAuthoritySchema(client);
437
+ return { schemaSha256: AUTHORITY_SCHEMA_SHA256, schemaVersion: 1, v: 1 };
438
+ }
439
+ const setup: OhLibSqlStatementV1[] = [AUTHORITY_SCHEMA_TABLE_STATEMENT, ...AUTHORITY_SCHEMA_STATEMENTS]
440
+ .map((sql) => ({ sql }));
441
+ setup.push({ sql: `INSERT INTO oh_authority_schemas(version, name, schema_sha256, applied_at)
442
+ VALUES (?, ?, ?, ?) ON CONFLICT(version) DO NOTHING`,
443
+ args: [AUTHORITY_SCHEMA_VERSION, AUTHORITY_SCHEMA_NAME, AUTHORITY_SCHEMA_SHA256, canonicalNow()] });
444
+ setup.push({ sql: `INSERT INTO oh_authority_contracts(contract_id, contract_sha256, manifest_json)
445
+ VALUES (?, ?, ?) ON CONFLICT(contract_id) DO NOTHING`, args: [OH_CONTRACT_MANIFEST_V1.contractId,
446
+ OH_CONTRACT_MANIFEST_V1.contractSha256, canonicalJson(OH_CONTRACT_MANIFEST_V1)] });
447
+ await client.batch(setup, "write");
448
+ await verifyAuthoritySchema(client);
449
+ return { schemaSha256: AUTHORITY_SCHEMA_SHA256, schemaVersion: 1, v: 1 };
450
+ }
451
+
452
+ async function initializeSpace(
453
+ client: OhLibSqlClientV1,
454
+ binding: OhStoreBindingV1,
455
+ ): Promise<void> {
456
+ const purged = await queryOne(client, { sql: PURGE_ROW_SELECT,
457
+ args: [binding.spaceId] });
458
+ if (purged !== null) throw new OhPurgedSpaceError(parsePurgeReceiptRow(
459
+ purged, binding.spaceId, binding.bindingSha256));
460
+ const now = canonicalNow();
461
+ try { await client.batch([
462
+ { sql: `INSERT INTO oh_authority_spaces(space_id, contract_id, generation,
463
+ head_operation_sha256, graph_revision_sha256, records_sha256, sequence, created_at, updated_at)
464
+ SELECT ?, ?, 0, NULL, NULL, ?, 0, ?, ?
465
+ WHERE NOT EXISTS (SELECT 1 FROM oh_authority_purges WHERE space_id = ?)
466
+ ON CONFLICT(space_id) DO NOTHING`,
467
+ args: [binding.spaceId, OH_CONTRACT_MANIFEST_V1.contractId, EMPTY_RECORDS_SHA256, now, now,
468
+ binding.spaceId] },
469
+ { sql: `INSERT INTO oh_authority_bindings(space_id, realm_id, profile_id, profile_kind,
470
+ profile_sha256, binding_sha256, binding_json, created_at)
471
+ SELECT ?, ?, ?, ?, ?, ?, ?, ?
472
+ WHERE NOT EXISTS (SELECT 1 FROM oh_authority_purges WHERE space_id = ?)
473
+ AND EXISTS (SELECT 1 FROM oh_authority_spaces WHERE space_id = ?)
474
+ ON CONFLICT(space_id) DO NOTHING`,
475
+ args: [binding.spaceId, binding.realmId, binding.profile.profileId, binding.profile.profileKind,
476
+ binding.profile.profileSha256, binding.bindingSha256, canonicalJson(binding), now,
477
+ binding.spaceId, binding.spaceId] },
478
+ { sql: `INSERT INTO oh_authority_commit_guards(value)
479
+ SELECT 'invalid' WHERE EXISTS (SELECT 1 FROM oh_authority_purges WHERE space_id = ?)
480
+ OR NOT EXISTS (SELECT 1 FROM oh_authority_spaces WHERE space_id = ?)
481
+ OR NOT EXISTS (SELECT 1 FROM oh_authority_bindings WHERE space_id = ? AND binding_sha256 = ?)`,
482
+ args: [binding.spaceId, binding.spaceId, binding.spaceId, binding.bindingSha256] },
483
+ ], "write"); } catch (error) {
484
+ const raced = await queryOne(client, { sql: PURGE_ROW_SELECT,
485
+ args: [binding.spaceId] });
486
+ if (raced !== null) throw new OhPurgedSpaceError(parsePurgeReceiptRow(
487
+ raced, binding.spaceId, binding.bindingSha256));
488
+ const persisted = await queryOne(client, { sql: BINDING_ROW_SELECT, args: [binding.spaceId] });
489
+ if (persisted !== null
490
+ && canonicalJson(parseBindingRow(persisted, binding.spaceId)) !== canonicalJson(binding)) {
491
+ throw new OhProfileError("The remote space is already bound to a different realm or profile.");
492
+ }
493
+ throw error;
494
+ }
495
+ const persisted = await queryOne(client, { sql: BINDING_ROW_SELECT, args: [binding.spaceId] });
496
+ if (persisted === null) {
497
+ const raced = await queryOne(client, { sql: PURGE_ROW_SELECT,
498
+ args: [binding.spaceId] });
499
+ if (raced !== null) throw new OhPurgedSpaceError(parsePurgeReceiptRow(
500
+ raced, binding.spaceId, binding.bindingSha256));
501
+ throw new OhIntegrityError("The remote space has no persisted binding after initialization.");
502
+ }
503
+ if (canonicalJson(parseBindingRow(persisted, binding.spaceId)) !== canonicalJson(binding)) {
504
+ throw new OhProfileError("The remote space is already bound to a different realm or profile.");
505
+ }
506
+ }
507
+
508
+ async function requireExistingSpace(
509
+ client: OhLibSqlClientV1,
510
+ binding: OhStoreBindingV1,
511
+ ): Promise<void> {
512
+ const results = await client.batch([
513
+ { sql: BINDING_ROW_SELECT, args: [binding.spaceId] },
514
+ { sql: `SELECT generation, graph_revision_sha256, head_operation_sha256,
515
+ records_sha256, sequence, contract_id FROM oh_authority_spaces WHERE space_id = ?`,
516
+ args: [binding.spaceId] },
517
+ { sql: PURGE_ROW_SELECT, args: [binding.spaceId] },
518
+ ], "read");
519
+ if (results.length !== 3) {
520
+ throw new OhIntegrityError("The remote authority returned an incomplete existing-space proof.");
521
+ }
522
+ const [bindingResult, spaceResult, purgeResult] = results as
523
+ [OhLibSqlResultV1, OhLibSqlResultV1, OhLibSqlResultV1];
524
+ const purgeRow = purgeResult.rows[0];
525
+ if (purgeRow !== undefined) {
526
+ throw new OhPurgedSpaceError(parsePurgeReceiptRow(
527
+ purgeRow, binding.spaceId, binding.bindingSha256));
528
+ }
529
+ const bindingRow = bindingResult.rows[0];
530
+ const spaceRow = spaceResult.rows[0];
531
+ if (bindingRow === undefined || spaceRow === undefined) {
532
+ throw new OhIntegrityError("The requested remote Oh space does not already exist.");
533
+ }
534
+ const persisted = parseBindingRow(bindingRow, binding.spaceId);
535
+ if (canonicalJson(persisted) !== canonicalJson(binding)) {
536
+ throw new OhProfileError("The remote space is bound to a different realm or profile.");
537
+ }
538
+ if (rowValue(spaceRow, "contract_id", 5) !== OH_CONTRACT_MANIFEST_V1.contractId) {
539
+ throw new OhIntegrityError("The existing remote space uses a different Oh contract.");
540
+ }
541
+ parseHeadRow(spaceRow);
542
+ }
543
+
544
+ const PURGE_PAYLOAD_TABLES = ["oh_authority_spaces", "oh_authority_bindings",
545
+ "oh_authority_operations", "oh_authority_operation_records", "oh_authority_records",
546
+ "oh_authority_dependencies"] as const;
547
+
548
+ async function assertRemotePurgeComplete(
549
+ client: OhLibSqlClientV1,
550
+ binding: OhStoreBindingV1,
551
+ expected: OhSpacePurgeReceiptV1,
552
+ ): Promise<void> {
553
+ const results = await client.batch([
554
+ { sql: PURGE_ROW_SELECT, args: [binding.spaceId] },
555
+ ...PURGE_PAYLOAD_TABLES.map((table) => ({
556
+ sql: `SELECT count(*) AS count FROM ${table} WHERE space_id = ?`,
557
+ args: [binding.spaceId],
558
+ })),
559
+ { sql: `SELECT count(*) AS count FROM oh_authority_operation_records AS materialized
560
+ LEFT JOIN oh_authority_operations AS operation
561
+ ON operation.operation_sha256 = materialized.operation_sha256
562
+ WHERE operation.operation_sha256 IS NULL OR operation.space_id <> materialized.space_id` },
563
+ ], "read");
564
+ const receiptRow = results[0]?.rows[0];
565
+ if (receiptRow === undefined
566
+ || canonicalJson(parsePurgeReceiptRow(receiptRow, binding.spaceId,
567
+ binding.bindingSha256)) !== canonicalJson(expected)) {
568
+ throw new OhIntegrityError("The remote purge receipt differs from the requested purge.");
569
+ }
570
+ for (let index = 0; index < PURGE_PAYLOAD_TABLES.length; index += 1) {
571
+ const countRow = results[index + 1]?.rows[0];
572
+ if (countRow === undefined || integer(rowValue(countRow, "count", 0)) !== 0) {
573
+ throw new OhIntegrityError(`Remote purge left rows in ${PURGE_PAYLOAD_TABLES[index]}.`);
574
+ }
575
+ }
576
+ const orphanRow = results[PURGE_PAYLOAD_TABLES.length + 1]?.rows[0];
577
+ if (orphanRow === undefined || integer(rowValue(orphanRow, "count", 0)) !== 0) {
578
+ throw new OhIntegrityError("Remote purge left an orphaned or cross-space operation record.");
579
+ }
580
+ }
581
+
582
+ class OhLibSqlStoreV1 implements OhStoreV1 {
583
+ readonly binding: OhStoreBindingV1;
584
+ readonly #client: OhLibSqlClientV1;
585
+ readonly #closeClient: boolean;
586
+ #closed = false;
587
+ #purged: OhSpacePurgeReceiptV1 | null = null;
588
+
589
+ constructor(client: OhLibSqlClientV1, binding: OhStoreBindingV1, closeClient: boolean) {
590
+ this.#client = client;
591
+ this.binding = binding;
592
+ this.#closeClient = closeClient;
593
+ }
594
+
595
+ #assertOpen(): void {
596
+ if (this.#purged !== null) throw new OhPurgedSpaceError(this.#purged);
597
+ if (this.#closed) throw new Error("The Oh libSQL store is closed.");
598
+ }
599
+
600
+ async head(): Promise<OhHeadV1> {
601
+ this.#assertOpen();
602
+ const row = await queryOne(this.#client, { sql: `SELECT generation, graph_revision_sha256,
603
+ head_operation_sha256, records_sha256, sequence FROM oh_authority_spaces WHERE space_id = ?`,
604
+ args: [this.binding.spaceId] });
605
+ if (row === null) {
606
+ const purged = await this.#readPurge();
607
+ if (purged !== null) { this.#purged = purged; throw new OhPurgedSpaceError(purged); }
608
+ throw new OhIntegrityError("The remote Oh space does not exist.");
609
+ }
610
+ return parseHeadRow(row);
611
+ }
612
+
613
+ async #readPurge(): Promise<OhSpacePurgeReceiptV1 | null> {
614
+ const row = await queryOne(this.#client, { sql: PURGE_ROW_SELECT,
615
+ args: [this.binding.spaceId] });
616
+ if (row === null) return null;
617
+ return parsePurgeReceiptRow(row, this.binding.spaceId, this.binding.bindingSha256);
618
+ }
619
+
620
+ async #headAt(reference: OhHeadRefV1): Promise<OhHeadV1> {
621
+ const parsed = parseOhHeadRefV1(reference);
622
+ if (parsed === null) throw new TypeError("Invalid Oh head reference.");
623
+ if (parsed.sequence === 0) return emptyOhHeadV1();
624
+ const row = await queryOne(this.#client, { sql: `SELECT ${OPERATION_ROW_COLUMNS} FROM oh_authority_operations
625
+ WHERE space_id = ? AND sequence = ?`, args: [this.binding.spaceId, parsed.sequence] });
626
+ if (row === null) throw new OhConflictError("The requested head is not present in this space.");
627
+ const operation = parseOperationRow(row, { spaceId: this.binding.spaceId });
628
+ if (operation.spaceId !== this.binding.spaceId || operation.sequence !== parsed.sequence
629
+ || operation.operationSha256 !== parsed.operationSha256) {
630
+ throw new OhConflictError("The requested sequence identifies a different operation head.");
631
+ }
632
+ return { generation: operation.sequence, graphRevisionSha256: operation.graphRevisionSha256,
633
+ operationSha256: operation.operationSha256, recordsSha256: operation.recordsSha256,
634
+ sequence: operation.sequence, v: 1 };
635
+ }
636
+
637
+ async #currentMaterializedSnapshot(expectedHead: OhHeadV1, maximumRecords: number): Promise<OhSnapshotV1> {
638
+ const provenancePredicate = `operation.space_id = ? AND (operation.operation_sha256 IS ?
639
+ OR operation.operation_sha256 IN (SELECT record.operation_sha256
640
+ FROM oh_authority_records AS record WHERE record.space_id = ?))`;
641
+ const results = await this.#client.batch([
642
+ { sql: `SELECT generation, graph_revision_sha256, head_operation_sha256, records_sha256, sequence
643
+ FROM oh_authority_spaces WHERE space_id = ?`, args: [this.binding.spaceId] },
644
+ { sql: `SELECT
645
+ (SELECT count(*) FROM (SELECT DISTINCT operation.operation_sha256
646
+ FROM oh_authority_operations AS operation WHERE ${provenancePredicate})) AS provenance_count,
647
+ (SELECT coalesce(sum(bytes), 0) FROM (SELECT DISTINCT operation.operation_sha256,
648
+ ${OPERATION_RESPONSE_BYTES} AS bytes FROM oh_authority_operations AS operation
649
+ WHERE ${provenancePredicate})) AS provenance_bytes,
650
+ (SELECT count(*) FROM oh_authority_records WHERE space_id = ?) AS record_count,
651
+ (SELECT coalesce(sum(${RECORD_RESPONSE_BYTES}), 0) FROM oh_authority_records AS record
652
+ WHERE record.space_id = ?) AS record_bytes,
653
+ (SELECT coalesce(sum(${DEPENDENCY_RESPONSE_BYTES}), 0)
654
+ FROM oh_authority_dependencies AS dependency
655
+ WHERE dependency.space_id = ?) AS dependency_bytes`,
656
+ args: [this.binding.spaceId, expectedHead.operationSha256, this.binding.spaceId,
657
+ this.binding.spaceId, expectedHead.operationSha256, this.binding.spaceId,
658
+ this.binding.spaceId, this.binding.spaceId, this.binding.spaceId] },
659
+ { sql: `SELECT record_key, kind, record_sha256, record_json, operation_sha256, sequence
660
+ FROM oh_authority_records AS record WHERE record.space_id = ?
661
+ AND (SELECT coalesce(sum(${RECORD_RESPONSE_BYTES}), 0)
662
+ FROM oh_authority_records AS record WHERE record.space_id = ?) <= ? ORDER BY record_key`, args: [this.binding.spaceId,
663
+ this.binding.spaceId, OH_LIBSQL_STORE_LIMITS_V1.snapshotComponentBytes] },
664
+ { sql: `SELECT record_key, dependency_key FROM oh_authority_dependencies
665
+ AS dependency WHERE dependency.space_id = ?
666
+ AND (SELECT coalesce(sum(${DEPENDENCY_RESPONSE_BYTES}), 0)
667
+ FROM oh_authority_dependencies AS dependency WHERE dependency.space_id = ?) <= ?
668
+ ORDER BY record_key, dependency_key`,
669
+ args: [this.binding.spaceId, this.binding.spaceId, OH_LIBSQL_STORE_LIMITS_V1.snapshotComponentBytes] },
670
+ { sql: `SELECT ${OPERATION_ROW_COLUMNS}
671
+ FROM oh_authority_operations AS operation
672
+ WHERE ${provenancePredicate}
673
+ AND (SELECT coalesce(sum(bytes), 0) FROM (SELECT DISTINCT candidate.operation_sha256,
674
+ ${OPERATION_RESPONSE_BYTES.replaceAll("operation.", "candidate.")} AS bytes
675
+ FROM oh_authority_operations AS candidate
676
+ WHERE candidate.space_id = ? AND (candidate.operation_sha256 IS ?
677
+ OR candidate.operation_sha256 IN (SELECT record.operation_sha256
678
+ FROM oh_authority_records AS record WHERE record.space_id = ?)))) <= ?
679
+ ORDER BY operation.sequence`,
680
+ args: [this.binding.spaceId, expectedHead.operationSha256, this.binding.spaceId,
681
+ this.binding.spaceId, expectedHead.operationSha256, this.binding.spaceId,
682
+ OH_LIBSQL_STORE_LIMITS_V1.snapshotComponentBytes] },
683
+ { sql: `SELECT count(*) AS count, min(sequence) AS minimum, max(sequence) AS maximum
684
+ FROM oh_authority_operations WHERE space_id = ?`, args: [this.binding.spaceId] },
685
+ ], "read");
686
+ if (results.length !== 6) throw new OhIntegrityError("The remote authority returned an incomplete snapshot batch.");
687
+ const [headResult, sizeResult, recordResult, dependencyResult, provenanceResult, historyResult] = results as
688
+ [OhLibSqlResultV1, OhLibSqlResultV1, OhLibSqlResultV1, OhLibSqlResultV1,
689
+ OhLibSqlResultV1, OhLibSqlResultV1];
690
+ const headRow = headResult.rows[0];
691
+ if (headRow === undefined) {
692
+ const purge = await this.#readPurge();
693
+ if (purge !== null) { this.#purged = purge; throw new OhPurgedSpaceError(purge); }
694
+ throw new OhIntegrityError("The remote Oh space disappeared while reading its snapshot.");
695
+ }
696
+ const head = parseHeadRow(headRow);
697
+ if (canonicalJson(head) !== canonicalJson(expectedHead)) {
698
+ throw new OhConflictError("The remote space head changed while reading its current snapshot.");
699
+ }
700
+ const size = sizeResult.rows[0];
701
+ const provenanceOperations = size === undefined ? null : integer(rowValue(size, "provenance_count", 0));
702
+ const provenanceBytes = size === undefined ? null : integer(rowValue(size, "provenance_bytes", 1));
703
+ const recordCount = size === undefined ? null : integer(rowValue(size, "record_count", 2));
704
+ const recordBytes = size === undefined ? null : integer(rowValue(size, "record_bytes", 3));
705
+ const dependencyBytes = size === undefined ? null : integer(rowValue(size, "dependency_bytes", 4));
706
+ if (provenanceOperations === null || provenanceBytes === null || recordCount === null
707
+ || recordBytes === null || dependencyBytes === null
708
+ || provenanceOperations > OH_LIBSQL_STORE_LIMITS_V1.historyOperations
709
+ || provenanceBytes > OH_LIBSQL_STORE_LIMITS_V1.snapshotComponentBytes
710
+ || recordBytes > OH_LIBSQL_STORE_LIMITS_V1.snapshotComponentBytes
711
+ || dependencyBytes > OH_LIBSQL_STORE_LIMITS_V1.snapshotComponentBytes) {
712
+ throw new RangeError("The current libSQL materialization exceeds its provider-safe response bounds.");
713
+ }
714
+ if (recordResult.rows.length !== recordCount || provenanceResult.rows.length !== provenanceOperations) {
715
+ throw new OhIntegrityError("The provider-safe snapshot queries omitted bounded authority rows.");
716
+ }
717
+ const history = historyResult.rows[0];
718
+ const operationCount = history === undefined ? null : integer(rowValue(history, "count", 0));
719
+ const minimumValue = history === undefined ? undefined : rowValue(history, "minimum", 1);
720
+ const maximumValue = history === undefined ? undefined : rowValue(history, "maximum", 2);
721
+ const minimumSequence = history === undefined ? null : integer(rowValue(history, "minimum", 1));
722
+ const maximumSequence = history === undefined ? null : integer(rowValue(history, "maximum", 2));
723
+ if (operationCount !== head.sequence
724
+ || (head.sequence === 0 && (minimumValue !== null || maximumValue !== null))
725
+ || (head.sequence > 0 && (minimumSequence !== 1 || maximumSequence !== head.sequence))) {
726
+ throw new OhIntegrityError("The remote operation history does not exactly cover its current head.");
727
+ }
728
+ if (recordResult.rows.length > maximumRecords) {
729
+ throw new RangeError("The remote graph exceeds the requested record snapshot bound.");
730
+ }
731
+ const provenanceBySha256 = new Map<Sha256Hex, OhOperationV1>();
732
+ for (const row of provenanceResult.rows) {
733
+ const operation = parseOperationRow(row, { spaceId: this.binding.spaceId });
734
+ if (provenanceBySha256.has(operation.operationSha256)) {
735
+ throw new OhIntegrityError("A current materialization provenance operation is invalid.");
736
+ }
737
+ provenanceBySha256.set(operation.operationSha256, operation);
738
+ }
739
+ if (provenanceBySha256.size !== provenanceOperations
740
+ || (head.operationSha256 !== null && !provenanceBySha256.has(head.operationSha256))) {
741
+ throw new OhIntegrityError("The current materialization omitted required provenance operations.");
742
+ }
743
+ if (head.sequence > 0) {
744
+ const terminal = head.operationSha256 === null ? undefined : provenanceBySha256.get(head.operationSha256);
745
+ if (terminal === undefined || terminal.sequence !== head.sequence
746
+ || terminal.graphRevisionSha256 !== head.graphRevisionSha256
747
+ || terminal.recordsSha256 !== head.recordsSha256) {
748
+ throw new OhIntegrityError("The remote space head differs from its terminal canonical operation.");
749
+ }
750
+ }
751
+ const materialized = recordResult.rows.map((row) => {
752
+ const json = rowValue(row, "record_json", 3);
753
+ if (typeof json !== "string") throw new OhIntegrityError("A materialized remote record is not JSON text.");
754
+ let value: unknown;
755
+ try { value = JSON.parse(json); } catch { throw new OhIntegrityError("A materialized remote record is invalid."); }
756
+ const record = parseKnowledgeGraphRecordV1(value);
757
+ const operationSha256 = parseSha256Hex(rowValue(row, "operation_sha256", 4));
758
+ const sequence = integer(rowValue(row, "sequence", 5));
759
+ if (record === null || canonicalJson(record) !== json || operationSha256 === null
760
+ || sequence === null || sequence < 1 || sequence > head.sequence
761
+ || rowValue(row, "record_key", 0) !== record.key
762
+ || rowValue(row, "kind", 1) !== record.kind
763
+ || rowValue(row, "record_sha256", 2) !== record.recordSha256) {
764
+ throw new OhIntegrityError("A materialized remote record is invalid.");
765
+ }
766
+ const provenance = provenanceBySha256.get(operationSha256);
767
+ if (provenance === undefined || provenance.sequence !== sequence
768
+ || !provenance.changes.some((change) => change.kind === "put"
769
+ && canonicalJson(change.record) === json)) {
770
+ throw new OhIntegrityError("A materialized remote record has no exact canonical provenance put.");
771
+ }
772
+ return { record, sequence };
773
+ });
774
+ const records = materialized.map(({ record }) => record);
775
+ if (canonicalSha256(records.map(knowledgeGraphRecordRefV1)) !== head.recordsSha256) {
776
+ throw new OhIntegrityError("Materialized remote records do not reproduce the current head.");
777
+ }
778
+ const dependencyRows = dependencyResult.rows.map((row) => ({
779
+ dependency_key: rowValue(row, "dependency_key", 1),
780
+ record_key: rowValue(row, "record_key", 0),
781
+ }));
782
+ const expectedDependencies = records.flatMap((record) =>
783
+ record.dependencies.map((dependency) => ({ dependency_key: dependency, record_key: record.key })));
784
+ if (canonicalJson(dependencyRows) !== canonicalJson(expectedDependencies)) {
785
+ throw new OhIntegrityError("Materialized remote dependencies do not match their record envelopes.");
786
+ }
787
+ return { head, records, v: 1 };
788
+ }
789
+
790
+ async snapshot(options: Readonly<{
791
+ head?: OhHeadRefV1;
792
+ maximumRecords?: number;
793
+ }> = {}): Promise<OhSnapshotV1> {
794
+ this.#assertOpen();
795
+ const current = await this.head();
796
+ const target = options.head === undefined ? current : await this.#headAt(options.head);
797
+ if (target.sequence > current.sequence) throw new OhConflictError("The requested head is ahead of this space.");
798
+ const maximumRecords = options.maximumRecords ?? OH_GRAPH_LIMITS_V1.recordsPerSnapshot;
799
+ if (!Number.isSafeInteger(maximumRecords) || maximumRecords < 1
800
+ || maximumRecords > OH_GRAPH_LIMITS_V1.recordsPerSnapshot) {
801
+ throw new RangeError(`maximumRecords must be an integer from 1 through ${OH_GRAPH_LIMITS_V1.recordsPerSnapshot}.`);
802
+ }
803
+ if (target.operationSha256 === current.operationSha256) {
804
+ return await this.#currentMaterializedSnapshot(current, maximumRecords);
805
+ }
806
+ if (target.sequence > OH_LIBSQL_STORE_LIMITS_V1.historyOperations) {
807
+ throw new RangeError("The requested libSQL history exceeds its operation replay bound.");
808
+ }
809
+ const historyResults = await this.#client.batch([
810
+ { sql: `SELECT count(*) AS count, min(operation.sequence) AS minimum,
811
+ max(operation.sequence) AS maximum,
812
+ coalesce(sum(length(CAST(operation.operation_json AS BLOB))), 0) AS canonical_bytes,
813
+ coalesce(sum(${OPERATION_RESPONSE_BYTES}), 0) AS response_bytes
814
+ FROM oh_authority_operations AS operation
815
+ WHERE operation.space_id = ? AND operation.sequence <= ?`,
816
+ args: [this.binding.spaceId, target.sequence] },
817
+ { sql: `SELECT ${OPERATION_ROW_COLUMNS} FROM oh_authority_operations AS operation
818
+ WHERE operation.space_id = ? AND operation.sequence <= ?
819
+ AND (SELECT coalesce(sum(length(CAST(candidate.operation_json AS BLOB))), 0)
820
+ FROM oh_authority_operations AS candidate
821
+ WHERE candidate.space_id = ? AND candidate.sequence <= ?) <= ?
822
+ AND (SELECT coalesce(sum(${OPERATION_RESPONSE_BYTES.replaceAll("operation.", "candidate.")}), 0)
823
+ FROM oh_authority_operations AS candidate
824
+ WHERE candidate.space_id = ? AND candidate.sequence <= ?) <= ?
825
+ ORDER BY operation.sequence`, args: [this.binding.spaceId, target.sequence,
826
+ this.binding.spaceId, target.sequence, OH_LIBSQL_STORE_LIMITS_V1.historyBytes,
827
+ this.binding.spaceId, target.sequence, OH_LIBSQL_STORE_LIMITS_V1.providerResponseBytes] },
828
+ { sql: PURGE_ROW_SELECT, args: [this.binding.spaceId] },
829
+ ], "read");
830
+ if (historyResults.length !== 3) {
831
+ throw new OhIntegrityError("The remote authority returned an incomplete history batch.");
832
+ }
833
+ const [historySizeResult, historyRowResult, purgeResult] = historyResults as
834
+ [OhLibSqlResultV1, OhLibSqlResultV1, OhLibSqlResultV1];
835
+ const historySizeRow = historySizeResult.rows[0];
836
+ const historyBytes = historySizeRow === undefined ? null
837
+ : integer(rowValue(historySizeRow, "canonical_bytes", 3));
838
+ const responseBytes = historySizeRow === undefined ? null
839
+ : integer(rowValue(historySizeRow, "response_bytes", 4));
840
+ if (historyBytes === null || historyBytes > OH_LIBSQL_STORE_LIMITS_V1.historyBytes
841
+ || responseBytes === null || responseBytes > OH_LIBSQL_STORE_LIMITS_V1.providerResponseBytes) {
842
+ throw new RangeError("The requested libSQL history exceeds its provider-safe replay bounds.");
843
+ }
844
+ const historyCount = historySizeRow === undefined ? null : integer(rowValue(historySizeRow, "count", 0));
845
+ const minimumSequence = historySizeRow === undefined ? null : integer(rowValue(historySizeRow, "minimum", 1));
846
+ const maximumSequence = historySizeRow === undefined ? null : integer(rowValue(historySizeRow, "maximum", 2));
847
+ if (historyCount !== target.sequence
848
+ || (target.sequence === 0 && (rowValue(historySizeRow!, "minimum", 1) !== null
849
+ || rowValue(historySizeRow!, "maximum", 2) !== null))
850
+ || (target.sequence > 0 && (minimumSequence !== 1 || maximumSequence !== target.sequence))
851
+ || historyRowResult.rows.length !== historyCount) {
852
+ const purgeRow = purgeResult.rows[0];
853
+ if (purgeRow !== undefined) {
854
+ const purge = parsePurgeReceiptRow(purgeRow, this.binding.spaceId, this.binding.bindingSha256);
855
+ this.#purged = purge;
856
+ throw new OhPurgedSpaceError(purge);
857
+ }
858
+ throw new OhIntegrityError("The remote operation history does not exactly cover the requested head.");
859
+ }
860
+ const operations = historyRowResult.rows.map((row) => parseOperationRow(row,
861
+ { spaceId: this.binding.spaceId }));
862
+ const snapshot = replayOhOperationsV1(this.binding.spaceId, operations, maximumRecords);
863
+ if (snapshot.head.operationSha256 !== target.operationSha256
864
+ || snapshot.head.recordsSha256 !== target.recordsSha256) {
865
+ throw new OhIntegrityError("Remote operation replay does not reproduce the requested head.");
866
+ }
867
+ return snapshot;
868
+ }
869
+
870
+ async changesSince(
871
+ fromValue: OhHeadRefV1,
872
+ options: Readonly<{ limit?: number; through?: OhHeadRefV1 }> = {},
873
+ ): Promise<OhChangesPageV1> {
874
+ this.#assertOpen();
875
+ const from = parseOhHeadRefV1(fromValue);
876
+ if (from === null) throw new TypeError("Invalid change-feed cursor.");
877
+ const requestedThrough = options.through === undefined ? undefined : parseOhHeadRefV1(options.through);
878
+ if (requestedThrough === null) throw new TypeError("Invalid change-feed through head.");
879
+ const limit = normalizeLimit(options.limit, OH_LIBSQL_STORE_LIMITS_V1.changeFeedLimit,
880
+ OH_LIBSQL_STORE_LIMITS_V1.changeFeedLimit);
881
+ const throughSequence = requestedThrough?.sequence ?? null;
882
+ const results = await this.#client.batch([
883
+ { sql: `SELECT generation, graph_revision_sha256, head_operation_sha256, records_sha256, sequence
884
+ FROM oh_authority_spaces WHERE space_id = ?`, args: [this.binding.spaceId] },
885
+ { sql: `SELECT ${OPERATION_ROW_COLUMNS} FROM oh_authority_operations
886
+ WHERE space_id = ? AND sequence = ?`, args: [this.binding.spaceId, from.sequence] },
887
+ { sql: `SELECT ${OPERATION_ROW_COLUMNS} FROM oh_authority_operations
888
+ WHERE space_id = ? AND sequence = ?`, args: [this.binding.spaceId, throughSequence] },
889
+ { sql: `SELECT count(*) AS count, coalesce(sum(response_bytes), 0) AS response_bytes FROM (
890
+ SELECT ${OPERATION_RESPONSE_BYTES.replaceAll("operation.", "candidate.")} AS response_bytes
891
+ FROM oh_authority_operations AS candidate
892
+ WHERE candidate.space_id = ? AND candidate.sequence > ?
893
+ AND candidate.sequence <= coalesce(?,
894
+ (SELECT sequence FROM oh_authority_spaces WHERE space_id = ?))
895
+ ORDER BY candidate.sequence LIMIT ?
896
+ )`, args: [this.binding.spaceId, from.sequence, throughSequence,
897
+ this.binding.spaceId, limit + 1] },
898
+ { sql: `SELECT ${OPERATION_ROW_COLUMNS} FROM oh_authority_operations
899
+ AS operation WHERE operation.space_id = ? AND operation.sequence > ?
900
+ AND operation.sequence <= coalesce(?,
901
+ (SELECT sequence FROM oh_authority_spaces WHERE space_id = ?))
902
+ AND (SELECT coalesce(sum(response_bytes), 0) FROM (
903
+ SELECT ${OPERATION_RESPONSE_BYTES.replaceAll("operation.", "candidate.")} AS response_bytes
904
+ FROM oh_authority_operations AS candidate
905
+ WHERE candidate.space_id = ? AND candidate.sequence > ?
906
+ AND candidate.sequence <= coalesce(?,
907
+ (SELECT sequence FROM oh_authority_spaces WHERE space_id = ?))
908
+ ORDER BY candidate.sequence LIMIT ?
909
+ )) <= ?
910
+ ORDER BY operation.sequence LIMIT ?`,
911
+ args: [this.binding.spaceId, from.sequence, throughSequence, this.binding.spaceId,
912
+ this.binding.spaceId, from.sequence, throughSequence, this.binding.spaceId, limit + 1,
913
+ OH_LIBSQL_STORE_LIMITS_V1.providerResponseBytes, limit + 1] },
914
+ { sql: PURGE_ROW_SELECT, args: [this.binding.spaceId] },
915
+ ], "read");
916
+ if (results.length !== 6) throw new OhIntegrityError("The remote authority returned an incomplete change-feed batch.");
917
+ const [currentResult, fromResult, throughResult, pageSizeResult, pageResult, purgeResult] = results as
918
+ [OhLibSqlResultV1, OhLibSqlResultV1, OhLibSqlResultV1, OhLibSqlResultV1,
919
+ OhLibSqlResultV1, OhLibSqlResultV1];
920
+ const currentRow = currentResult.rows[0];
921
+ if (currentRow === undefined) {
922
+ const purgeRow = purgeResult.rows[0];
923
+ if (purgeRow !== undefined) {
924
+ const purge = parsePurgeReceiptRow(purgeRow, this.binding.spaceId, this.binding.bindingSha256);
925
+ this.#purged = purge;
926
+ throw new OhPurgedSpaceError(purge);
927
+ }
928
+ throw new OhIntegrityError("The remote Oh space disappeared while reading its change feed.");
929
+ }
930
+ const current = parseHeadRow(currentRow);
931
+ const resolveHead = (reference: OhHeadRefV1, result: OhLibSqlResultV1): OhHeadV1 => {
932
+ if (reference.sequence === 0) return emptyOhHeadV1();
933
+ const row = result.rows[0];
934
+ if (row === undefined) throw new OhConflictError("A requested change-feed head is not present in this space.");
935
+ const operation = parseOperationRow(row, { spaceId: this.binding.spaceId });
936
+ if (operation.spaceId !== this.binding.spaceId || operation.sequence !== reference.sequence
937
+ || operation.operationSha256 !== reference.operationSha256) {
938
+ throw new OhConflictError("A requested change-feed sequence identifies a different operation head.");
939
+ }
940
+ return { generation: operation.sequence, graphRevisionSha256: operation.graphRevisionSha256,
941
+ operationSha256: operation.operationSha256, recordsSha256: operation.recordsSha256,
942
+ sequence: operation.sequence, v: 1 };
943
+ };
944
+ const fromHead = resolveHead(from, fromResult);
945
+ const through = requestedThrough === undefined ? current : resolveHead(requestedThrough, throughResult);
946
+ if (fromHead.sequence > through.sequence || through.sequence > current.sequence) {
947
+ throw new OhConflictError("The change-feed bounds do not identify one remote history prefix.");
948
+ }
949
+ const pageSizeRow = pageSizeResult.rows[0];
950
+ const pageCount = pageSizeRow === undefined ? null : integer(rowValue(pageSizeRow, "count", 0));
951
+ const pageResponseBytes = pageSizeRow === undefined ? null
952
+ : integer(rowValue(pageSizeRow, "response_bytes", 1));
953
+ if (pageCount === null || pageCount > limit + 1 || pageResponseBytes === null) {
954
+ throw new OhIntegrityError("The remote change feed returned invalid response bounds.");
955
+ }
956
+ if (pageResponseBytes > OH_LIBSQL_STORE_LIMITS_V1.providerResponseBytes) {
957
+ throw new RangeError("The requested change-feed page exceeds its provider response bound.");
958
+ }
959
+ const parsed = pageResult.rows.map((row) => parseOperationRow(row, { spaceId: this.binding.spaceId }));
960
+ if (parsed.length !== pageCount) {
961
+ throw new OhIntegrityError("The remote change feed omitted provider-bounded rows.");
962
+ }
963
+ const hasMore = parsed.length > limit;
964
+ const operations = parsed.slice(0, limit);
965
+ let prior: OhHeadRefV1 = fromHead;
966
+ for (const operation of parsed) {
967
+ if (operation.spaceId !== this.binding.spaceId
968
+ || operation.sequence !== prior.sequence + 1
969
+ || operation.parentOperationSha256 !== prior.operationSha256) {
970
+ throw new OhIntegrityError("The remote change feed contains a gap or fork.");
971
+ }
972
+ prior = { operationSha256: operation.operationSha256, sequence: operation.sequence };
973
+ }
974
+ if (!hasMore && (prior.sequence !== through.sequence
975
+ || prior.operationSha256 !== through.operationSha256)) {
976
+ throw new OhIntegrityError("The remote change feed does not reach its pinned through head.");
977
+ }
978
+ const last = operations.at(-1);
979
+ const to = last === undefined
980
+ ? { operationSha256: fromHead.operationSha256, sequence: fromHead.sequence }
981
+ : { operationSha256: last.operationSha256, sequence: last.sequence };
982
+ return { from: { operationSha256: fromHead.operationSha256, sequence: fromHead.sequence },
983
+ hasMore, operations, through, to, v: 1 };
984
+ }
985
+
986
+ async #assertMaterializedSnapshot(snapshot: OhSnapshotV1): Promise<void> {
987
+ if (snapshot.head.sequence > OH_LIBSQL_STORE_LIMITS_V1.historyOperations) {
988
+ throw new RangeError("The libSQL authority exceeds its explicit verification operation bound.");
989
+ }
990
+ const verificationResults = await this.#client.batch([
991
+ { sql: `SELECT * FROM (WITH bounded_operation AS (
992
+ SELECT * FROM oh_authority_operations
993
+ WHERE space_id = ? AND sequence <= ?
994
+ ) SELECT count(*) AS operation_count, min(operation.sequence) AS minimum,
995
+ max(operation.sequence) AS maximum,
996
+ coalesce(sum(length(CAST(operation.operation_json AS BLOB))), 0) AS canonical_bytes,
997
+ coalesce(sum(${OPERATION_RESPONSE_BYTES}), 0) AS operation_response_bytes,
998
+ (SELECT coalesce(sum(${RECORD_RESPONSE_BYTES}), 0)
999
+ FROM oh_authority_records AS record WHERE record.space_id = ?) AS record_response_bytes,
1000
+ (SELECT coalesce(sum(${DEPENDENCY_RESPONSE_BYTES}), 0)
1001
+ FROM oh_authority_dependencies AS dependency
1002
+ WHERE dependency.space_id = ?) AS dependency_response_bytes,
1003
+ (SELECT coalesce(sum(${OPERATION_RECORD_RESPONSE_BYTES}), 0)
1004
+ FROM oh_authority_operation_records AS materialized
1005
+ JOIN bounded_operation AS owner
1006
+ ON owner.operation_sha256 = materialized.operation_sha256) AS operation_record_response_bytes
1007
+ FROM bounded_operation AS operation)`, args: [this.binding.spaceId, snapshot.head.sequence,
1008
+ this.binding.spaceId, this.binding.spaceId] },
1009
+ { sql: `SELECT ${OPERATION_ROW_COLUMNS}
1010
+ FROM oh_authority_operations AS operation
1011
+ WHERE operation.space_id = ? AND operation.sequence <= ?
1012
+ AND (SELECT coalesce(sum(length(CAST(candidate.operation_json AS BLOB))), 0)
1013
+ FROM oh_authority_operations AS candidate
1014
+ WHERE candidate.space_id = ? AND candidate.sequence <= ?) <= ?
1015
+ AND (SELECT coalesce(sum(${OPERATION_RESPONSE_BYTES.replaceAll("operation.", "candidate.")}), 0)
1016
+ FROM oh_authority_operations AS candidate
1017
+ WHERE candidate.space_id = ? AND candidate.sequence <= ?) <= ?
1018
+ ORDER BY operation.sequence`, args: [this.binding.spaceId, snapshot.head.sequence,
1019
+ this.binding.spaceId, snapshot.head.sequence, OH_LIBSQL_STORE_LIMITS_V1.historyBytes,
1020
+ this.binding.spaceId, snapshot.head.sequence, OH_LIBSQL_STORE_LIMITS_V1.providerResponseBytes] },
1021
+ { sql: `SELECT record_key, kind, record_sha256, record_json, operation_sha256, sequence
1022
+ FROM oh_authority_records AS record WHERE record.space_id = ?
1023
+ AND (SELECT coalesce(sum(${RECORD_RESPONSE_BYTES}), 0)
1024
+ FROM oh_authority_records AS record WHERE record.space_id = ?) <= ?
1025
+ ORDER BY record.record_key`, args: [this.binding.spaceId, this.binding.spaceId,
1026
+ OH_LIBSQL_STORE_LIMITS_V1.snapshotComponentBytes] },
1027
+ { sql: `SELECT record_key, dependency_key FROM oh_authority_dependencies AS dependency
1028
+ WHERE dependency.space_id = ?
1029
+ AND (SELECT coalesce(sum(${DEPENDENCY_RESPONSE_BYTES}), 0)
1030
+ FROM oh_authority_dependencies AS dependency WHERE dependency.space_id = ?) <= ?
1031
+ ORDER BY dependency.record_key, dependency.dependency_key`, args: [this.binding.spaceId,
1032
+ this.binding.spaceId, OH_LIBSQL_STORE_LIMITS_V1.snapshotComponentBytes] },
1033
+ { sql: `SELECT materialized.space_id, materialized.operation_sha256, materialized.ordinal,
1034
+ materialized.record_key, materialized.change_kind, materialized.record_sha256
1035
+ FROM oh_authority_operation_records AS materialized
1036
+ JOIN oh_authority_operations AS operation
1037
+ ON operation.operation_sha256 = materialized.operation_sha256
1038
+ WHERE operation.space_id = ? AND operation.sequence <= ?
1039
+ AND (SELECT coalesce(sum(${OPERATION_RECORD_RESPONSE_BYTES}), 0)
1040
+ FROM oh_authority_operation_records AS materialized
1041
+ JOIN oh_authority_operations AS owner
1042
+ ON owner.operation_sha256 = materialized.operation_sha256
1043
+ WHERE owner.space_id = ? AND owner.sequence <= ?) <= ?
1044
+ ORDER BY operation.sequence, materialized.ordinal`, args: [this.binding.spaceId,
1045
+ snapshot.head.sequence, this.binding.spaceId, snapshot.head.sequence,
1046
+ OH_LIBSQL_STORE_LIMITS_V1.snapshotComponentBytes] },
1047
+ { sql: `SELECT generation, graph_revision_sha256, head_operation_sha256, records_sha256, sequence
1048
+ FROM oh_authority_spaces WHERE space_id = ?`, args: [this.binding.spaceId] },
1049
+ ], "read");
1050
+ if (verificationResults.length !== 6) {
1051
+ throw new OhIntegrityError("The remote authority returned an incomplete verification batch.");
1052
+ }
1053
+ const [sizeResult, operationResult, recordResult, dependencyResult, operationRecordResult, headResult] =
1054
+ verificationResults as [OhLibSqlResultV1, OhLibSqlResultV1, OhLibSqlResultV1,
1055
+ OhLibSqlResultV1, OhLibSqlResultV1, OhLibSqlResultV1];
1056
+ const sizeRow = sizeResult.rows[0];
1057
+ const operationCount = sizeRow === undefined ? null : integer(rowValue(sizeRow, "operation_count", 0));
1058
+ const minimumValue = sizeRow === undefined ? undefined : rowValue(sizeRow, "minimum", 1);
1059
+ const maximumValue = sizeRow === undefined ? undefined : rowValue(sizeRow, "maximum", 2);
1060
+ const minimumSequence = sizeRow === undefined ? null : integer(rowValue(sizeRow, "minimum", 1));
1061
+ const maximumSequence = sizeRow === undefined ? null : integer(rowValue(sizeRow, "maximum", 2));
1062
+ const historyBytes = sizeRow === undefined ? null : integer(rowValue(sizeRow, "canonical_bytes", 3));
1063
+ const operationResponseBytes = sizeRow === undefined ? null
1064
+ : integer(rowValue(sizeRow, "operation_response_bytes", 4));
1065
+ const recordResponseBytes = sizeRow === undefined ? null
1066
+ : integer(rowValue(sizeRow, "record_response_bytes", 5));
1067
+ const dependencyResponseBytes = sizeRow === undefined ? null
1068
+ : integer(rowValue(sizeRow, "dependency_response_bytes", 6));
1069
+ const operationRecordResponseBytes = sizeRow === undefined ? null
1070
+ : integer(rowValue(sizeRow, "operation_record_response_bytes", 7));
1071
+ if (historyBytes === null || historyBytes > OH_LIBSQL_STORE_LIMITS_V1.historyBytes
1072
+ || operationResponseBytes === null
1073
+ || operationResponseBytes > OH_LIBSQL_STORE_LIMITS_V1.providerResponseBytes
1074
+ || recordResponseBytes === null
1075
+ || recordResponseBytes > OH_LIBSQL_STORE_LIMITS_V1.snapshotComponentBytes
1076
+ || dependencyResponseBytes === null
1077
+ || dependencyResponseBytes > OH_LIBSQL_STORE_LIMITS_V1.snapshotComponentBytes
1078
+ || operationRecordResponseBytes === null
1079
+ || operationRecordResponseBytes > OH_LIBSQL_STORE_LIMITS_V1.snapshotComponentBytes) {
1080
+ throw new RangeError("The libSQL authority exceeds its provider-safe verification bounds.");
1081
+ }
1082
+ if (operationCount !== snapshot.head.sequence
1083
+ || (snapshot.head.sequence === 0 && (minimumValue !== null || maximumValue !== null))
1084
+ || (snapshot.head.sequence > 0
1085
+ && (minimumSequence !== 1 || maximumSequence !== snapshot.head.sequence))
1086
+ || operationResult.rows.length !== operationCount) {
1087
+ throw new OhIntegrityError("The remote operation history does not exactly cover its verified head.");
1088
+ }
1089
+ const headRow = headResult.rows[0];
1090
+ if (headRow === undefined) throw new OhIntegrityError("The remote authority lost its head during verification.");
1091
+ if (canonicalJson(parseHeadRow(headRow)) !== canonicalJson(snapshot.head)) {
1092
+ throw new OhConflictError("The remote authority head changed during verification.");
1093
+ }
1094
+ const operations = operationResult.rows.map((row) => {
1095
+ return parseOperationRow(row, { spaceId: this.binding.spaceId });
1096
+ });
1097
+ const replayed = replayOhOperationsV1(this.binding.spaceId, operations);
1098
+ if (canonicalJson(replayed) !== canonicalJson(snapshot)) {
1099
+ throw new OhIntegrityError("Remote operation replay changed during materialization verification.");
1100
+ }
1101
+ const materializedBy = new Map<string, Readonly<{ operationSha256: Sha256Hex; sequence: number }>>();
1102
+ for (const operation of operations) {
1103
+ for (const change of operation.changes) {
1104
+ const key = change.kind === "put" ? change.record.key : change.key;
1105
+ if (change.kind === "put") materializedBy.set(key,
1106
+ { operationSha256: operation.operationSha256, sequence: operation.sequence });
1107
+ else materializedBy.delete(key);
1108
+ }
1109
+ }
1110
+ const records: KnowledgeGraphRecordV1[] = recordResult.rows.map((row) => {
1111
+ const json = rowValue(row, "record_json", 3);
1112
+ if (typeof json !== "string") throw new OhIntegrityError("A materialized remote record is not JSON text.");
1113
+ let value: unknown;
1114
+ try { value = JSON.parse(json); } catch { throw new OhIntegrityError("A materialized remote record is invalid."); }
1115
+ const record = parseKnowledgeGraphRecordV1(value);
1116
+ const provenance = record === null ? undefined : materializedBy.get(record.key);
1117
+ if (record === null || canonicalJson(record) !== json
1118
+ || rowValue(row, "record_key", 0) !== record.key
1119
+ || rowValue(row, "kind", 1) !== record.kind
1120
+ || rowValue(row, "record_sha256", 2) !== record.recordSha256
1121
+ || provenance === undefined
1122
+ || rowValue(row, "operation_sha256", 4) !== provenance.operationSha256
1123
+ || integer(rowValue(row, "sequence", 5)) !== provenance.sequence) {
1124
+ throw new OhIntegrityError("A materialized remote record differs from operation replay.");
1125
+ }
1126
+ return record;
1127
+ });
1128
+ if (canonicalJson(records) !== canonicalJson(snapshot.records)) {
1129
+ throw new OhIntegrityError("Remote materialized records do not match operation replay.");
1130
+ }
1131
+ const dependencyRows = dependencyResult.rows.map((row) => ({
1132
+ dependency_key: rowValue(row, "dependency_key", 1),
1133
+ record_key: rowValue(row, "record_key", 0),
1134
+ }));
1135
+ const expectedDependencies = snapshot.records.flatMap((record) =>
1136
+ record.dependencies.map((dependency) => ({ dependency_key: dependency, record_key: record.key })));
1137
+ if (canonicalJson(dependencyRows) !== canonicalJson(expectedDependencies)) {
1138
+ throw new OhIntegrityError("Remote materialized dependencies do not match operation replay.");
1139
+ }
1140
+ const operationRecordRows = operationRecordResult.rows.map((row) => ({
1141
+ change_kind: rowValue(row, "change_kind", 4),
1142
+ operation_sha256: rowValue(row, "operation_sha256", 1),
1143
+ ordinal: integer(rowValue(row, "ordinal", 2)),
1144
+ record_key: rowValue(row, "record_key", 3),
1145
+ record_sha256: rowValue(row, "record_sha256", 5),
1146
+ space_id: rowValue(row, "space_id", 0),
1147
+ }));
1148
+ const expectedOperationRecords = operations.flatMap((operation) =>
1149
+ operation.changes.map((change, ordinal) => ({ change_kind: change.kind,
1150
+ operation_sha256: operation.operationSha256, ordinal,
1151
+ record_key: change.kind === "put" ? change.record.key : change.key,
1152
+ record_sha256: change.kind === "put" ? change.record.recordSha256 : change.priorSha256,
1153
+ space_id: this.binding.spaceId })));
1154
+ if (canonicalJson(operationRecordRows) !== canonicalJson(expectedOperationRecords)) {
1155
+ throw new OhIntegrityError("Remote operation-record rows do not match operation replay.");
1156
+ }
1157
+ }
1158
+
1159
+ async #operationById(operationId: string): Promise<OhOperationV1 | null> {
1160
+ const row = await queryOne(this.#client, { sql: `SELECT ${OPERATION_ROW_COLUMNS} FROM oh_authority_operations
1161
+ WHERE space_id = ? AND operation_id = ?`, args: [this.binding.spaceId, operationId] });
1162
+ if (row === null) return null;
1163
+ return parseOperationRow(row, { operationId, spaceId: this.binding.spaceId });
1164
+ }
1165
+
1166
+ async #commitPreflight(operationId: string): Promise<Readonly<{
1167
+ current: OhHeadV1;
1168
+ duplicate: OhOperationV1 | null;
1169
+ }>> {
1170
+ const results = await this.#client.batch([
1171
+ { sql: `SELECT ${OPERATION_ROW_COLUMNS} FROM oh_authority_operations
1172
+ WHERE space_id = ? AND operation_id = ?`, args: [this.binding.spaceId, operationId] },
1173
+ { sql: `SELECT generation, graph_revision_sha256, head_operation_sha256, records_sha256, sequence
1174
+ FROM oh_authority_spaces WHERE space_id = ?`, args: [this.binding.spaceId] },
1175
+ { sql: PURGE_ROW_SELECT, args: [this.binding.spaceId] },
1176
+ ], "read");
1177
+ if (results.length !== 3) throw new OhIntegrityError("The remote authority returned an incomplete commit preflight.");
1178
+ const [duplicateResult, headResult, purgeResult] = results as
1179
+ [OhLibSqlResultV1, OhLibSqlResultV1, OhLibSqlResultV1];
1180
+ const headRow = headResult.rows[0];
1181
+ if (headRow === undefined) {
1182
+ const purgeRow = purgeResult.rows[0];
1183
+ if (purgeRow !== undefined) {
1184
+ const purge = parsePurgeReceiptRow(purgeRow, this.binding.spaceId, this.binding.bindingSha256);
1185
+ this.#purged = purge;
1186
+ throw new OhPurgedSpaceError(purge);
1187
+ }
1188
+ throw new OhIntegrityError("The remote space disappeared during commit preflight.");
1189
+ }
1190
+ const duplicateRow = duplicateResult.rows[0];
1191
+ return { current: parseHeadRow(headRow), duplicate: duplicateRow === undefined ? null
1192
+ : parseOperationRow(duplicateRow, { operationId, spaceId: this.binding.spaceId }) };
1193
+ }
1194
+
1195
+ async #assertOperationReachable(operation: OhOperationV1, expectedHead: OhHeadV1): Promise<void> {
1196
+ if (operation.sequence < 1 || operation.sequence > expectedHead.sequence) {
1197
+ throw new OhIntegrityError("A remote idempotent operation is not reachable from the current head.");
1198
+ }
1199
+ const results = await this.#client.batch([
1200
+ { sql: `SELECT * FROM (WITH RECURSIVE authority_chain(sequence, operation_sha256) AS (
1201
+ SELECT sequence, operation_sha256 FROM oh_authority_operations
1202
+ WHERE space_id = ? AND sequence = ? AND operation_sha256 = ?
1203
+ UNION ALL
1204
+ SELECT candidate.sequence, candidate.operation_sha256
1205
+ FROM oh_authority_operations AS candidate
1206
+ JOIN authority_chain AS prior
1207
+ ON candidate.space_id = ? AND candidate.sequence = prior.sequence + 1
1208
+ AND candidate.parent_operation_sha256 = prior.operation_sha256
1209
+ WHERE candidate.sequence <= ?
1210
+ ) SELECT count(*) AS count, min(sequence) AS minimum, max(sequence) AS maximum,
1211
+ (SELECT operation_sha256 FROM authority_chain ORDER BY sequence DESC LIMIT 1) AS terminal_sha256
1212
+ FROM authority_chain)`, args: [this.binding.spaceId, operation.sequence,
1213
+ operation.operationSha256, this.binding.spaceId, expectedHead.sequence] },
1214
+ { sql: `SELECT ${OPERATION_ROW_COLUMNS} FROM oh_authority_operations
1215
+ WHERE space_id = ? AND sequence = ?`, args: [this.binding.spaceId, expectedHead.sequence] },
1216
+ { sql: `SELECT generation, graph_revision_sha256, head_operation_sha256, records_sha256, sequence
1217
+ FROM oh_authority_spaces WHERE space_id = ?`, args: [this.binding.spaceId] },
1218
+ { sql: PURGE_ROW_SELECT, args: [this.binding.spaceId] },
1219
+ ], "read");
1220
+ if (results.length !== 4) throw new OhIntegrityError("The remote authority returned an incomplete reachability proof.");
1221
+ const [chainResult, terminalResult, headResult, purgeResult] = results as
1222
+ [OhLibSqlResultV1, OhLibSqlResultV1, OhLibSqlResultV1, OhLibSqlResultV1];
1223
+ const headRow = headResult.rows[0];
1224
+ if (headRow === undefined) {
1225
+ const purgeRow = purgeResult.rows[0];
1226
+ if (purgeRow !== undefined) {
1227
+ const purge = parsePurgeReceiptRow(purgeRow, this.binding.spaceId, this.binding.bindingSha256);
1228
+ this.#purged = purge;
1229
+ throw new OhPurgedSpaceError(purge);
1230
+ }
1231
+ throw new OhIntegrityError("The remote space disappeared during an idempotency proof.");
1232
+ }
1233
+ const current = parseHeadRow(headRow);
1234
+ if (canonicalJson(current) !== canonicalJson(expectedHead)) {
1235
+ throw new OhConflictError("The remote space head changed during an idempotency proof.");
1236
+ }
1237
+ const chain = chainResult.rows[0];
1238
+ const count = chain === undefined ? null : integer(rowValue(chain, "count", 0));
1239
+ const minimum = chain === undefined ? null : integer(rowValue(chain, "minimum", 1));
1240
+ const maximum = chain === undefined ? null : integer(rowValue(chain, "maximum", 2));
1241
+ const terminalSha256 = chain === undefined ? null : rowValue(chain, "terminal_sha256", 3);
1242
+ if (count !== expectedHead.sequence - operation.sequence + 1
1243
+ || minimum !== operation.sequence || maximum !== expectedHead.sequence
1244
+ || terminalSha256 !== expectedHead.operationSha256) {
1245
+ throw new OhIntegrityError("A remote idempotent operation has no exact path to the current head.");
1246
+ }
1247
+ const terminalRow = terminalResult.rows[0];
1248
+ if (terminalRow === undefined || expectedHead.operationSha256 === null) {
1249
+ throw new OhIntegrityError("The remote current head operation is missing.");
1250
+ }
1251
+ const terminal = parseOperationRow(terminalRow, { operationSha256: expectedHead.operationSha256,
1252
+ spaceId: this.binding.spaceId });
1253
+ if (terminal.sequence !== expectedHead.sequence
1254
+ || terminal.graphRevisionSha256 !== expectedHead.graphRevisionSha256
1255
+ || terminal.recordsSha256 !== expectedHead.recordsSha256) {
1256
+ throw new OhIntegrityError("The remote space head differs from its terminal canonical operation.");
1257
+ }
1258
+ }
1259
+
1260
+ async commit(input: OhCommitInputV1): Promise<OhOperationV1> {
1261
+ this.#assertOpen();
1262
+ const actorId = safeCode(input.actorId);
1263
+ const operationId = safeCode(input.operationId);
1264
+ const changes = canonicalKnowledgeGraphChangesV1(input.changes);
1265
+ if (actorId === null || operationId === null || changes.length === 0) throw new TypeError("Invalid Oh commit input.");
1266
+ if (changes.length > OH_LIBSQL_STORE_LIMITS_V1.changesPerCommit) {
1267
+ throw new RangeError("A direct libSQL commit exceeds its change-count bound.");
1268
+ }
1269
+ const dependencies = changes.reduce((count, change) => count
1270
+ + (change.kind === "put" ? change.record.dependencies.length : 0), 0);
1271
+ if (dependencies > OH_LIBSQL_STORE_LIMITS_V1.dependenciesPerCommit) {
1272
+ throw new RangeError("A direct libSQL commit exceeds its dependency-count bound.");
1273
+ }
1274
+ const { current, duplicate } = await this.#commitPreflight(operationId);
1275
+ if (duplicate !== null) {
1276
+ await this.#assertOperationReachable(duplicate, current);
1277
+ if (duplicate.actorId !== actorId || canonicalJson(duplicate.changes) !== canonicalJson(changes)) {
1278
+ throw new OhConflictError("The operation ID is already bound to different content.");
1279
+ }
1280
+ return duplicate;
1281
+ }
1282
+ if (!Number.isSafeInteger(input.expectedHead.generation) || input.expectedHead.generation < 0
1283
+ || current.generation !== input.expectedHead.generation
1284
+ || current.operationSha256 !== input.expectedHead.operationSha256) {
1285
+ throw new OhConflictError("The expected head does not match the current remote space head.");
1286
+ }
1287
+ const snapshot = await this.#currentMaterializedSnapshot(current, OH_GRAPH_LIMITS_V1.recordsPerSnapshot);
1288
+ const transition = transitionOhSnapshotV1({ actorId, changes,
1289
+ instant: input.instant ?? canonicalNow(), operationId, snapshot, spaceId: this.binding.spaceId });
1290
+ const operation = transition.operation;
1291
+ if (utf8ByteLength(canonicalJson(operation)) > OH_LIBSQL_STORE_LIMITS_V1.operationBytes) {
1292
+ throw new RangeError("A direct libSQL operation exceeds its canonical byte bound.");
1293
+ }
1294
+ const existsOperation = "EXISTS (SELECT 1 FROM oh_authority_operations WHERE operation_sha256 = ?)";
1295
+ const statements: OhLibSqlStatementV1[] = [{
1296
+ sql: `INSERT INTO oh_authority_operations(operation_sha256, space_id, sequence,
1297
+ operation_id, parent_operation_sha256, graph_revision_sha256, records_sha256,
1298
+ operation_json, instant)
1299
+ SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?
1300
+ WHERE EXISTS (SELECT 1 FROM oh_authority_spaces
1301
+ WHERE space_id = ? AND generation = ? AND head_operation_sha256 IS ?)`,
1302
+ args: [operation.operationSha256, this.binding.spaceId, operation.sequence, operation.operationId,
1303
+ operation.parentOperationSha256, operation.graphRevisionSha256, operation.recordsSha256,
1304
+ canonicalJson(operation), operation.instant, this.binding.spaceId, current.generation,
1305
+ current.operationSha256],
1306
+ }];
1307
+ for (const [ordinal, change] of operation.changes.entries()) {
1308
+ const key = change.kind === "put" ? change.record.key : change.key;
1309
+ const digest = change.kind === "put" ? change.record.recordSha256 : change.priorSha256;
1310
+ statements.push({ sql: `INSERT INTO oh_authority_operation_records(space_id, operation_sha256,
1311
+ ordinal, record_key, change_kind, record_sha256)
1312
+ SELECT ?, ?, ?, ?, ?, ? WHERE ${existsOperation}`,
1313
+ args: [this.binding.spaceId, operation.operationSha256, ordinal, key, change.kind, digest,
1314
+ operation.operationSha256] });
1315
+ statements.push({ sql: `DELETE FROM oh_authority_dependencies WHERE space_id = ? AND record_key = ?
1316
+ AND ${existsOperation}`, args: [this.binding.spaceId, key, operation.operationSha256] });
1317
+ if (change.kind === "put") {
1318
+ statements.push({ sql: `INSERT INTO oh_authority_records(space_id, record_key, kind,
1319
+ record_sha256, record_json, operation_sha256, sequence)
1320
+ SELECT ?, ?, ?, ?, ?, ?, ? WHERE ${existsOperation}
1321
+ ON CONFLICT(space_id, record_key) DO UPDATE SET kind = excluded.kind,
1322
+ record_sha256 = excluded.record_sha256, record_json = excluded.record_json,
1323
+ operation_sha256 = excluded.operation_sha256, sequence = excluded.sequence`,
1324
+ args: [this.binding.spaceId, key, change.record.kind, change.record.recordSha256,
1325
+ canonicalJson(change.record), operation.operationSha256, operation.sequence,
1326
+ operation.operationSha256] });
1327
+ } else {
1328
+ statements.push({ sql: `DELETE FROM oh_authority_records WHERE space_id = ? AND record_key = ?
1329
+ AND record_sha256 = ? AND ${existsOperation}`,
1330
+ args: [this.binding.spaceId, key, change.priorSha256, operation.operationSha256] });
1331
+ }
1332
+ }
1333
+ for (const change of operation.changes) {
1334
+ if (change.kind !== "put") continue;
1335
+ for (const dependency of change.record.dependencies) {
1336
+ statements.push({ sql: `INSERT INTO oh_authority_dependencies(space_id, record_key, dependency_key)
1337
+ SELECT ?, ?, ? WHERE ${existsOperation}`,
1338
+ args: [this.binding.spaceId, change.record.key, dependency, operation.operationSha256] });
1339
+ }
1340
+ }
1341
+ statements.push({ sql: `UPDATE oh_authority_spaces SET generation = ?, head_operation_sha256 = ?,
1342
+ graph_revision_sha256 = ?, records_sha256 = ?, sequence = ?, updated_at = ?
1343
+ WHERE space_id = ? AND generation = ? AND head_operation_sha256 IS ? AND ${existsOperation}`,
1344
+ args: [operation.sequence, operation.operationSha256, operation.graphRevisionSha256,
1345
+ operation.recordsSha256, operation.sequence, operation.instant, this.binding.spaceId,
1346
+ current.generation, current.operationSha256, operation.operationSha256] });
1347
+ statements.push({ sql: `INSERT INTO oh_authority_commit_guards(value)
1348
+ SELECT 'invalid' WHERE NOT EXISTS (SELECT 1 FROM oh_authority_spaces
1349
+ WHERE space_id = ? AND generation = ? AND head_operation_sha256 = ?)`,
1350
+ args: [this.binding.spaceId, operation.sequence, operation.operationSha256] });
1351
+ statements.push({ sql: `SELECT ${OPERATION_ROW_COLUMNS} FROM oh_authority_operations
1352
+ WHERE space_id = ? AND operation_id = ?`, args: [this.binding.spaceId, operationId] });
1353
+ statements.push({ sql: `SELECT generation, graph_revision_sha256, head_operation_sha256, records_sha256, sequence
1354
+ FROM oh_authority_spaces WHERE space_id = ?`, args: [this.binding.spaceId] });
1355
+ let writeResults: readonly OhLibSqlResultV1[];
1356
+ try {
1357
+ writeResults = await this.#client.batch(statements, "write");
1358
+ } catch (error) {
1359
+ const raced = await this.#operationById(operationId);
1360
+ const head = await this.head();
1361
+ if (raced !== null && raced.actorId === actorId
1362
+ && canonicalJson(raced.changes) === canonicalJson(changes)) {
1363
+ await this.#assertOperationReachable(raced, head);
1364
+ return raced;
1365
+ }
1366
+ if (head.operationSha256 !== current.operationSha256) {
1367
+ throw new OhConflictError("The remote space head changed while committing.");
1368
+ }
1369
+ throw error;
1370
+ }
1371
+ if (writeResults.length !== statements.length) {
1372
+ throw new OhIntegrityError("The remote authority returned an incomplete commit result batch.");
1373
+ }
1374
+ const persistedRow = writeResults.at(-2)?.rows[0];
1375
+ const persistedHeadRow = writeResults.at(-1)?.rows[0];
1376
+ if (persistedRow === undefined || persistedHeadRow === undefined) {
1377
+ throw new OhIntegrityError("The remote authority omitted its persisted commit result.");
1378
+ }
1379
+ const persisted = parseOperationRow(persistedRow, { operationId, spaceId: this.binding.spaceId });
1380
+ const persistedHead = parseHeadRow(persistedHeadRow);
1381
+ if (canonicalJson(persisted) !== canonicalJson(operation)
1382
+ || persistedHead.operationSha256 !== operation.operationSha256
1383
+ || persistedHead.sequence !== operation.sequence
1384
+ || persistedHead.graphRevisionSha256 !== operation.graphRevisionSha256
1385
+ || persistedHead.recordsSha256 !== operation.recordsSha256) {
1386
+ throw new OhIntegrityError("The remote authority did not persist the committed operation exactly.");
1387
+ }
1388
+ return persisted;
1389
+ }
1390
+
1391
+ async exportDependencyClosure(input: Readonly<{
1392
+ head?: OhHeadRefV1;
1393
+ maximumRecords?: number;
1394
+ roots: readonly string[];
1395
+ }>): Promise<OhDependencyClosureV1> {
1396
+ if (!this.binding.profile.capabilities.dependencyClosureExport) {
1397
+ throw new OhProfileError("This remote profile does not permit dependency-closure export.");
1398
+ }
1399
+ const snapshot = await this.snapshot({ ...(input.head === undefined ? {} : { head: input.head }),
1400
+ ...(input.maximumRecords === undefined ? {} : { maximumRecords: input.maximumRecords }) });
1401
+ return createOhDependencyClosureV1({ binding: this.binding,
1402
+ ...(input.maximumRecords === undefined ? {} : { maximumRecords: input.maximumRecords }),
1403
+ roots: input.roots, snapshot });
1404
+ }
1405
+
1406
+ async verify(): Promise<OhStoreVerificationV1> {
1407
+ this.#assertOpen();
1408
+ const snapshot = await this.snapshot();
1409
+ await this.#assertMaterializedSnapshot(snapshot);
1410
+ return { head: snapshot.head, integrity: "verified", operations: snapshot.head.sequence,
1411
+ records: snapshot.records.length, v: 1 };
1412
+ }
1413
+
1414
+ async #assertPurgeComplete(expected: OhSpacePurgeReceiptV1): Promise<void> {
1415
+ await assertRemotePurgeComplete(this.#client, this.binding, expected);
1416
+ }
1417
+
1418
+ async purgeWorkingSpace(purgedAt: string): Promise<OhSpacePurgeReceiptV1> {
1419
+ this.#assertOpen();
1420
+ if (this.binding.profile.profileKind !== "working"
1421
+ || !this.binding.profile.capabilities.wholeSpacePurge) {
1422
+ throw new OhProfileError("Whole-space purge requires a bound working profile.");
1423
+ }
1424
+ for (let attempt = 0; attempt < 3; attempt += 1) {
1425
+ const existing = await this.#readPurge();
1426
+ if (existing !== null) {
1427
+ await this.#assertPurgeComplete(existing);
1428
+ this.#purged = existing;
1429
+ return existing;
1430
+ }
1431
+ const head = await this.head();
1432
+ const receipt = createOhSpacePurgeReceiptV1({ binding: this.binding, priorHead: head, purgedAt });
1433
+ const receiptExists = "EXISTS (SELECT 1 FROM oh_authority_purges WHERE space_id = ? AND receipt_sha256 = ?)";
1434
+ const statements: OhLibSqlStatementV1[] = [{ sql: `INSERT INTO oh_authority_purges(space_id,
1435
+ binding_sha256, prior_operation_sha256, prior_sequence, purged_at, receipt_sha256, receipt_json)
1436
+ SELECT ?, ?, ?, ?, ?, ?, ? WHERE EXISTS (SELECT 1 FROM oh_authority_spaces
1437
+ WHERE space_id = ? AND generation = ? AND head_operation_sha256 IS ?)
1438
+ AND EXISTS (SELECT 1 FROM oh_authority_bindings WHERE space_id = ? AND binding_sha256 = ?)`,
1439
+ args: [this.binding.spaceId, this.binding.bindingSha256, head.operationSha256, head.sequence,
1440
+ receipt.purgedAt, receipt.receiptSha256, canonicalJson(receipt), this.binding.spaceId,
1441
+ head.generation, head.operationSha256, this.binding.spaceId, this.binding.bindingSha256] }];
1442
+ const guardedDelete = (table: string): OhLibSqlStatementV1 => ({
1443
+ sql: `DELETE FROM ${table} WHERE space_id = ? AND ${receiptExists}`,
1444
+ args: [this.binding.spaceId, this.binding.spaceId, receipt.receiptSha256],
1445
+ });
1446
+ statements.push({ sql: `DELETE FROM oh_authority_operation_records
1447
+ WHERE operation_sha256 IN (SELECT operation_sha256 FROM oh_authority_operations WHERE space_id = ?)
1448
+ AND ${receiptExists}`,
1449
+ args: [this.binding.spaceId, this.binding.spaceId, receipt.receiptSha256] });
1450
+ statements.push(guardedDelete("oh_authority_dependencies"));
1451
+ statements.push(guardedDelete("oh_authority_records"));
1452
+ statements.push(guardedDelete("oh_authority_operations"));
1453
+ statements.push(guardedDelete("oh_authority_bindings"));
1454
+ statements.push(guardedDelete("oh_authority_spaces"));
1455
+ statements.push({ sql: `INSERT INTO oh_authority_commit_guards(value)
1456
+ SELECT 'invalid' WHERE EXISTS (SELECT 1 FROM oh_authority_spaces WHERE space_id = ?)
1457
+ OR EXISTS (SELECT 1 FROM oh_authority_bindings WHERE space_id = ?)
1458
+ OR EXISTS (SELECT 1 FROM oh_authority_operations WHERE space_id = ?)
1459
+ OR EXISTS (SELECT 1 FROM oh_authority_operation_records WHERE space_id = ?)
1460
+ OR EXISTS (SELECT 1 FROM oh_authority_operation_records AS materialized
1461
+ LEFT JOIN oh_authority_operations AS operation
1462
+ ON operation.operation_sha256 = materialized.operation_sha256
1463
+ WHERE operation.operation_sha256 IS NULL OR operation.space_id <> materialized.space_id)
1464
+ OR EXISTS (SELECT 1 FROM oh_authority_records WHERE space_id = ?)
1465
+ OR EXISTS (SELECT 1 FROM oh_authority_dependencies WHERE space_id = ?)
1466
+ OR NOT ${receiptExists}`,
1467
+ args: [this.binding.spaceId, this.binding.spaceId, this.binding.spaceId,
1468
+ this.binding.spaceId, this.binding.spaceId, this.binding.spaceId,
1469
+ this.binding.spaceId, receipt.receiptSha256] });
1470
+ try { await this.#client.batch(statements, "write"); } catch {
1471
+ const raced = await this.#readPurge();
1472
+ if (raced !== null) {
1473
+ await this.#assertPurgeComplete(raced);
1474
+ this.#purged = raced;
1475
+ return raced;
1476
+ }
1477
+ continue;
1478
+ }
1479
+ const persisted = await this.#readPurge();
1480
+ if (persisted !== null) {
1481
+ await this.#assertPurgeComplete(persisted);
1482
+ this.#purged = persisted;
1483
+ return persisted;
1484
+ }
1485
+ }
1486
+ throw new OhConflictError("The remote working space changed repeatedly while purging.");
1487
+ }
1488
+
1489
+ async close(): Promise<void> {
1490
+ if (this.#closed) return;
1491
+ this.#closed = true;
1492
+ if (this.#closeClient) this.#client.close?.();
1493
+ }
1494
+ }
1495
+
1496
+ function bindOhLibSqlStoreAuthorityV1(
1497
+ client: OhLibSqlClientV1,
1498
+ binding: OhStoreBindingV1,
1499
+ profile: OhStoreProfileV1,
1500
+ closeClient: boolean,
1501
+ ): OhStoreAuthorityV1 {
1502
+ const authority = new OhLibSqlStoreV1(client, binding, closeClient);
1503
+ const store: OhStoreV1 = Object.freeze({
1504
+ binding,
1505
+ changesSince: (from: OhHeadRefV1, changeOptions?: Readonly<{ limit?: number; through?: OhHeadRefV1 }>) =>
1506
+ authority.changesSince(from, changeOptions),
1507
+ close: () => authority.close(),
1508
+ commit: (input: OhCommitInputV1) => authority.commit(input),
1509
+ exportDependencyClosure: (input: Readonly<{
1510
+ head?: OhHeadRefV1;
1511
+ maximumRecords?: number;
1512
+ roots: readonly string[];
1513
+ }>) => authority.exportDependencyClosure(input),
1514
+ head: () => authority.head(),
1515
+ snapshot: (snapshotOptions?: Readonly<{ head?: OhHeadRefV1; maximumRecords?: number }>) =>
1516
+ authority.snapshot(snapshotOptions),
1517
+ verify: () => authority.verify(),
1518
+ });
1519
+ let purge: OhSpacePurgeReceiptV1 | null = null;
1520
+ const host: OhStoreHostControlV1 = Object.freeze({
1521
+ binding,
1522
+ purgeWorkingSpace: async (input: Readonly<{ purgedAt?: string }>) => {
1523
+ if (profile.profileKind !== "working" || !profile.capabilities.wholeSpacePurge) {
1524
+ throw new OhProfileError("This host handle is not bound to a purgeable working profile.");
1525
+ }
1526
+ if (purge !== null) return purge;
1527
+ purge = await authority.purgeWorkingSpace(input.purgedAt ?? canonicalNow());
1528
+ return purge;
1529
+ },
1530
+ });
1531
+ return Object.freeze({ host, store });
1532
+ }
1533
+
1534
+ /** Opens a direct libSQL/Turso authority; this is not operation-log sync. */
1535
+ export async function createOhLibSqlStoreAuthorityV1(
1536
+ client: OhLibSqlClientV1,
1537
+ options: OhLibSqlStoreAuthorityOptionsV1 = {},
1538
+ ): Promise<OhStoreAuthorityV1> {
1539
+ const profile = parseOhStoreProfileV1(options.profile ?? OH_CANONICAL_STORE_PROFILE_V1);
1540
+ if (profile === null) throw new TypeError("Invalid libSQL store profile.");
1541
+ const spaceId = options.spaceId ?? "default";
1542
+ const binding = createOhStoreBindingV1({ profile,
1543
+ realmId: options.realmId ?? `realm:${spaceId}`, spaceId, v: 1 });
1544
+ await verifyAuthoritySchema(client);
1545
+ await initializeSpace(client, binding);
1546
+ return bindOhLibSqlStoreAuthorityV1(client, binding, profile, options.closeClient ?? false);
1547
+ }
1548
+
1549
+ /**
1550
+ * Opens an already-bound direct libSQL/Turso authority without creating or
1551
+ * updating data. This seam is for separately held read or purge custody that
1552
+ * must fail closed instead of acquiring space-creation authority.
1553
+ */
1554
+ export async function openExistingOhLibSqlStoreAuthorityV1(
1555
+ client: OhLibSqlClientV1,
1556
+ options: OhLibSqlStoreAuthorityOptionsV1 = {},
1557
+ ): Promise<OhStoreAuthorityV1> {
1558
+ const profile = parseOhStoreProfileV1(options.profile ?? OH_CANONICAL_STORE_PROFILE_V1);
1559
+ if (profile === null) throw new TypeError("Invalid libSQL store profile.");
1560
+ const spaceId = options.spaceId ?? "default";
1561
+ const binding = createOhStoreBindingV1({ profile,
1562
+ realmId: options.realmId ?? `realm:${spaceId}`, spaceId, v: 1 });
1563
+ await verifyAuthoritySchema(client);
1564
+ await requireExistingSpace(client, binding);
1565
+ return bindOhLibSqlStoreAuthorityV1(client, binding, profile, options.closeClient ?? false);
1566
+ }
1567
+
1568
+ /**
1569
+ * Purges an existing working authority or atomically fences its exact binding
1570
+ * when creation never completed. The empty-space receipt prevents a delayed
1571
+ * creator from resurrecting abandoned custody without granting the purge
1572
+ * credential permission to create a space or binding.
1573
+ */
1574
+ export async function purgeOhLibSqlWorkingSpaceV1(
1575
+ client: OhLibSqlClientV1,
1576
+ options: OhLibSqlStoreAuthorityOptionsV1 & Readonly<{ purgedAt?: string }> = {},
1577
+ ): Promise<OhSpacePurgeReceiptV1> {
1578
+ const closeClient = options.closeClient ?? false;
1579
+ try {
1580
+ const profile = parseOhStoreProfileV1(options.profile ?? OH_WORKING_STORE_PROFILE_V1);
1581
+ if (profile === null) throw new TypeError("Invalid libSQL store profile.");
1582
+ if (profile.profileKind !== "working" || !profile.capabilities.wholeSpacePurge) {
1583
+ throw new OhProfileError("Whole-space purge requires a bound working profile.");
1584
+ }
1585
+ const spaceId = options.spaceId ?? "default";
1586
+ const binding = createOhStoreBindingV1({ profile,
1587
+ realmId: options.realmId ?? `realm:${spaceId}`, spaceId, v: 1 });
1588
+ const purgedAt = options.purgedAt ?? canonicalNow();
1589
+ await verifyAuthoritySchema(client);
1590
+
1591
+ for (let attempt = 0; attempt < 3; attempt += 1) {
1592
+ const proof = await client.batch([
1593
+ { sql: BINDING_ROW_SELECT, args: [binding.spaceId] },
1594
+ { sql: SPACE_PURGE_PROOF_SELECT, args: [binding.spaceId] },
1595
+ { sql: PURGE_ROW_SELECT, args: [binding.spaceId] },
1596
+ ], "read");
1597
+ if (proof.length !== 3) {
1598
+ throw new OhIntegrityError("The remote authority returned an incomplete purge proof.");
1599
+ }
1600
+ const [bindingResult, spaceResult, purgeResult] = proof as
1601
+ [OhLibSqlResultV1, OhLibSqlResultV1, OhLibSqlResultV1];
1602
+ const existingPurge = purgeResult.rows[0];
1603
+ if (existingPurge !== undefined) {
1604
+ const receipt = parsePurgeReceiptRow(existingPurge, binding.spaceId, binding.bindingSha256);
1605
+ await assertRemotePurgeComplete(client, binding, receipt);
1606
+ return receipt;
1607
+ }
1608
+ const bindingRow = bindingResult.rows[0];
1609
+ const spaceRow = spaceResult.rows[0];
1610
+ if ((bindingRow === undefined) !== (spaceRow === undefined)) {
1611
+ throw new OhIntegrityError("The remote authority has only half of its space binding.");
1612
+ }
1613
+ if (bindingRow !== undefined && spaceRow !== undefined) {
1614
+ const persisted = parseBindingRow(bindingRow, binding.spaceId);
1615
+ if (canonicalJson(persisted) !== canonicalJson(binding)) {
1616
+ throw new OhProfileError("The remote space is bound to a different realm or profile.");
1617
+ }
1618
+ if (rowValue(spaceRow, "contract_id", 5) !== OH_CONTRACT_MANIFEST_V1.contractId) {
1619
+ throw new OhIntegrityError("The existing remote space uses a different Oh contract.");
1620
+ }
1621
+ parseHeadRow(spaceRow);
1622
+ const authority = new OhLibSqlStoreV1(client, binding, false);
1623
+ return await authority.purgeWorkingSpace(purgedAt);
1624
+ }
1625
+
1626
+ const receipt = createOhSpacePurgeReceiptV1({
1627
+ binding,
1628
+ priorHead: emptyOhHeadV1(),
1629
+ purgedAt,
1630
+ });
1631
+ const receiptJson = canonicalJson(receipt);
1632
+ try {
1633
+ await client.batch([
1634
+ { sql: `INSERT INTO oh_authority_purges(space_id, binding_sha256,
1635
+ prior_operation_sha256, prior_sequence, purged_at, receipt_sha256, receipt_json)
1636
+ SELECT ?, ?, NULL, 0, ?, ?, ?
1637
+ WHERE NOT EXISTS (SELECT 1 FROM oh_authority_spaces WHERE space_id = ?)
1638
+ AND NOT EXISTS (SELECT 1 FROM oh_authority_bindings WHERE space_id = ?)
1639
+ ON CONFLICT(space_id) DO NOTHING`,
1640
+ args: [binding.spaceId, binding.bindingSha256, receipt.purgedAt,
1641
+ receipt.receiptSha256, receiptJson, binding.spaceId, binding.spaceId] },
1642
+ { sql: `INSERT INTO oh_authority_commit_guards(value)
1643
+ SELECT 'invalid' WHERE EXISTS (SELECT 1 FROM oh_authority_spaces WHERE space_id = ?)
1644
+ OR EXISTS (SELECT 1 FROM oh_authority_bindings WHERE space_id = ?)
1645
+ OR EXISTS (SELECT 1 FROM oh_authority_operations WHERE space_id = ?)
1646
+ OR EXISTS (SELECT 1 FROM oh_authority_operation_records WHERE space_id = ?)
1647
+ OR EXISTS (SELECT 1 FROM oh_authority_records WHERE space_id = ?)
1648
+ OR EXISTS (SELECT 1 FROM oh_authority_dependencies WHERE space_id = ?)
1649
+ OR EXISTS (SELECT 1 FROM oh_authority_operation_records AS materialized
1650
+ LEFT JOIN oh_authority_operations AS operation
1651
+ ON operation.operation_sha256 = materialized.operation_sha256
1652
+ WHERE operation.operation_sha256 IS NULL
1653
+ OR operation.space_id <> materialized.space_id)
1654
+ OR NOT EXISTS (SELECT 1 FROM oh_authority_purges
1655
+ WHERE space_id = ? AND receipt_sha256 = ?)`,
1656
+ args: [binding.spaceId, binding.spaceId, binding.spaceId, binding.spaceId,
1657
+ binding.spaceId, binding.spaceId, binding.spaceId, receipt.receiptSha256] },
1658
+ ], "write");
1659
+ } catch (error) {
1660
+ const recovery = await client.batch([
1661
+ { sql: BINDING_ROW_SELECT, args: [binding.spaceId] },
1662
+ { sql: SPACE_PURGE_PROOF_SELECT, args: [binding.spaceId] },
1663
+ { sql: PURGE_ROW_SELECT, args: [binding.spaceId] },
1664
+ ], "read");
1665
+ if (recovery.length !== 3) {
1666
+ throw new OhIntegrityError("The remote authority returned an incomplete purge recovery proof.");
1667
+ }
1668
+ const raced = recovery[2]?.rows[0];
1669
+ if (raced !== undefined) {
1670
+ const persisted = parsePurgeReceiptRow(raced, binding.spaceId, binding.bindingSha256);
1671
+ await assertRemotePurgeComplete(client, binding, persisted);
1672
+ return persisted;
1673
+ }
1674
+ if (recovery[0]?.rows[0] !== undefined || recovery[1]?.rows[0] !== undefined) continue;
1675
+ throw error;
1676
+ }
1677
+ const persisted = await queryOne(client, { sql: PURGE_ROW_SELECT, args: [binding.spaceId] });
1678
+ if (persisted === null) continue;
1679
+ const exact = parsePurgeReceiptRow(persisted, binding.spaceId, binding.bindingSha256);
1680
+ await assertRemotePurgeComplete(client, binding, exact);
1681
+ return exact;
1682
+ }
1683
+ throw new OhConflictError("The remote working space changed repeatedly while fencing purge.");
1684
+ } finally {
1685
+ if (closeClient) client.close?.();
1686
+ }
1687
+ }