@proletariat/cli 0.3.88 → 0.3.89
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/commands/db/repair.d.ts +14 -0
- package/dist/commands/db/repair.js +186 -0
- package/dist/commands/db/repair.js.map +1 -0
- package/dist/commands/session/list.js +42 -0
- package/dist/commands/session/list.js.map +1 -1
- package/dist/commands/session/poke.d.ts +6 -0
- package/dist/commands/session/poke.js +40 -0
- package/dist/commands/session/poke.js.map +1 -1
- package/dist/commands/work/start.d.ts +1 -0
- package/dist/commands/work/start.js +20 -1
- package/dist/commands/work/start.js.map +1 -1
- package/dist/lib/dashboard/data.js +2 -2
- package/dist/lib/dashboard/data.js.map +1 -1
- package/dist/lib/database/db-safety.d.ts +59 -0
- package/dist/lib/database/db-safety.js +295 -0
- package/dist/lib/database/db-safety.js.map +1 -0
- package/dist/lib/database/driver.d.ts +1 -1
- package/dist/lib/database/driver.js +2 -1
- package/dist/lib/database/driver.js.map +1 -1
- package/dist/lib/database/index.d.ts +1 -0
- package/dist/lib/database/index.js +2 -0
- package/dist/lib/database/index.js.map +1 -1
- package/dist/lib/database/migrations/0012_add_action_network_allowlist.d.ts +9 -0
- package/dist/lib/database/migrations/0012_add_action_network_allowlist.js +22 -0
- package/dist/lib/database/migrations/0012_add_action_network_allowlist.js.map +1 -0
- package/dist/lib/database/migrations/index.js +2 -0
- package/dist/lib/database/migrations/index.js.map +1 -1
- package/dist/lib/database/workspace.d.ts +6 -1
- package/dist/lib/database/workspace.js +37 -1
- package/dist/lib/database/workspace.js.map +1 -1
- package/dist/lib/execution/config.d.ts +13 -0
- package/dist/lib/execution/config.js +60 -0
- package/dist/lib/execution/config.js.map +1 -1
- package/dist/lib/execution/devcontainer.d.ts +2 -0
- package/dist/lib/execution/devcontainer.js +6 -1
- package/dist/lib/execution/devcontainer.js.map +1 -1
- package/dist/lib/execution/runners/docker-management.d.ts +6 -0
- package/dist/lib/execution/runners/docker-management.js +28 -12
- package/dist/lib/execution/runners/docker-management.js.map +1 -1
- package/dist/lib/execution/runners/sandbox.js +2 -1
- package/dist/lib/execution/runners/sandbox.js.map +1 -1
- package/dist/lib/execution/spawner.d.ts +2 -0
- package/dist/lib/execution/spawner.js +1 -0
- package/dist/lib/execution/spawner.js.map +1 -1
- package/dist/lib/execution/storage.d.ts +43 -9
- package/dist/lib/execution/storage.js +58 -43
- package/dist/lib/execution/storage.js.map +1 -1
- package/dist/lib/execution/types.d.ts +1 -0
- package/dist/lib/execution/types.js.map +1 -1
- package/dist/lib/pmo/find-pmo.js +10 -10
- package/dist/lib/pmo/find-pmo.js.map +1 -1
- package/dist/lib/pmo/schema.d.ts +1 -1
- package/dist/lib/pmo/schema.js +1 -0
- package/dist/lib/pmo/schema.js.map +1 -1
- package/dist/lib/pmo/storage/actions.js +9 -3
- package/dist/lib/pmo/storage/actions.js.map +1 -1
- package/dist/lib/pmo/storage/types.d.ts +1 -0
- package/dist/lib/pmo/types.d.ts +1 -0
- package/dist/lib/pmo/types.js.map +1 -1
- package/dist/lib/registry/index.d.ts +2 -2
- package/dist/lib/registry/index.js +5 -6
- package/dist/lib/registry/index.js.map +1 -1
- package/dist/lib/session-store.js +2 -2
- package/dist/lib/session-store.js.map +1 -1
- package/dist/lib/work-lifecycle/action-chaining.js +4 -0
- package/dist/lib/work-lifecycle/action-chaining.js.map +1 -1
- package/oclif.manifest.json +950 -889
- package/package.json +1 -1
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Safety — WAL mode, auto-backup, corruption recovery.
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - WAL journal mode configuration
|
|
6
|
+
* - Rotating backup (keeps last 5 copies)
|
|
7
|
+
* - Integrity check on open with auto-recovery
|
|
8
|
+
* - Manual repair via dump/reimport
|
|
9
|
+
*
|
|
10
|
+
* See: PRLT-1081
|
|
11
|
+
*/
|
|
12
|
+
import Database from 'better-sqlite3';
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
const MAX_BACKUPS = 5;
|
|
16
|
+
/**
|
|
17
|
+
* Enable WAL journal mode on a database connection.
|
|
18
|
+
* WAL allows concurrent readers with one writer and is significantly
|
|
19
|
+
* more resistant to corruption than the default journal_mode=delete.
|
|
20
|
+
*/
|
|
21
|
+
export function enableWALMode(db) {
|
|
22
|
+
db.pragma('journal_mode = WAL');
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get the backup path for a given database path and backup number.
|
|
26
|
+
*/
|
|
27
|
+
export function getBackupPath(dbPath, n) {
|
|
28
|
+
return `${dbPath}.backup.${n}`;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Create a rotating backup of the database file.
|
|
32
|
+
* Keeps the last MAX_BACKUPS copies, numbered 1 (newest) through MAX_BACKUPS (oldest).
|
|
33
|
+
* Rotates existing backups before copying the current database.
|
|
34
|
+
*
|
|
35
|
+
* Returns true if backup was created, false if source didn't exist.
|
|
36
|
+
*/
|
|
37
|
+
export function createRotatingBackup(dbPath) {
|
|
38
|
+
if (!fs.existsSync(dbPath)) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
// Rotate existing backups: delete oldest, shift others up
|
|
42
|
+
const oldest = getBackupPath(dbPath, MAX_BACKUPS);
|
|
43
|
+
if (fs.existsSync(oldest)) {
|
|
44
|
+
fs.unlinkSync(oldest);
|
|
45
|
+
}
|
|
46
|
+
for (let i = MAX_BACKUPS - 1; i >= 1; i--) {
|
|
47
|
+
const src = getBackupPath(dbPath, i);
|
|
48
|
+
const dst = getBackupPath(dbPath, i + 1);
|
|
49
|
+
if (fs.existsSync(src)) {
|
|
50
|
+
fs.renameSync(src, dst);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Copy current database as backup.1 (newest)
|
|
54
|
+
try {
|
|
55
|
+
fs.copyFileSync(dbPath, getBackupPath(dbPath, 1));
|
|
56
|
+
// Also copy WAL and SHM files if they exist (for WAL-mode databases)
|
|
57
|
+
const walPath = `${dbPath}-wal`;
|
|
58
|
+
const shmPath = `${dbPath}-shm`;
|
|
59
|
+
if (fs.existsSync(walPath)) {
|
|
60
|
+
fs.copyFileSync(walPath, `${getBackupPath(dbPath, 1)}-wal`);
|
|
61
|
+
}
|
|
62
|
+
if (fs.existsSync(shmPath)) {
|
|
63
|
+
fs.copyFileSync(shmPath, `${getBackupPath(dbPath, 1)}-shm`);
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Backup failure is not fatal — log and continue
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Run PRAGMA integrity_check on a database.
|
|
74
|
+
* Returns { ok: true } if the database is healthy, or { ok: false, errors } with details.
|
|
75
|
+
*/
|
|
76
|
+
export function checkIntegrity(db) {
|
|
77
|
+
try {
|
|
78
|
+
const rows = db.pragma('integrity_check');
|
|
79
|
+
const errors = rows
|
|
80
|
+
.map(r => r.integrity_check)
|
|
81
|
+
.filter(msg => msg !== 'ok');
|
|
82
|
+
return { ok: errors.length === 0, errors };
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
return {
|
|
86
|
+
ok: false,
|
|
87
|
+
errors: [error instanceof Error ? error.message : String(error)],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Quick integrity check using PRAGMA quick_check (faster than full integrity_check).
|
|
93
|
+
* Skips checking that the contents of table rows match the indexes.
|
|
94
|
+
*/
|
|
95
|
+
export function quickCheckIntegrity(db) {
|
|
96
|
+
try {
|
|
97
|
+
const rows = db.pragma('quick_check');
|
|
98
|
+
const errors = rows
|
|
99
|
+
.map(r => r.quick_check)
|
|
100
|
+
.filter(msg => msg !== 'ok');
|
|
101
|
+
return { ok: errors.length === 0, errors };
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
return {
|
|
105
|
+
ok: false,
|
|
106
|
+
errors: [error instanceof Error ? error.message : String(error)],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Attempt to repair a corrupted database.
|
|
112
|
+
*
|
|
113
|
+
* Strategy:
|
|
114
|
+
* 1. Try dump/reimport — opens the corrupt DB, dumps all SQL, creates a new DB
|
|
115
|
+
* 2. If dump fails, fall back to the most recent backup
|
|
116
|
+
*
|
|
117
|
+
* The original corrupt file is preserved as dbPath.corrupt for forensics.
|
|
118
|
+
*/
|
|
119
|
+
export function repairDatabase(dbPath) {
|
|
120
|
+
// Try dump/reimport first
|
|
121
|
+
const dumpResult = attemptDumpReimport(dbPath);
|
|
122
|
+
if (dumpResult.success) {
|
|
123
|
+
return dumpResult;
|
|
124
|
+
}
|
|
125
|
+
// Fall back to backup restore
|
|
126
|
+
const backupResult = attemptBackupRestore(dbPath);
|
|
127
|
+
if (backupResult.success) {
|
|
128
|
+
return backupResult;
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
success: false,
|
|
132
|
+
method: 'none',
|
|
133
|
+
message: `Could not repair database. Dump failed: ${dumpResult.message}. No usable backups found.`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Attempt recovery via .dump and reimport.
|
|
138
|
+
* Opens the corrupt database, extracts as much SQL as possible,
|
|
139
|
+
* then creates a fresh database from that SQL.
|
|
140
|
+
*/
|
|
141
|
+
function attemptDumpReimport(dbPath) {
|
|
142
|
+
let corruptDb = null;
|
|
143
|
+
let newDb = null;
|
|
144
|
+
const tempPath = `${dbPath}.repair-temp`;
|
|
145
|
+
try {
|
|
146
|
+
// Open corrupt database — may partially work
|
|
147
|
+
corruptDb = new Database(dbPath, { readonly: true });
|
|
148
|
+
// Dump all recoverable SQL
|
|
149
|
+
const tables = corruptDb.prepare("SELECT sql FROM sqlite_master WHERE sql IS NOT NULL ORDER BY CASE type WHEN 'table' THEN 1 WHEN 'index' THEN 2 ELSE 3 END").all();
|
|
150
|
+
if (tables.length === 0) {
|
|
151
|
+
return { success: false, method: 'dump-reimport', message: 'No tables found in corrupt database' };
|
|
152
|
+
}
|
|
153
|
+
// Create new database with recovered schema
|
|
154
|
+
newDb = new Database(tempPath);
|
|
155
|
+
newDb.pragma('journal_mode = WAL');
|
|
156
|
+
for (const { sql } of tables) {
|
|
157
|
+
try {
|
|
158
|
+
newDb.exec(sql);
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// Skip objects that fail to recreate (e.g., references to missing tables)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Copy data table by table
|
|
165
|
+
const tableNames = corruptDb.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'").all();
|
|
166
|
+
let rowsRecovered = 0;
|
|
167
|
+
for (const { name } of tableNames) {
|
|
168
|
+
try {
|
|
169
|
+
const rows = corruptDb.prepare(`SELECT * FROM "${name}"`).all();
|
|
170
|
+
if (rows.length === 0)
|
|
171
|
+
continue;
|
|
172
|
+
const columns = Object.keys(rows[0]);
|
|
173
|
+
const placeholders = columns.map(() => '?').join(', ');
|
|
174
|
+
const insertSql = `INSERT OR IGNORE INTO "${name}" (${columns.map(c => `"${c}"`).join(', ')}) VALUES (${placeholders})`;
|
|
175
|
+
const insertStmt = newDb.prepare(insertSql);
|
|
176
|
+
const insertAll = newDb.transaction((data) => {
|
|
177
|
+
for (const row of data) {
|
|
178
|
+
insertStmt.run(...columns.map(c => row[c]));
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
insertAll(rows);
|
|
182
|
+
rowsRecovered += rows.length;
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// Skip tables that can't be read
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
corruptDb.close();
|
|
189
|
+
corruptDb = null;
|
|
190
|
+
newDb.close();
|
|
191
|
+
newDb = null;
|
|
192
|
+
// Swap files: corrupt → .corrupt, repaired → original
|
|
193
|
+
const corruptBackupPath = `${dbPath}.corrupt`;
|
|
194
|
+
if (fs.existsSync(corruptBackupPath)) {
|
|
195
|
+
fs.unlinkSync(corruptBackupPath);
|
|
196
|
+
}
|
|
197
|
+
fs.renameSync(dbPath, corruptBackupPath);
|
|
198
|
+
fs.renameSync(tempPath, dbPath);
|
|
199
|
+
// Clean up old WAL/SHM files from the corrupt database
|
|
200
|
+
for (const suffix of ['-wal', '-shm']) {
|
|
201
|
+
const f = `${dbPath}${suffix}`;
|
|
202
|
+
if (fs.existsSync(f)) {
|
|
203
|
+
fs.unlinkSync(f);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
success: true,
|
|
208
|
+
method: 'dump-reimport',
|
|
209
|
+
message: `Recovered ${rowsRecovered} rows from ${tableNames.length} tables. Corrupt file saved as ${path.basename(corruptBackupPath)}.`,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
// Clean up on failure
|
|
214
|
+
if (corruptDb) {
|
|
215
|
+
try {
|
|
216
|
+
corruptDb.close();
|
|
217
|
+
}
|
|
218
|
+
catch { /* ignore */ }
|
|
219
|
+
}
|
|
220
|
+
if (newDb) {
|
|
221
|
+
try {
|
|
222
|
+
newDb.close();
|
|
223
|
+
}
|
|
224
|
+
catch { /* ignore */ }
|
|
225
|
+
}
|
|
226
|
+
if (fs.existsSync(tempPath)) {
|
|
227
|
+
try {
|
|
228
|
+
fs.unlinkSync(tempPath);
|
|
229
|
+
}
|
|
230
|
+
catch { /* ignore */ }
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
success: false,
|
|
234
|
+
method: 'dump-reimport',
|
|
235
|
+
message: error instanceof Error ? error.message : String(error),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Attempt recovery by restoring from the most recent valid backup.
|
|
241
|
+
* Tries backups 1 through MAX_BACKUPS, validates each with integrity_check.
|
|
242
|
+
*/
|
|
243
|
+
function attemptBackupRestore(dbPath) {
|
|
244
|
+
for (let i = 1; i <= MAX_BACKUPS; i++) {
|
|
245
|
+
const backupPath = getBackupPath(dbPath, i);
|
|
246
|
+
if (!fs.existsSync(backupPath)) {
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
// Validate the backup
|
|
250
|
+
let backupDb = null;
|
|
251
|
+
try {
|
|
252
|
+
backupDb = new Database(backupPath, { readonly: true });
|
|
253
|
+
const check = checkIntegrity(backupDb);
|
|
254
|
+
backupDb.close();
|
|
255
|
+
backupDb = null;
|
|
256
|
+
if (!check.ok) {
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
// Backup is valid — swap it in
|
|
260
|
+
const corruptBackupPath = `${dbPath}.corrupt`;
|
|
261
|
+
if (fs.existsSync(corruptBackupPath)) {
|
|
262
|
+
fs.unlinkSync(corruptBackupPath);
|
|
263
|
+
}
|
|
264
|
+
fs.renameSync(dbPath, corruptBackupPath);
|
|
265
|
+
fs.copyFileSync(backupPath, dbPath);
|
|
266
|
+
// Clean up old WAL/SHM files
|
|
267
|
+
for (const suffix of ['-wal', '-shm']) {
|
|
268
|
+
const f = `${dbPath}${suffix}`;
|
|
269
|
+
if (fs.existsSync(f)) {
|
|
270
|
+
fs.unlinkSync(f);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
success: true,
|
|
275
|
+
method: 'backup-restore',
|
|
276
|
+
message: `Restored from backup.${i}. Corrupt file saved as ${path.basename(corruptBackupPath)}.`,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
if (backupDb) {
|
|
281
|
+
try {
|
|
282
|
+
backupDb.close();
|
|
283
|
+
}
|
|
284
|
+
catch { /* ignore */ }
|
|
285
|
+
}
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
success: false,
|
|
291
|
+
method: 'backup-restore',
|
|
292
|
+
message: 'No valid backups found',
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=db-safety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-safety.js","sourceRoot":"","sources":["../../../src/lib/database/db-safety.ts"],"names":[],"mappings":"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"}
|
|
@@ -99,7 +99,7 @@ export declare class BetterSqlite3Driver implements DatabaseDriver {
|
|
|
99
99
|
export declare function wrapDatabase(db: Database.Database): DatabaseDriver;
|
|
100
100
|
/**
|
|
101
101
|
* Create a DatabaseDriver by opening a new better-sqlite3 connection.
|
|
102
|
-
* Configures standard pragmas (foreign keys, busy timeout).
|
|
102
|
+
* Configures standard pragmas (WAL mode, foreign keys, busy timeout).
|
|
103
103
|
*/
|
|
104
104
|
export declare function openDriver(dbPath: string, options?: {
|
|
105
105
|
foreignKeys?: boolean;
|
|
@@ -73,10 +73,11 @@ export function wrapDatabase(db) {
|
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
75
75
|
* Create a DatabaseDriver by opening a new better-sqlite3 connection.
|
|
76
|
-
* Configures standard pragmas (foreign keys, busy timeout).
|
|
76
|
+
* Configures standard pragmas (WAL mode, foreign keys, busy timeout).
|
|
77
77
|
*/
|
|
78
78
|
export function openDriver(dbPath, options) {
|
|
79
79
|
const db = new Database(dbPath);
|
|
80
|
+
db.pragma('journal_mode = WAL');
|
|
80
81
|
if (options?.foreignKeys !== false) {
|
|
81
82
|
db.pragma('foreign_keys = ON');
|
|
82
83
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver.js","sourceRoot":"","sources":["../../../src/lib/database/driver.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"driver.js","sourceRoot":"","sources":["../../../src/lib/database/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAA;AAyErC,gFAAgF;AAChF,sCAAsC;AACtC,gFAAgF;AAEhF;;;;;GAKG;AACH,MAAM,OAAO,mBAAmB;IACV;IAApB,YAAoB,EAAqB;QAArB,OAAE,GAAF,EAAE,CAAmB;IAAG,CAAC;IAE7C,OAAO,CAA8B,GAAW;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACjC,OAAO;YACL,GAAG,EAAE,CAAC,GAAG,MAAiB,EAAa,EAAE;gBACvC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAA;gBAClC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,CAAC,eAAe,EAAE,CAAA;YAC7E,CAAC;YACD,GAAG,EAAE,CAAC,GAAG,MAAiB,EAAiB,EAAE;gBAC3C,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAkB,CAAA;YAC7C,CAAC;YACD,GAAG,EAAE,CAAC,GAAG,MAAiB,EAAO,EAAE;gBACjC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAQ,CAAA;YACnC,CAAC;SACF,CAAA;IACH,CAAC;IAED,IAAI,CAAC,GAAW;QACd,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACnB,CAAC;IAED,MAAM,CAAC,MAAc,EAAE,OAA8B;QACnD,OAAO,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC,CAAC;IAED,WAAW,CAA4C,EAAK;QAC1D,OAAO,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,CAAiB,CAAA;IAChD,CAAC;IAED,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAA;IACjB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,EAAE,CAAC,IAAI,CAAA;IACrB,CAAC;IAED;;;OAGG;IACH,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,EAAE,CAAA;IAChB,CAAC;CACF;AAED,gFAAgF;AAChF,oBAAoB;AACpB,gFAAgF;AAEhF;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,EAAqB;IAChD,OAAO,IAAI,mBAAmB,CAAC,EAAE,CAAC,CAAA;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,OAAyD;IAClG,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC/B,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAA;IAC/B,IAAI,OAAO,EAAE,WAAW,KAAK,KAAK,EAAE,CAAC;QACnC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAA;IAChC,CAAC;IACD,IAAI,OAAO,EAAE,WAAW,KAAK,SAAS,EAAE,CAAC;QACvC,EAAE,CAAC,MAAM,CAAC,kBAAkB,OAAO,CAAC,WAAW,EAAE,CAAC,CAAA;IACpD,CAAC;SAAM,CAAC;QACN,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAA;IAClC,CAAC;IACD,OAAO,IAAI,mBAAmB,CAAC,EAAE,CAAC,CAAA;AACpC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,MAAsB;IACnD,IAAI,MAAM,YAAY,mBAAmB,EAAE,CAAC;QAC1C,OAAO,MAAM,CAAC,GAAG,CAAA;IACnB,CAAC;IACD,2DAA2D;IAC3D,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAA;IACtB,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,SAAS,IAAI,GAAG,EAAE,CAAC;QACvD,OAAO,GAAwB,CAAA;IACjC,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAA;AAChF,CAAC"}
|
|
@@ -25,3 +25,4 @@ export { type MediaItem, addMediaItemToDatabase, updateMediaItemStatus, getWorks
|
|
|
25
25
|
export { checkPMOExists, getPMOSetting, dropPMOTables, upsertWorkspaceSetting, } from './pmo-bootstrap.js';
|
|
26
26
|
export { type DatabaseDriver, type PreparedStatement, type RunResult, BetterSqlite3Driver, wrapDatabase, openDriver, getRawDatabase, } from './driver.js';
|
|
27
27
|
export { SettingsStore, createSettingsStore, } from './settings-store.js';
|
|
28
|
+
export { enableWALMode, createRotatingBackup, checkIntegrity, quickCheckIntegrity, repairDatabase, getBackupPath, type IntegrityCheckResult, type RepairResult, } from './db-safety.js';
|
|
@@ -35,4 +35,6 @@ export { checkPMOExists, getPMOSetting, dropPMOTables, upsertWorkspaceSetting, }
|
|
|
35
35
|
export { BetterSqlite3Driver, wrapDatabase, openDriver, getRawDatabase, } from './driver.js';
|
|
36
36
|
// Settings store
|
|
37
37
|
export { SettingsStore, createSettingsStore, } from './settings-store.js';
|
|
38
|
+
// Database safety (WAL, backup, integrity, repair)
|
|
39
|
+
export { enableWALMode, createRotatingBackup, checkIntegrity, quickCheckIntegrity, repairDatabase, getBackupPath, } from './db-safety.js';
|
|
38
40
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/database/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,0DAA0D;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAEzD,sBAAsB;AACtB,OAAO,EAEL,WAAW,EACX,eAAe,EACf,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AAEvB,mBAAmB;AACnB,OAAO,EAML,mBAAmB,EACnB,2BAA2B,EAC3B,8BAA8B,EAC9B,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,aAAa,CAAA;AAEpB,wBAAwB;AACxB,OAAO,EAEL,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,mBAAmB,CAAA;AAE1B,mBAAmB;AACnB,OAAO,EAGL,cAAc,EACd,cAAc,EACd,SAAS,EACT,QAAQ,EACR,WAAW,EACX,WAAW,EACX,aAAa,EACb,sBAAsB,EACtB,aAAa,GACd,MAAM,aAAa,CAAA;AAEpB,sBAAsB;AACtB,OAAO,EAEL,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,gBAAgB,CAAA;AAEvB,wBAAwB;AACxB,OAAO,EAEL,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,2BAA2B,GAC5B,MAAM,YAAY,CAAA;AAEnB,2BAA2B;AAC3B,OAAO,EACL,cAAc,EACd,aAAa,EACb,aAAa,EACb,sBAAsB,GACvB,MAAM,oBAAoB,CAAA;AAE3B,8BAA8B;AAC9B,OAAO,EAIL,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,cAAc,GACf,MAAM,aAAa,CAAA;AAEpB,iBAAiB;AACjB,OAAO,EACL,aAAa,EACb,mBAAmB,GACpB,MAAM,qBAAqB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/database/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,0DAA0D;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAEzD,sBAAsB;AACtB,OAAO,EAEL,WAAW,EACX,eAAe,EACf,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AAEvB,mBAAmB;AACnB,OAAO,EAML,mBAAmB,EACnB,2BAA2B,EAC3B,8BAA8B,EAC9B,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,aAAa,CAAA;AAEpB,wBAAwB;AACxB,OAAO,EAEL,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,mBAAmB,CAAA;AAE1B,mBAAmB;AACnB,OAAO,EAGL,cAAc,EACd,cAAc,EACd,SAAS,EACT,QAAQ,EACR,WAAW,EACX,WAAW,EACX,aAAa,EACb,sBAAsB,EACtB,aAAa,GACd,MAAM,aAAa,CAAA;AAEpB,sBAAsB;AACtB,OAAO,EAEL,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,gBAAgB,CAAA;AAEvB,wBAAwB;AACxB,OAAO,EAEL,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,2BAA2B,GAC5B,MAAM,YAAY,CAAA;AAEnB,2BAA2B;AAC3B,OAAO,EACL,cAAc,EACd,aAAa,EACb,aAAa,EACb,sBAAsB,GACvB,MAAM,oBAAoB,CAAA;AAE3B,8BAA8B;AAC9B,OAAO,EAIL,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,cAAc,GACf,MAAM,aAAa,CAAA;AAEpB,iBAAiB;AACjB,OAAO,EACL,aAAa,EACb,mBAAmB,GACpB,MAAM,qBAAqB,CAAA;AAE5B,mDAAmD;AACnD,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,aAAa,GAGd,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration 0012 — Add network_allowlist column to pmo_actions
|
|
3
|
+
*
|
|
4
|
+
* Enables per-action network allowlist configuration.
|
|
5
|
+
* Stores a JSON array of domain strings (e.g., '["api.linear.app"]').
|
|
6
|
+
* NULL means use workspace/global defaults only.
|
|
7
|
+
*/
|
|
8
|
+
import type { Migration } from '../migrator.js';
|
|
9
|
+
export declare const addActionNetworkAllowlist: Migration;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration 0012 — Add network_allowlist column to pmo_actions
|
|
3
|
+
*
|
|
4
|
+
* Enables per-action network allowlist configuration.
|
|
5
|
+
* Stores a JSON array of domain strings (e.g., '["api.linear.app"]').
|
|
6
|
+
* NULL means use workspace/global defaults only.
|
|
7
|
+
*/
|
|
8
|
+
export const addActionNetworkAllowlist = {
|
|
9
|
+
id: '0012',
|
|
10
|
+
name: 'add_action_network_allowlist',
|
|
11
|
+
up: (db) => {
|
|
12
|
+
const tableExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='pmo_actions'").get();
|
|
13
|
+
if (!tableExists)
|
|
14
|
+
return;
|
|
15
|
+
const tableInfo = db.prepare("PRAGMA table_info(pmo_actions)").all();
|
|
16
|
+
if (tableInfo.some(col => col.name === 'network_allowlist')) {
|
|
17
|
+
return; // Column already exists
|
|
18
|
+
}
|
|
19
|
+
db.exec("ALTER TABLE pmo_actions ADD COLUMN network_allowlist TEXT");
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=0012_add_action_network_allowlist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0012_add_action_network_allowlist.js","sourceRoot":"","sources":["../../../../src/lib/database/migrations/0012_add_action_network_allowlist.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,MAAM,CAAC,MAAM,yBAAyB,GAAc;IAClD,EAAE,EAAE,MAAM;IACV,IAAI,EAAE,8BAA8B;IACpC,EAAE,EAAE,CAAC,EAAqB,EAAE,EAAE;QAC5B,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAC5B,0EAA0E,CAC3E,CAAC,GAAG,EAAE,CAAA;QACP,IAAI,CAAC,WAAW;YAAE,OAAM;QAExB,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC,GAAG,EAAwB,CAAA;QAC1F,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,mBAAmB,CAAC,EAAE,CAAC;YAC5D,OAAM,CAAC,wBAAwB;QACjC,CAAC;QAED,EAAE,CAAC,IAAI,CACL,2DAA2D,CAC5D,CAAA;IACH,CAAC;CACF,CAAA"}
|
|
@@ -15,6 +15,7 @@ import { addAgentMountMode } from './0008_add_agent_mount_mode.js';
|
|
|
15
15
|
import { createMediaItems } from './0009_create_media_items.js';
|
|
16
16
|
import { addTicketPosition } from './0010_add_ticket_position.js';
|
|
17
17
|
import { addReviewGate } from './0011_add_review_gate.js';
|
|
18
|
+
import { addActionNetworkAllowlist } from './0012_add_action_network_allowlist.js';
|
|
18
19
|
/**
|
|
19
20
|
* Ordered list of all migrations.
|
|
20
21
|
* New migrations should be appended to the end of this array.
|
|
@@ -31,5 +32,6 @@ export const ALL_MIGRATIONS = [
|
|
|
31
32
|
createMediaItems,
|
|
32
33
|
addTicketPosition,
|
|
33
34
|
addReviewGate,
|
|
35
|
+
addActionNetworkAllowlist,
|
|
34
36
|
];
|
|
35
37
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/database/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAA;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/database/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAA;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAA;AAElF;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,QAAQ;IACR,SAAS;IACT,eAAe;IACf,aAAa;IACb,qBAAqB;IACrB,kBAAkB;IAClB,kBAAkB;IAClB,iBAAiB;IACjB,gBAAgB;IAChB,iBAAiB;IACjB,aAAa;IACb,yBAAyB;CAC1B,CAAA"}
|
|
@@ -28,7 +28,12 @@ export declare function getDatabasePath(workspacePath: string): string;
|
|
|
28
28
|
*/
|
|
29
29
|
export declare function getConfigPath(workspacePath: string): string;
|
|
30
30
|
/**
|
|
31
|
-
* Open workspace database connection
|
|
31
|
+
* Open workspace database connection.
|
|
32
|
+
*
|
|
33
|
+
* Safety features (PRLT-1081):
|
|
34
|
+
* - Creates a rotating backup before opening (keeps last 5)
|
|
35
|
+
* - Enables WAL journal mode for corruption resistance
|
|
36
|
+
* - Runs a quick integrity check; auto-repairs if corruption detected
|
|
32
37
|
*/
|
|
33
38
|
export declare function openWorkspaceDatabase(workspacePath: string): Database.Database;
|
|
34
39
|
/**
|
|
@@ -13,6 +13,7 @@ import { ALL_MIGRATIONS } from './migrations/index.js';
|
|
|
13
13
|
import { createDrizzleConnection } from './drizzle.js';
|
|
14
14
|
import { workspace as workspaceTable, } from './drizzle-schema.js';
|
|
15
15
|
import { BetterSqlite3Driver } from './driver.js';
|
|
16
|
+
import { enableWALMode, createRotatingBackup, quickCheckIntegrity, repairDatabase, } from './db-safety.js';
|
|
16
17
|
/**
|
|
17
18
|
* Open the workspace database, wrap it with Drizzle, run a function,
|
|
18
19
|
* and close the connection. Handles the open/close lifecycle.
|
|
@@ -68,13 +69,20 @@ export function getConfigPath(workspacePath) {
|
|
|
68
69
|
return path.join(workspacePath, '.proletariat', 'config.json');
|
|
69
70
|
}
|
|
70
71
|
/**
|
|
71
|
-
* Open workspace database connection
|
|
72
|
+
* Open workspace database connection.
|
|
73
|
+
*
|
|
74
|
+
* Safety features (PRLT-1081):
|
|
75
|
+
* - Creates a rotating backup before opening (keeps last 5)
|
|
76
|
+
* - Enables WAL journal mode for corruption resistance
|
|
77
|
+
* - Runs a quick integrity check; auto-repairs if corruption detected
|
|
72
78
|
*/
|
|
73
79
|
export function openWorkspaceDatabase(workspacePath) {
|
|
74
80
|
const dbPath = getDatabasePath(workspacePath);
|
|
75
81
|
if (!fs.existsSync(dbPath)) {
|
|
76
82
|
throw new Error(`Database not found: ${dbPath}. Run 'prlt new' first.`);
|
|
77
83
|
}
|
|
84
|
+
// Auto-backup before opening (cheap insurance against corruption)
|
|
85
|
+
createRotatingBackup(dbPath);
|
|
78
86
|
let db;
|
|
79
87
|
try {
|
|
80
88
|
db = new Database(dbPath);
|
|
@@ -83,8 +91,35 @@ export function openWorkspaceDatabase(workspacePath) {
|
|
|
83
91
|
throwIfNativeBindingError(error, 'openWorkspaceDatabase');
|
|
84
92
|
throw error;
|
|
85
93
|
}
|
|
94
|
+
// Enable WAL mode — allows concurrent readers with one writer,
|
|
95
|
+
// significantly more resistant to corruption than journal_mode=delete
|
|
96
|
+
enableWALMode(db);
|
|
86
97
|
db.pragma('foreign_keys = ON');
|
|
87
98
|
db.pragma('busy_timeout = 5000');
|
|
99
|
+
// Quick integrity check on startup
|
|
100
|
+
const integrity = quickCheckIntegrity(db);
|
|
101
|
+
if (!integrity.ok) {
|
|
102
|
+
db.close();
|
|
103
|
+
// Attempt auto-repair
|
|
104
|
+
const repair = repairDatabase(dbPath);
|
|
105
|
+
if (!repair.success) {
|
|
106
|
+
throw new Error(`Database corruption detected in ${dbPath}.\n` +
|
|
107
|
+
`Integrity errors: ${integrity.errors.join('; ')}\n` +
|
|
108
|
+
`Auto-repair failed: ${repair.message}\n` +
|
|
109
|
+
`Run 'prlt db repair' for manual recovery options.`);
|
|
110
|
+
}
|
|
111
|
+
// Re-open the repaired database
|
|
112
|
+
try {
|
|
113
|
+
db = new Database(dbPath);
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
throwIfNativeBindingError(error, 'openWorkspaceDatabase (post-repair)');
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
enableWALMode(db);
|
|
120
|
+
db.pragma('foreign_keys = ON');
|
|
121
|
+
db.pragma('busy_timeout = 5000');
|
|
122
|
+
}
|
|
88
123
|
runDrizzleMigrations(db, ALL_MIGRATIONS);
|
|
89
124
|
ensureEphemeralAgentTypes(db);
|
|
90
125
|
return db;
|
|
@@ -120,6 +155,7 @@ export function createWorkspaceDatabase(workspacePath, type, workspaceName, hasP
|
|
|
120
155
|
throwIfNativeBindingError(error, 'createWorkspaceDatabase');
|
|
121
156
|
throw error;
|
|
122
157
|
}
|
|
158
|
+
enableWALMode(db);
|
|
123
159
|
db.pragma('foreign_keys = ON');
|
|
124
160
|
runDrizzleMigrations(db, ALL_MIGRATIONS);
|
|
125
161
|
const ddb = createDrizzleConnection(db);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../src/lib/database/workspace.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAA;AACrC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAC7B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,uBAAuB,EAAkB,MAAM,cAAc,CAAA;AACtE,OAAO,EACL,SAAS,IAAI,cAAc,GAC5B,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../src/lib/database/workspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -65,6 +65,19 @@ export declare function setDefaultCleanupPolicy(db: Database.Database, policy: C
|
|
|
65
65
|
* Set the cleanup policy for a specific action.
|
|
66
66
|
*/
|
|
67
67
|
export declare function setActionCleanupPolicy(db: Database.Database, actionId: string, policy: CleanupPolicy): void;
|
|
68
|
+
/**
|
|
69
|
+
* Resolve the network allowlist for a spawn, merging layers:
|
|
70
|
+
* 1. Action-level: action.networkAllowlist (from pmo_actions table)
|
|
71
|
+
* 2. Per-action override: network.actions.{actionId} (from workspace_settings)
|
|
72
|
+
* 3. Workspace global: firewall.allowlistDomains (from ExecutionConfig)
|
|
73
|
+
*
|
|
74
|
+
* All layers are merged (union). Duplicates are removed.
|
|
75
|
+
*/
|
|
76
|
+
export declare function getNetworkAllowlist(config: ExecutionConfig, actionId?: string, actionNetworkAllowlist?: string[], db?: Database.Database): string[];
|
|
77
|
+
/**
|
|
78
|
+
* Set the network allowlist for a specific action in workspace_settings.
|
|
79
|
+
*/
|
|
80
|
+
export declare function setActionNetworkAllowlist(db: Database.Database, actionId: string, domains: string[]): void;
|
|
68
81
|
/**
|
|
69
82
|
* Save terminal app preference
|
|
70
83
|
*/
|
|
@@ -302,6 +302,66 @@ export function setDefaultCleanupPolicy(db, policy) {
|
|
|
302
302
|
export function setActionCleanupPolicy(db, actionId, policy) {
|
|
303
303
|
setSetting(db, `cleanup.actions.${actionId}`, policy);
|
|
304
304
|
}
|
|
305
|
+
// =============================================================================
|
|
306
|
+
// Network Allowlist Configuration
|
|
307
|
+
// =============================================================================
|
|
308
|
+
/**
|
|
309
|
+
* Resolve the network allowlist for a spawn, merging layers:
|
|
310
|
+
* 1. Action-level: action.networkAllowlist (from pmo_actions table)
|
|
311
|
+
* 2. Per-action override: network.actions.{actionId} (from workspace_settings)
|
|
312
|
+
* 3. Workspace global: firewall.allowlistDomains (from ExecutionConfig)
|
|
313
|
+
*
|
|
314
|
+
* All layers are merged (union). Duplicates are removed.
|
|
315
|
+
*/
|
|
316
|
+
export function getNetworkAllowlist(config, actionId, actionNetworkAllowlist, db) {
|
|
317
|
+
const domains = new Set();
|
|
318
|
+
// Layer 1: workspace-level firewall.allowlistDomains (always applied)
|
|
319
|
+
for (const domain of config.firewall.allowlistDomains) {
|
|
320
|
+
domains.add(domain.trim().toLowerCase());
|
|
321
|
+
}
|
|
322
|
+
// Layer 2: per-action override from workspace_settings
|
|
323
|
+
if (db && actionId) {
|
|
324
|
+
const settingValue = getSetting(db, `network.actions.${actionId}`);
|
|
325
|
+
if (settingValue) {
|
|
326
|
+
try {
|
|
327
|
+
const parsed = JSON.parse(settingValue);
|
|
328
|
+
if (Array.isArray(parsed)) {
|
|
329
|
+
for (const d of parsed) {
|
|
330
|
+
if (typeof d === 'string' && d.trim()) {
|
|
331
|
+
domains.add(d.trim().toLowerCase());
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
catch {
|
|
337
|
+
// Backward-compatible fallback: comma-separated
|
|
338
|
+
for (const d of settingValue.split(',')) {
|
|
339
|
+
if (d.trim())
|
|
340
|
+
domains.add(d.trim().toLowerCase());
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// Layer 3: action-level networkAllowlist (from pmo_actions table)
|
|
346
|
+
if (actionNetworkAllowlist) {
|
|
347
|
+
for (const domain of actionNetworkAllowlist) {
|
|
348
|
+
domains.add(domain.trim().toLowerCase());
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return [...domains].filter(Boolean);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Set the network allowlist for a specific action in workspace_settings.
|
|
355
|
+
*/
|
|
356
|
+
export function setActionNetworkAllowlist(db, actionId, domains) {
|
|
357
|
+
const cleaned = [...new Set(domains.map(d => d.trim().toLowerCase()).filter(Boolean))];
|
|
358
|
+
if (cleaned.length === 0) {
|
|
359
|
+
settingsFor(db).delete(`network.actions.${actionId}`);
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
setSetting(db, `network.actions.${actionId}`, JSON.stringify(cleaned));
|
|
363
|
+
}
|
|
364
|
+
}
|
|
305
365
|
/**
|
|
306
366
|
* Save terminal app preference
|
|
307
367
|
*/
|