@sixb/sqlite 0.1.0 → 0.1.2

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 (110) hide show
  1. package/README.md +18 -13
  2. package/dist/action-run-storage.d.ts +5 -2
  3. package/dist/action-run-storage.d.ts.map +1 -1
  4. package/dist/agents/agent-storage.d.ts +4 -2
  5. package/dist/agents/agent-storage.d.ts.map +1 -1
  6. package/dist/agents/rows.d.ts +3 -10
  7. package/dist/agents/rows.d.ts.map +1 -1
  8. package/dist/agents/runs.d.ts +3 -2
  9. package/dist/agents/runs.d.ts.map +1 -1
  10. package/dist/ai-usage-storage.d.ts +22 -0
  11. package/dist/ai-usage-storage.d.ts.map +1 -0
  12. package/dist/auth-storage/service-accounts.d.ts.map +1 -1
  13. package/dist/auth-storage/shared.d.ts +1 -10
  14. package/dist/auth-storage/shared.d.ts.map +1 -1
  15. package/dist/connector-connection-storage.d.ts +9 -0
  16. package/dist/connector-connection-storage.d.ts.map +1 -0
  17. package/dist/execution-storage.d.ts +14 -0
  18. package/dist/execution-storage.d.ts.map +1 -0
  19. package/dist/index.d.ts +13 -9
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +4114 -1149
  22. package/dist/index.js.map +30 -27
  23. package/dist/latest-run-query.d.ts.map +1 -1
  24. package/dist/migrations.d.ts +0 -1
  25. package/dist/migrations.d.ts.map +1 -1
  26. package/dist/ontology-storage/materialization-session.d.ts +50 -8
  27. package/dist/ontology-storage/materialization-session.d.ts.map +1 -1
  28. package/dist/ontology-storage/materialization-state.d.ts +4 -5
  29. package/dist/ontology-storage/materialization-state.d.ts.map +1 -1
  30. package/dist/ontology-storage/materialization-writer.d.ts.map +1 -1
  31. package/dist/ontology-storage/materializations.d.ts +0 -2
  32. package/dist/ontology-storage/materializations.d.ts.map +1 -1
  33. package/dist/ontology-storage/outbox.d.ts.map +1 -1
  34. package/dist/ontology-storage/shared.d.ts +3 -3
  35. package/dist/ontology-storage/shared.d.ts.map +1 -1
  36. package/dist/ontology-storage/sources.d.ts.map +1 -1
  37. package/dist/pipeline-run-storage.d.ts +7 -2
  38. package/dist/pipeline-run-storage.d.ts.map +1 -1
  39. package/dist/projection-run-storage.d.ts +9 -2
  40. package/dist/projection-run-storage.d.ts.map +1 -1
  41. package/dist/run-list-query.d.ts +1 -1
  42. package/dist/run-list-query.d.ts.map +1 -1
  43. package/dist/sync-run-storage.d.ts +7 -2
  44. package/dist/sync-run-storage.d.ts.map +1 -1
  45. package/dist/testing.d.ts +6 -0
  46. package/dist/testing.d.ts.map +1 -0
  47. package/dist/transactions.d.ts +3 -0
  48. package/dist/transactions.d.ts.map +1 -1
  49. package/dist/webhook-run-storage.d.ts +9 -2
  50. package/dist/webhook-run-storage.d.ts.map +1 -1
  51. package/dist/workflow-run-storage.d.ts +7 -3
  52. package/dist/workflow-run-storage.d.ts.map +1 -1
  53. package/package.json +4 -3
  54. package/src/action-run-storage.ts +51 -74
  55. package/src/agents/agent-storage.ts +5 -3
  56. package/src/agents/rows.ts +8 -40
  57. package/src/agents/runs.ts +27 -21
  58. package/src/ai-usage-storage.ts +324 -0
  59. package/src/auth-storage/service-accounts.ts +14 -21
  60. package/src/auth-storage/shared.ts +0 -22
  61. package/src/connector-connection-storage.ts +784 -0
  62. package/src/execution-storage.ts +158 -0
  63. package/src/index.ts +63 -22
  64. package/src/latest-run-query.ts +7 -1
  65. package/src/migrations/002-workflow-run-output.sql +27 -0
  66. package/src/migrations/003-merge-sync-runs.sql +71 -0
  67. package/src/migrations/004-executions.sql +142 -0
  68. package/src/migrations/005-workflow-executions.sql +7 -0
  69. package/src/migrations/006-narrow-ontology-source-root-index.sql +4 -0
  70. package/src/migrations/007-split-overrides.sql +154 -0
  71. package/src/migrations/008-action-executions.sql +4 -0
  72. package/src/migrations/009-agent-executions.sql +115 -0
  73. package/src/migrations/010-ai-usage-accounting-foundation.sql +74 -0
  74. package/src/migrations/011-sync-failure-record.sql +22 -0
  75. package/src/migrations/012-pipeline-failure-record.sql +45 -0
  76. package/src/migrations/013-workflow-failure-record.sql +45 -0
  77. package/src/migrations/014-agent-failure-record.sql +59 -0
  78. package/src/migrations/015-projection-failure-record.sql +20 -0
  79. package/src/migrations/016-webhook-run-failure-record.sql +19 -0
  80. package/src/migrations/017-action-failure-record.sql +65 -0
  81. package/src/migrations/018-ontology-outbox-failure-record.sql +80 -0
  82. package/src/migrations/019-webhook-delivery-failure-record.sql +62 -0
  83. package/src/migrations/020-drop-run-usage-projections.sql +7 -0
  84. package/src/migrations/021-sync-pipeline-executions.sql +101 -0
  85. package/src/migrations/022-projection-executions.sql +244 -0
  86. package/src/migrations/023-webhook-executions.sql +51 -0
  87. package/src/migrations/024-ontology-commit-executions.sql +58 -0
  88. package/src/migrations/025-connector-connections.sql +257 -0
  89. package/src/migrations.ts +126 -5
  90. package/src/ontology-storage/materialization-session.ts +317 -143
  91. package/src/ontology-storage/materialization-state.ts +398 -150
  92. package/src/ontology-storage/materialization-writer.ts +142 -67
  93. package/src/ontology-storage/materializations.ts +67 -141
  94. package/src/ontology-storage/outbox.ts +10 -3
  95. package/src/ontology-storage/shared.ts +10 -4
  96. package/src/ontology-storage/sources.ts +4 -1
  97. package/src/pipeline-run-storage.ts +128 -43
  98. package/src/projection-run-storage.ts +209 -97
  99. package/src/run-list-query.ts +9 -4
  100. package/src/sync-run-storage.ts +120 -34
  101. package/src/testing.ts +20 -0
  102. package/src/transactions.ts +10 -3
  103. package/src/webhook-run-storage.ts +118 -74
  104. package/src/workflow-run-storage.ts +124 -133
  105. package/dist/validation.d.ts +0 -5
  106. package/dist/validation.d.ts.map +0 -1
  107. package/dist/webhook-delivery-storage.d.ts +0 -27
  108. package/dist/webhook-delivery-storage.d.ts.map +0 -1
  109. package/src/validation.ts +0 -30
  110. package/src/webhook-delivery-storage.ts +0 -272
