@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.
@@ -178,22 +178,22 @@ export declare function purgeScopedSecretsDirect(databaseUrl: string, orgId?: st
178
178
  deleted: number;
179
179
  }>;
180
180
  /**
181
- * Bulk-delete `environments` (and their FK-dependent rows) for an org, or for
182
- * every org when `orgId` is omitted. `environment_bindings` /
183
- * `environment_variables` / `environment_source_overrides` cascade
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
- * `environments(id)` with ON DELETE SET NULL, so deleting environments alone
186
- * would leave orphaned `held_runs` rows carrying a null environment reference;
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 environments don't leak between
190
- * categories) and exposed via `kici-admin environment purge`.
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 purgeEnvironmentsDirect(databaseUrl: string, orgId?: string): Promise<{
193
- environmentsDeleted: number;
192
+ export declare function purgeContextsDirect(databaseUrl: string, orgId?: string): Promise<{
193
+ contextsDeleted: number;
194
194
  heldRunsDeleted: number;
195
195
  }>;
196
- export interface SeedEnvironmentOpts {
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 SeedEnvironmentResult {
208
+ export interface SeedContextResult {
209
209
  envId: string;
210
210
  created: boolean;
211
211
  }
212
212
  /**
213
- * Upsert an environment row keyed by (org_id, name). Returns the env id and
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 seedEnvironmentDirect(databaseUrl: string, opts: SeedEnvironmentOpts): Promise<SeedEnvironmentResult>;
218
- export interface DeleteEnvironmentOpts {
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 environment keyed by (org_id, name). Returns whether a row was
224
- * removed. The `environment_bindings`, `environment_variables`, and
225
- * `environment_source_overrides` children all carry
226
- * `FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE`,
227
- * so a single DELETE on `environments` cascades to those children. The
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 environment reference. Pending held runs
230
- * still reference the environment, so this helper pre-checks their count and
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 deleteEnvironmentDirect(databaseUrl: string, opts: DeleteEnvironmentOpts): Promise<{
233
+ export declare function deleteContextDirect(databaseUrl: string, opts: DeleteContextOpts): Promise<{
234
234
  deleted: boolean;
235
235
  }>;
236
- export interface SeedEnvironmentBindingOpts {
236
+ export interface SeedContextBindingOpts {
237
237
  orgId: string;
238
- envName: string;
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 `environment_bindings` row connecting `envName` to `scopePattern`
245
- * (scoped to `hostPattern`, default `'**'`). Throws if the environment does
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 seedEnvironmentBindingDirect(databaseUrl: string, opts: SeedEnvironmentBindingOpts): Promise<{
248
+ export declare function seedContextBindingDirect(databaseUrl: string, opts: SeedContextBindingOpts): Promise<{
249
249
  created: boolean;
250
250
  }>;
251
- export interface SetEnvironmentPolicyOpts {
251
+ export interface SetContextPolicyOpts {
252
252
  orgId: string;
253
- envName: string;
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 environment is missing.
264
+ * were NOT in `opts` are left untouched. Throws if the context is missing.
265
265
  */
