@straiffi/archon 1.8.21 → 1.8.23
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.
- package/dist/client/assets/{ActivityView-BcguXTZ5.js → ActivityView-BaIZ8eHC.js} +1 -1
- package/dist/client/assets/GitHubActionsDialog-BFCqikDY.js +1 -0
- package/dist/client/assets/VerificationDialog-B1_6HMdt.js +4 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-DnC7Twj0.js → architectureDiagram-3BPJPVTR-Dl5UF67P.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-D0VbjiKd.js → blockDiagram-GPEHLZMM-DCcERfrZ.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CzQ3l15K.js → c4Diagram-AAUBKEIU-BGhbASFm.js} +1 -1
- package/dist/client/assets/channel-BfskvH2B.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-B5UGiqLW.js → chunk-2J33WTMH-C1ARozTV.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-SCksTqtu.js → chunk-3OPIFGDE-BEovLizF.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-IOkwLOtG.js → chunk-5ZQYHXKU-C5MmlLa_.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-Do60Xs9p.js → chunk-727SXJPM-8y8jBk4n.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-CuQT3imB.js → chunk-AQP2D5EJ-q-mByAd3.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-BkxMIESX.js → chunk-CSCIHK7Q-BOx2mLSz.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-uUU3sWgR.js → chunk-KSCS5N6A-zEwQFq7q.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-DLYccV6J.js → chunk-L5ZTLDWV-C80z6rY_.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-CgJFfCRZ.js → chunk-LZXEDZCA-BLaEsGPd.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-D7IQSQfK.js → chunk-ND2GUHAM-x26BZ95L.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-B4O6JWAo.js → chunk-NZK2D7GU-D2WAxr1p.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-DidlQEqb.js → chunk-O5CBEL6O-DDPCrzKh.js} +1 -1
- package/dist/client/assets/{chunk-WU5MYG2G-2-oq_Gue.js → chunk-WU5MYG2G-CE-JcvIc.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-D4HPfxL3.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DQQ_WqAU.js +1 -0
- package/dist/client/assets/{dagre-BM42HDAG-TubuN0hR.js → dagre-BM42HDAG-Bf7wpUk_.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-DNcUk6rV.js → diagram-2AECGRRQ-BQoKmc3B.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-B1sJn4w_.js → diagram-5GNKFQAL-D2jarPLn.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-CnW6ZuQe.js → diagram-KO2AKTUF-Bcbbjvsl.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-YHUmDzyS.js → diagram-LMA3HP47-t862RRBQ.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-BkOQphxq.js → diagram-OG6HWLK6-CacbMcO0.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-oNMxAdxN.js → erDiagram-TEJ5UH35-DRQ79baI.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-ByuCV-Am.js → flowDiagram-I6XJVG4X-BfW4KEdc.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-CRkNH8Ft.js → ganttDiagram-6RSMTGT7-BPIl0TAj.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-DRXzXjd8.js → gitGraphDiagram-PVQCEYII-CRIusBMV.js} +1 -1
- package/dist/client/assets/index-CZ1z72fo.js +276 -0
- package/dist/client/assets/index-SMj5ZmMs.css +2 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-CJ4-hWch.js → infoDiagram-5YYISTIA-DTKzK8EJ.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-CW1xqvim.js → ishikawaDiagram-YF4QCWOH-DVIHZLvL.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-BVVFg8_h.js → journeyDiagram-JHISSGLW-CQBZ4tCx.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-AcLZ63tA.js → kanban-definition-UN3LZRKU-D7naegR0.js} +1 -1
- package/dist/client/assets/{line-CG_TG6Ci.js → line-CizZlaeV.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-UDLSm_c3.js → mermaid-parser.core-NrDqgpZa.js} +1 -1
- package/dist/client/assets/{mermaid.core-IvBk22DF.js → mermaid.core-CwVO3oX0.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-BflWNtnl.js → mindmap-definition-RKZ34NQL-BWxy3Aa_.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-Dm1iGMm7.js → pieDiagram-4H26LBE5-B3gXpmBn.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-CM4zJd_R.js → quadrantDiagram-W4KKPZXB-Dpp4g8Al.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-miuP86cp.js → requirementDiagram-4Y6WPE33-lFKXnxml.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-zUcRagtr.js → sankeyDiagram-5OEKKPKP-BBdtwqrS.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BRYqVpsT.js → sequenceDiagram-3UESZ5HK-ANpVZzqm.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-DwcF0DJm.js → stateDiagram-AJRCARHV-D58ZxmKY.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Cv8cmDfz.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-BzH929s_.js → timeline-definition-PNZ67QCA-B6FK8IQC.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-BIq8rooy.js → vennDiagram-CIIHVFJN-lFWtZEEY.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-CyV_gL5J.js → wardleyDiagram-YWT4CUSO-DteAVp4l.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-Dxo-U-qe.js → xychartDiagram-2RQKCTM6-CNcDlRLN.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +359 -21
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +152 -4
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/approvalReconciliation.js +101 -0
- package/dist/server/lib/approvalReconciliation.js.map +1 -0
- package/dist/server/lib/approvalRequests.js +587 -0
- package/dist/server/lib/approvalRequests.js.map +1 -0
- package/dist/server/lib/approvalRoutes.js +143 -0
- package/dist/server/lib/approvalRoutes.js.map +1 -0
- package/dist/server/lib/buildExecutionEnvironment.js +128 -11
- package/dist/server/lib/buildExecutionEnvironment.js.map +1 -1
- package/dist/server/lib/checkDefinitions.js +29 -1
- package/dist/server/lib/checkDefinitions.js.map +1 -1
- package/dist/server/lib/checkRunner.js +306 -27
- package/dist/server/lib/checkRunner.js.map +1 -1
- package/dist/server/lib/checkRuns.js +4 -2
- package/dist/server/lib/checkRuns.js.map +1 -1
- package/dist/server/lib/consequentialActionAuthority.js +142 -0
- package/dist/server/lib/consequentialActionAuthority.js.map +1 -0
- package/dist/server/lib/consequentialActions.js +231 -0
- package/dist/server/lib/consequentialActions.js.map +1 -0
- package/dist/server/lib/dockerSandboxEnvironmentOperations.js +119 -0
- package/dist/server/lib/dockerSandboxEnvironmentOperations.js.map +1 -1
- package/dist/server/lib/dockerSandboxExecutionEnvironment.js +194 -14
- package/dist/server/lib/dockerSandboxExecutionEnvironment.js.map +1 -1
- package/dist/server/lib/dockerSandboxExecutionProvider.js +1 -1
- package/dist/server/lib/dockerSandboxExecutionProvider.js.map +1 -1
- package/dist/server/lib/dockerSandboxNetworkPolicy.js +222 -0
- package/dist/server/lib/dockerSandboxNetworkPolicy.js.map +1 -0
- package/dist/server/lib/executionEnvironmentContexts.js +4 -2
- package/dist/server/lib/executionEnvironmentContexts.js.map +1 -1
- package/dist/server/lib/executionEnvironmentLifecycle.js +34 -0
- package/dist/server/lib/executionEnvironmentLifecycle.js.map +1 -1
- package/dist/server/lib/executionEnvironmentRoutes.js +68 -6
- package/dist/server/lib/executionEnvironmentRoutes.js.map +1 -1
- package/dist/server/lib/executionEnvironmentValidation.js +71 -5
- package/dist/server/lib/executionEnvironmentValidation.js.map +1 -1
- package/dist/server/lib/executionEnvironmentValidationOperations.js +155 -11
- package/dist/server/lib/executionEnvironmentValidationOperations.js.map +1 -1
- package/dist/server/lib/executionEnvironments.js +11 -5
- package/dist/server/lib/executionEnvironments.js.map +1 -1
- package/dist/server/lib/executionProfileStore.js +12 -3
- package/dist/server/lib/executionProfileStore.js.map +1 -1
- package/dist/server/lib/executionProfiles.js +131 -8
- package/dist/server/lib/executionProfiles.js.map +1 -1
- package/dist/server/lib/executionReconciliation.js +206 -143
- package/dist/server/lib/executionReconciliation.js.map +1 -1
- package/dist/server/lib/executionRunAuthority.js +175 -7
- package/dist/server/lib/executionRunAuthority.js.map +1 -1
- package/dist/server/lib/executionRuns.js +26 -4
- package/dist/server/lib/executionRuns.js.map +1 -1
- package/dist/server/lib/executionTimeline.js +2 -1
- package/dist/server/lib/executionTimeline.js.map +1 -1
- package/dist/server/lib/git.js +52 -10
- package/dist/server/lib/git.js.map +1 -1
- package/dist/server/lib/gitPushApprovals.js +367 -0
- package/dist/server/lib/gitPushApprovals.js.map +1 -0
- package/dist/server/lib/mobileAccess.js +115 -1
- package/dist/server/lib/mobileAccess.js.map +1 -1
- package/dist/server/lib/productionCheckApprovals.js +106 -0
- package/dist/server/lib/productionCheckApprovals.js.map +1 -0
- package/dist/server/lib/reviewFindings.js +14 -8
- package/dist/server/lib/reviewFindings.js.map +1 -1
- package/dist/server/lib/types.js +40 -0
- package/dist/server/lib/types.js.map +1 -1
- package/dist/server/lib/workspaceProcessEnvironment.js +2 -2
- package/dist/server/lib/workspaceProcessEnvironment.js.map +1 -1
- package/dist/server/workers/review.js +19 -11
- package/dist/server/workers/review.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/GitHubActionsDialog-BGecTzoq.js +0 -1
- package/dist/client/assets/VerificationDialog-D4QkMLZr.js +0 -4
- package/dist/client/assets/channel-BwRO4uiw.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BIszcze-.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-D5dvxldS.js +0 -1
- package/dist/client/assets/index-CYPgEn1h.css +0 -2
- package/dist/client/assets/index-Ck2OKMsl.js +0 -276
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DmICWsmn.js +0 -1
package/dist/server/db.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createHash } from 'crypto';
|
|
|
3
3
|
import { parseCheckDefinitionsJsonStrict, parseLegacyTestCommandsJsonStrict, projectCheckDefinitionsToTestCommands, } from './lib/checkDefinitions.js';
|
|
4
4
|
import { ensureParentDirectory, resolveArchonDbPath } from './lib/runtimePaths.js';
|
|
5
5
|
import { TRANSCRIPT_RUN_TEXT_LIMIT_BYTES, truncateUtf8 } from './lib/transcriptRuns.js';
|
|
6
|
-
import { createExecutionProfile, fingerprintExecutionProfile, serializeExecutionProfile, } from './lib/executionProfiles.js';
|
|
6
|
+
import { createExecutionProfile, EXECUTION_PROFILE_SCHEMA_VERSION, fingerprintExecutionProfile, normalizeExecutionProfile, serializeExecutionProfile, } from './lib/executionProfiles.js';
|
|
7
7
|
const dbPath = ensureParentDirectory(resolveArchonDbPath());
|
|
8
8
|
const db = new Database(dbPath);
|
|
9
9
|
db.pragma('foreign_keys = ON');
|
|
@@ -181,7 +181,7 @@ db.exec(`
|
|
|
181
181
|
id TEXT PRIMARY KEY,
|
|
182
182
|
project_id TEXT NOT NULL,
|
|
183
183
|
revision INTEGER NOT NULL CHECK (revision > 0),
|
|
184
|
-
schema_version INTEGER NOT NULL CHECK (schema_version
|
|
184
|
+
schema_version INTEGER NOT NULL CHECK (schema_version IN (1, 2)),
|
|
185
185
|
fingerprint TEXT NOT NULL CHECK (length(fingerprint) = 64),
|
|
186
186
|
profile_json TEXT NOT NULL CHECK (
|
|
187
187
|
json_valid(profile_json)
|
|
@@ -220,6 +220,46 @@ db.exec(`
|
|
|
220
220
|
CREATE INDEX IF NOT EXISTS idx_execution_profile_audit_project
|
|
221
221
|
ON execution_profile_audit_events(project_id, created_at DESC, id DESC);
|
|
222
222
|
`);
|
|
223
|
+
const executionProfileRevisionsTableSql = db.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'execution_profile_revisions'").get()?.sql ?? '';
|
|
224
|
+
if (!executionProfileRevisionsTableSql.includes('schema_version IN (1, 2)')) {
|
|
225
|
+
db.pragma('foreign_keys = OFF');
|
|
226
|
+
db.transaction(() => {
|
|
227
|
+
const referencingTriggers = db.prepare(`
|
|
228
|
+
SELECT name FROM sqlite_master
|
|
229
|
+
WHERE type = 'trigger' AND instr(sql, 'execution_profile_revisions') > 0
|
|
230
|
+
`).all();
|
|
231
|
+
for (const trigger of referencingTriggers) {
|
|
232
|
+
db.exec(`DROP TRIGGER IF EXISTS "${trigger.name.replaceAll('"', '""')}"`);
|
|
233
|
+
}
|
|
234
|
+
db.exec(`
|
|
235
|
+
CREATE TABLE execution_profile_revisions_v2 (
|
|
236
|
+
id TEXT PRIMARY KEY,
|
|
237
|
+
project_id TEXT NOT NULL,
|
|
238
|
+
revision INTEGER NOT NULL CHECK (revision > 0),
|
|
239
|
+
schema_version INTEGER NOT NULL CHECK (schema_version IN (1, 2)),
|
|
240
|
+
fingerprint TEXT NOT NULL CHECK (length(fingerprint) = 64),
|
|
241
|
+
profile_json TEXT NOT NULL CHECK (
|
|
242
|
+
json_valid(profile_json)
|
|
243
|
+
AND json_type(profile_json) = 'object'
|
|
244
|
+
AND length(CAST(profile_json AS BLOB)) BETWEEN 2 AND 16384
|
|
245
|
+
),
|
|
246
|
+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
247
|
+
UNIQUE (project_id, revision),
|
|
248
|
+
UNIQUE (project_id, fingerprint),
|
|
249
|
+
UNIQUE (project_id, id),
|
|
250
|
+
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
|
|
251
|
+
);
|
|
252
|
+
INSERT INTO execution_profile_revisions_v2 (
|
|
253
|
+
id, project_id, revision, schema_version, fingerprint, profile_json, created_at
|
|
254
|
+
)
|
|
255
|
+
SELECT id, project_id, revision, schema_version, fingerprint, profile_json, created_at
|
|
256
|
+
FROM execution_profile_revisions;
|
|
257
|
+
DROP TABLE execution_profile_revisions;
|
|
258
|
+
ALTER TABLE execution_profile_revisions_v2 RENAME TO execution_profile_revisions;
|
|
259
|
+
`);
|
|
260
|
+
})();
|
|
261
|
+
db.pragma('foreign_keys = ON');
|
|
262
|
+
}
|
|
223
263
|
const backfillExecutionProfiles = () => {
|
|
224
264
|
const projects = db.prepare(`
|
|
225
265
|
SELECT id, build_execution_provider, active_execution_profile_revision_id
|
|
@@ -231,7 +271,7 @@ const backfillExecutionProfiles = () => {
|
|
|
231
271
|
const insertRevision = db.prepare(`
|
|
232
272
|
INSERT OR IGNORE INTO execution_profile_revisions (
|
|
233
273
|
id, project_id, revision, schema_version, fingerprint, profile_json
|
|
234
|
-
) VALUES (?, ?, 1,
|
|
274
|
+
) VALUES (?, ?, 1, ${EXECUTION_PROFILE_SCHEMA_VERSION}, ?, ?)
|
|
235
275
|
`);
|
|
236
276
|
const activateRevision = db.prepare(`
|
|
237
277
|
UPDATE projects SET active_execution_profile_revision_id = ? WHERE id = ?
|
|
@@ -257,7 +297,70 @@ const backfillExecutionProfiles = () => {
|
|
|
257
297
|
}
|
|
258
298
|
})();
|
|
259
299
|
};
|
|
300
|
+
const backfillExecutionProfilesToSchemaV2 = () => {
|
|
301
|
+
const legacyRows = db.prepare(`
|
|
302
|
+
SELECT projects.id AS project_id,
|
|
303
|
+
revisions.id AS revision_id,
|
|
304
|
+
revisions.profile_json
|
|
305
|
+
FROM projects
|
|
306
|
+
INNER JOIN execution_profile_revisions revisions
|
|
307
|
+
ON revisions.id = projects.active_execution_profile_revision_id
|
|
308
|
+
AND revisions.project_id = projects.id
|
|
309
|
+
WHERE revisions.schema_version = 1 AND projects.deletion_started_at IS NULL
|
|
310
|
+
`).all();
|
|
311
|
+
const nextRevisionNumber = db.prepare(`
|
|
312
|
+
SELECT COALESCE(MAX(revision), 0) + 1 AS revision
|
|
313
|
+
FROM execution_profile_revisions WHERE project_id = ?
|
|
314
|
+
`);
|
|
315
|
+
const findRevisionByFingerprint = db.prepare(`
|
|
316
|
+
SELECT id FROM execution_profile_revisions WHERE project_id = ? AND fingerprint = ?
|
|
317
|
+
`);
|
|
318
|
+
const insertRevision = db.prepare(`
|
|
319
|
+
INSERT OR IGNORE INTO execution_profile_revisions (
|
|
320
|
+
id, project_id, revision, schema_version, fingerprint, profile_json
|
|
321
|
+
) VALUES (?, ?, ?, ${EXECUTION_PROFILE_SCHEMA_VERSION}, ?, ?)
|
|
322
|
+
`);
|
|
323
|
+
const activateRevision = db.prepare(`
|
|
324
|
+
UPDATE projects SET active_execution_profile_revision_id = ?
|
|
325
|
+
WHERE id = ? AND active_execution_profile_revision_id = ?
|
|
326
|
+
`);
|
|
327
|
+
const insertEvent = db.prepare(`
|
|
328
|
+
INSERT OR IGNORE INTO execution_profile_audit_events (
|
|
329
|
+
id, project_id, event_type, profile_revision_id, previous_profile_revision_id
|
|
330
|
+
) VALUES (?, ?, 'revision_activated', ?, ?)
|
|
331
|
+
`);
|
|
332
|
+
db.transaction(() => {
|
|
333
|
+
for (const row of legacyRows) {
|
|
334
|
+
let normalized;
|
|
335
|
+
try {
|
|
336
|
+
normalized = normalizeExecutionProfile(JSON.parse(row.profile_json));
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
normalized = null;
|
|
340
|
+
}
|
|
341
|
+
if (!normalized?.ok) {
|
|
342
|
+
throw new Error(`Stored execution profile revision ${row.revision_id} is invalid`);
|
|
343
|
+
}
|
|
344
|
+
const fingerprint = fingerprintExecutionProfile(normalized.profile);
|
|
345
|
+
const existing = findRevisionByFingerprint.get(row.project_id, fingerprint);
|
|
346
|
+
let revisionId;
|
|
347
|
+
if (existing) {
|
|
348
|
+
revisionId = existing.id;
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
revisionId = `${row.project_id}:execution-profile:v2`;
|
|
352
|
+
const revisionNumber = nextRevisionNumber.get(row.project_id).revision;
|
|
353
|
+
insertRevision.run(revisionId, row.project_id, revisionNumber, fingerprint, serializeExecutionProfile(normalized.profile));
|
|
354
|
+
}
|
|
355
|
+
const activated = activateRevision.run(revisionId, row.project_id, row.revision_id);
|
|
356
|
+
if (activated.changes > 0) {
|
|
357
|
+
insertEvent.run(`${revisionId}:v2-backfill`, row.project_id, revisionId, row.revision_id);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
})();
|
|
361
|
+
};
|
|
260
362
|
backfillExecutionProfiles();
|
|
363
|
+
backfillExecutionProfilesToSchemaV2();
|
|
261
364
|
const hostCompatibilityProfile = createExecutionProfile('host');
|
|
262
365
|
const hostCompatibilityProfileJson = serializeExecutionProfile(hostCompatibilityProfile).replaceAll("'", "''");
|
|
263
366
|
const hostCompatibilityFingerprint = fingerprintExecutionProfile(hostCompatibilityProfile);
|
|
@@ -272,7 +375,7 @@ db.exec(`
|
|
|
272
375
|
INSERT INTO execution_profile_revisions (
|
|
273
376
|
id, project_id, revision, schema_version, fingerprint, profile_json
|
|
274
377
|
) VALUES (
|
|
275
|
-
NEW.id || ':execution-profile:1', NEW.id, 1,
|
|
378
|
+
NEW.id || ':execution-profile:1', NEW.id, 1, ${EXECUTION_PROFILE_SCHEMA_VERSION},
|
|
276
379
|
CASE WHEN NEW.build_execution_provider = 'docker_sandbox'
|
|
277
380
|
THEN '${dockerProfileFingerprint}' ELSE '${hostCompatibilityFingerprint}' END,
|
|
278
381
|
CASE WHEN NEW.build_execution_provider = 'docker_sandbox'
|
|
@@ -2092,6 +2195,7 @@ db.exec(`
|
|
|
2092
2195
|
stage TEXT NOT NULL,
|
|
2093
2196
|
diff_signature TEXT,
|
|
2094
2197
|
workspace_signature TEXT,
|
|
2198
|
+
change_scope TEXT,
|
|
2095
2199
|
message_id TEXT,
|
|
2096
2200
|
model TEXT,
|
|
2097
2201
|
variant TEXT,
|
|
@@ -2109,6 +2213,7 @@ const migrateReviewRunsLifecycleSchema = () => {
|
|
|
2109
2213
|
const workspaceSignatureColumn = columns.find(column => column.name === 'workspace_signature');
|
|
2110
2214
|
const needsMigration = diffSignatureColumn?.notnull === 1
|
|
2111
2215
|
|| workspaceSignatureColumn?.notnull === 1
|
|
2216
|
+
|| !columns.some(column => column.name === 'change_scope')
|
|
2112
2217
|
|| !columns.some(column => column.name === 'model')
|
|
2113
2218
|
|| !columns.some(column => column.name === 'variant')
|
|
2114
2219
|
|| !columns.some(column => column.name === 'failure_message')
|
|
@@ -2129,6 +2234,7 @@ const migrateReviewRunsLifecycleSchema = () => {
|
|
|
2129
2234
|
stage TEXT NOT NULL,
|
|
2130
2235
|
diff_signature TEXT,
|
|
2131
2236
|
workspace_signature TEXT,
|
|
2237
|
+
change_scope TEXT,
|
|
2132
2238
|
message_id TEXT,
|
|
2133
2239
|
model TEXT,
|
|
2134
2240
|
variant TEXT,
|
|
@@ -2143,12 +2249,13 @@ const migrateReviewRunsLifecycleSchema = () => {
|
|
|
2143
2249
|
db.exec(`
|
|
2144
2250
|
INSERT INTO review_runs_v2 (
|
|
2145
2251
|
id, ticket_id, project_id, worktree_bundle_id, stage, diff_signature,
|
|
2146
|
-
workspace_signature, message_id, model, variant, failure_message,
|
|
2252
|
+
workspace_signature, change_scope, message_id, model, variant, failure_message,
|
|
2147
2253
|
status, created_at, updated_at
|
|
2148
2254
|
)
|
|
2149
2255
|
SELECT
|
|
2150
2256
|
id, ticket_id, project_id, worktree_bundle_id, stage, diff_signature,
|
|
2151
|
-
${selectColumn('workspace_signature', 'NULL')},
|
|
2257
|
+
${selectColumn('workspace_signature', 'NULL')},
|
|
2258
|
+
${selectColumn('change_scope', 'NULL')}, message_id,
|
|
2152
2259
|
${selectColumn('model', 'NULL')}, ${selectColumn('variant', 'NULL')},
|
|
2153
2260
|
${selectColumn('failure_message', 'NULL')}, status, created_at,
|
|
2154
2261
|
${selectColumn('updated_at', 'created_at')}
|
|
@@ -2614,6 +2721,217 @@ db.exec(`
|
|
|
2614
2721
|
END;
|
|
2615
2722
|
|
|
2616
2723
|
`);
|
|
2724
|
+
db.exec(`
|
|
2725
|
+
CREATE TABLE IF NOT EXISTS approval_requests (
|
|
2726
|
+
id TEXT PRIMARY KEY,
|
|
2727
|
+
project_id TEXT NOT NULL,
|
|
2728
|
+
execution_run_id TEXT NOT NULL,
|
|
2729
|
+
action_kind TEXT NOT NULL,
|
|
2730
|
+
action_schema_version INTEGER NOT NULL,
|
|
2731
|
+
action_json TEXT NOT NULL,
|
|
2732
|
+
action_fingerprint TEXT NOT NULL,
|
|
2733
|
+
authority_schema_version INTEGER NOT NULL,
|
|
2734
|
+
authority_json TEXT NOT NULL,
|
|
2735
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
2736
|
+
expires_at DATETIME NOT NULL,
|
|
2737
|
+
decision_at DATETIME,
|
|
2738
|
+
consumed_at DATETIME,
|
|
2739
|
+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
2740
|
+
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
2741
|
+
UNIQUE (id, project_id),
|
|
2742
|
+
UNIQUE (execution_run_id),
|
|
2743
|
+
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
2744
|
+
FOREIGN KEY (execution_run_id, project_id) REFERENCES execution_runs(id, project_id) ON DELETE CASCADE,
|
|
2745
|
+
CHECK (length(id) BETWEEN 1 AND 128),
|
|
2746
|
+
CHECK (action_kind IN ('git_push', 'custom_check')),
|
|
2747
|
+
CHECK (action_schema_version = 1),
|
|
2748
|
+
CHECK (length(CAST(action_json AS BLOB)) BETWEEN 2 AND 65536),
|
|
2749
|
+
CHECK (length(action_fingerprint) = 64 AND action_fingerprint NOT GLOB '*[^0-9a-f]*'),
|
|
2750
|
+
CHECK (authority_schema_version = 1),
|
|
2751
|
+
CHECK (length(CAST(authority_json AS BLOB)) BETWEEN 2 AND 16384),
|
|
2752
|
+
CHECK (status IN ('pending', 'approved', 'denied', 'cancelled', 'expired', 'invalidated', 'consumed')),
|
|
2753
|
+
CHECK (status NOT IN ('approved', 'denied', 'consumed') OR decision_at IS NOT NULL),
|
|
2754
|
+
CHECK (status <> 'pending' OR decision_at IS NULL),
|
|
2755
|
+
CHECK ((status = 'consumed') = (consumed_at IS NOT NULL))
|
|
2756
|
+
);
|
|
2757
|
+
|
|
2758
|
+
CREATE TABLE IF NOT EXISTS approval_request_events (
|
|
2759
|
+
id TEXT PRIMARY KEY,
|
|
2760
|
+
project_id TEXT NOT NULL,
|
|
2761
|
+
approval_request_id TEXT NOT NULL,
|
|
2762
|
+
sequence INTEGER NOT NULL,
|
|
2763
|
+
event_type TEXT NOT NULL,
|
|
2764
|
+
from_status TEXT,
|
|
2765
|
+
to_status TEXT NOT NULL,
|
|
2766
|
+
actor_classification TEXT NOT NULL,
|
|
2767
|
+
actor_reference TEXT,
|
|
2768
|
+
reason TEXT,
|
|
2769
|
+
metadata_schema_version INTEGER NOT NULL DEFAULT 1,
|
|
2770
|
+
metadata_json TEXT,
|
|
2771
|
+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
2772
|
+
UNIQUE (approval_request_id, sequence),
|
|
2773
|
+
FOREIGN KEY (approval_request_id, project_id) REFERENCES approval_requests(id, project_id) ON DELETE CASCADE,
|
|
2774
|
+
CHECK (sequence >= 1),
|
|
2775
|
+
CHECK (length(event_type) BETWEEN 1 AND 100),
|
|
2776
|
+
CHECK (from_status IS NULL OR from_status IN ('pending', 'approved', 'denied', 'cancelled', 'expired', 'invalidated', 'consumed')),
|
|
2777
|
+
CHECK (to_status IN ('pending', 'approved', 'denied', 'cancelled', 'expired', 'invalidated', 'consumed')),
|
|
2778
|
+
CHECK (actor_classification IN ('human', 'system', 'action_executor')),
|
|
2779
|
+
CHECK (actor_reference IS NULL OR length(CAST(actor_reference AS BLOB)) BETWEEN 1 AND 200),
|
|
2780
|
+
CHECK (reason IS NULL OR length(CAST(reason AS BLOB)) <= 2000),
|
|
2781
|
+
CHECK (metadata_schema_version = 1),
|
|
2782
|
+
CHECK (metadata_json IS NULL OR length(CAST(metadata_json AS BLOB)) <= 4096)
|
|
2783
|
+
);
|
|
2784
|
+
|
|
2785
|
+
CREATE TRIGGER IF NOT EXISTS preserve_approval_request_identity
|
|
2786
|
+
BEFORE UPDATE OF id, project_id, execution_run_id, action_kind, action_schema_version,
|
|
2787
|
+
action_json, action_fingerprint, authority_schema_version, authority_json, expires_at, created_at
|
|
2788
|
+
ON approval_requests
|
|
2789
|
+
BEGIN
|
|
2790
|
+
SELECT RAISE(ABORT, 'Approval request identity and evidence are immutable');
|
|
2791
|
+
END;
|
|
2792
|
+
|
|
2793
|
+
CREATE TRIGGER IF NOT EXISTS preserve_approval_request_decision_evidence
|
|
2794
|
+
BEFORE UPDATE OF decision_at, consumed_at ON approval_requests
|
|
2795
|
+
WHEN (OLD.decision_at IS NOT NULL AND NEW.decision_at IS NOT OLD.decision_at)
|
|
2796
|
+
OR (OLD.consumed_at IS NOT NULL AND NEW.consumed_at IS NOT OLD.consumed_at)
|
|
2797
|
+
BEGIN
|
|
2798
|
+
SELECT RAISE(ABORT, 'Approval request decision evidence is immutable');
|
|
2799
|
+
END;
|
|
2800
|
+
|
|
2801
|
+
CREATE TRIGGER IF NOT EXISTS validate_approval_request_status_transition
|
|
2802
|
+
BEFORE UPDATE OF status ON approval_requests
|
|
2803
|
+
WHEN NOT (
|
|
2804
|
+
(OLD.status = 'pending' AND NEW.status IN ('approved', 'denied', 'cancelled', 'expired', 'invalidated'))
|
|
2805
|
+
OR (OLD.status = 'approved' AND NEW.status IN ('consumed', 'expired', 'invalidated'))
|
|
2806
|
+
)
|
|
2807
|
+
BEGIN
|
|
2808
|
+
SELECT RAISE(ABORT, 'Invalid approval request status transition');
|
|
2809
|
+
END;
|
|
2810
|
+
|
|
2811
|
+
CREATE TRIGGER IF NOT EXISTS preserve_approval_request_events
|
|
2812
|
+
BEFORE UPDATE ON approval_request_events
|
|
2813
|
+
BEGIN
|
|
2814
|
+
SELECT RAISE(ABORT, 'Approval request events are append-only');
|
|
2815
|
+
END;
|
|
2816
|
+
|
|
2817
|
+
CREATE TRIGGER IF NOT EXISTS prevent_approval_request_event_deletion
|
|
2818
|
+
BEFORE DELETE ON approval_request_events
|
|
2819
|
+
WHEN EXISTS (
|
|
2820
|
+
SELECT 1 FROM projects
|
|
2821
|
+
WHERE id = OLD.project_id AND deletion_started_at IS NULL
|
|
2822
|
+
)
|
|
2823
|
+
BEGIN
|
|
2824
|
+
SELECT RAISE(ABORT, 'Approval request events are append-only');
|
|
2825
|
+
END;
|
|
2826
|
+
|
|
2827
|
+
CREATE INDEX IF NOT EXISTS idx_approval_requests_project_created
|
|
2828
|
+
ON approval_requests(project_id, created_at DESC, id DESC);
|
|
2829
|
+
CREATE INDEX IF NOT EXISTS idx_approval_requests_project_status_expiry
|
|
2830
|
+
ON approval_requests(project_id, status, expires_at, id);
|
|
2831
|
+
CREATE INDEX IF NOT EXISTS idx_approval_requests_action_kind
|
|
2832
|
+
ON approval_requests(project_id, action_kind, created_at DESC, id DESC);
|
|
2833
|
+
CREATE INDEX IF NOT EXISTS idx_approval_request_events_sequence
|
|
2834
|
+
ON approval_request_events(project_id, approval_request_id, sequence ASC);
|
|
2835
|
+
`);
|
|
2836
|
+
const migrateApprovalRequestActionLimit = () => {
|
|
2837
|
+
const tableSql = db.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'approval_requests'").get()?.sql ?? '';
|
|
2838
|
+
if (tableSql.includes('BETWEEN 2 AND 65536')) {
|
|
2839
|
+
return;
|
|
2840
|
+
}
|
|
2841
|
+
db.exec('PRAGMA foreign_keys = OFF');
|
|
2842
|
+
try {
|
|
2843
|
+
db.exec('BEGIN');
|
|
2844
|
+
db.exec(`
|
|
2845
|
+
CREATE TABLE approval_requests_v2 (
|
|
2846
|
+
id TEXT PRIMARY KEY,
|
|
2847
|
+
project_id TEXT NOT NULL,
|
|
2848
|
+
execution_run_id TEXT NOT NULL,
|
|
2849
|
+
action_kind TEXT NOT NULL,
|
|
2850
|
+
action_schema_version INTEGER NOT NULL,
|
|
2851
|
+
action_json TEXT NOT NULL,
|
|
2852
|
+
action_fingerprint TEXT NOT NULL,
|
|
2853
|
+
authority_schema_version INTEGER NOT NULL,
|
|
2854
|
+
authority_json TEXT NOT NULL,
|
|
2855
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
2856
|
+
expires_at DATETIME NOT NULL,
|
|
2857
|
+
decision_at DATETIME,
|
|
2858
|
+
consumed_at DATETIME,
|
|
2859
|
+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
2860
|
+
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
2861
|
+
UNIQUE (id, project_id),
|
|
2862
|
+
UNIQUE (execution_run_id),
|
|
2863
|
+
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
2864
|
+
FOREIGN KEY (execution_run_id, project_id) REFERENCES execution_runs(id, project_id) ON DELETE CASCADE,
|
|
2865
|
+
CHECK (length(id) BETWEEN 1 AND 128),
|
|
2866
|
+
CHECK (action_kind IN ('git_push', 'custom_check')),
|
|
2867
|
+
CHECK (action_schema_version = 1),
|
|
2868
|
+
CHECK (length(CAST(action_json AS BLOB)) BETWEEN 2 AND 65536),
|
|
2869
|
+
CHECK (length(action_fingerprint) = 64 AND action_fingerprint NOT GLOB '*[^0-9a-f]*'),
|
|
2870
|
+
CHECK (authority_schema_version = 1),
|
|
2871
|
+
CHECK (length(CAST(authority_json AS BLOB)) BETWEEN 2 AND 16384),
|
|
2872
|
+
CHECK (status IN ('pending', 'approved', 'denied', 'cancelled', 'expired', 'invalidated', 'consumed')),
|
|
2873
|
+
CHECK (status NOT IN ('approved', 'denied', 'consumed') OR decision_at IS NOT NULL),
|
|
2874
|
+
CHECK (status <> 'pending' OR decision_at IS NULL),
|
|
2875
|
+
CHECK ((status = 'consumed') = (consumed_at IS NOT NULL))
|
|
2876
|
+
);
|
|
2877
|
+
INSERT INTO approval_requests_v2 (
|
|
2878
|
+
id, project_id, execution_run_id, action_kind, action_schema_version, action_json,
|
|
2879
|
+
action_fingerprint, authority_schema_version, authority_json, status, expires_at,
|
|
2880
|
+
decision_at, consumed_at, created_at, updated_at
|
|
2881
|
+
)
|
|
2882
|
+
SELECT
|
|
2883
|
+
id, project_id, execution_run_id, action_kind, action_schema_version, action_json,
|
|
2884
|
+
action_fingerprint, authority_schema_version, authority_json, status, expires_at,
|
|
2885
|
+
decision_at, consumed_at, created_at, updated_at
|
|
2886
|
+
FROM approval_requests;
|
|
2887
|
+
DROP TABLE approval_requests;
|
|
2888
|
+
ALTER TABLE approval_requests_v2 RENAME TO approval_requests;
|
|
2889
|
+
`);
|
|
2890
|
+
db.exec('COMMIT');
|
|
2891
|
+
}
|
|
2892
|
+
catch (error) {
|
|
2893
|
+
db.exec('ROLLBACK');
|
|
2894
|
+
throw error;
|
|
2895
|
+
}
|
|
2896
|
+
finally {
|
|
2897
|
+
db.exec('PRAGMA foreign_keys = ON');
|
|
2898
|
+
}
|
|
2899
|
+
db.exec(`
|
|
2900
|
+
CREATE TRIGGER preserve_approval_request_identity
|
|
2901
|
+
BEFORE UPDATE OF id, project_id, execution_run_id, action_kind, action_schema_version,
|
|
2902
|
+
action_json, action_fingerprint, authority_schema_version, authority_json, expires_at, created_at
|
|
2903
|
+
ON approval_requests
|
|
2904
|
+
BEGIN
|
|
2905
|
+
SELECT RAISE(ABORT, 'Approval request identity and evidence are immutable');
|
|
2906
|
+
END;
|
|
2907
|
+
|
|
2908
|
+
CREATE TRIGGER preserve_approval_request_decision_evidence
|
|
2909
|
+
BEFORE UPDATE OF decision_at, consumed_at ON approval_requests
|
|
2910
|
+
WHEN (OLD.decision_at IS NOT NULL AND NEW.decision_at IS NOT OLD.decision_at)
|
|
2911
|
+
OR (OLD.consumed_at IS NOT NULL AND NEW.consumed_at IS NOT OLD.consumed_at)
|
|
2912
|
+
BEGIN
|
|
2913
|
+
SELECT RAISE(ABORT, 'Approval request decision evidence is immutable');
|
|
2914
|
+
END;
|
|
2915
|
+
|
|
2916
|
+
CREATE TRIGGER validate_approval_request_status_transition
|
|
2917
|
+
BEFORE UPDATE OF status ON approval_requests
|
|
2918
|
+
WHEN NOT (
|
|
2919
|
+
(OLD.status = 'pending' AND NEW.status IN ('approved', 'denied', 'cancelled', 'expired', 'invalidated'))
|
|
2920
|
+
OR (OLD.status = 'approved' AND NEW.status IN ('consumed', 'expired', 'invalidated'))
|
|
2921
|
+
)
|
|
2922
|
+
BEGIN
|
|
2923
|
+
SELECT RAISE(ABORT, 'Invalid approval request status transition');
|
|
2924
|
+
END;
|
|
2925
|
+
|
|
2926
|
+
CREATE INDEX idx_approval_requests_project_created
|
|
2927
|
+
ON approval_requests(project_id, created_at DESC, id DESC);
|
|
2928
|
+
CREATE INDEX idx_approval_requests_project_status_expiry
|
|
2929
|
+
ON approval_requests(project_id, status, expires_at, id);
|
|
2930
|
+
CREATE INDEX idx_approval_requests_action_kind
|
|
2931
|
+
ON approval_requests(project_id, action_kind, created_at DESC, id DESC);
|
|
2932
|
+
`);
|
|
2933
|
+
};
|
|
2934
|
+
migrateApprovalRequestActionLimit();
|
|
2617
2935
|
db.exec(`
|
|
2618
2936
|
CREATE TABLE IF NOT EXISTS build_setup_evidence (
|
|
2619
2937
|
id TEXT PRIMARY KEY,
|
|
@@ -3102,7 +3420,7 @@ db.exec(`
|
|
|
3102
3420
|
CHECK (length(definition_fingerprint) = 64 AND definition_fingerprint NOT GLOB '*[^0-9a-f]*'),
|
|
3103
3421
|
CHECK (outcome IS NULL OR outcome IN ('passed', 'command_failure', 'spawn_failure',
|
|
3104
3422
|
'infrastructure_failure', 'evidence_persistence_failure', 'timeout',
|
|
3105
|
-
'workspace_changed_before_start', 'user_stop', 'restart_loss', 'shutdown_loss')),
|
|
3423
|
+
'workspace_changed_before_start', 'user_stop', 'restart_loss', 'shutdown_loss', 'ambiguous_process_loss')),
|
|
3106
3424
|
CHECK (output_revision >= 0 AND retained_start_offset >= 0 AND retained_end_offset >= retained_start_offset
|
|
3107
3425
|
AND total_persisted_bytes >= retained_end_offset),
|
|
3108
3426
|
CHECK (output_retention_state IN ('retained', 'expired'))
|
|
@@ -3113,14 +3431,23 @@ ensureColumn('check_attempt_details', 'retained_output', "TEXT NOT NULL DEFAULT
|
|
|
3113
3431
|
const checkAttemptSchema = db.prepare(`
|
|
3114
3432
|
SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'check_attempt_details'
|
|
3115
3433
|
`).get();
|
|
3116
|
-
if (checkAttemptSchema && !checkAttemptSchema.sql.includes('evidence_persistence_failure')
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3434
|
+
if (checkAttemptSchema && (!checkAttemptSchema.sql.includes('evidence_persistence_failure')
|
|
3435
|
+
|| !checkAttemptSchema.sql.includes('ambiguous_process_loss'))) {
|
|
3436
|
+
const foreignKeysEnabled = db.pragma('foreign_keys', { simple: true }) === 1;
|
|
3437
|
+
if (foreignKeysEnabled) {
|
|
3438
|
+
db.pragma('foreign_keys = OFF');
|
|
3439
|
+
}
|
|
3440
|
+
try {
|
|
3441
|
+
const referencingTriggers = db.prepare(`
|
|
3442
|
+
SELECT name FROM sqlite_master
|
|
3443
|
+
WHERE type = 'trigger' AND sql LIKE '%check_attempt_details%'
|
|
3444
|
+
`).all();
|
|
3445
|
+
for (const trigger of referencingTriggers) {
|
|
3446
|
+
db.exec(`DROP TRIGGER IF EXISTS "${trigger.name.replaceAll('"', '""')}"`);
|
|
3447
|
+
}
|
|
3448
|
+
db.transaction(() => {
|
|
3449
|
+
db.exec(`
|
|
3450
|
+
CREATE TABLE check_attempt_details_replacement (
|
|
3124
3451
|
execution_run_id TEXT PRIMARY KEY,
|
|
3125
3452
|
batch_run_id TEXT NOT NULL,
|
|
3126
3453
|
definition_id TEXT NOT NULL,
|
|
@@ -3146,13 +3473,13 @@ if (checkAttemptSchema && !checkAttemptSchema.sql.includes('evidence_persistence
|
|
|
3146
3473
|
CHECK (length(definition_fingerprint) = 64 AND definition_fingerprint NOT GLOB '*[^0-9a-f]*'),
|
|
3147
3474
|
CHECK (outcome IS NULL OR outcome IN ('passed', 'command_failure', 'spawn_failure',
|
|
3148
3475
|
'infrastructure_failure', 'evidence_persistence_failure', 'timeout',
|
|
3149
|
-
'workspace_changed_before_start', 'user_stop', 'restart_loss', 'shutdown_loss')),
|
|
3476
|
+
'workspace_changed_before_start', 'user_stop', 'restart_loss', 'shutdown_loss', 'ambiguous_process_loss')),
|
|
3150
3477
|
CHECK (output_revision >= 0 AND retained_start_offset >= 0 AND retained_end_offset >= retained_start_offset
|
|
3151
3478
|
AND total_persisted_bytes >= retained_end_offset),
|
|
3152
3479
|
CHECK (output_retention_state IN ('retained', 'expired'))
|
|
3153
3480
|
);
|
|
3154
3481
|
|
|
3155
|
-
INSERT INTO
|
|
3482
|
+
INSERT INTO check_attempt_details_replacement (
|
|
3156
3483
|
execution_run_id, batch_run_id, definition_id, command_snapshot_json, definition_fingerprint,
|
|
3157
3484
|
initial_workspace_identity_json, final_workspace_identity_json, outcome, rerun_of_attempt_run_id,
|
|
3158
3485
|
exit_code, exit_signal, exit_error, output_revision, retained_start_offset, retained_end_offset,
|
|
@@ -3163,11 +3490,22 @@ if (checkAttemptSchema && !checkAttemptSchema.sql.includes('evidence_persistence
|
|
|
3163
3490
|
initial_workspace_identity_json, final_workspace_identity_json, outcome, rerun_of_attempt_run_id,
|
|
3164
3491
|
exit_code, exit_signal, exit_error, output_revision, retained_start_offset, retained_end_offset,
|
|
3165
3492
|
total_persisted_bytes, retained_output, output_retention_state
|
|
3166
|
-
FROM
|
|
3493
|
+
FROM check_attempt_details;
|
|
3167
3494
|
|
|
3168
|
-
DROP TABLE
|
|
3169
|
-
|
|
3170
|
-
|
|
3495
|
+
DROP TABLE check_attempt_details;
|
|
3496
|
+
ALTER TABLE check_attempt_details_replacement RENAME TO check_attempt_details;
|
|
3497
|
+
`);
|
|
3498
|
+
})();
|
|
3499
|
+
}
|
|
3500
|
+
finally {
|
|
3501
|
+
if (foreignKeysEnabled) {
|
|
3502
|
+
db.pragma('foreign_keys = ON');
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
const foreignKeyViolation = db.pragma('foreign_key_check')[0];
|
|
3506
|
+
if (foreignKeyViolation) {
|
|
3507
|
+
throw new Error(`Check attempt migration left an invalid foreign key: ${JSON.stringify(foreignKeyViolation)}`);
|
|
3508
|
+
}
|
|
3171
3509
|
}
|
|
3172
3510
|
db.exec(`
|
|
3173
3511
|
CREATE TABLE IF NOT EXISTS check_attempt_diagnostic_parsers (
|