@@ -0,0 +1,257 @@
1
+ CREATE TABLE connector_connection_runs (
2
+ project_id TEXT NOT NULL,
3
+ connector_id TEXT NOT NULL,
4
+ id TEXT NOT NULL,
5
+ kind TEXT NOT NULL CHECK (kind IN ('connect', 'reauthorize')),
6
+ slot TEXT NOT NULL,
7
+ initiated_by_execution_id TEXT NOT NULL,
8
+ status TEXT NOT NULL CHECK (status IN ('waiting', 'running', 'succeeded', 'failed', 'cancelled', 'expired')),
9
+ waiting_for TEXT CHECK (waiting_for IN ('provider_authorization', 'account_selection')),
10
+ processing_id TEXT,
11
+ callback_started_at TEXT,
12
+ expires_at TEXT,
13
+ authorization_id TEXT,
14
+ cleanup_authorization_id TEXT,
15
+ connections TEXT CHECK (
16
+ connections IS NULL OR (json_valid(connections) AND json_type(connections) = 'array')
17
+ ),
18
+ error TEXT CHECK (error IS NULL OR (json_valid(error) AND json_type(error) = 'object')),
19
+ created_at TEXT NOT NULL,
20
+ updated_at TEXT NOT NULL,
21
+ finished_at TEXT,
22
+ PRIMARY KEY (project_id, connector_id, id),
23
+ UNIQUE (project_id, id),
24
+ CHECK (
25
+ (
26
+ status = 'waiting'
27
+ AND waiting_for = 'provider_authorization'
28
+ AND processing_id IS NULL
29
+ AND callback_started_at IS NULL
30
+ AND expires_at IS NOT NULL
31
+ AND authorization_id IS NULL
32
+ AND cleanup_authorization_id IS NULL
33
+ AND connections IS NULL
34
+ AND error IS NULL
35
+ AND finished_at IS NULL
36
+ )
37
+ OR
38
+ (
39
+ status = 'waiting'
40
+ AND waiting_for = 'account_selection'
41
+ AND processing_id IS NULL
42
+ AND callback_started_at IS NULL
43
+ AND expires_at IS NOT NULL
44
+ AND authorization_id IS NOT NULL
45
+ AND cleanup_authorization_id IS NULL
46
+ AND connections IS NULL
47
+ AND error IS NULL
48
+ AND finished_at IS NULL
49
+ )
50
+ OR
51
+ (
52
+ status = 'running'
53
+ AND waiting_for IS NULL
54
+ AND processing_id IS NOT NULL
55
+ AND callback_started_at IS NOT NULL
56
+ AND expires_at IS NOT NULL
57
+ AND cleanup_authorization_id IS NULL
58
+ AND connections IS NULL
59
+ AND error IS NULL
60
+ AND finished_at IS NULL
61
+ )
62
+ OR
63
+ (
64
+ status = 'succeeded'
65
+ AND waiting_for IS NULL
66
+ AND processing_id IS NULL
67
+ AND callback_started_at IS NULL
68
+ AND expires_at IS NULL
69
+ AND authorization_id IS NOT NULL
70
+ AND connections IS NOT NULL
71
+ AND error IS NULL
72
+ AND finished_at IS NOT NULL
73
+ )
74
+ OR
75
+ (
76
+ status = 'failed'
77
+ AND waiting_for IS NULL
78
+ AND processing_id IS NULL
79
+ AND callback_started_at IS NULL
80
+ AND expires_at IS NULL
81
+ AND cleanup_authorization_id IS NULL
82
+ AND connections IS NULL
83
+ AND error IS NOT NULL
84
+ AND finished_at IS NOT NULL
85
+ )
86
+ OR
87
+ (
88
+ status IN ('cancelled', 'expired')
89
+ AND waiting_for IS NULL
90
+ AND processing_id IS NULL
91
+ AND callback_started_at IS NULL
92
+ AND expires_at IS NULL
93
+ AND cleanup_authorization_id IS NULL
94
+ AND connections IS NULL
95
+ AND error IS NULL
96
+ AND finished_at IS NOT NULL
97
+ )
98
+ )
99
+ );
100
+
101
+ CREATE INDEX idx_connector_runs_status
102
+ ON connector_connection_runs (project_id, connector_id, status, updated_at);
103
+
104
+ CREATE TABLE connector_authorization_attempts (
105
+ project_id TEXT NOT NULL,
106
+ connector_id TEXT NOT NULL,
107
+ id TEXT NOT NULL,
108
+ slot TEXT NOT NULL,
109
+ initiated_by_execution_id TEXT NOT NULL,
110
+ state_hash TEXT NOT NULL,
111
+ code_verifier TEXT NOT NULL CHECK (
112
+ json_valid(code_verifier) AND json_type(code_verifier) = 'object'
113
+ ),
114
+ redirect_uri TEXT NOT NULL,
115
+ connection_run_id TEXT,
116
+ return_to TEXT,
117
+ callback_binding_hash TEXT,
118
+ reauthorization_id TEXT,
119
+ reauthorization_revision INTEGER CHECK (
120
+ reauthorization_revision IS NULL OR reauthorization_revision >= 0
121
+ ),
122
+ reauthorization_connection_ids TEXT CHECK (
123
+ reauthorization_connection_ids IS NULL
124
+ OR (json_valid(reauthorization_connection_ids) AND json_type(reauthorization_connection_ids) = 'array')
125
+ ),
126
+ created_at TEXT NOT NULL,
127
+ expires_at TEXT NOT NULL,
128
+ PRIMARY KEY (project_id, connector_id, id),
129
+ UNIQUE (project_id, id),
130
+ UNIQUE (project_id, connector_id, connection_run_id),
131
+ FOREIGN KEY (project_id, connector_id, connection_run_id)
132
+ REFERENCES connector_connection_runs (project_id, connector_id, id)
133
+ ON DELETE RESTRICT,
134
+ CHECK (
135
+ (connection_run_id IS NULL AND return_to IS NULL AND callback_binding_hash IS NULL)
136
+ OR
137
+ (connection_run_id IS NOT NULL AND return_to IS NOT NULL AND callback_binding_hash IS NOT NULL)
138
+ ),
139
+ CHECK (
140
+ (reauthorization_id IS NULL AND reauthorization_revision IS NULL AND reauthorization_connection_ids IS NULL)
141
+ OR
142
+ (reauthorization_id IS NOT NULL AND reauthorization_revision IS NOT NULL AND reauthorization_connection_ids IS NOT NULL)
143
+ )
144
+ );
145
+
146
+ CREATE INDEX idx_connector_attempts_expiry
147
+ ON connector_authorization_attempts (project_id, connector_id, expires_at);
148
+
149
+ CREATE TABLE connector_authorizations (
150
+ project_id TEXT NOT NULL,
151
+ connector_id TEXT NOT NULL,
152
+ id TEXT NOT NULL,
153
+ authorized_by TEXT NOT NULL CHECK (
154
+ json_valid(authorized_by) AND json_type(authorized_by) = 'object'
155
+ ),
156
+ credentials TEXT CHECK (
157
+ credentials IS NULL OR (json_valid(credentials) AND json_type(credentials) = 'object')
158
+ ),
159
+ credential_expires_at TEXT,
160
+ scopes TEXT NOT NULL CHECK (json_valid(scopes) AND json_type(scopes) = 'array'),
161
+ accounts TEXT NOT NULL CHECK (json_valid(accounts) AND json_type(accounts) = 'array'),
162
+ status TEXT NOT NULL CHECK (status IN ('pending_selection', 'active', 'needs_reauthorization', 'revocation_pending', 'revoked')),
163
+ selection_expires_at TEXT,
164
+ revision INTEGER NOT NULL CHECK (revision >= 0),
165
+ mutation_id TEXT,
166
+ mutation_kind TEXT CHECK (mutation_kind IN ('refresh', 'reauthorization', 'revocation')),
167
+ mutation_phase TEXT CHECK (mutation_phase IN ('prepared', 'executing', 'result_staged')),
168
+ mutation_holder_id TEXT,
169
+ mutation_expires_at TEXT,
170
+ mutation_deadline_at TEXT,
171
+ mutation_expected_connection_ids TEXT CHECK (
172
+ mutation_expected_connection_ids IS NULL
173
+ OR (json_valid(mutation_expected_connection_ids) AND json_type(mutation_expected_connection_ids) = 'array')
174
+ ),
175
+ staged_credentials TEXT CHECK (
176
+ staged_credentials IS NULL
177
+ OR (json_valid(staged_credentials) AND json_type(staged_credentials) = 'object')
178
+ ),
179
+ staged_credential_expires_at TEXT,
180
+ staged_scopes TEXT CHECK (
181
+ staged_scopes IS NULL OR (json_valid(staged_scopes) AND json_type(staged_scopes) = 'array')
182
+ ),
183
+ created_at TEXT NOT NULL,
184
+ updated_at TEXT NOT NULL,
185
+ PRIMARY KEY (project_id, connector_id, id),
186
+ UNIQUE (project_id, id),
187
+ CHECK (
188
+ (mutation_id IS NULL AND mutation_kind IS NULL AND mutation_phase IS NULL AND mutation_holder_id IS NULL AND mutation_expires_at IS NULL AND mutation_deadline_at IS NULL AND mutation_expected_connection_ids IS NULL AND staged_credentials IS NULL AND staged_credential_expires_at IS NULL AND staged_scopes IS NULL)
189
+ OR
190
+ (mutation_id IS NOT NULL AND mutation_kind IS NOT NULL AND mutation_phase IS NOT NULL AND mutation_holder_id IS NOT NULL AND mutation_expires_at IS NOT NULL AND mutation_deadline_at IS NOT NULL)
191
+ ),
192
+ CHECK (
193
+ (
194
+ mutation_phase IS NULL
195
+ AND staged_credentials IS NULL
196
+ AND staged_credential_expires_at IS NULL
197
+ AND staged_scopes IS NULL
198
+ )
199
+ OR
200
+ (
201
+ mutation_phase IN ('prepared', 'executing')
202
+ AND staged_credentials IS NULL
203
+ AND staged_credential_expires_at IS NULL
204
+ AND staged_scopes IS NULL
205
+ )
206
+ OR
207
+ (
208
+ mutation_phase = 'result_staged'
209
+ AND mutation_kind = 'revocation'
210
+ AND staged_credentials IS NULL
211
+ AND staged_credential_expires_at IS NULL
212
+ AND staged_scopes IS NULL
213
+ )
214
+ OR
215
+ (
216
+ mutation_phase = 'result_staged'
217
+ AND mutation_kind IN ('refresh', 'reauthorization')
218
+ AND staged_credentials IS NOT NULL
219
+ AND staged_scopes IS NOT NULL
220
+ )
221
+ ),
222
+ CHECK ((status = 'pending_selection') = (selection_expires_at IS NOT NULL)),
223
+ CHECK ((status = 'revoked') = (credentials IS NULL))
224
+ );
225
+
226
+ CREATE INDEX idx_connector_authorizations_status
227
+ ON connector_authorizations (project_id, connector_id, status, updated_at);
228
+ CREATE INDEX idx_connector_authorizations_mutation_expiry
229
+ ON connector_authorizations (project_id, connector_id, mutation_expires_at)
230
+ WHERE mutation_id IS NOT NULL;
231
+
232
+ CREATE TABLE connector_connections (
233
+ project_id TEXT NOT NULL,
234
+ connector_id TEXT NOT NULL,
235
+ id TEXT NOT NULL,
236
+ authorization_id TEXT NOT NULL,
237
+ slot TEXT NOT NULL,
238
+ account TEXT NOT NULL CHECK (json_valid(account) AND json_type(account) = 'object'),
239
+ account_id TEXT NOT NULL,
240
+ status TEXT NOT NULL CHECK (status IN ('connected', 'disconnected')),
241
+ disconnected_at TEXT,
242
+ created_at TEXT NOT NULL,
243
+ updated_at TEXT NOT NULL,
244
+ PRIMARY KEY (project_id, connector_id, id),
245
+ UNIQUE (project_id, id),
246
+ UNIQUE (project_id, connector_id, slot),
247
+ FOREIGN KEY (project_id, connector_id, authorization_id)
248
+ REFERENCES connector_authorizations (project_id, connector_id, id)
249
+ ON DELETE RESTRICT,
250
+ CHECK ((status = 'connected') = (disconnected_at IS NULL)),
251
+ CHECK (json_extract(account, '$.id') IS NOT NULL AND json_extract(account, '$.id') = account_id)
252
+ );
253
+
254
+ CREATE INDEX idx_connector_connections_authorization
255
+ ON connector_connections (project_id, connector_id, authorization_id, status, id);
256
+ CREATE INDEX idx_connector_connections_status
257
+ ON connector_connections (project_id, connector_id, status, id);
package/src/migrations.ts CHANGED
@@ -17,6 +17,58 @@ import {
17
17
  step,
18
18
  } from "@sixb/core/storage"