266
- export declare function setEnvironmentPolicyDirect(databaseUrl: string, opts: SetEnvironmentPolicyOpts): Promise<void>;
267
- export interface EnvironmentRow {
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 environments WHERE org_id = $1, ordered by name.
282
+ * SELECT * FROM contexts WHERE org_id = $1, ordered by name.
283
283
  */
284
- export declare function listEnvironmentsDirect(databaseUrl: string, opts: {
284
+ export declare function listContextsDirect(databaseUrl: string, opts: {
285
285
  orgId: string;
286
286
  }): Promise<{
287
- environments: EnvironmentRow[];
287
+ contexts: ContextRow[];
288
288
  }>;
289
- export interface EnvironmentVariableRow {
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 EnvironmentBindingRow {
295
+ export interface ContextBindingRow {
296
296
  scope_pattern: string;
297
297
  host_pattern: string;
298
298
  created_at: string;
299
299
  }
300
- export interface ShowEnvironmentResult {
301
- environment: EnvironmentRow;
302
- variables: EnvironmentVariableRow[];
303
- bindings: EnvironmentBindingRow[];
300
+ export interface ShowContextResult {
301
+ context: ContextRow;
302
+ variables: ContextVariableRow[];
303
+ bindings: ContextBindingRow[];
304
304
  }
305
305
  /**
306
- * Fetch a single environment row joined with its variables and bindings.
307
- * Throws if the environment does not exist.
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 showEnvironmentDirect(databaseUrl: string, opts: {
309
+ export declare function showContextDirect(databaseUrl: string, opts: {
310
310
  orgId: string;
311
311
  name: string;
312
- }): Promise<ShowEnvironmentResult>;
313
- export interface CreateEnvironmentTemplateOpts {
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 environment template + its seed variables in one
326
- * transaction. Templates are represented as environments with `type='template'`
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 createEnvironmentTemplateDirect(databaseUrl: string, opts: CreateEnvironmentTemplateOpts): Promise<{
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 SetEnvironmentSecretOpts {
334
+ export interface SetContextSecretOpts {
335
335
  orgId: string;
336
- environment: string;
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=environment, key).
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 setEnvironmentSecretDirect(databaseUrl: string, opts: SetEnvironmentSecretOpts): Promise<{
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
- environment: string | null;
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-environment names (JSON-encoded `string[]`), or null. */
423
- environments: string | null;
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, environment,
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
- envName?: string;
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 `environments` (and their FK-dependent rows) for an org, or for
345
- * every org when `orgId` is omitted. `environment_bindings` /
346
- * `environment_variables` / `environment_source_overrides` cascade
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
- * `environments(id)` with ON DELETE SET NULL, so deleting environments alone
349
- * would leave orphaned `held_runs` rows carrying a null environment reference;
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 environments don't leak between
353
- * categories) and exposed via `kici-admin environment purge`.
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 purgeEnvironmentsDirect(databaseUrl, orgId) {
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 environments ${where}`, params);
363
+ const envs = await client.query(`DELETE FROM contexts ${where}`, params);
364
364
  await client.query("COMMIT");
365
365
  return {
366
- environmentsDeleted: envs.rowCount ?? 0,
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 `setEnvironmentPolicyDirect`. Kept as an
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 environment row keyed by (org_id, name). Returns the env id and
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 seedEnvironmentDirect(databaseUrl, opts) {
397
- if (opts.waitTimerSeconds != null && opts.waitTimerSeconds < 0) throw new Error(`environment: waitTimerSeconds must be >= 0 (got ${opts.waitTimerSeconds})`);
398
- if (opts.holdExpirySeconds != null && opts.holdExpirySeconds < 0) throw new Error(`environment: holdExpirySeconds must be >= 0 (got ${opts.holdExpirySeconds})`);
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 environments
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, environments.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, environments.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(`environment: upsert returned no row for ${opts.name}`);
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 environment keyed by (org_id, name). Returns whether a row was
444
- * removed. The `environment_bindings`, `environment_variables`, and
445
- * `environment_source_overrides` children all carry
446
- * `FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE`,
447
- * so a single DELETE on `environments` cascades to those children. The
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 environment reference. Pending held runs
450
- * still reference the environment, so this helper pre-checks their count and
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 deleteEnvironmentDirect(databaseUrl, opts) {
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 environments e ON e.id = hr.environment_id
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(`environment has ${pendingCount} pending held run(s) — approve or reject them first`);
464
- return { deleted: (await pool.query(`DELETE FROM environments WHERE org_id = $1 AND name = $2 RETURNING id`, [opts.orgId, opts.name])).rows.length > 0 };
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 `environment_bindings` row connecting `envName` to `scopePattern`
471
- * (scoped to `hostPattern`, default `'**'`). Throws if the environment does
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 seedEnvironmentBindingDirect(databaseUrl, opts) {
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 environments WHERE org_id = $1 AND name = $2`, [opts.orgId, opts.envName]);
481
- if (envRow.rows.length === 0) throw new Error(`environment: not found (org=${opts.orgId}, name=${opts.envName})`);
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 environment_bindings (org_id, environment_id, scope_pattern, host_pattern)
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 environment is missing.
498
+ * were NOT in `opts` are left untouched. Throws if the context is missing.
499
499
  */
500
- async function setEnvironmentPolicyDirect(databaseUrl, opts) {
501
- if (opts.waitTimerSeconds != null && opts.waitTimerSeconds < 0) throw new Error(`environment: waitTimerSeconds must be >= 0 (got ${opts.waitTimerSeconds})`);
502
- if (opts.holdExpirySeconds != null && opts.holdExpirySeconds < 0) throw new Error(`environment: holdExpirySeconds must be >= 0 (got ${opts.holdExpirySeconds})`);
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(`environment: unknown policy column ${column}`);
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("environment: setEnvironmentPolicy requires at least one policy field");
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.envName);
525
+ params.push(opts.orgId, opts.contextName);
526
526
  const orgParam = `$${idx}`;
527
527
  const nameParam = `$${idx + 1}`;
528
- const sql = `UPDATE environments
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(`environment: not found (org=${opts.orgId}, name=${opts.envName})`);
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 environments WHERE org_id = $1, ordered by name.
537
+ * SELECT * FROM contexts WHERE org_id = $1, ordered by name.
538
538
  */
539
- async function listEnvironmentsDirect(databaseUrl, opts) {
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 { environments: (await pool.query(`SELECT id, org_id, name, type, enabled, branch_restrictions, required_reviewers,
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 environments
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 environment row joined with its variables and bindings.
557
- * Throws if the environment does not exist.
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 showEnvironmentDirect(databaseUrl, opts) {
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 environments
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(`environment: not found (org=${opts.orgId}, name=${opts.name})`);
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 environment_variables
574
- WHERE environment_id = $1
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 environment_bindings
578
- WHERE environment_id = $1
577
+ FROM context_bindings
578
+ WHERE context_id = $1
579
579
  ORDER BY scope_pattern, host_pattern`, [env.id]);
580
580
  return {
581
- environment: env,
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 environment template + its seed variables in one
591
- * transaction. Templates are represented as environments with `type='template'`
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 createEnvironmentTemplateDirect(databaseUrl, opts) {
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 environments
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, environments.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(`environment: template upsert returned no row`);
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 environment_variables (org_id, environment_id, key, value, locked)
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, environment_id, key) DO UPDATE SET
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=environment, key).
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 setEnvironmentSecretDirect(databaseUrl, opts) {
659
- if (!opts.orgId) throw new Error("environment: orgId required");
660
- if (!opts.environment) throw new Error("environment: environment name required");
661
- if (!opts.key) throw new Error("environment: key required");
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.environment,
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, environment, trust_tier, created_at,
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, environment, trust_tier, created_at,
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, environments
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.environments
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 envName = opts.envName ?? "ci-security-env";
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 environments (org_id, name, type, enabled)
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, envName])).rows[0].id;
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, environment_id, hold_type, queue_type, reason, expires_at)
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, createDbRole, createEnvironmentTemplateDirect, createJoinTokenDirect, createReadOnlyDbUser, deleteCronLastFiredDirect, deleteCrossRepoTrustDirect, deleteEnvironmentDirect, 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, listCrossRepoTrustBySourceRoutingKeyDirect, listEnvironmentsDirect, listExecutionJobsDirect, listExecutionRunsDirect, listHeldRunApprovalsDirect, listKiciEventsDirect, listQueueDirect, listRegistrationsByRoutingKeyDirect, listRegistrationsDirect, maskDatabaseUrl, paginateUnprocessedEventsKeysetDirect, parseDatabaseUrl, platformConnectionExistsDirect, pollKiciEventsDirect, prunePeerCredentialsDirect, purgeEnvironmentsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, readStoredMigrationContentHash, registerWorkflowManualDirect, resetRaftStateDirect, resolvePlatformWebhookSourceRoutingKeyDirect, restoreSoftDeletedGenericWebhookSourceDirect, seedApiKeyInlineDirect, seedCiSecurityFixturesDirect, seedCrossRepoTrustDirect, seedEnvironmentBindingDirect, seedEnvironmentDirect, seedGenericWebhookSourceDirect, seedSourcePrivateKeyDirect, seedSyntheticGithubSourceDirect, seedUniversalGitSourceDirect, seedWebhookSecretDirect, setEnvironmentPolicyDirect, setEnvironmentSecretDirect, showEnvironmentDirect, 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 };
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
@@ -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
@@ -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, purgeEnvironmentsDirect, seedEnvironmentDirect, deleteEnvironmentDirect, seedEnvironmentBindingDirect, setEnvironmentPolicyDirect, listEnvironmentsDirect, showEnvironmentDirect, createEnvironmentTemplateDirect, setEnvironmentSecretDirect, 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 SeedEnvironmentOpts, type SeedEnvironmentResult, type SeedEnvironmentBindingOpts, type SetEnvironmentPolicyOpts, type EnvironmentRow, type EnvironmentVariableRow, type EnvironmentBindingRow, type ShowEnvironmentResult, type CreateEnvironmentTemplateOpts, type SetEnvironmentSecretOpts, 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';
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, createDbRole, createEnvironmentTemplateDirect, createJoinTokenDirect, createReadOnlyDbUser, deleteCronLastFiredDirect, deleteCrossRepoTrustDirect, deleteEnvironmentDirect, 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, listCrossRepoTrustBySourceRoutingKeyDirect, listEnvironmentsDirect, listExecutionJobsDirect, listExecutionRunsDirect, listHeldRunApprovalsDirect, listKiciEventsDirect, listQueueDirect, listRegistrationsByRoutingKeyDirect, listRegistrationsDirect, maskDatabaseUrl, paginateUnprocessedEventsKeysetDirect, parseDatabaseUrl, platformConnectionExistsDirect, pollKiciEventsDirect, prunePeerCredentialsDirect, purgeEnvironmentsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, readStoredMigrationContentHash, registerWorkflowManualDirect, resetRaftStateDirect, resolvePlatformWebhookSourceRoutingKeyDirect, restoreSoftDeletedGenericWebhookSourceDirect, seedApiKeyInlineDirect, seedCiSecurityFixturesDirect, seedCrossRepoTrustDirect, seedEnvironmentBindingDirect, seedEnvironmentDirect, seedGenericWebhookSourceDirect, seedSourcePrivateKeyDirect, seedSyntheticGithubSourceDirect, seedUniversalGitSourceDirect, seedWebhookSecretDirect, setEnvironmentPolicyDirect, setEnvironmentSecretDirect, showEnvironmentDirect, 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";
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, createEnvironmentTemplateDirect, createHealthRoutes, createJoinTokenDirect, createMeter, createMetricsRoutes, createPool, createReadOnlyDbUser, createS3Client, decodeChunk, decrypt, deleteCronLastFiredDirect, deleteCrossRepoTrustDirect, deleteEnvironmentDirect, 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, listCrossRepoTrustBySourceRoutingKeyDirect, listEnvironmentsDirect, listExecutionJobsDirect, listExecutionRunsDirect, listHeldRunApprovalsDirect, listKiciEventsDirect, listQueueDirect, listRegistrationsByRoutingKeyDirect, listRegistrationsDirect, maskDatabaseUrl, paginateUnprocessedEventsKeysetDirect, parseDatabaseUrl, parseManifest, platformConnectionExistsDirect, pollKiciEventsDirect, prunePeerCredentialsDirect, purgeEnvironmentsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, readStoredMigrationContentHash, redactConfig, registerWorkflowManualDirect, resetRaftStateDirect, resolvePlatformWebhookSourceRoutingKeyDirect, resolveTableConfig, restoreSoftDeletedGenericWebhookSourceDirect, seedApiKeyInlineDirect, seedCiSecurityFixturesDirect, seedCrossRepoTrustDirect, seedEnvironmentBindingDirect, seedEnvironmentDirect, seedGenericWebhookSourceDirect, seedSourcePrivateKeyDirect, seedSyntheticGithubSourceDirect, seedUniversalGitSourceDirect, seedWebhookSecretDirect, serializeManifest, setEnvironmentPolicyDirect, setEnvironmentSecretDirect, setupGracefulShutdown, showEnvironmentDirect, 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 };
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.26",
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.26"
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.26",
6
- "documentNamespace": "https://kici.dev/sbom/%40kici-dev%2Fshared/0.1.26/d99e3d57-fa38-4d0a-b1d9-e16cb8b34870",
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-06T04:29:33Z",
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.26",
699
+ "SPDXID": "SPDXRef-Package--kici-dev-core-0.1.27",
700
700
  "name": "@kici-dev/core",
701
- "versionInfo": "0.1.26",
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.26"
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.26",
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.26"
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.26",
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.26",
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.26",
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.26",
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.26",
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.26",
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.26",
5241
+ "relatedSpdxElement": "SPDXRef-Package--kici-dev-core-0.1.27",
5242
5242
  "relationshipType": "DEPENDS_ON"
5243
5243
  },
5244
5244
  {