@kici-dev/shared 0.1.26 → 0.1.27
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/db-admin.d.ts +58 -58
- package/dist/db-admin.js +82 -82
- package/dist/db-collation.d.ts +49 -0
- package/dist/db-collation.js +68 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/package.json +2 -2
- package/sbom.spdx.json +15 -15
package/dist/db-admin.d.ts
CHANGED
|
@@ -178,22 +178,22 @@ export declare function purgeScopedSecretsDirect(databaseUrl: string, orgId?: st
|
|
|
178
178
|
deleted: number;
|
|
179
179
|
}>;
|
|
180
180
|
/**
|
|
181
|
-
* Bulk-delete `
|
|
182
|
-
* every org when `orgId` is omitted. `
|
|
183
|
-
* `
|
|
181
|
+
* Bulk-delete `contexts` (and their FK-dependent rows) for an org, or for
|
|
182
|
+
* every org when `orgId` is omitted. `context_bindings` /
|
|
183
|
+
* `context_variables` / `context_source_overrides` cascade
|
|
184
184
|
* automatically (ON DELETE CASCADE). `held_runs` and `execution_runs` reference
|
|
185
|
-
* `
|
|
186
|
-
* would leave orphaned `held_runs` rows carrying a null
|
|
185
|
+
* `contexts(id)` with ON DELETE SET NULL, so deleting contexts alone
|
|
186
|
+
* would leave orphaned `held_runs` rows carrying a null context reference;
|
|
187
187
|
* this helper deletes the org's `held_runs` too so a warm-start reset gets a
|
|
188
188
|
* clean slate. Runs in a transaction so both deletes commit atomically. Used by
|
|
189
|
-
* the E2E warm-start reset (so seeded
|
|
190
|
-
* categories) and exposed via `kici-admin
|
|
189
|
+
* the E2E warm-start reset (so seeded contexts don't leak between
|
|
190
|
+
* categories) and exposed via `kici-admin context purge`.
|
|
191
191
|
*/
|
|
192
|
-
export declare function
|
|
193
|
-
|
|
192
|
+
export declare function purgeContextsDirect(databaseUrl: string, orgId?: string): Promise<{
|
|
193
|
+
contextsDeleted: number;
|
|
194
194
|
heldRunsDeleted: number;
|
|
195
195
|
}>;
|
|
196
|
-
export interface
|
|
196
|
+
export interface SeedContextOpts {
|
|
197
197
|
orgId: string;
|
|
198
198
|
name: string;
|
|
199
199
|
type?: string;
|
|
@@ -205,52 +205,52 @@ export interface SeedEnvironmentOpts {
|
|
|
205
205
|
minimumTrust?: string | null;
|
|
206
206
|
globPattern?: string | null;
|
|
207
207
|
}
|
|
208
|
-
export interface
|
|
208
|
+
export interface SeedContextResult {
|
|
209
209
|
envId: string;
|
|
210
210
|
created: boolean;
|
|
211
211
|
}
|
|
212
212
|
/**
|
|
213
|
-
* Upsert an
|
|
213
|
+
* Upsert an context row keyed by (org_id, name). Returns the env id and
|
|
214
214
|
* whether the row was newly inserted. `branchRestrictions` / `requiredReviewers`
|
|
215
215
|
* are JSON-serialised server-side; pass them as plain arrays or objects.
|
|
216
216
|
*/
|
|
217
|
-
export declare function
|
|
218
|
-
export interface
|
|
217
|
+
export declare function seedContextDirect(databaseUrl: string, opts: SeedContextOpts): Promise<SeedContextResult>;
|
|
218
|
+
export interface DeleteContextOpts {
|
|
219
219
|
orgId: string;
|
|
220
220
|
name: string;
|
|
221
221
|
}
|
|
222
222
|
/**
|
|
223
|
-
* Delete an
|
|
224
|
-
* removed. The `
|
|
225
|
-
* `
|
|
226
|
-
* `FOREIGN KEY (
|
|
227
|
-
* so a single DELETE on `
|
|
223
|
+
* Delete an context keyed by (org_id, name). Returns whether a row was
|
|
224
|
+
* removed. The `context_bindings`, `context_variables`, and
|
|
225
|
+
* `context_source_overrides` children all carry
|
|
226
|
+
* `FOREIGN KEY (context_id) REFERENCES contexts(id) ON DELETE CASCADE`,
|
|
227
|
+
* so a single DELETE on `contexts` cascades to those children. The
|
|
228
228
|
* `held_runs` FK uses `ON DELETE SET NULL`, so terminal held-run history
|
|
229
|
-
* survives the delete with a null
|
|
230
|
-
* still reference the
|
|
229
|
+
* survives the delete with a null context reference. Pending held runs
|
|
230
|
+
* still reference the context, so this helper pre-checks their count and
|
|
231
231
|
* throws before issuing the DELETE — approve or reject them first.
|
|
232
232
|
*/
|
|
233
|
-
export declare function
|
|
233
|
+
export declare function deleteContextDirect(databaseUrl: string, opts: DeleteContextOpts): Promise<{
|
|
234
234
|
deleted: boolean;
|
|
235
235
|
}>;
|
|
236
|
-
export interface
|
|
236
|
+
export interface SeedContextBindingOpts {
|
|
237
237
|
orgId: string;
|
|
238
|
-
|
|
238
|
+
contextName: string;
|
|
239
239
|
scopePattern: string;
|
|
240
240
|
/** Host selector; defaults to `'**'` (all hosts). */
|
|
241
241
|
hostPattern?: string;
|
|
242
242
|
}
|
|
243
243
|
/**
|
|
244
|
-
* Upsert an `
|
|
245
|
-
* (scoped to `hostPattern`, default `'**'`). Throws if the
|
|
244
|
+
* Upsert an `context_bindings` row connecting `contextName` to `scopePattern`
|
|
245
|
+
* (scoped to `hostPattern`, default `'**'`). Throws if the context does
|
|
246
246
|
* not exist.
|
|
247
247
|
*/
|
|
248
|
-
export declare function
|
|
248
|
+
export declare function seedContextBindingDirect(databaseUrl: string, opts: SeedContextBindingOpts): Promise<{
|
|
249
249
|
created: boolean;
|
|
250
250
|
}>;
|
|
251
|
-
export interface
|
|
251
|
+
export interface SetContextPolicyOpts {
|
|
252
252
|
orgId: string;
|
|
253
|
-
|
|
253
|
+
contextName: string;
|
|
254
254
|
branchRestrictions?: unknown;
|
|
255
255
|
requiredReviewers?: unknown;
|
|
256
256
|
waitTimerSeconds?: number | null;
|
|
@@ -261,10 +261,10 @@ export interface SetEnvironmentPolicyOpts {
|
|
|
261
261
|
}
|
|
262
262
|
/**
|
|
263
263
|
* UPDATE only the policy fields that were explicitly provided. Columns that
|
|
264
|
-
* were NOT in `opts` are left untouched. Throws if the
|
|
264
|
+
* were NOT in `opts` are left untouched. Throws if the context is missing.
|
|
265
265
|
*/
|
|
266
|
-
export declare function
|
|
267
|
-
export interface
|
|
266
|
+
export declare function setContextPolicyDirect(databaseUrl: string, opts: SetContextPolicyOpts): Promise<void>;
|
|
267
|
+
export interface ContextRow {
|
|
268
268
|
id: string;
|
|
269
269
|
org_id: string;
|
|
270
270
|
name: string;
|
|
@@ -279,38 +279,38 @@ export interface EnvironmentRow {
|
|
|
279
279
|
updated_at: string;
|
|
280
280
|
}
|
|
281
281
|
/**
|
|
282
|
-
* SELECT * FROM
|
|
282
|
+
* SELECT * FROM contexts WHERE org_id = $1, ordered by name.
|
|
283
283
|
*/
|
|
284
|
-
export declare function
|
|
284
|
+
export declare function listContextsDirect(databaseUrl: string, opts: {
|
|
285
285
|
orgId: string;
|
|
286
286
|
}): Promise<{
|
|
287
|
-
|
|
287
|
+
contexts: ContextRow[];
|
|
288
288
|
}>;
|
|
289
|
-
export interface
|
|
289
|
+
export interface ContextVariableRow {
|
|
290
290
|
key: string;
|
|
291
291
|
value: string;
|
|
292
292
|
locked: boolean;
|
|
293
293
|
updated_at: string;
|
|
294
294
|
}
|
|
295
|
-
export interface
|
|
295
|
+
export interface ContextBindingRow {
|
|
296
296
|
scope_pattern: string;
|
|
297
297
|
host_pattern: string;
|
|
298
298
|
created_at: string;
|
|
299
299
|
}
|
|
300
|
-
export interface
|
|
301
|
-
|
|
302
|
-
variables:
|
|
303
|
-
bindings:
|
|
300
|
+
export interface ShowContextResult {
|
|
301
|
+
context: ContextRow;
|
|
302
|
+
variables: ContextVariableRow[];
|
|
303
|
+
bindings: ContextBindingRow[];
|
|
304
304
|
}
|
|
305
305
|
/**
|
|
306
|
-
* Fetch a single
|
|
307
|
-
* Throws if the
|
|
306
|
+
* Fetch a single context row joined with its variables and bindings.
|
|
307
|
+
* Throws if the context does not exist.
|
|
308
308
|
*/
|
|
309
|
-
export declare function
|
|
309
|
+
export declare function showContextDirect(databaseUrl: string, opts: {
|
|
310
310
|
orgId: string;
|
|
311
311
|
name: string;
|
|
312
|
-
}): Promise<
|
|
313
|
-
export interface
|
|
312
|
+
}): Promise<ShowContextResult>;
|
|
313
|
+
export interface CreateContextTemplateOpts {
|
|
314
314
|
orgId: string;
|
|
315
315
|
templateName: string;
|
|
316
316
|
type?: string;
|
|
@@ -322,27 +322,27 @@ export interface CreateEnvironmentTemplateOpts {
|
|
|
322
322
|
variables?: Record<string, string>;
|
|
323
323
|
}
|
|
324
324
|
/**
|
|
325
|
-
* Create (or update) an
|
|
326
|
-
* transaction. Templates are represented as
|
|
325
|
+
* Create (or update) an context template + its seed variables in one
|
|
326
|
+
* transaction. Templates are represented as contexts with `type='template'`
|
|
327
327
|
* by convention. Returns `{ envId, variablesSet }`.
|
|
328
328
|
*/
|
|
329
|
-
export declare function
|
|
329
|
+
export declare function createContextTemplateDirect(databaseUrl: string, opts: CreateContextTemplateOpts): Promise<{
|
|
330
330
|
envId: string;
|
|
331
331
|
created: boolean;
|
|
332
332
|
variablesSet: number;
|
|
333
333
|
}>;
|
|
334
|
-
export interface
|
|
334
|
+
export interface SetContextSecretOpts {
|
|
335
335
|
orgId: string;
|
|
336
|
-
|
|
336
|
+
context: string;
|
|
337
337
|
key: string;
|
|
338
338
|
encryptedValue: string;
|
|
339
339
|
}
|
|
340
340
|
/**
|
|
341
|
-
* UPSERT a scoped_secrets row keyed by (org_id, scope=
|
|
341
|
+
* UPSERT a scoped_secrets row keyed by (org_id, scope=context, key).
|
|
342
342
|
* Writes the value verbatim — the caller is responsible for encryption
|
|
343
343
|
* (matches the stage-4 deferral noted in the plan).
|
|
344
344
|
*/
|
|
345
|
-
export declare function
|
|
345
|
+
export declare function setContextSecretDirect(databaseUrl: string, opts: SetContextSecretOpts): Promise<{
|
|
346
346
|
inserted: boolean;
|
|
347
347
|
}>;
|
|
348
348
|
export interface DispatchQueueRow {
|
|
@@ -400,7 +400,7 @@ export interface ExecutionRunRow {
|
|
|
400
400
|
ref: string;
|
|
401
401
|
sha: string;
|
|
402
402
|
routing_key: string | null;
|
|
403
|
-
|
|
403
|
+
context: string | null;
|
|
404
404
|
trust_tier: string | null;
|
|
405
405
|
created_at: string;
|
|
406
406
|
started_at: string;
|
|
@@ -419,8 +419,8 @@ export interface ExecutionJobRow {
|
|
|
419
419
|
duration_ms: number | null;
|
|
420
420
|
created_at: string;
|
|
421
421
|
error_message: string | null;
|
|
422
|
-
/** Ordered bound deployment-
|
|
423
|
-
|
|
422
|
+
/** Ordered bound deployment-context names (JSON-encoded `string[]`), or null. */
|
|
423
|
+
contexts: string | null;
|
|
424
424
|
}
|
|
425
425
|
export interface ListExecutionRunsOpts {
|
|
426
426
|
routingKey?: string;
|
|
@@ -869,7 +869,7 @@ export interface SeedUniversalGitSourceOpts {
|
|
|
869
869
|
export declare function seedUniversalGitSourceDirect(databaseUrl: string, opts: SeedUniversalGitSourceOpts): Promise<void>;
|
|
870
870
|
/**
|
|
871
871
|
* Seed the ci-security orchestrator fixtures expected by the security
|
|
872
|
-
* pipeline e2e: sources row for dashboard orgId resolution,
|
|
872
|
+
* pipeline e2e: sources row for dashboard orgId resolution, context,
|
|
873
873
|
* two execution_runs (unknown + trusted), two execution_jobs, and a
|
|
874
874
|
* security held_run for the unknown contributor.
|
|
875
875
|
*
|
|
@@ -877,7 +877,7 @@ export declare function seedUniversalGitSourceDirect(databaseUrl: string, opts:
|
|
|
877
877
|
*/
|
|
878
878
|
export interface SeedCiSecurityFixturesOpts {
|
|
879
879
|
orgId: string;
|
|
880
|
-
|
|
880
|
+
contextName?: string;
|
|
881
881
|
sourceName?: string;
|
|
882
882
|
sourceRoutingKey?: string;
|
|
883
883
|
runsRoutingKey: string;
|
package/dist/db-admin.js
CHANGED
|
@@ -341,18 +341,18 @@ async function purgeScopedSecretsDirect(databaseUrl, orgId) {
|
|
|
341
341
|
}
|
|
342
342
|
}
|
|
343
343
|
/**
|
|
344
|
-
* Bulk-delete `
|
|
345
|
-
* every org when `orgId` is omitted. `
|
|
346
|
-
* `
|
|
344
|
+
* Bulk-delete `contexts` (and their FK-dependent rows) for an org, or for
|
|
345
|
+
* every org when `orgId` is omitted. `context_bindings` /
|
|
346
|
+
* `context_variables` / `context_source_overrides` cascade
|
|
347
347
|
* automatically (ON DELETE CASCADE). `held_runs` and `execution_runs` reference
|
|
348
|
-
* `
|
|
349
|
-
* would leave orphaned `held_runs` rows carrying a null
|
|
348
|
+
* `contexts(id)` with ON DELETE SET NULL, so deleting contexts alone
|
|
349
|
+
* would leave orphaned `held_runs` rows carrying a null context reference;
|
|
350
350
|
* this helper deletes the org's `held_runs` too so a warm-start reset gets a
|
|
351
351
|
* clean slate. Runs in a transaction so both deletes commit atomically. Used by
|
|
352
|
-
* the E2E warm-start reset (so seeded
|
|
353
|
-
* categories) and exposed via `kici-admin
|
|
352
|
+
* the E2E warm-start reset (so seeded contexts don't leak between
|
|
353
|
+
* categories) and exposed via `kici-admin context purge`.
|
|
354
354
|
*/
|
|
355
|
-
async function
|
|
355
|
+
async function purgeContextsDirect(databaseUrl, orgId) {
|
|
356
356
|
const pool = createPool(databaseUrl);
|
|
357
357
|
const client = await pool.connect();
|
|
358
358
|
try {
|
|
@@ -360,10 +360,10 @@ async function purgeEnvironmentsDirect(databaseUrl, orgId) {
|
|
|
360
360
|
const where = orgId ? "WHERE org_id = $1" : "";
|
|
361
361
|
const params = orgId ? [orgId] : [];
|
|
362
362
|
const held = await client.query(`DELETE FROM held_runs ${where}`, params);
|
|
363
|
-
const envs = await client.query(`DELETE FROM
|
|
363
|
+
const envs = await client.query(`DELETE FROM contexts ${where}`, params);
|
|
364
364
|
await client.query("COMMIT");
|
|
365
365
|
return {
|
|
366
|
-
|
|
366
|
+
contextsDeleted: envs.rowCount ?? 0,
|
|
367
367
|
heldRunsDeleted: held.rowCount ?? 0
|
|
368
368
|
};
|
|
369
369
|
} catch (err) {
|
|
@@ -375,7 +375,7 @@ async function purgeEnvironmentsDirect(databaseUrl, orgId) {
|
|
|
375
375
|
}
|
|
376
376
|
}
|
|
377
377
|
/**
|
|
378
|
-
* Allowed policy field names for `
|
|
378
|
+
* Allowed policy field names for `setContextPolicyDirect`. Kept as an
|
|
379
379
|
* explicit allowlist so the column-name interpolation in the UPDATE string
|
|
380
380
|
* can never be driven by unsanitised caller input.
|
|
381
381
|
*/
|
|
@@ -389,13 +389,13 @@ const ENV_POLICY_COLUMNS = /* @__PURE__ */ new Set([
|
|
|
389
389
|
"allow_local_execution"
|
|
390
390
|
]);
|
|
391
391
|
/**
|
|
392
|
-
* Upsert an
|
|
392
|
+
* Upsert an context row keyed by (org_id, name). Returns the env id and
|
|
393
393
|
* whether the row was newly inserted. `branchRestrictions` / `requiredReviewers`
|
|
394
394
|
* are JSON-serialised server-side; pass them as plain arrays or objects.
|
|
395
395
|
*/
|
|
396
|
-
async function
|
|
397
|
-
if (opts.waitTimerSeconds != null && opts.waitTimerSeconds < 0) throw new Error(`
|
|
398
|
-
if (opts.holdExpirySeconds != null && opts.holdExpirySeconds < 0) throw new Error(`
|
|
396
|
+
async function seedContextDirect(databaseUrl, opts) {
|
|
397
|
+
if (opts.waitTimerSeconds != null && opts.waitTimerSeconds < 0) throw new Error(`context: waitTimerSeconds must be >= 0 (got ${opts.waitTimerSeconds})`);
|
|
398
|
+
if (opts.holdExpirySeconds != null && opts.holdExpirySeconds < 0) throw new Error(`context: holdExpirySeconds must be >= 0 (got ${opts.holdExpirySeconds})`);
|
|
399
399
|
const pool = new pg.Pool({
|
|
400
400
|
connectionString: databaseUrl,
|
|
401
401
|
max: 1
|
|
@@ -403,20 +403,20 @@ async function seedEnvironmentDirect(databaseUrl, opts) {
|
|
|
403
403
|
try {
|
|
404
404
|
const branchJson = JSON.stringify(opts.branchRestrictions ?? []);
|
|
405
405
|
const reviewersJson = opts.requiredReviewers === void 0 ? null : JSON.stringify(opts.requiredReviewers);
|
|
406
|
-
const row = (await pool.query(`INSERT INTO
|
|
406
|
+
const row = (await pool.query(`INSERT INTO contexts
|
|
407
407
|
(org_id, name, type, enabled, branch_restrictions, required_reviewers,
|
|
408
408
|
wait_timer_seconds, hold_expiry_seconds, minimum_trust, glob_pattern)
|
|
409
409
|
VALUES ($1, $2, COALESCE($3, 'fixed'), COALESCE($4, true), $5::jsonb, $6::jsonb,
|
|
410
410
|
$7, COALESCE($8, 86400), $9, $10)
|
|
411
411
|
ON CONFLICT (org_id, name) DO UPDATE SET
|
|
412
|
-
type = COALESCE(EXCLUDED.type,
|
|
412
|
+
type = COALESCE(EXCLUDED.type, contexts.type),
|
|
413
413
|
enabled = EXCLUDED.enabled,
|
|
414
414
|
branch_restrictions = EXCLUDED.branch_restrictions,
|
|
415
415
|
required_reviewers = EXCLUDED.required_reviewers,
|
|
416
416
|
wait_timer_seconds = EXCLUDED.wait_timer_seconds,
|
|
417
417
|
hold_expiry_seconds = EXCLUDED.hold_expiry_seconds,
|
|
418
418
|
minimum_trust = EXCLUDED.minimum_trust,
|
|
419
|
-
glob_pattern = COALESCE(EXCLUDED.glob_pattern,
|
|
419
|
+
glob_pattern = COALESCE(EXCLUDED.glob_pattern, contexts.glob_pattern),
|
|
420
420
|
updated_at = now()
|
|
421
421
|
RETURNING id, (xmax = 0) AS inserted`, [
|
|
422
422
|
opts.orgId,
|
|
@@ -430,7 +430,7 @@ async function seedEnvironmentDirect(databaseUrl, opts) {
|
|
|
430
430
|
opts.minimumTrust ?? null,
|
|
431
431
|
opts.globPattern ?? null
|
|
432
432
|
])).rows[0];
|
|
433
|
-
if (!row) throw new Error(`
|
|
433
|
+
if (!row) throw new Error(`context: upsert returned no row for ${opts.name}`);
|
|
434
434
|
return {
|
|
435
435
|
envId: row.id,
|
|
436
436
|
created: row.inserted
|
|
@@ -440,47 +440,47 @@ async function seedEnvironmentDirect(databaseUrl, opts) {
|
|
|
440
440
|
}
|
|
441
441
|
}
|
|
442
442
|
/**
|
|
443
|
-
* Delete an
|
|
444
|
-
* removed. The `
|
|
445
|
-
* `
|
|
446
|
-
* `FOREIGN KEY (
|
|
447
|
-
* so a single DELETE on `
|
|
443
|
+
* Delete an context keyed by (org_id, name). Returns whether a row was
|
|
444
|
+
* removed. The `context_bindings`, `context_variables`, and
|
|
445
|
+
* `context_source_overrides` children all carry
|
|
446
|
+
* `FOREIGN KEY (context_id) REFERENCES contexts(id) ON DELETE CASCADE`,
|
|
447
|
+
* so a single DELETE on `contexts` cascades to those children. The
|
|
448
448
|
* `held_runs` FK uses `ON DELETE SET NULL`, so terminal held-run history
|
|
449
|
-
* survives the delete with a null
|
|
450
|
-
* still reference the
|
|
449
|
+
* survives the delete with a null context reference. Pending held runs
|
|
450
|
+
* still reference the context, so this helper pre-checks their count and
|
|
451
451
|
* throws before issuing the DELETE — approve or reject them first.
|
|
452
452
|
*/
|
|
453
|
-
async function
|
|
453
|
+
async function deleteContextDirect(databaseUrl, opts) {
|
|
454
454
|
const pool = new pg.Pool({
|
|
455
455
|
connectionString: databaseUrl,
|
|
456
456
|
max: 1
|
|
457
457
|
});
|
|
458
458
|
try {
|
|
459
459
|
const pending = await pool.query(`SELECT count(*)::text AS count FROM held_runs hr
|
|
460
|
-
JOIN
|
|
460
|
+
JOIN contexts e ON e.id = hr.context_id
|
|
461
461
|
WHERE e.org_id = $1 AND e.name = $2 AND hr.status = 'pending'`, [opts.orgId, opts.name]);
|
|
462
462
|
const pendingCount = Number(pending.rows[0]?.count ?? 0);
|
|
463
|
-
if (pendingCount > 0) throw new Error(`
|
|
464
|
-
return { deleted: (await pool.query(`DELETE FROM
|
|
463
|
+
if (pendingCount > 0) throw new Error(`context has ${pendingCount} pending held run(s) — approve or reject them first`);
|
|
464
|
+
return { deleted: (await pool.query(`DELETE FROM contexts WHERE org_id = $1 AND name = $2 RETURNING id`, [opts.orgId, opts.name])).rows.length > 0 };
|
|
465
465
|
} finally {
|
|
466
466
|
await pool.end();
|
|
467
467
|
}
|
|
468
468
|
}
|
|
469
469
|
/**
|
|
470
|
-
* Upsert an `
|
|
471
|
-
* (scoped to `hostPattern`, default `'**'`). Throws if the
|
|
470
|
+
* Upsert an `context_bindings` row connecting `contextName` to `scopePattern`
|
|
471
|
+
* (scoped to `hostPattern`, default `'**'`). Throws if the context does
|
|
472
472
|
* not exist.
|
|
473
473
|
*/
|
|
474
|
-
async function
|
|
474
|
+
async function seedContextBindingDirect(databaseUrl, opts) {
|
|
475
475
|
const pool = new pg.Pool({
|
|
476
476
|
connectionString: databaseUrl,
|
|
477
477
|
max: 1
|
|
478
478
|
});
|
|
479
479
|
try {
|
|
480
|
-
const envRow = await pool.query(`SELECT id FROM
|
|
481
|
-
if (envRow.rows.length === 0) throw new Error(`
|
|
480
|
+
const envRow = await pool.query(`SELECT id FROM contexts WHERE org_id = $1 AND name = $2`, [opts.orgId, opts.contextName]);
|
|
481
|
+
if (envRow.rows.length === 0) throw new Error(`context: not found (org=${opts.orgId}, name=${opts.contextName})`);
|
|
482
482
|
const envId = envRow.rows[0].id;
|
|
483
|
-
return { created: (await pool.query(`INSERT INTO
|
|
483
|
+
return { created: (await pool.query(`INSERT INTO context_bindings (org_id, context_id, scope_pattern, host_pattern)
|
|
484
484
|
VALUES ($1, $2, $3, $4)
|
|
485
485
|
ON CONFLICT DO NOTHING
|
|
486
486
|
RETURNING (xmax = 0) AS inserted`, [
|
|
@@ -495,16 +495,16 @@ async function seedEnvironmentBindingDirect(databaseUrl, opts) {
|
|
|
495
495
|
}
|
|
496
496
|
/**
|
|
497
497
|
* UPDATE only the policy fields that were explicitly provided. Columns that
|
|
498
|
-
* were NOT in `opts` are left untouched. Throws if the
|
|
498
|
+
* were NOT in `opts` are left untouched. Throws if the context is missing.
|
|
499
499
|
*/
|
|
500
|
-
async function
|
|
501
|
-
if (opts.waitTimerSeconds != null && opts.waitTimerSeconds < 0) throw new Error(`
|
|
502
|
-
if (opts.holdExpirySeconds != null && opts.holdExpirySeconds < 0) throw new Error(`
|
|
500
|
+
async function setContextPolicyDirect(databaseUrl, opts) {
|
|
501
|
+
if (opts.waitTimerSeconds != null && opts.waitTimerSeconds < 0) throw new Error(`context: waitTimerSeconds must be >= 0 (got ${opts.waitTimerSeconds})`);
|
|
502
|
+
if (opts.holdExpirySeconds != null && opts.holdExpirySeconds < 0) throw new Error(`context: holdExpirySeconds must be >= 0 (got ${opts.holdExpirySeconds})`);
|
|
503
503
|
const setClauses = [];
|
|
504
504
|
const params = [];
|
|
505
505
|
let idx = 1;
|
|
506
506
|
const addSet = (column, value, cast) => {
|
|
507
|
-
if (!ENV_POLICY_COLUMNS.has(column)) throw new Error(`
|
|
507
|
+
if (!ENV_POLICY_COLUMNS.has(column)) throw new Error(`context: unknown policy column ${column}`);
|
|
508
508
|
setClauses.push(`${column} = $${idx}${cast ? `::${cast}` : ""}`);
|
|
509
509
|
params.push(value);
|
|
510
510
|
idx += 1;
|
|
@@ -516,36 +516,36 @@ async function setEnvironmentPolicyDirect(databaseUrl, opts) {
|
|
|
516
516
|
if (opts.minimumTrust !== void 0) addSet("minimum_trust", opts.minimumTrust);
|
|
517
517
|
if (opts.enabled !== void 0) addSet("enabled", opts.enabled);
|
|
518
518
|
if (opts.allowLocalExecution !== void 0) addSet("allow_local_execution", opts.allowLocalExecution);
|
|
519
|
-
if (setClauses.length === 0) throw new Error("
|
|
519
|
+
if (setClauses.length === 0) throw new Error("context: setContextPolicy requires at least one policy field");
|
|
520
520
|
const pool = new pg.Pool({
|
|
521
521
|
connectionString: databaseUrl,
|
|
522
522
|
max: 1
|
|
523
523
|
});
|
|
524
524
|
try {
|
|
525
|
-
params.push(opts.orgId, opts.
|
|
525
|
+
params.push(opts.orgId, opts.contextName);
|
|
526
526
|
const orgParam = `$${idx}`;
|
|
527
527
|
const nameParam = `$${idx + 1}`;
|
|
528
|
-
const sql = `UPDATE
|
|
528
|
+
const sql = `UPDATE contexts
|
|
529
529
|
SET ${setClauses.join(", ")}, updated_at = now()
|
|
530
530
|
WHERE org_id = ${orgParam} AND name = ${nameParam}`;
|
|
531
|
-
if (((await pool.query(sql, params)).rowCount ?? 0) === 0) throw new Error(`
|
|
531
|
+
if (((await pool.query(sql, params)).rowCount ?? 0) === 0) throw new Error(`context: not found (org=${opts.orgId}, name=${opts.contextName})`);
|
|
532
532
|
} finally {
|
|
533
533
|
await pool.end();
|
|
534
534
|
}
|
|
535
535
|
}
|
|
536
536
|
/**
|
|
537
|
-
* SELECT * FROM
|
|
537
|
+
* SELECT * FROM contexts WHERE org_id = $1, ordered by name.
|
|
538
538
|
*/
|
|
539
|
-
async function
|
|
539
|
+
async function listContextsDirect(databaseUrl, opts) {
|
|
540
540
|
const pool = new pg.Pool({
|
|
541
541
|
connectionString: databaseUrl,
|
|
542
542
|
max: 1
|
|
543
543
|
});
|
|
544
544
|
try {
|
|
545
|
-
return {
|
|
545
|
+
return { contexts: (await pool.query(`SELECT id, org_id, name, type, enabled, branch_restrictions, required_reviewers,
|
|
546
546
|
wait_timer_seconds, hold_expiry_seconds, minimum_trust,
|
|
547
547
|
created_at, updated_at
|
|
548
|
-
FROM
|
|
548
|
+
FROM contexts
|
|
549
549
|
WHERE org_id = $1
|
|
550
550
|
ORDER BY name`, [opts.orgId])).rows };
|
|
551
551
|
} finally {
|
|
@@ -553,10 +553,10 @@ async function listEnvironmentsDirect(databaseUrl, opts) {
|
|
|
553
553
|
}
|
|
554
554
|
}
|
|
555
555
|
/**
|
|
556
|
-
* Fetch a single
|
|
557
|
-
* Throws if the
|
|
556
|
+
* Fetch a single context row joined with its variables and bindings.
|
|
557
|
+
* Throws if the context does not exist.
|
|
558
558
|
*/
|
|
559
|
-
async function
|
|
559
|
+
async function showContextDirect(databaseUrl, opts) {
|
|
560
560
|
const pool = new pg.Pool({
|
|
561
561
|
connectionString: databaseUrl,
|
|
562
562
|
max: 1
|
|
@@ -565,20 +565,20 @@ async function showEnvironmentDirect(databaseUrl, opts) {
|
|
|
565
565
|
const envResult = await pool.query(`SELECT id, org_id, name, type, enabled, branch_restrictions, required_reviewers,
|
|
566
566
|
wait_timer_seconds, hold_expiry_seconds, minimum_trust,
|
|
567
567
|
created_at, updated_at
|
|
568
|
-
FROM
|
|
568
|
+
FROM contexts
|
|
569
569
|
WHERE org_id = $1 AND name = $2`, [opts.orgId, opts.name]);
|
|
570
|
-
if (envResult.rows.length === 0) throw new Error(`
|
|
570
|
+
if (envResult.rows.length === 0) throw new Error(`context: not found (org=${opts.orgId}, name=${opts.name})`);
|
|
571
571
|
const env = envResult.rows[0];
|
|
572
572
|
const variables = await pool.query(`SELECT key, value, locked, updated_at
|
|
573
|
-
FROM
|
|
574
|
-
WHERE
|
|
573
|
+
FROM context_variables
|
|
574
|
+
WHERE context_id = $1
|
|
575
575
|
ORDER BY key`, [env.id]);
|
|
576
576
|
const bindings = await pool.query(`SELECT scope_pattern, host_pattern, created_at
|
|
577
|
-
FROM
|
|
578
|
-
WHERE
|
|
577
|
+
FROM context_bindings
|
|
578
|
+
WHERE context_id = $1
|
|
579
579
|
ORDER BY scope_pattern, host_pattern`, [env.id]);
|
|
580
580
|
return {
|
|
581
|
-
|
|
581
|
+
context: env,
|
|
582
582
|
variables: variables.rows,
|
|
583
583
|
bindings: bindings.rows
|
|
584
584
|
};
|
|
@@ -587,11 +587,11 @@ async function showEnvironmentDirect(databaseUrl, opts) {
|
|
|
587
587
|
}
|
|
588
588
|
}
|
|
589
589
|
/**
|
|
590
|
-
* Create (or update) an
|
|
591
|
-
* transaction. Templates are represented as
|
|
590
|
+
* Create (or update) an context template + its seed variables in one
|
|
591
|
+
* transaction. Templates are represented as contexts with `type='template'`
|
|
592
592
|
* by convention. Returns `{ envId, variablesSet }`.
|
|
593
593
|
*/
|
|
594
|
-
async function
|
|
594
|
+
async function createContextTemplateDirect(databaseUrl, opts) {
|
|
595
595
|
const pool = new pg.Pool({
|
|
596
596
|
connectionString: databaseUrl,
|
|
597
597
|
max: 1
|
|
@@ -599,12 +599,12 @@ async function createEnvironmentTemplateDirect(databaseUrl, opts) {
|
|
|
599
599
|
const client = await pool.connect();
|
|
600
600
|
try {
|
|
601
601
|
await client.query("BEGIN");
|
|
602
|
-
const row = (await client.query(`INSERT INTO
|
|
602
|
+
const row = (await client.query(`INSERT INTO contexts
|
|
603
603
|
(org_id, name, type, enabled, branch_restrictions, required_reviewers,
|
|
604
604
|
wait_timer_seconds, hold_expiry_seconds, minimum_trust)
|
|
605
605
|
VALUES ($1, $2, COALESCE($3, 'template'), true, $4::jsonb, $5::jsonb, $6, COALESCE($7, 86400), $8)
|
|
606
606
|
ON CONFLICT (org_id, name) DO UPDATE SET
|
|
607
|
-
type = COALESCE(EXCLUDED.type,
|
|
607
|
+
type = COALESCE(EXCLUDED.type, contexts.type),
|
|
608
608
|
branch_restrictions = EXCLUDED.branch_restrictions,
|
|
609
609
|
required_reviewers = EXCLUDED.required_reviewers,
|
|
610
610
|
wait_timer_seconds = EXCLUDED.wait_timer_seconds,
|
|
@@ -621,12 +621,12 @@ async function createEnvironmentTemplateDirect(databaseUrl, opts) {
|
|
|
621
621
|
opts.holdExpirySeconds ?? null,
|
|
622
622
|
opts.minimumTrust ?? null
|
|
623
623
|
])).rows[0];
|
|
624
|
-
if (!row) throw new Error(`
|
|
624
|
+
if (!row) throw new Error(`context: template upsert returned no row`);
|
|
625
625
|
let variablesSet = 0;
|
|
626
626
|
if (opts.variables) for (const [key, value] of Object.entries(opts.variables)) {
|
|
627
|
-
await client.query(`INSERT INTO
|
|
627
|
+
await client.query(`INSERT INTO context_variables (org_id, context_id, key, value, locked)
|
|
628
628
|
VALUES ($1, $2, $3, $4, false)
|
|
629
|
-
ON CONFLICT (org_id,
|
|
629
|
+
ON CONFLICT (org_id, context_id, key) DO UPDATE SET
|
|
630
630
|
value = EXCLUDED.value,
|
|
631
631
|
updated_at = now()`, [
|
|
632
632
|
opts.orgId,
|
|
@@ -651,14 +651,14 @@ async function createEnvironmentTemplateDirect(databaseUrl, opts) {
|
|
|
651
651
|
}
|
|
652
652
|
}
|
|
653
653
|
/**
|
|
654
|
-
* UPSERT a scoped_secrets row keyed by (org_id, scope=
|
|
654
|
+
* UPSERT a scoped_secrets row keyed by (org_id, scope=context, key).
|
|
655
655
|
* Writes the value verbatim — the caller is responsible for encryption
|
|
656
656
|
* (matches the stage-4 deferral noted in the plan).
|
|
657
657
|
*/
|
|
658
|
-
async function
|
|
659
|
-
if (!opts.orgId) throw new Error("
|
|
660
|
-
if (!opts.
|
|
661
|
-
if (!opts.key) throw new Error("
|
|
658
|
+
async function setContextSecretDirect(databaseUrl, opts) {
|
|
659
|
+
if (!opts.orgId) throw new Error("context: orgId required");
|
|
660
|
+
if (!opts.context) throw new Error("context: context name required");
|
|
661
|
+
if (!opts.key) throw new Error("context: key required");
|
|
662
662
|
const pool = new pg.Pool({
|
|
663
663
|
connectionString: databaseUrl,
|
|
664
664
|
max: 1
|
|
@@ -671,7 +671,7 @@ async function setEnvironmentSecretDirect(databaseUrl, opts) {
|
|
|
671
671
|
updated_at = now()
|
|
672
672
|
RETURNING (xmax = 0) AS inserted`, [
|
|
673
673
|
opts.orgId,
|
|
674
|
-
opts.
|
|
674
|
+
opts.context,
|
|
675
675
|
opts.key,
|
|
676
676
|
opts.encryptedValue
|
|
677
677
|
])).rows[0]?.inserted ?? false };
|
|
@@ -789,7 +789,7 @@ async function listExecutionRunsDirect(databaseUrl, opts = {}) {
|
|
|
789
789
|
const limit = Math.max(1, Math.min(1e3, opts.limit ?? 100));
|
|
790
790
|
const where = clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : "";
|
|
791
791
|
return { runs: (await pool.query(`SELECT id, run_id, workflow_name, status, provider, repo_identifier,
|
|
792
|
-
ref, sha, routing_key,
|
|
792
|
+
ref, sha, routing_key, context, trust_tier, created_at,
|
|
793
793
|
started_at, completed_at, duration_ms
|
|
794
794
|
FROM execution_runs
|
|
795
795
|
${where}
|
|
@@ -807,7 +807,7 @@ async function showExecutionRunDirect(databaseUrl, opts) {
|
|
|
807
807
|
const pool = createPool(databaseUrl);
|
|
808
808
|
try {
|
|
809
809
|
const runResult = await pool.query(`SELECT id, run_id, workflow_name, status, provider, repo_identifier,
|
|
810
|
-
ref, sha, routing_key,
|
|
810
|
+
ref, sha, routing_key, context, trust_tier, created_at,
|
|
811
811
|
started_at, completed_at, duration_ms
|
|
812
812
|
FROM execution_runs
|
|
813
813
|
WHERE run_id = $1`, [opts.runId]);
|
|
@@ -816,7 +816,7 @@ async function showExecutionRunDirect(databaseUrl, opts) {
|
|
|
816
816
|
return {
|
|
817
817
|
run,
|
|
818
818
|
jobs: (await pool.query(`SELECT id, run_id, job_id, job_name, status, agent_id,
|
|
819
|
-
started_at, completed_at, duration_ms, created_at, error_message,
|
|
819
|
+
started_at, completed_at, duration_ms, created_at, error_message, contexts
|
|
820
820
|
FROM execution_jobs
|
|
821
821
|
WHERE run_id = $1
|
|
822
822
|
ORDER BY created_at ASC`, [run.run_id])).rows
|
|
@@ -834,7 +834,7 @@ async function listExecutionJobsDirect(databaseUrl, opts) {
|
|
|
834
834
|
try {
|
|
835
835
|
return { jobs: (await pool.query(`SELECT j.id, j.run_id, j.job_id, j.job_name, j.status, j.agent_id,
|
|
836
836
|
j.started_at, j.completed_at, j.duration_ms, j.created_at, j.error_message,
|
|
837
|
-
j.
|
|
837
|
+
j.contexts
|
|
838
838
|
FROM execution_jobs j
|
|
839
839
|
INNER JOIN execution_runs r ON r.run_id = j.run_id
|
|
840
840
|
WHERE r.run_id::text = $1 OR r.id::text = $1
|
|
@@ -1649,7 +1649,7 @@ async function seedUniversalGitSourceDirect(databaseUrl, opts) {
|
|
|
1649
1649
|
}
|
|
1650
1650
|
}
|
|
1651
1651
|
async function seedCiSecurityFixturesDirect(databaseUrl, opts) {
|
|
1652
|
-
const
|
|
1652
|
+
const contextName = opts.contextName ?? "ci-security-env";
|
|
1653
1653
|
const sourceName = opts.sourceName ?? "ci-security-dashboard-resolver";
|
|
1654
1654
|
const sourceRoutingKey = opts.sourceRoutingKey ?? `generic:${opts.orgId}:ci-security-dashboard`;
|
|
1655
1655
|
const pool = createPool(databaseUrl);
|
|
@@ -1661,10 +1661,10 @@ async function seedCiSecurityFixturesDirect(databaseUrl, opts) {
|
|
|
1661
1661
|
sourceRoutingKey,
|
|
1662
1662
|
opts.orgId
|
|
1663
1663
|
]);
|
|
1664
|
-
const envId = (await pool.query(`INSERT INTO
|
|
1664
|
+
const envId = (await pool.query(`INSERT INTO contexts (org_id, name, type, enabled)
|
|
1665
1665
|
VALUES ($1, $2, \'fixed\', true)
|
|
1666
1666
|
ON CONFLICT (org_id, name) DO UPDATE SET enabled = true
|
|
1667
|
-
RETURNING id`, [opts.orgId,
|
|
1667
|
+
RETURNING id`, [opts.orgId, contextName])).rows[0].id;
|
|
1668
1668
|
await pool.query(`INSERT INTO execution_runs (
|
|
1669
1669
|
run_id, workflow_name, provider, repo_identifier,
|
|
1670
1670
|
ref, sha, delivery_id, status, trust_tier, lock_file_source,
|
|
@@ -1677,7 +1677,7 @@ async function seedCiSecurityFixturesDirect(databaseUrl, opts) {
|
|
|
1677
1677
|
]);
|
|
1678
1678
|
await pool.query(`INSERT INTO execution_jobs (job_id, run_id, job_name, status)
|
|
1679
1679
|
VALUES ($1, $2, \'security-test-job\', \'pending\')`, [opts.unknownJobId, opts.unknownRunId]);
|
|
1680
|
-
const heldRunId = (await pool.query(`INSERT INTO held_runs (org_id, run_id, job_id,
|
|
1680
|
+
const heldRunId = (await pool.query(`INSERT INTO held_runs (org_id, run_id, job_id, context_id, hold_type, queue_type, reason, expires_at)
|
|
1681
1681
|
VALUES ($1, $2, $3, $4, \'unknown_contributor\', \'security\',
|
|
1682
1682
|
\'Unknown contributor requires approval\', NOW() + INTERVAL \'72 hours\')
|
|
1683
1683
|
RETURNING id`, [
|
|
@@ -2754,6 +2754,6 @@ async function terminateIdleDbBackendsDirect(databaseUrl) {
|
|
|
2754
2754
|
}
|
|
2755
2755
|
}
|
|
2756
2756
|
//#endregion
|
|
2757
|
-
export { MIGRATION_HASH_TABLE, PROVIDER_HASH_KEY, REGISTERABLE_TRIGGER_TYPES, apiKeyExistsDirect, bumpRegistryVersionDirect, bumpRegistryVersionSimpleDirect, cleanupExecutionRowsDirect, clearDispatchQueueDirect, clearPeerCredentialsRevokedAtByIdsDirect, computeMigrationsHash, countActivePeerCredentialsByInstanceDirect, countCronLastFiredDirect, countHeldRunsByRunIdDirect, countWebhookSourcesByConnectionIdDirect,
|
|
2757
|
+
export { MIGRATION_HASH_TABLE, PROVIDER_HASH_KEY, REGISTERABLE_TRIGGER_TYPES, apiKeyExistsDirect, bumpRegistryVersionDirect, bumpRegistryVersionSimpleDirect, cleanupExecutionRowsDirect, clearDispatchQueueDirect, clearPeerCredentialsRevokedAtByIdsDirect, computeMigrationsHash, countActivePeerCredentialsByInstanceDirect, countCronLastFiredDirect, countHeldRunsByRunIdDirect, countWebhookSourcesByConnectionIdDirect, createContextTemplateDirect, createDbRole, createJoinTokenDirect, createReadOnlyDbUser, deleteContextDirect, deleteCronLastFiredDirect, deleteCrossRepoTrustDirect, deleteExecutionRunsByWorkflowNameDirect, deleteGenericWebhookSourcesByNameDirect, deleteJoinTokensByCreatedByDirect, deleteKiciEventsDirect, deleteOrgSettingsByCustomerIdDirect, deletePeerCredentialsByInstanceIdLikeDirect, deleteWorkflowRegistrationsDirect, describeTableColumnsDirect, dropAndCreateDatabase, dropDatabaseDirect, emitKiciEventDirect, ensureDatabase, ensureOrgOwnerMemberDirect, findAnyUserApiKeyIdDirect, getExecutionRunSecurityDirect, getGenericWebhookSourceByRoutingKeyDirect, getHeldRunByIdDirect, getPeerCredentialRevokedAtDirect, getRegistryVersionDirect, getWebhookSourceByRoutingKeyDirect, getWorkflowRegistrationByIdDirect, insertCronLastFiredNowDirect, insertCrossRepoTrustStrictDirect, insertKiciEventAtDirect, insertKiciEventRawDirect, insertPeerCredentialExpiredDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, isSchemaCurrent, isSchemaCurrentFromFilesDirect, latestExecutionRunByStatusDirect, listActiveGenericWebhookSourcesDirect, listActivePeerCredentialsExcludingDirect, listContextsDirect, listCrossRepoTrustBySourceRoutingKeyDirect, listExecutionJobsDirect, listExecutionRunsDirect, listHeldRunApprovalsDirect, listKiciEventsDirect, listQueueDirect, listRegistrationsByRoutingKeyDirect, listRegistrationsDirect, maskDatabaseUrl, paginateUnprocessedEventsKeysetDirect, parseDatabaseUrl, platformConnectionExistsDirect, pollKiciEventsDirect, prunePeerCredentialsDirect, purgeContextsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, readStoredMigrationContentHash, registerWorkflowManualDirect, resetRaftStateDirect, resolvePlatformWebhookSourceRoutingKeyDirect, restoreSoftDeletedGenericWebhookSourceDirect, seedApiKeyInlineDirect, seedCiSecurityFixturesDirect, seedContextBindingDirect, seedContextDirect, seedCrossRepoTrustDirect, seedGenericWebhookSourceDirect, seedSourcePrivateKeyDirect, seedSyntheticGithubSourceDirect, seedUniversalGitSourceDirect, seedWebhookSecretDirect, setContextPolicyDirect, setContextSecretDirect, showContextDirect, showExecutionRunDirect, showKiciEventDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, storeMigrationContentHashInTableDirect, tableExistsDirect, terminateIdleDbBackendsDirect, updateGenericWebhookVerificationConfigDirect, updateOrgSettingsDeniedReposDirect, updateSourceRoutingKeyDirect, updateWorkflowRegistrationCommitShaDirect, upsertCronLastFiredDirect, upsertOrgSettingsGlobalWorkflowsDirect, verifyKiciEventNotifyDirect, waitForEventLogRowByDeliveryIdDirect, waitForExecutionRunStatusSinceDirect, waitForLatestExecutionJobStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformRegistrationsDirect, waitForPostgresDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, waitForRunCompletionDirect };
|
|
2758
2758
|
|
|
2759
2759
|
//# sourceMappingURL=db-admin.js.map
|
package/dist/db-collation.d.ts
CHANGED
|
@@ -57,4 +57,53 @@ export declare function reindexDatabaseConcurrently(pool: pg.Pool, dbName: strin
|
|
|
57
57
|
* Metadata-only; safe to run any time after a REINDEX has rebuilt the indexes.
|
|
58
58
|
*/
|
|
59
59
|
export declare function refreshDatabaseCollationVersion(pool: pg.Pool, dbName: string): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* The two-step operator remediation for collation drift on `dbName`, as a
|
|
62
|
+
* single copy-pasteable string. Surfaced in the startup ERROR line and the
|
|
63
|
+
* hard-fail message so an operator sees exactly what to run.
|
|
64
|
+
*/
|
|
65
|
+
export declare function collationDriftRemediation(dbName: string): string;
|
|
66
|
+
/**
|
|
67
|
+
* Minimal structural logger the startup check needs. `winston.Logger`
|
|
68
|
+
* satisfies it, so both the orchestrator and Platform pass their own logger
|
|
69
|
+
* without a shared winston dependency here.
|
|
70
|
+
*/
|
|
71
|
+
export interface CollationDriftStartupLogger {
|
|
72
|
+
info(message: string, meta?: Record<string, unknown>): void;
|
|
73
|
+
warn(message: string, meta?: Record<string, unknown>): void;
|
|
74
|
+
error(message: string, meta?: Record<string, unknown>): void;
|
|
75
|
+
}
|
|
76
|
+
/** Env var name that turns a detected drift into a startup refusal. */
|
|
77
|
+
export declare const FAIL_ON_COLLATION_DRIFT_ENV = "KICI_DB_FAIL_ON_COLLATION_DRIFT";
|
|
78
|
+
/**
|
|
79
|
+
* Read the opt-in hard-fail toggle from an environment map. When set to
|
|
80
|
+
* `true`, {@link checkCollationDriftAtStartup} throws on detected drift instead
|
|
81
|
+
* of logging and continuing. Defaults to off (detect + warn loudly).
|
|
82
|
+
*/
|
|
83
|
+
export declare function shouldFailOnCollationDrift(env: NodeJS.ProcessEnv): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Boot-time collation-drift guard shared by the orchestrator and Platform.
|
|
86
|
+
*
|
|
87
|
+
* Runs {@link getDatabaseCollationDrift} after the DB connection + migrations
|
|
88
|
+
* are up and before the service starts serving. Behavior:
|
|
89
|
+
*
|
|
90
|
+
* - **No drift** → logs one info line and returns `null`.
|
|
91
|
+
* - **Drift** → logs a single loud, structured ERROR line naming the database,
|
|
92
|
+
* the recorded-vs-actual collation versions, the exact remediation command,
|
|
93
|
+
* and the risk (text index lookups may silently miss present rows — the
|
|
94
|
+
* failure mode that read a present source private key back as absent). Does
|
|
95
|
+
* NOT crash by default; a drifted DB still serves most traffic and crashing
|
|
96
|
+
* every node is worse than a loud, alertable warning. Returns the drift.
|
|
97
|
+
* - **`failOnDrift: true`** (opt-in via {@link FAIL_ON_COLLATION_DRIFT_ENV})
|
|
98
|
+
* → throws after logging, so strict operators can refuse to boot on drift.
|
|
99
|
+
* - **Probe failure** (the query itself throws) → logs a WARN and returns
|
|
100
|
+
* `null`. A probe bug must never take down every node; unconfirmed drift is
|
|
101
|
+
* not a reason to crash, and `failOnDrift` gates confirmed drift only.
|
|
102
|
+
*
|
|
103
|
+
* The caller is responsible for reflecting the result into its
|
|
104
|
+
* `kici_db_collation_drift{database=…}` gauge (1 on drift, 0 clean).
|
|
105
|
+
*/
|
|
106
|
+
export declare function checkCollationDriftAtStartup(pool: pg.Pool, dbName: string, logger: CollationDriftStartupLogger, options?: {
|
|
107
|
+
failOnDrift?: boolean;
|
|
108
|
+
}): Promise<CollationDrift | null>;
|
|
60
109
|
//# sourceMappingURL=db-collation.d.ts.map
|
package/dist/db-collation.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import "./rolldown-runtime-ClRpJifh.js";
|
|
2
2
|
import pg from "pg";
|
|
3
|
+
import { toErrorMessage } from "@kici-dev/core";
|
|
3
4
|
//#region src/db-collation.ts
|
|
4
5
|
/**
|
|
5
6
|
* Read `pg_database.datcollversion` and
|
|
@@ -46,7 +47,73 @@ async function refreshDatabaseCollationVersion(pool, dbName) {
|
|
|
46
47
|
const quoted = pg.escapeIdentifier(dbName);
|
|
47
48
|
await pool.query(`ALTER DATABASE ${quoted} REFRESH COLLATION VERSION`);
|
|
48
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* The two-step operator remediation for collation drift on `dbName`, as a
|
|
52
|
+
* single copy-pasteable string. Surfaced in the startup ERROR line and the
|
|
53
|
+
* hard-fail message so an operator sees exactly what to run.
|
|
54
|
+
*/
|
|
55
|
+
function collationDriftRemediation(dbName) {
|
|
56
|
+
const quoted = pg.escapeIdentifier(dbName);
|
|
57
|
+
return `REINDEX DATABASE CONCURRENTLY ${quoted}; ALTER DATABASE ${quoted} REFRESH COLLATION VERSION;`;
|
|
58
|
+
}
|
|
59
|
+
/** Env var name that turns a detected drift into a startup refusal. */
|
|
60
|
+
const FAIL_ON_COLLATION_DRIFT_ENV = "KICI_DB_FAIL_ON_COLLATION_DRIFT";
|
|
61
|
+
/**
|
|
62
|
+
* Read the opt-in hard-fail toggle from an environment map. When set to
|
|
63
|
+
* `true`, {@link checkCollationDriftAtStartup} throws on detected drift instead
|
|
64
|
+
* of logging and continuing. Defaults to off (detect + warn loudly).
|
|
65
|
+
*/
|
|
66
|
+
function shouldFailOnCollationDrift(env) {
|
|
67
|
+
return env[FAIL_ON_COLLATION_DRIFT_ENV] === "true";
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Boot-time collation-drift guard shared by the orchestrator and Platform.
|
|
71
|
+
*
|
|
72
|
+
* Runs {@link getDatabaseCollationDrift} after the DB connection + migrations
|
|
73
|
+
* are up and before the service starts serving. Behavior:
|
|
74
|
+
*
|
|
75
|
+
* - **No drift** → logs one info line and returns `null`.
|
|
76
|
+
* - **Drift** → logs a single loud, structured ERROR line naming the database,
|
|
77
|
+
* the recorded-vs-actual collation versions, the exact remediation command,
|
|
78
|
+
* and the risk (text index lookups may silently miss present rows — the
|
|
79
|
+
* failure mode that read a present source private key back as absent). Does
|
|
80
|
+
* NOT crash by default; a drifted DB still serves most traffic and crashing
|
|
81
|
+
* every node is worse than a loud, alertable warning. Returns the drift.
|
|
82
|
+
* - **`failOnDrift: true`** (opt-in via {@link FAIL_ON_COLLATION_DRIFT_ENV})
|
|
83
|
+
* → throws after logging, so strict operators can refuse to boot on drift.
|
|
84
|
+
* - **Probe failure** (the query itself throws) → logs a WARN and returns
|
|
85
|
+
* `null`. A probe bug must never take down every node; unconfirmed drift is
|
|
86
|
+
* not a reason to crash, and `failOnDrift` gates confirmed drift only.
|
|
87
|
+
*
|
|
88
|
+
* The caller is responsible for reflecting the result into its
|
|
89
|
+
* `kici_db_collation_drift{database=…}` gauge (1 on drift, 0 clean).
|
|
90
|
+
*/
|
|
91
|
+
async function checkCollationDriftAtStartup(pool, dbName, logger, options = {}) {
|
|
92
|
+
let drift;
|
|
93
|
+
try {
|
|
94
|
+
drift = await getDatabaseCollationDrift(pool, dbName);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
logger.warn("Collation-drift startup probe failed; skipping drift check", {
|
|
97
|
+
database: dbName,
|
|
98
|
+
error: toErrorMessage(err)
|
|
99
|
+
});
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
if (!drift) {
|
|
103
|
+
logger.info("Database collation version is consistent", { database: dbName });
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
logger.error("Database collation drift detected — text-column b-tree indexes may silently miss present rows (e.g. secrets/sources reads reporting present rows as missing). Repair with the remediation below.", {
|
|
107
|
+
database: dbName,
|
|
108
|
+
stampedCollationVersion: drift.stamped,
|
|
109
|
+
actualCollationVersion: drift.actual,
|
|
110
|
+
remediation: collationDriftRemediation(dbName),
|
|
111
|
+
risk: "corrupted-text-btree-index"
|
|
112
|
+
});
|
|
113
|
+
if (options.failOnDrift) throw new Error(`Database "${dbName}" has collation drift (stamped=${drift.stamped}, actual=${drift.actual}) and ${FAIL_ON_COLLATION_DRIFT_ENV} is set. Remediate: ${collationDriftRemediation(dbName)}`);
|
|
114
|
+
return drift;
|
|
115
|
+
}
|
|
49
116
|
//#endregion
|
|
50
|
-
export { getDatabaseCollationDrift, refreshDatabaseCollationVersion, reindexDatabaseConcurrently };
|
|
117
|
+
export { FAIL_ON_COLLATION_DRIFT_ENV, checkCollationDriftAtStartup, collationDriftRemediation, getDatabaseCollationDrift, refreshDatabaseCollationVersion, reindexDatabaseConcurrently, shouldFailOnCollationDrift };
|
|
51
118
|
|
|
52
119
|
//# sourceMappingURL=db-collation.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { redactConfig, addLogsToArchive, MAX_LOG_BYTES } from './diagnostics/bun
|
|
|
5
5
|
export { chunkBuffer, BundleChunkAssembler, ChunkRequestWaiter, FLEET_CHUNK_BYTES, type BundleChunkFrame, } from './diagnostics/bundle-chunks.js';
|
|
6
6
|
export { createPool, createDb, type CreatePoolOptions, type PgPoolErrorSource } from './db.js';
|
|
7
7
|
export { isPgUniqueViolation } from './pg-errors.js';
|
|
8
|
-
export { parseDatabaseUrl, maskDatabaseUrl, dropAndCreateDatabase, dropDatabaseDirect, ensureDatabase, type EnsureDatabaseOpts, createDbRole, createReadOnlyDbUser, computeMigrationsHash, storeMigrationContentHash, readStoredMigrationContentHash, isSchemaCurrent, clearDispatchQueueDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, purgeScopedSecretsDirect,
|
|
8
|
+
export { parseDatabaseUrl, maskDatabaseUrl, dropAndCreateDatabase, dropDatabaseDirect, ensureDatabase, type EnsureDatabaseOpts, createDbRole, createReadOnlyDbUser, computeMigrationsHash, storeMigrationContentHash, readStoredMigrationContentHash, isSchemaCurrent, clearDispatchQueueDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, purgeScopedSecretsDirect, purgeContextsDirect, seedContextDirect, deleteContextDirect, seedContextBindingDirect, setContextPolicyDirect, listContextsDirect, showContextDirect, createContextTemplateDirect, setContextSecretDirect, listQueueDirect, showQueueEntryDirect, listExecutionRunsDirect, showExecutionRunDirect, listExecutionJobsDirect, listRegistrationsDirect, showRegistrationDirect, registerWorkflowManualDirect, resetRaftStateDirect, emitKiciEventDirect, seedGenericWebhookSourceDirect, purgeSecretBackendsDirect, apiKeyExistsDirect, seedApiKeyInlineDirect, platformConnectionExistsDirect, countWebhookSourcesByConnectionIdDirect, getWebhookSourceByRoutingKeyDirect, findAnyUserApiKeyIdDirect, seedSyntheticGithubSourceDirect, seedWebhookSecretDirect, seedSourcePrivateKeyDirect, bumpRegistryVersionDirect, pollKiciEventsDirect, waitForPostgresDirect, waitForRunCompletionDirect, cleanupExecutionRowsDirect, isSchemaCurrentFromFilesDirect, storeMigrationContentHashInTableDirect, createJoinTokenDirect, deleteJoinTokensByCreatedByDirect, updateSourceRoutingKeyDirect, prunePeerCredentialsDirect, waitForPlatformRegistrationsDirect, seedUniversalGitSourceDirect, seedCiSecurityFixturesDirect, waitForExecutionRunStatusSinceDirect, latestExecutionRunByStatusDirect, waitForLatestExecutionJobStatusDirect, describeTableColumnsDirect, tableExistsDirect, insertKiciEventRawDirect, showKiciEventDirect, listKiciEventsDirect, deleteKiciEventsDirect, insertKiciEventAtDirect, paginateUnprocessedEventsKeysetDirect, verifyKiciEventNotifyDirect, seedCrossRepoTrustDirect, listCrossRepoTrustBySourceRoutingKeyDirect, deleteCrossRepoTrustDirect, insertCrossRepoTrustStrictDirect, deleteWorkflowRegistrationsDirect, getWorkflowRegistrationByIdDirect, listRegistrationsByRoutingKeyDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, updateWorkflowRegistrationCommitShaDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, getRegistryVersionDirect, bumpRegistryVersionSimpleDirect, upsertCronLastFiredDirect, countCronLastFiredDirect, insertCronLastFiredNowDirect, deleteCronLastFiredDirect, deleteExecutionRunsByWorkflowNameDirect, getGenericWebhookSourceByRoutingKeyDirect, listActiveGenericWebhookSourcesDirect, updateGenericWebhookVerificationConfigDirect, deleteGenericWebhookSourcesByNameDirect, restoreSoftDeletedGenericWebhookSourceDirect, upsertOrgSettingsGlobalWorkflowsDirect, updateOrgSettingsDeniedReposDirect, deleteOrgSettingsByCustomerIdDirect, getExecutionRunSecurityDirect, getHeldRunByIdDirect, listHeldRunApprovalsDirect, countHeldRunsByRunIdDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForEventLogRowByDeliveryIdDirect, resolvePlatformWebhookSourceRoutingKeyDirect, ensureOrgOwnerMemberDirect, deletePeerCredentialsByInstanceIdLikeDirect, insertPeerCredentialExpiredDirect, getPeerCredentialRevokedAtDirect, listActivePeerCredentialsExcludingDirect, clearPeerCredentialsRevokedAtByIdsDirect, countActivePeerCredentialsByInstanceDirect, terminateIdleDbBackendsDirect, type ColumnInfo, type KiciEventRow, type CrossRepoTrustRow, type WorkflowRegistrationFullRow, type RegistrationsScopedResult, type LatestExecutionRunResult, type WaitForLatestJobResult, type ExecutionRunSecurityRow, type HeldRunSecurityRow, type EventLogRow as PlatformEventLogRow, type UpsertOrgSettingsOpts, type OrgSettingsRepoPatternEntry, type InsertKiciEventRawOpts, type EmitKiciEventOpts, type SeedGenericWebhookSourceOpts, REGISTERABLE_TRIGGER_TYPES, MIGRATION_HASH_TABLE, type PurgeStaleExecutionResult, type PurgeStaleSourcesResult, type SeedContextOpts, type SeedContextResult, type SeedContextBindingOpts, type SetContextPolicyOpts, type ContextRow, type ContextVariableRow, type ContextBindingRow, type ShowContextResult, type CreateContextTemplateOpts, type SetContextSecretOpts, type DispatchQueueRow, type ListQueueOpts, type ExecutionRunRow, type ExecutionJobRow, type ListExecutionRunsOpts, type WorkflowRegistrationRow, type ListRegistrationsOpts, type ListRegistrationsResult, type ShowRegistrationResult, type RegisterWorkflowManualOpts, type RegisterWorkflowManualResult, } from './db-admin.js';
|
|
9
9
|
export { createMetricsRoutes, type MetricsRoutesDeps } from './routes/metrics.js';
|
|
10
10
|
export { createHealthRoutes, type HealthRoutesDeps } from './routes/health.js';
|
|
11
11
|
export { getReconnectDelay } from './reconnect-delay.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./rolldown-runtime-ClRpJifh.js";
|
|
2
2
|
import { createDb, createPool } from "./db.js";
|
|
3
|
-
import { MIGRATION_HASH_TABLE, REGISTERABLE_TRIGGER_TYPES, apiKeyExistsDirect, bumpRegistryVersionDirect, bumpRegistryVersionSimpleDirect, cleanupExecutionRowsDirect, clearDispatchQueueDirect, clearPeerCredentialsRevokedAtByIdsDirect, computeMigrationsHash, countActivePeerCredentialsByInstanceDirect, countCronLastFiredDirect, countHeldRunsByRunIdDirect, countWebhookSourcesByConnectionIdDirect,
|
|
3
|
+
import { MIGRATION_HASH_TABLE, REGISTERABLE_TRIGGER_TYPES, apiKeyExistsDirect, bumpRegistryVersionDirect, bumpRegistryVersionSimpleDirect, cleanupExecutionRowsDirect, clearDispatchQueueDirect, clearPeerCredentialsRevokedAtByIdsDirect, computeMigrationsHash, countActivePeerCredentialsByInstanceDirect, countCronLastFiredDirect, countHeldRunsByRunIdDirect, countWebhookSourcesByConnectionIdDirect, createContextTemplateDirect, createDbRole, createJoinTokenDirect, createReadOnlyDbUser, deleteContextDirect, deleteCronLastFiredDirect, deleteCrossRepoTrustDirect, deleteExecutionRunsByWorkflowNameDirect, deleteGenericWebhookSourcesByNameDirect, deleteJoinTokensByCreatedByDirect, deleteKiciEventsDirect, deleteOrgSettingsByCustomerIdDirect, deletePeerCredentialsByInstanceIdLikeDirect, deleteWorkflowRegistrationsDirect, describeTableColumnsDirect, dropAndCreateDatabase, dropDatabaseDirect, emitKiciEventDirect, ensureDatabase, ensureOrgOwnerMemberDirect, findAnyUserApiKeyIdDirect, getExecutionRunSecurityDirect, getGenericWebhookSourceByRoutingKeyDirect, getHeldRunByIdDirect, getPeerCredentialRevokedAtDirect, getRegistryVersionDirect, getWebhookSourceByRoutingKeyDirect, getWorkflowRegistrationByIdDirect, insertCronLastFiredNowDirect, insertCrossRepoTrustStrictDirect, insertKiciEventAtDirect, insertKiciEventRawDirect, insertPeerCredentialExpiredDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, isSchemaCurrent, isSchemaCurrentFromFilesDirect, latestExecutionRunByStatusDirect, listActiveGenericWebhookSourcesDirect, listActivePeerCredentialsExcludingDirect, listContextsDirect, listCrossRepoTrustBySourceRoutingKeyDirect, listExecutionJobsDirect, listExecutionRunsDirect, listHeldRunApprovalsDirect, listKiciEventsDirect, listQueueDirect, listRegistrationsByRoutingKeyDirect, listRegistrationsDirect, maskDatabaseUrl, paginateUnprocessedEventsKeysetDirect, parseDatabaseUrl, platformConnectionExistsDirect, pollKiciEventsDirect, prunePeerCredentialsDirect, purgeContextsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, readStoredMigrationContentHash, registerWorkflowManualDirect, resetRaftStateDirect, resolvePlatformWebhookSourceRoutingKeyDirect, restoreSoftDeletedGenericWebhookSourceDirect, seedApiKeyInlineDirect, seedCiSecurityFixturesDirect, seedContextBindingDirect, seedContextDirect, seedCrossRepoTrustDirect, seedGenericWebhookSourceDirect, seedSourcePrivateKeyDirect, seedSyntheticGithubSourceDirect, seedUniversalGitSourceDirect, seedWebhookSecretDirect, setContextPolicyDirect, setContextSecretDirect, showContextDirect, showExecutionRunDirect, showKiciEventDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, storeMigrationContentHashInTableDirect, tableExistsDirect, terminateIdleDbBackendsDirect, updateGenericWebhookVerificationConfigDirect, updateOrgSettingsDeniedReposDirect, updateSourceRoutingKeyDirect, updateWorkflowRegistrationCommitShaDirect, upsertCronLastFiredDirect, upsertOrgSettingsGlobalWorkflowsDirect, verifyKiciEventNotifyDirect, waitForEventLogRowByDeliveryIdDirect, waitForExecutionRunStatusSinceDirect, waitForLatestExecutionJobStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformRegistrationsDirect, waitForPostgresDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, waitForRunCompletionDirect } from "./db-admin.js";
|
|
4
4
|
import { setupGracefulShutdown } from "./graceful-shutdown.js";
|
|
5
5
|
import { decrypt, deriveKey, encrypt, generateMasterKey } from "./secret-crypto.js";
|
|
6
6
|
import { RingBuffer } from "./ring-buffer.js";
|
|
@@ -26,4 +26,4 @@ import { ChunkLru } from "./cold-store/lru.js";
|
|
|
26
26
|
import { DEFAULT_TABLE_CONFIG, resolveTableConfig } from "./cold-store/config.js";
|
|
27
27
|
import "./cold-store/index.js";
|
|
28
28
|
export * from "@kici-dev/core";
|
|
29
|
-
export { BaseColdStore, BundleChunkAssembler, COLD_BUCKET_NAMES, ChunkLru, ChunkRequestWaiter, DEFAULT_TABLE_CONFIG, FLEET_CHUNK_BYTES, MAX_LOG_BYTES, MIGRATION_HASH_TABLE, REGISTERABLE_TRIGGER_TYPES, RingBuffer, addLogsToArchive, apiKeyExistsDirect, bumpRegistryVersionDirect, bumpRegistryVersionSimpleDirect, chunkBuffer, chunkObjectKey, cleanupExecutionRowsDirect, clearDispatchQueueDirect, clearPeerCredentialsRevokedAtByIdsDirect, coldDaysToBucket, coldStoreArchiveBytesTotal, coldStoreArchiveCyclesTotal, coldStoreArchiveDurationSeconds, coldStoreArchiveRowsTotal, coldStorePurgeBytesTotal, coldStorePurgeChunksTotal, coldStorePurgeDurationSeconds, coldStoreRehydrateBytesTotal, coldStoreRehydrateDurationSeconds, coldStoreRehydrateRequestsTotal, coldStoreReplayDurationSeconds, coldStoreReplayRowsTotal, coldStoreVerifyFailuresTotal, collectRuntimeMetricNames, computeChunkId, computeMigrationsHash, countActivePeerCredentialsByInstanceDirect, countCronLastFiredDirect, countHeldRunsByRunIdDirect, countWebhookSourcesByConnectionIdDirect, createDb, createDbRole,
|
|
29
|
+
export { BaseColdStore, BundleChunkAssembler, COLD_BUCKET_NAMES, ChunkLru, ChunkRequestWaiter, DEFAULT_TABLE_CONFIG, FLEET_CHUNK_BYTES, MAX_LOG_BYTES, MIGRATION_HASH_TABLE, REGISTERABLE_TRIGGER_TYPES, RingBuffer, addLogsToArchive, apiKeyExistsDirect, bumpRegistryVersionDirect, bumpRegistryVersionSimpleDirect, chunkBuffer, chunkObjectKey, cleanupExecutionRowsDirect, clearDispatchQueueDirect, clearPeerCredentialsRevokedAtByIdsDirect, coldDaysToBucket, coldStoreArchiveBytesTotal, coldStoreArchiveCyclesTotal, coldStoreArchiveDurationSeconds, coldStoreArchiveRowsTotal, coldStorePurgeBytesTotal, coldStorePurgeChunksTotal, coldStorePurgeDurationSeconds, coldStoreRehydrateBytesTotal, coldStoreRehydrateDurationSeconds, coldStoreRehydrateRequestsTotal, coldStoreReplayDurationSeconds, coldStoreReplayRowsTotal, coldStoreVerifyFailuresTotal, collectRuntimeMetricNames, computeChunkId, computeMigrationsHash, countActivePeerCredentialsByInstanceDirect, countCronLastFiredDirect, countHeldRunsByRunIdDirect, countWebhookSourcesByConnectionIdDirect, createContextTemplateDirect, createDb, createDbRole, createHealthRoutes, createJoinTokenDirect, createMeter, createMetricsRoutes, createPool, createReadOnlyDbUser, createS3Client, decodeChunk, decrypt, deleteContextDirect, deleteCronLastFiredDirect, deleteCrossRepoTrustDirect, deleteExecutionRunsByWorkflowNameDirect, deleteGenericWebhookSourcesByNameDirect, deleteJoinTokensByCreatedByDirect, deleteKiciEventsDirect, deleteOrgSettingsByCustomerIdDirect, deletePeerCredentialsByInstanceIdLikeDirect, deleteWorkflowRegistrationsDirect, deriveKey, describeTableColumnsDirect, dropAndCreateDatabase, dropDatabaseDirect, emitKiciEventDirect, encodeChunk, encodeKeySegment, encrypt, ensureDatabase, ensureOrgOwnerMemberDirect, findAnyUserApiKeyIdDirect, generateMasterKey, getExecutionRunSecurityDirect, getGenericWebhookSourceByRoutingKeyDirect, getHeldRunByIdDirect, getPeerCredentialRevokedAtDirect, getPrometheusExporter, getReconnectDelay, getRegistryVersionDirect, getWebhookSourceByRoutingKeyDirect, getWorkflowRegistrationByIdDirect, initTelemetry, insertCronLastFiredNowDirect, insertCrossRepoTrustStrictDirect, insertKiciEventAtDirect, insertKiciEventRawDirect, insertPeerCredentialExpiredDirect, insertWorkflowRegistrationRawDirect, insertWorkflowRegistrationStrictDirect, isLongerColdRetention, isPgUniqueViolation, isSchemaCurrent, isSchemaCurrentFromFilesDirect, latestExecutionRunByStatusDirect, listActiveGenericWebhookSourcesDirect, listActivePeerCredentialsExcludingDirect, listContextsDirect, listCrossRepoTrustBySourceRoutingKeyDirect, listExecutionJobsDirect, listExecutionRunsDirect, listHeldRunApprovalsDirect, listKiciEventsDirect, listQueueDirect, listRegistrationsByRoutingKeyDirect, listRegistrationsDirect, maskDatabaseUrl, paginateUnprocessedEventsKeysetDirect, parseDatabaseUrl, parseManifest, platformConnectionExistsDirect, pollKiciEventsDirect, prunePeerCredentialsDirect, purgeContextsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, readStoredMigrationContentHash, redactConfig, registerWorkflowManualDirect, resetRaftStateDirect, resolvePlatformWebhookSourceRoutingKeyDirect, resolveTableConfig, restoreSoftDeletedGenericWebhookSourceDirect, seedApiKeyInlineDirect, seedCiSecurityFixturesDirect, seedContextBindingDirect, seedContextDirect, seedCrossRepoTrustDirect, seedGenericWebhookSourceDirect, seedSourcePrivateKeyDirect, seedSyntheticGithubSourceDirect, seedUniversalGitSourceDirect, seedWebhookSecretDirect, serializeManifest, setContextPolicyDirect, setContextSecretDirect, setupGracefulShutdown, showContextDirect, showExecutionRunDirect, showKiciEventDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, storeMigrationContentHashInTableDirect, tableExistsDirect, tablePrefix, tenantDayBucketPrefix, tenantDayPrefix, terminateIdleDbBackendsDirect, updateGenericWebhookVerificationConfigDirect, updateOrgSettingsDeniedReposDirect, updateSourceRoutingKeyDirect, updateWorkflowRegistrationCommitShaDirect, upsertCronLastFiredDirect, upsertOrgSettingsGlobalWorkflowsDirect, validateRequiredTools, verifyKiciEventNotifyDirect, waitForEventLogRowByDeliveryIdDirect, waitForExecutionRunStatusSinceDirect, waitForLatestExecutionJobStatusDirect, waitForPlatformEventLogDistinctRoutedDirect, waitForPlatformExecutionRunStatusDirect, waitForPlatformRegistrationsDirect, waitForPostgresDirect, waitForRegistrationsByRoutingKeyDirect, waitForRegistrationsUpdatedAtAdvanceDirect, waitForRunCompletionDirect };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kici-dev/shared",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.27",
|
|
4
4
|
"description": "Shared utilities for the KiCI CI/CD stack — logging, zx setup, crypto, telemetry, health and metrics routes. No business logic.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ci",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"yaml": "^2.9.0",
|
|
106
106
|
"zod": "^4.4.3",
|
|
107
107
|
"zx": "^8.8.5",
|
|
108
|
-
"@kici-dev/core": "0.1.
|
|
108
|
+
"@kici-dev/core": "0.1.27"
|
|
109
109
|
},
|
|
110
110
|
"devDependencies": {
|
|
111
111
|
"@opentelemetry/sdk-trace-base": "^2.7.1",
|
package/sbom.spdx.json
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"spdxVersion": "SPDX-2.3",
|
|
3
3
|
"dataLicense": "CC0-1.0",
|
|
4
4
|
"SPDXID": "SPDXRef-DOCUMENT",
|
|
5
|
-
"name": "@kici-dev/shared@0.1.
|
|
6
|
-
"documentNamespace": "https://kici.dev/sbom/%40kici-dev%2Fshared/0.1.
|
|
5
|
+
"name": "@kici-dev/shared@0.1.27",
|
|
6
|
+
"documentNamespace": "https://kici.dev/sbom/%40kici-dev%2Fshared/0.1.27/2cfd2811-2ab7-4669-81dd-baa01f6bc285",
|
|
7
7
|
"creationInfo": {
|
|
8
|
-
"created": "2026-07-
|
|
8
|
+
"created": "2026-07-10T06:03:45Z",
|
|
9
9
|
"creators": [
|
|
10
10
|
"Tool: kici-sbom-generator"
|
|
11
11
|
]
|
|
@@ -696,9 +696,9 @@
|
|
|
696
696
|
"homepage": "https://js-sdsl.org"
|
|
697
697
|
},
|
|
698
698
|
{
|
|
699
|
-
"SPDXID": "SPDXRef-Package--kici-dev-core-0.1.
|
|
699
|
+
"SPDXID": "SPDXRef-Package--kici-dev-core-0.1.27",
|
|
700
700
|
"name": "@kici-dev/core",
|
|
701
|
-
"versionInfo": "0.1.
|
|
701
|
+
"versionInfo": "0.1.27",
|
|
702
702
|
"downloadLocation": "NOASSERTION",
|
|
703
703
|
"filesAnalyzed": false,
|
|
704
704
|
"licenseConcluded": "NOASSERTION",
|
|
@@ -709,7 +709,7 @@
|
|
|
709
709
|
{
|
|
710
710
|
"referenceCategory": "PACKAGE-MANAGER",
|
|
711
711
|
"referenceType": "purl",
|
|
712
|
-
"referenceLocator": "pkg:npm/%40kici-dev/core@0.1.
|
|
712
|
+
"referenceLocator": "pkg:npm/%40kici-dev/core@0.1.27"
|
|
713
713
|
}
|
|
714
714
|
],
|
|
715
715
|
"description": "Light shared utilities for the KiCI stack (logging, errors, formatting, crypto, zx init, the TypeScript ESM loader hook). No server-side dependencies.",
|
|
@@ -718,7 +718,7 @@
|
|
|
718
718
|
{
|
|
719
719
|
"SPDXID": "SPDXRef-RootPackage",
|
|
720
720
|
"name": "@kici-dev/shared",
|
|
721
|
-
"versionInfo": "0.1.
|
|
721
|
+
"versionInfo": "0.1.27",
|
|
722
722
|
"downloadLocation": "NOASSERTION",
|
|
723
723
|
"filesAnalyzed": false,
|
|
724
724
|
"licenseConcluded": "NOASSERTION",
|
|
@@ -729,7 +729,7 @@
|
|
|
729
729
|
{
|
|
730
730
|
"referenceCategory": "PACKAGE-MANAGER",
|
|
731
731
|
"referenceType": "purl",
|
|
732
|
-
"referenceLocator": "pkg:npm/%40kici-dev/shared@0.1.
|
|
732
|
+
"referenceLocator": "pkg:npm/%40kici-dev/shared@0.1.27"
|
|
733
733
|
}
|
|
734
734
|
],
|
|
735
735
|
"description": "Shared utilities for the KiCI CI/CD stack — logging, zx setup, crypto, telemetry, health and metrics routes. No business logic.",
|
|
@@ -5202,32 +5202,32 @@
|
|
|
5202
5202
|
"relationshipType": "DEPENDS_ON"
|
|
5203
5203
|
},
|
|
5204
5204
|
{
|
|
5205
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.
|
|
5205
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.27",
|
|
5206
5206
|
"relatedSpdxElement": "SPDXRef-Package-oxc-transform-0.135.0",
|
|
5207
5207
|
"relationshipType": "DEPENDS_ON"
|
|
5208
5208
|
},
|
|
5209
5209
|
{
|
|
5210
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.
|
|
5210
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.27",
|
|
5211
5211
|
"relatedSpdxElement": "SPDXRef-Package-picocolors-1.1.1",
|
|
5212
5212
|
"relationshipType": "DEPENDS_ON"
|
|
5213
5213
|
},
|
|
5214
5214
|
{
|
|
5215
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.
|
|
5215
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.27",
|
|
5216
5216
|
"relatedSpdxElement": "SPDXRef-Package-winston-daily-rotate-file-5.0.0",
|
|
5217
5217
|
"relationshipType": "DEPENDS_ON"
|
|
5218
5218
|
},
|
|
5219
5219
|
{
|
|
5220
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.
|
|
5220
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.27",
|
|
5221
5221
|
"relatedSpdxElement": "SPDXRef-Package-winston-3.19.0",
|
|
5222
5222
|
"relationshipType": "DEPENDS_ON"
|
|
5223
5223
|
},
|
|
5224
5224
|
{
|
|
5225
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.
|
|
5225
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.27",
|
|
5226
5226
|
"relatedSpdxElement": "SPDXRef-Package-zod-4.4.3",
|
|
5227
5227
|
"relationshipType": "DEPENDS_ON"
|
|
5228
5228
|
},
|
|
5229
5229
|
{
|
|
5230
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.
|
|
5230
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.27",
|
|
5231
5231
|
"relatedSpdxElement": "SPDXRef-Package-zx-8.8.5",
|
|
5232
5232
|
"relationshipType": "DEPENDS_ON"
|
|
5233
5233
|
},
|
|
@@ -5238,7 +5238,7 @@
|
|
|
5238
5238
|
},
|
|
5239
5239
|
{
|
|
5240
5240
|
"spdxElementId": "SPDXRef-RootPackage",
|
|
5241
|
-
"relatedSpdxElement": "SPDXRef-Package--kici-dev-core-0.1.
|
|
5241
|
+
"relatedSpdxElement": "SPDXRef-Package--kici-dev-core-0.1.27",
|
|
5242
5242
|
"relationshipType": "DEPENDS_ON"
|
|
5243
5243
|
},
|
|
5244
5244
|
{
|