19
19
  import initialSchemaSql from "./migrations/001-initial-schema.sql" with { type: "text" }
20
+ import workflowRunOutputSql from "./migrations/002-workflow-run-output.sql" with { type: "text" }
21
+ import mergeSyncRunsSql from "./migrations/003-merge-sync-runs.sql" with { type: "text" }
22
+ import executionsSql from "./migrations/004-executions.sql" with { type: "text" }
23
+ import workflowExecutionsSql from "./migrations/005-workflow-executions.sql" with { type: "text" }
24
+ import narrowOntologySourceRootIndexSql from "./migrations/006-narrow-ontology-source-root-index.sql" with {
25
+ type: "text",
26
+ }
27
+ import splitOverridesSql from "./migrations/007-split-overrides.sql" with { type: "text" }
28
+ import actionExecutionsSql from "./migrations/008-action-executions.sql" with { type: "text" }
29
+ import agentExecutionsSql from "./migrations/009-agent-executions.sql" with { type: "text" }
30
+ import aiUsageAccountingFoundationSql from "./migrations/010-ai-usage-accounting-foundation.sql" with {
31
+ type: "text",
32
+ }
33
+ import syncFailureRecordSql from "./migrations/011-sync-failure-record.sql" with { type: "text" }
34
+ import pipelineFailureRecordSql from "./migrations/012-pipeline-failure-record.sql" with {
35
+ type: "text",
36
+ }
37
+ import workflowFailureRecordSql from "./migrations/013-workflow-failure-record.sql" with {
38
+ type: "text",
39
+ }
40
+ import agentFailureRecordSql from "./migrations/014-agent-failure-record.sql" with { type: "text" }
41
+ import projectionFailureRecordSql from "./migrations/015-projection-failure-record.sql" with {
42
+ type: "text",
43
+ }
44
+ import webhookRunFailureRecordSql from "./migrations/016-webhook-run-failure-record.sql" with {
45
+ type: "text",
46
+ }
47
+ import actionFailureRecordSql from "./migrations/017-action-failure-record.sql" with {
48
+ type: "text",
49
+ }
50
+ import ontologyOutboxFailureRecordSql from "./migrations/018-ontology-outbox-failure-record.sql" with {
51
+ type: "text",
52
+ }
53
+ import webhookDeliveryFailureRecordSql from "./migrations/019-webhook-delivery-failure-record.sql" with {
54
+ type: "text",
55
+ }
56
+ import dropRunUsageProjectionsSql from "./migrations/020-drop-run-usage-projections.sql" with {
57
+ type: "text",
58
+ }
59
+ import syncPipelineExecutionsSql from "./migrations/021-sync-pipeline-executions.sql" with {
60
+ type: "text",
61
+ }
62
+ import projectionExecutionsSql from "./migrations/022-projection-executions.sql" with {
63
+ type: "text",
64
+ }
65
+ import webhookExecutionsSql from "./migrations/023-webhook-executions.sql" with { type: "text" }
66
+ import ontologyCommitExecutionsSql from "./migrations/024-ontology-commit-executions.sql" with {
67
+ type: "text",
68
+ }
69
+ import connectorConnectionsSql from "./migrations/025-connector-connections.sql" with {
70
+ type: "text",
71
+ }
20
72
 
21
73
  const MIGRATIONS_TABLE_SQL = `
22
74
  CREATE TABLE IF NOT EXISTS sixb_migrations (
@@ -36,7 +88,68 @@ export const SQLITE_STORAGE_FILE = "storage.sqlite"
36
88
 
37
89
  export const sqliteStorageMigrations = defineMigrations({
38
90
  adapterId: SQLITE_STORAGE_ADAPTER_ID,
39
- steps: [sqliteSql("001-initial-schema", initialSchemaSql)],
91
+ steps: [
92
+ sqliteSql("001-initial-schema", initialSchemaSql),
93
+ sqliteSql("002-workflow-run-output", workflowRunOutputSql),
94
+ sqliteSql("003-merge-sync-runs", mergeSyncRunsSql),
95
+ sqliteSql("004-executions", executionsSql),
96
+ sqliteSql("005-workflow-executions", workflowExecutionsSql),
97
+ sqliteSql("006-narrow-ontology-source-root-index", narrowOntologySourceRootIndexSql),
98
+ sqliteSql("007-split-overrides", splitOverridesSql),
99
+ sqliteSql("008-action-executions", actionExecutionsSql),
100
+ sqliteSql("009-agent-executions", agentExecutionsSql),
101
+ sqliteSql("010-ai-usage-accounting-foundation", aiUsageAccountingFoundationSql),
102
+ sqliteSql("011-sync-failure-record", syncFailureRecordSql),
103
+ sqliteSql("012-pipeline-failure-record", pipelineFailureRecordSql),
104
+ sqliteSql("013-workflow-failure-record", workflowFailureRecordSql),
105
+ sqliteSql("014-agent-failure-record", agentFailureRecordSql),
106
+ sqliteSql("015-projection-failure-record", projectionFailureRecordSql),
107
+ sqliteSql("016-webhook-run-failure-record", webhookRunFailureRecordSql),
108
+ sqliteSql("017-action-failure-record", actionFailureRecordSql),
109
+ sqliteSql("018-ontology-outbox-failure-record", ontologyOutboxFailureRecordSql),
110
+ sqliteSql("019-webhook-delivery-failure-record", webhookDeliveryFailureRecordSql),
111
+ sqliteSql("020-drop-run-usage-projections", dropRunUsageProjectionsSql),
112
+ sqliteSql("021-sync-pipeline-executions", syncPipelineExecutionsSql),
113
+ sqliteStep(
114
+ "022-projection-executions",
115
+ (db) => {
116
+ if (db.query("SELECT 1 FROM projection_runs LIMIT 1").get()) {
117
+ throw new Error(
118
+ "[SixbSqliteStorage] Projection execution migration cannot preserve legacy runs with unknown authority."
119
+ )
120
+ }
121
+ db.run(projectionExecutionsSql)
122
+ },
123
+ { checksum: checksum(projectionExecutionsSql) }
124
+ ),
125
+ sqliteStep(
126
+ "023-webhook-executions",
127
+ (db) => {
128
+ const hasRuns = db.query("SELECT 1 FROM webhook_runs LIMIT 1").get()
129
+ const hasDeliveries = db.query("SELECT 1 FROM webhook_deliveries LIMIT 1").get()
130
+ if (hasRuns || hasDeliveries) {
131
+ throw new Error(
132
+ "[SixbSqliteStorage] Webhook execution migration cannot preserve legacy runs or deliveries with unknown authority."
133
+ )
134
+ }
135
+ db.run(webhookExecutionsSql)
136
+ },
137
+ { checksum: checksum(webhookExecutionsSql) }
138
+ ),
139
+ sqliteStep(
140
+ "024-ontology-commit-executions",
141
+ (db) => {
142
+ if (db.query("SELECT 1 FROM ontology_commits LIMIT 1").get()) {
143
+ throw new Error(
144
+ "[SixbSqliteStorage] Ontology commit execution migration cannot preserve commits with unknown authority."
145
+ )
146
+ }
147
+ db.run(ontologyCommitExecutionsSql)
148
+ },
149
+ { checksum: checksum(ontologyCommitExecutionsSql) }
150
+ ),
151
+ sqliteSql("025-connector-connections", connectorConnectionsSql),
152
+ ],
40
153
  })
41
154
 
42
155
  export function sqliteStoragePath(basePath: string): string {
@@ -114,10 +227,6 @@ export async function migrateSqliteStorage(basePath: string): Promise<void> {
114
227
  }
115
228
  }
116
229
 
117
- export async function migrateSqliteDatabase(path: string): Promise<void> {
118
- await createSqliteMigrator({ path, migrations: sqliteStorageMigrations }).migrate()
119
- }
120
-
121
230
  function sqliteMigrationHistoryStore(db: Database): MigrationHistoryStore {
122
231
  return {
123
232
  ensure() {
@@ -150,15 +259,27 @@ function sqliteMigrationHistoryStore(db: Database): MigrationHistoryStore {
150
259
  `).run(at, adapterId, migration.version)
151
260
  },
152
261
  async transaction(run) {
262
+ // SQLite cannot rebuild a referenced parent table while foreign-key enforcement is active,
263
+ // even when the replacement satisfies every deferred reference. Migrations therefore run
264
+ // with enforcement paused, validate the complete schema before commit, then restore it.
265
+ db.run("PRAGMA foreign_keys = OFF")
153
266
  db.run("BEGIN")
154
267
 
155
268
  try {
156
269
  const result = await run()
270
+ const violations = db.query("PRAGMA foreign_key_check").all()
271
+ if (violations.length > 0) {
272
+ throw new Error(
273
+ `[${SQLITE_STORAGE_ADAPTER_ID}] Migration produced ${violations.length} foreign-key violation(s).`
274
+ )
275
+ }
157
276
  db.run("COMMIT")
158
277
  return result
159
278
  } catch (error) {
160
279
  rollbackQuietly(db)
161
280
  throw error
281
+ } finally {
282
+ db.run("PRAGMA foreign_keys = ON")
162
283
  }
163
284
  },
164
285
  }