@kici-dev/orchestrator 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/__test-helpers__/mock-db.d.ts +4 -0
  2. package/dist/agent/agent-version.d.ts +34 -0
  3. package/dist/agent/dispatcher.d.ts +70 -0
  4. package/dist/app.d.ts +23 -1
  5. package/dist/cache/global-eval-round-cache.d.ts +88 -0
  6. package/dist/cache/index.d.ts +3 -0
  7. package/dist/cache/pending-global-evals.d.ts +42 -0
  8. package/dist/cache/pending-inits.d.ts +10 -0
  9. package/dist/cli/commands/cluster-settings.d.ts +41 -3
  10. package/dist/cli/commands/runs.d.ts +1 -0
  11. package/dist/cli.js +1252 -623
  12. package/dist/cluster/cluster-settings-reader.d.ts +53 -1
  13. package/dist/config.d.ts +27 -0
  14. package/dist/content-requirements-cache.d.ts +55 -0
  15. package/dist/db/migrations/109_cluster_settings_cache_knobs.d.ts +4 -0
  16. package/dist/db/migrations/110_cluster_settings_global_eval_knobs.d.ts +4 -0
  17. package/dist/db/migrations/111_cluster_settings_global_eval_wait.d.ts +4 -0
  18. package/dist/db/migrations/112_execution_runs_workflow_repo.d.ts +4 -0
  19. package/dist/db/migrations/113_execution_runs_workflow_repo_index.d.ts +30 -0
  20. package/dist/db/migrations/114_ingest_queue_claim.d.ts +4 -0
  21. package/dist/db/migrations/115_global_workflows_cluster_switch.d.ts +9 -0
  22. package/dist/db/types.d.ts +60 -2
  23. package/dist/metrics/agent-metrics-aggregator.d.ts +2 -2
  24. package/dist/metrics/prometheus.d.ts +59 -0
  25. package/dist/orchestrator-core.d.ts +12 -1
  26. package/dist/pipeline/content-filter.d.ts +71 -0
  27. package/dist/pipeline/dispatch-matched-workflow.d.ts +247 -8
  28. package/dist/pipeline/global-eval-round.d.ts +293 -0
  29. package/dist/pipeline/job-contexts.d.ts +16 -17
  30. package/dist/pipeline/process-webhook.d.ts +7 -0
  31. package/dist/pipeline/processor.d.ts +56 -2
  32. package/dist/pipeline/route-or-dispatch-jobs.d.ts +6 -0
  33. package/dist/pipeline/test-pipeline.d.ts +12 -0
  34. package/dist/pipeline/webhook-payload-store.d.ts +20 -0
  35. package/dist/provenance/backfill-run.d.ts +10 -1
  36. package/dist/provider-registry.d.ts +38 -3
  37. package/dist/providers/github/check-status-poster.d.ts +22 -3
  38. package/dist/providers/github/commit-message.d.ts +20 -0
  39. package/dist/providers/github/file-contents.d.ts +40 -0
  40. package/dist/providers/github/index.d.ts +2 -0
  41. package/dist/providers/universal-git/config.d.ts +2 -0
  42. package/dist/providers/universal-git/normalizer.d.ts +10 -0
  43. package/dist/queue/cleanup.d.ts +7 -1
  44. package/dist/queue/job-queue.d.ts +69 -6
  45. package/dist/queue/terminalize-unroutable.d.ts +13 -0
  46. package/dist/registration/registration-run-match.d.ts +47 -0
  47. package/dist/reporting/check-run-reporter.d.ts +52 -1
  48. package/dist/reporting/execution-tracker.d.ts +117 -7
  49. package/dist/reporting/log-chunk-sink.d.ts +8 -5
  50. package/dist/routes/admin-org-settings.d.ts +5 -0
  51. package/dist/routes/admin.d.ts +6 -0
  52. package/dist/scaler/manager.d.ts +10 -8
  53. package/dist/secrets/pg-secret-store.d.ts +20 -2
  54. package/dist/security/global-workflow-policy.d.ts +52 -12
  55. package/dist/server.js +27579 -23783
  56. package/dist/standalone.js +5865 -2211
  57. package/dist/webhook/ingest-accept.d.ts +70 -0
  58. package/dist/webhook/ingest-overflow-buffer.d.ts +35 -4
  59. package/dist/webhook/ingest-overflow-replayer.d.ts +50 -6
  60. package/dist/ws/agent-handler.d.ts +3 -0
  61. package/dist/ws/dashboard-global-workflows-handler.d.ts +30 -9
  62. package/dist/ws/execution-status-frame.d.ts +32 -0
  63. package/dist/ws/platform-client.d.ts +14 -0
  64. package/dist/ws/test-relay-handlers.d.ts +35 -10
  65. package/installer-image-digests.json +3 -3
  66. package/package.json +4 -4
  67. package/sbom.spdx.json +57 -52
  68. package/dist/pipeline/inline-eval.d.ts +0 -44
package/dist/cli.js CHANGED
@@ -6,11 +6,11 @@ import path, { dirname, join, resolve } from "node:path";
6
6
  import * as fs$1 from "node:fs";
7
7
  import fs, { chmodSync, closeSync, constants, createReadStream, createWriteStream, existsSync, mkdirSync, mkdtempSync, openSync, promises, readFileSync, realpathSync, rmSync, statSync, unwatchFile, watchFile, writeFileSync } from "node:fs";
8
8
  import { Command, Option } from "commander";
9
- import { AgentPlatform, BaseColdStore, ChunkLru, addLogsToArchive, chunkObjectKey, clearDispatchQueueDirect, computeChunkId, computeMigrationsHash, createContextTemplateDirect, createDb, createDbRole, createLogger, createPool, createReadOnlyDbUser, createS3Client, decodeChunk, decrypt, deleteContextDirect, deriveKey, diagnoseExitCode, dropAndCreateDatabase, emitKiciEventDirect, encodeKeySegment, encrypt, ensureDatabase, formatBytes, formatUptime, isSchemaCurrent, kiciMkdtemp, listCheckRunTrackingDirect, listContextsDirect, listExecutionRunsDirect, listQueueDirect, listRegistrationsDirect, maskDatabaseUrl, parseDatabaseUrl, parseManifest, prunePeerCredentialsDirect, purgeContextsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, registerWorkflowManualDirect, resetRaftStateDirect, seedContextBindingDirect, seedContextDirect, setContextPolicyDirect, setContextSecretDirect, sha256, showContextDirect, showExecutionRunDirect, showQueueEntryDirect, showRegistrationDirect, splitAgentPlatform, storeMigrationContentHash, tablePrefix, toErrorMessage } from "@kici-dev/shared";
9
+ import { AgentPlatform, BaseColdStore, ChunkLru, addLogsToArchive, chunkObjectKey, clearDispatchQueueDirect, computeChunkId, computeMigrationsHash, createContextTemplateDirect, createDb, createDbRole, createLogger, createPool, createReadOnlyDbUser, createS3Client, decodeChunk, decrypt, deleteContextDirect, deriveKey, diagnoseExitCode, dropAndCreateDatabase, emitKiciEventDirect, encodeKeySegment, encrypt, ensureDatabase, formatBytes, formatUptime, isSchemaCurrent, kiciMkdtemp, listCheckRunTrackingDirect, listContextsDirect, listExecutionRunsDirect, listQueueDirect, listRegistrationsDirect, maskDatabaseUrl, parseDatabaseUrl, parseManifest, prunePeerCredentialsDirect, purgeContextsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, registerWorkflowManualDirect, resetRaftStateDirect, seedContextBindingDirect, seedContextDirect, serializeError, setContextPolicyDirect, setContextSecretDirect, sha256, showContextDirect, showExecutionRunDirect, showQueueEntryDirect, showRegistrationDirect, splitAgentPlatform, storeMigrationContentHash, tablePrefix, toErrorMessage } from "@kici-dev/shared";
10
+ import { AccessLogSource, DEFAULT_APPROVAL_EXPIRY_HOURS, ExecutionJobStatus, KICI_AGENT_ENV_PREFIX, KNOWN_ROLES, OrchestratorMode, PLATFORM_CONNECTED_MODES, PRIVILEGED_ROOT_LABEL, ScalerBackendType, ScalerEventType, TERMINAL_JOB_STATES, TERMINAL_RUN_STATES, WS_MAX_PAYLOAD_BYTES, accessLogWarmSqlCase, agentLabelOf, assertValidSecretKey, attestationVerifyStatusSchema, flattenActor, getAccessLogColdDays, getSecretAuditLogColdDays, matcherSatisfiedBy, minAccessLogWarmDays, minSecretAuditLogWarmDays, parseHostPropertyAssignments, scalerAgentLabels, scalerPlatformSchema, secretAuditLogWarmSqlCase, shouldRecordAccess, shouldRecordSecretResolve } from "@kici-dev/engine";
10
11
  import crypto$1, { createDecipheriv, createHash, createHmac, createPublicKey, generateKeyPairSync, hkdfSync, randomBytes, randomUUID } from "node:crypto";
11
12
  import { createInterface } from "node:readline";
12
13
  import { sql } from "kysely";
13
- import { AccessLogSource, DEFAULT_APPROVAL_EXPIRY_HOURS, ExecutionJobStatus, KICI_AGENT_ENV_PREFIX, KNOWN_ROLES, OrchestratorMode, PLATFORM_CONNECTED_MODES, PRIVILEGED_ROOT_LABEL, ScalerBackendType, ScalerEventType, TERMINAL_JOB_STATES, TERMINAL_RUN_STATES, WS_MAX_PAYLOAD_BYTES, accessLogWarmSqlCase, agentLabelOf, attestationVerifyStatusSchema, flattenActor, getAccessLogColdDays, getSecretAuditLogColdDays, matcherSatisfiedBy, minAccessLogWarmDays, minSecretAuditLogWarmDays, parseHostPropertyAssignments, scalerAgentLabels, scalerPlatformSchema, secretAuditLogWarmSqlCase, shouldRecordAccess, shouldRecordSecretResolve } from "@kici-dev/engine";
14
14
  import { access, chmod, constants as constants$1, copyFile, link, mkdir, open, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
15
15
  import { parse, stringify } from "yaml";
16
16
  import { z } from "zod";
@@ -36,6 +36,7 @@ import { confirm, input, password, select } from "@inquirer/prompts";
36
36
  import JSZip from "jszip";
37
37
  import { pipeline } from "node:stream/promises";
38
38
  import { isCiEnvironment } from "@kici-dev/shared/ci-env";
39
+ import { setTimeout as setTimeout$1 } from "node:timers/promises";
39
40
  import { $ } from "zx";
40
41
  import "pg";
41
42
  import { DASHBOARD_WRITE_OPERATIONS, DASHBOARD_WRITE_OPERATIONS_BY_NAME, DashboardWriteCategory, DashboardWritePolicyState, DashboardWriteSensitivity } from "@kici-dev/engine/protocol/dashboard-write-operations";
@@ -783,17 +784,36 @@ var PgSecretStore = class PgSecretStore {
783
784
  }
784
785
  return result;
785
786
  }
786
- /**
787
- * Set (create or update) a secret in a scope.
788
- * Encrypts the value with AAD = "orgId:scope:key".
789
- */
790
787
  /** Check if a scope is internal/operational (always allowed regardless of toggle). */
791
788
  isInternalScope(scope) {
792
789
  const colonIdx = scope.indexOf(":");
793
790
  const path = colonIdx >= 0 ? scope.slice(colonIdx + 1) : scope;
794
791
  return path.startsWith("__source__/") || path.startsWith("__webhook__/");
795
792
  }
793
+ /**
794
+ * Set (create or update) a secret in a scope.
795
+ * Encrypts the value with AAD = "orgId:scope:key".
796
+ *
797
+ * Rejects a key outside `[A-Za-z0-9._-]` before doing anything else. The AAD
798
+ * is a plain concatenation, so a `:` in the key would let two distinct
799
+ * locations render one AAD (scope 'b' + key 'c:d' equals scope 'b:c' + key
800
+ * 'd') and a ciphertext written at one would authenticate at the other. The
801
+ * check sits ahead of the customerSecretsEnabled gate so internal scopes get
802
+ * no exemption — the binding has to hold for every writer.
803
+ *
804
+ * Callers pass a bare scope path, so the AAD's middle field is colon-free
805
+ * too: the admin route and the dashboard handler both run the scope
806
+ * validator immediately before calling in, and `source-store` builds its
807
+ * scope from a uuid. That precondition is what makes the whole triple
808
+ * recoverable, and it is the caller's to keep — this method does not
809
+ * re-check it.
810
+ *
811
+ * Write-path only: getSecrets, listKeys, deleteSecret, deleteScope,
812
+ * renameScope, getAllSecrets and createScope stay unvalidated, which is what
813
+ * keeps a key stored before this rule readable and deletable.
814
+ */
796
815
  async setSecret(orgId, scope, key, value) {
816
+ assertValidSecretKey(key);
797
817
  if (!this.customerSecretsEnabled && !this.isInternalScope(scope)) throw new Error("PG customer secrets are disabled. Use an external secret backend or enable pgCustomerSecrets in config.");
798
818
  const aad = `${orgId}:${scope}:${key}`;
799
819
  const encrypted = encrypt(value, this.masterKey, this.keyVersion, aad);
@@ -1491,6 +1511,7 @@ function registerSecretCommands(program, getClient) {
1491
1511
  }
1492
1512
  const dbUrl = resolveDirectDbUrl$10(opts.databaseUrl);
1493
1513
  if (dbUrl) {
1514
+ assertValidSecretKey(key);
1494
1515
  await setContextSecretDirect(dbUrl, {
1495
1516
  orgId,
1496
1517
  context: scope,
@@ -2492,8 +2513,8 @@ server:
2492
2513
  //#endregion
2493
2514
  //#region src/db/migrations/001_initial.ts
2494
2515
  var _001_initial_exports = /* @__PURE__ */ __exportAll({
2495
- down: () => down$107,
2496
- up: () => up$107
2516
+ down: () => down$114,
2517
+ up: () => up$114
2497
2518
  });
2498
2519
  /**
2499
2520
  * Squashed initial migration -- creates the complete Orchestrator database schema.
@@ -3185,7 +3206,7 @@ const DDL_STATEMENTS = [
3185
3206
  `ALTER TABLE ONLY public.held_runs
3186
3207
  ADD CONSTRAINT held_runs_environment_id_fkey FOREIGN KEY (environment_id) REFERENCES public.environments(id);`
3187
3208
  ];
3188
- async function up$107(db) {
3209
+ async function up$114(db) {
3189
3210
  for (const stmt of DDL_STATEMENTS) await sql.raw(stmt).execute(db);
3190
3211
  await sql`
3191
3212
  INSERT INTO cluster_meta (key, value)
@@ -3207,7 +3228,7 @@ async function up$107(db) {
3207
3228
  * Rollback drops everything created above. Uses CASCADE on table drops to cut
3208
3229
  * through the FK graph without relying on exact topological order.
3209
3230
  */
3210
- async function down$107(db) {
3231
+ async function down$114(db) {
3211
3232
  for (const [trig, tbl] of [["source_secrets_change_trigger", "scoped_secrets"], ["sources_change_trigger", "sources"]]) await sql.raw(`DROP TRIGGER IF EXISTS ${trig} ON public.${tbl}`).execute(db);
3212
3233
  for (const table of [
3213
3234
  "workflow_registrations",
@@ -3254,8 +3275,8 @@ async function down$107(db) {
3254
3275
  //#endregion
3255
3276
  //#region src/db/migrations/002_config_versions_key_version.ts
3256
3277
  var _002_config_versions_key_version_exports = /* @__PURE__ */ __exportAll({
3257
- down: () => down$106,
3258
- up: () => up$106
3278
+ down: () => down$113,
3279
+ up: () => up$113
3259
3280
  });
3260
3281
  /**
3261
3282
  * Add key_version column to config_versions so that sensitive-field encryption
@@ -3269,13 +3290,13 @@ var _002_config_versions_key_version_exports = /* @__PURE__ */ __exportAll({
3269
3290
  * No index is needed: rotation does a full-table scan; reads are by
3270
3291
  * `version` primary key and never filter on `key_version`.
3271
3292
  */
3272
- async function up$106(db) {
3293
+ async function up$113(db) {
3273
3294
  await sql`
3274
3295
  ALTER TABLE public.config_versions
3275
3296
  ADD COLUMN key_version integer NOT NULL DEFAULT 1
3276
3297
  `.execute(db);
3277
3298
  }
3278
- async function down$106(db) {
3299
+ async function down$113(db) {
3279
3300
  await sql`
3280
3301
  ALTER TABLE public.config_versions
3281
3302
  DROP COLUMN key_version
@@ -3284,8 +3305,8 @@ async function down$106(db) {
3284
3305
  //#endregion
3285
3306
  //#region src/db/migrations/003_access_log.ts
3286
3307
  var _003_access_log_exports = /* @__PURE__ */ __exportAll({
3287
- down: () => down$105,
3288
- up: () => up$105
3308
+ down: () => down$112,
3309
+ up: () => up$112
3289
3310
  });
3290
3311
  /**
3291
3312
  * Access log: one row per read or orchestrator-admin mutation attributable
@@ -3309,7 +3330,7 @@ var _003_access_log_exports = /* @__PURE__ */ __exportAll({
3309
3330
  * Retention is TTL-based via expires_at; packages/orchestrator/src/queue/
3310
3331
  * cleanup.ts picks up the prune pass.
3311
3332
  */
3312
- async function up$105(db) {
3333
+ async function up$112(db) {
3313
3334
  await sql`
3314
3335
  CREATE TABLE public.access_log (
3315
3336
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
@@ -3347,28 +3368,28 @@ async function up$105(db) {
3347
3368
  ON public.access_log (actor_type, actor_id, created_at DESC)
3348
3369
  `.execute(db);
3349
3370
  }
3350
- async function down$105(db) {
3371
+ async function down$112(db) {
3351
3372
  await sql`DROP TABLE IF EXISTS public.access_log`.execute(db);
3352
3373
  }
3353
3374
  //#endregion
3354
3375
  //#region src/db/migrations/004_rename_bundle_to_source.ts
3355
3376
  var _004_rename_bundle_to_source_exports = /* @__PURE__ */ __exportAll({
3356
- down: () => down$104,
3357
- up: () => up$104
3377
+ down: () => down$111,
3378
+ up: () => up$111
3358
3379
  });
3359
- async function up$104(db) {
3380
+ async function up$111(db) {
3360
3381
  await db.schema.alterTable("dispatch_queue").renameColumn("bundle_url", "source_tar_url").execute();
3361
3382
  await db.schema.alterTable("dispatch_queue").renameColumn("bundle_hash", "source_tar_hash").execute();
3362
3383
  }
3363
- async function down$104(db) {
3384
+ async function down$111(db) {
3364
3385
  await db.schema.alterTable("dispatch_queue").renameColumn("source_tar_url", "bundle_url").execute();
3365
3386
  await db.schema.alterTable("dispatch_queue").renameColumn("source_tar_hash", "bundle_hash").execute();
3366
3387
  }
3367
3388
  //#endregion
3368
3389
  //#region src/db/migrations/005_cold_store_chunk_counter.ts
3369
3390
  var _005_cold_store_chunk_counter_exports = /* @__PURE__ */ __exportAll({
3370
- down: () => down$103,
3371
- up: () => up$103
3391
+ down: () => down$110,
3392
+ up: () => up$110
3372
3393
  });
3373
3394
  /**
3374
3395
  * Cold-store chunk counter table.
@@ -3385,7 +3406,7 @@ var _005_cold_store_chunk_counter_exports = /* @__PURE__ */ __exportAll({
3385
3406
  *
3386
3407
  * sections 5 and 8.
3387
3408
  */
3388
- async function up$103(db) {
3409
+ async function up$110(db) {
3389
3410
  await sql`
3390
3411
  CREATE TABLE public.cold_store_chunk_counts (
3391
3412
  db TEXT NOT NULL,
@@ -3403,14 +3424,14 @@ async function up$103(db) {
3403
3424
  ON public.cold_store_chunk_counts (db, table_name)
3404
3425
  `.execute(db);
3405
3426
  }
3406
- async function down$103(db) {
3427
+ async function down$110(db) {
3407
3428
  await sql`DROP TABLE IF EXISTS public.cold_store_chunk_counts`.execute(db);
3408
3429
  }
3409
3430
  //#endregion
3410
3431
  //#region src/db/migrations/006_runs_jobs_steps_archived_at.ts
3411
3432
  var _006_runs_jobs_steps_archived_at_exports = /* @__PURE__ */ __exportAll({
3412
- down: () => down$102,
3413
- up: () => up$102
3433
+ down: () => down$109,
3434
+ up: () => up$109
3414
3435
  });
3415
3436
  /**
3416
3437
  * `execution_runs` / `execution_jobs` / `execution_steps` cold-store
@@ -3446,7 +3467,7 @@ var _006_runs_jobs_steps_archived_at_exports = /* @__PURE__ */ __exportAll({
3446
3467
  * - `idx_execution_jobs_routing_key_created (routing_key, created_at)`
3447
3468
  * - `idx_execution_steps_routing_key_created (routing_key, created_at)`
3448
3469
  */
3449
- async function up$102(db) {
3470
+ async function up$109(db) {
3450
3471
  await sql`
3451
3472
  ALTER TABLE public.execution_runs
3452
3473
  ADD COLUMN archived_at TIMESTAMPTZ NULL,
@@ -3491,7 +3512,7 @@ async function up$102(db) {
3491
3512
  ON public.execution_steps (routing_key, created_at)
3492
3513
  `.execute(db);
3493
3514
  }
3494
- async function down$102(db) {
3515
+ async function down$109(db) {
3495
3516
  await sql`DROP INDEX IF EXISTS public.idx_execution_steps_routing_key_created`.execute(db);
3496
3517
  await sql`
3497
3518
  ALTER TABLE public.execution_steps
@@ -3516,8 +3537,8 @@ async function down$102(db) {
3516
3537
  //#endregion
3517
3538
  //#region src/db/migrations/007_audit_logs_archived_at.ts
3518
3539
  var _007_audit_logs_archived_at_exports = /* @__PURE__ */ __exportAll({
3519
- down: () => down$101,
3520
- up: () => up$101
3540
+ down: () => down$108,
3541
+ up: () => up$108
3521
3542
  });
3522
3543
  /**
3523
3544
  * `secret_audit_log` and `access_log` cold-store schema additions, plus
@@ -3557,7 +3578,7 @@ var _007_audit_logs_archived_at_exports = /* @__PURE__ */ __exportAll({
3557
3578
  * `down()` would not have meaningful retention bounds. Acceptable for
3558
3579
  * staging.
3559
3580
  */
3560
- async function up$101(db) {
3581
+ async function up$108(db) {
3561
3582
  await sql`
3562
3583
  ALTER TABLE public.secret_audit_log
3563
3584
  ADD COLUMN archived_at TIMESTAMPTZ NULL,
@@ -3578,7 +3599,7 @@ async function up$101(db) {
3578
3599
  DROP COLUMN IF EXISTS expires_at
3579
3600
  `.execute(db);
3580
3601
  }
3581
- async function down$101(db) {
3602
+ async function down$108(db) {
3582
3603
  await sql`
3583
3604
  ALTER TABLE public.access_log
3584
3605
  ADD COLUMN expires_at TIMESTAMPTZ NOT NULL DEFAULT (now() + INTERVAL '90 days')
@@ -3606,8 +3627,8 @@ async function down$101(db) {
3606
3627
  //#endregion
3607
3628
  //#region src/db/migrations/008_event_log_archived_at.ts
3608
3629
  var _008_event_log_archived_at_exports = /* @__PURE__ */ __exportAll({
3609
- down: () => down$100,
3610
- up: () => up$100
3630
+ down: () => down$107,
3631
+ up: () => up$107
3611
3632
  });
3612
3633
  /**
3613
3634
  * `event_log` cold-store schema additions plus removal of the
@@ -3645,7 +3666,7 @@ var _008_event_log_archived_at_exports = /* @__PURE__ */ __exportAll({
3645
3666
  * — best effort; rows inserted between `up()` and a hypothetical
3646
3667
  * `down()` would not have meaningful retention bounds.
3647
3668
  */
3648
- async function up$100(db) {
3669
+ async function up$107(db) {
3649
3670
  await sql`
3650
3671
  ALTER TABLE public.event_log
3651
3672
  ADD COLUMN archived_at TIMESTAMPTZ NULL,
@@ -3661,7 +3682,7 @@ async function up$100(db) {
3661
3682
  DROP COLUMN IF EXISTS expires_at
3662
3683
  `.execute(db);
3663
3684
  }
3664
- async function down$100(db) {
3685
+ async function down$107(db) {
3665
3686
  await sql`
3666
3687
  ALTER TABLE public.event_log
3667
3688
  ADD COLUMN expires_at TIMESTAMPTZ NOT NULL DEFAULT (now() + INTERVAL '30 days')
@@ -3680,8 +3701,8 @@ async function down$100(db) {
3680
3701
  //#endregion
3681
3702
  //#region src/db/migrations/009_access_log_trigram.ts
3682
3703
  var _009_access_log_trigram_exports = /* @__PURE__ */ __exportAll({
3683
- down: () => down$99,
3684
- up: () => up$99
3704
+ down: () => down$106,
3705
+ up: () => up$106
3685
3706
  });
3686
3707
  /**
3687
3708
  * Trigram (pg_trgm) index on access_log.error_message for the federated
@@ -3694,7 +3715,7 @@ var _009_access_log_trigram_exports = /* @__PURE__ */ __exportAll({
3694
3715
  * EXISTS` are both safe to re-run. No CONCURRENTLY because Kysely runs
3695
3716
  * migrations inside a transaction; the lock is brief on a sampled table.
3696
3717
  */
3697
- async function up$99(db) {
3718
+ async function up$106(db) {
3698
3719
  await sql`CREATE EXTENSION IF NOT EXISTS pg_trgm`.execute(db);
3699
3720
  await sql`
3700
3721
  CREATE INDEX IF NOT EXISTS access_log_error_message_trgm_idx
@@ -3703,14 +3724,14 @@ async function up$99(db) {
3703
3724
  WHERE error_message IS NOT NULL
3704
3725
  `.execute(db);
3705
3726
  }
3706
- async function down$99(db) {
3727
+ async function down$106(db) {
3707
3728
  await sql`DROP INDEX IF EXISTS public.access_log_error_message_trgm_idx`.execute(db);
3708
3729
  }
3709
3730
  //#endregion
3710
3731
  //#region src/db/migrations/010_cold_store_chunks.ts
3711
3732
  var _010_cold_store_chunks_exports = /* @__PURE__ */ __exportAll({
3712
- down: () => down$98,
3713
- up: () => up$98
3733
+ down: () => down$105,
3734
+ up: () => up$105
3714
3735
  });
3715
3736
  /**
3716
3737
  * Cold-store chunk index — Phase 2 (cold-store purge).
@@ -3742,7 +3763,7 @@ var _010_cold_store_chunks_exports = /* @__PURE__ */ __exportAll({
3742
3763
  * forever. Adapters that don't opt into per-bucket archival via
3743
3764
  * `coldTtlDays` don't insert here either.
3744
3765
  */
3745
- async function up$98(db) {
3766
+ async function up$105(db) {
3746
3767
  await sql`
3747
3768
  CREATE TABLE public.cold_store_chunks (
3748
3769
  db TEXT NOT NULL,
@@ -3769,14 +3790,14 @@ async function up$98(db) {
3769
3790
  ON public.cold_store_chunks (db, table_name, tenant_id, archived_at DESC)
3770
3791
  `.execute(db);
3771
3792
  }
3772
- async function down$98(db) {
3793
+ async function down$105(db) {
3773
3794
  await sql`DROP TABLE IF EXISTS public.cold_store_chunks`.execute(db);
3774
3795
  }
3775
3796
  //#endregion
3776
3797
  //#region src/db/migrations/011_drop_source_secrets_notify.ts
3777
3798
  var _011_drop_source_secrets_notify_exports = /* @__PURE__ */ __exportAll({
3778
- down: () => down$97,
3779
- up: () => up$97
3799
+ down: () => down$104,
3800
+ up: () => up$104
3780
3801
  });
3781
3802
  /**
3782
3803
  * Drop the `source_secrets_change_trigger` and the
@@ -3795,11 +3816,11 @@ var _011_drop_source_secrets_notify_exports = /* @__PURE__ */ __exportAll({
3795
3816
  * in `001_initial.ts`. They wake up no consumer until the `WebhookSecretManager`
3796
3817
  * is restored, so this migration is safe to roll back.
3797
3818
  */
3798
- async function up$97(db) {
3819
+ async function up$104(db) {
3799
3820
  await sql`DROP TRIGGER IF EXISTS source_secrets_change_trigger ON public.scoped_secrets`.execute(db);
3800
3821
  await sql`DROP FUNCTION IF EXISTS public.notify_source_secrets_change() CASCADE`.execute(db);
3801
3822
  }
3802
- async function down$97(db) {
3823
+ async function down$104(db) {
3803
3824
  await sql`
3804
3825
  CREATE OR REPLACE FUNCTION public.notify_source_secrets_change() RETURNS trigger
3805
3826
  LANGUAGE plpgsql
@@ -3838,8 +3859,8 @@ async function down$97(db) {
3838
3859
  //#endregion
3839
3860
  //#region src/db/migrations/012_peer_credentials_active_uniq.ts
3840
3861
  var _012_peer_credentials_active_uniq_exports = /* @__PURE__ */ __exportAll({
3841
- down: () => down$96,
3842
- up: () => up$96
3862
+ down: () => down$103,
3863
+ up: () => up$103
3843
3864
  });
3844
3865
  /**
3845
3866
  * Add a partial unique index on `peer_credentials (instance_id) WHERE
@@ -3865,7 +3886,7 @@ var _012_peer_credentials_active_uniq_exports = /* @__PURE__ */ __exportAll({
3865
3886
  * `down()` only drops the index; it does NOT undo the dedupe (there's no
3866
3887
  * safe way to recreate revoked rows, and the dedupe is monotonic).
3867
3888
  */
3868
- async function up$96(db) {
3889
+ async function up$103(db) {
3869
3890
  await sql`
3870
3891
  UPDATE public.peer_credentials
3871
3892
  SET revoked_at = NOW()
@@ -3883,14 +3904,14 @@ async function up$96(db) {
3883
3904
  WHERE revoked_at IS NULL
3884
3905
  `.execute(db);
3885
3906
  }
3886
- async function down$96(db) {
3907
+ async function down$103(db) {
3887
3908
  await sql`DROP INDEX IF EXISTS public.peer_credentials_active_uniq`.execute(db);
3888
3909
  }
3889
3910
  //#endregion
3890
3911
  //#region src/db/migrations/013_execution_log_bytes.ts
3891
3912
  var _013_execution_log_bytes_exports = /* @__PURE__ */ __exportAll({
3892
- down: () => down$95,
3893
- up: () => up$95
3913
+ down: () => down$102,
3914
+ up: () => up$102
3894
3915
  });
3895
3916
  /**
3896
3917
  * Add `log_bytes BIGINT NOT NULL DEFAULT 0` columns to `execution_runs` and
@@ -3909,7 +3930,7 @@ var _013_execution_log_bytes_exports = /* @__PURE__ */ __exportAll({
3909
3930
  *
3910
3931
  * Idempotent (`ADD COLUMN IF NOT EXISTS`).
3911
3932
  */
3912
- async function up$95(db) {
3933
+ async function up$102(db) {
3913
3934
  await sql`
3914
3935
  ALTER TABLE public.execution_runs
3915
3936
  ADD COLUMN IF NOT EXISTS log_bytes BIGINT NOT NULL DEFAULT 0
@@ -3919,15 +3940,15 @@ async function up$95(db) {
3919
3940
  ADD COLUMN IF NOT EXISTS log_bytes BIGINT NOT NULL DEFAULT 0
3920
3941
  `.execute(db);
3921
3942
  }
3922
- async function down$95(db) {
3943
+ async function down$102(db) {
3923
3944
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS log_bytes`.execute(db);
3924
3945
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS log_bytes`.execute(db);
3925
3946
  }
3926
3947
  //#endregion
3927
3948
  //#region src/db/migrations/014_kici_events_lease_retry.ts
3928
3949
  var _014_kici_events_lease_retry_exports = /* @__PURE__ */ __exportAll({
3929
- down: () => down$94,
3930
- up: () => up$94
3950
+ down: () => down$101,
3951
+ up: () => up$101
3931
3952
  });
3932
3953
  /**
3933
3954
  * Add lease + retry + DLQ columns to `kici_events` so the EventRouter can
@@ -3961,7 +3982,7 @@ var _014_kici_events_lease_retry_exports = /* @__PURE__ */ __exportAll({
3961
3982
  *
3962
3983
  * Idempotent (`ADD COLUMN IF NOT EXISTS` + `CREATE INDEX IF NOT EXISTS`).
3963
3984
  */
3964
- async function up$94(db) {
3985
+ async function up$101(db) {
3965
3986
  await sql`
3966
3987
  ALTER TABLE public.kici_events
3967
3988
  ADD COLUMN IF NOT EXISTS claimed_at TIMESTAMPTZ,
@@ -3992,7 +4013,7 @@ async function up$94(db) {
3992
4013
  WHERE dlq_at IS NOT NULL
3993
4014
  `.execute(db);
3994
4015
  }
3995
- async function down$94(db) {
4016
+ async function down$101(db) {
3996
4017
  await sql`DROP INDEX IF EXISTS public.idx_kici_events_dlq`.execute(db);
3997
4018
  await sql`DROP INDEX IF EXISTS public.idx_kici_events_lease_expired`.execute(db);
3998
4019
  await sql`DROP INDEX IF EXISTS public.idx_kici_events_retry_due`.execute(db);
@@ -4010,8 +4031,8 @@ async function down$94(db) {
4010
4031
  //#endregion
4011
4032
  //#region src/db/migrations/015_org_settings_customer_scoped.ts
4012
4033
  var _015_org_settings_customer_scoped_exports = /* @__PURE__ */ __exportAll({
4013
- down: () => down$93,
4014
- up: () => up$93
4034
+ down: () => down$100,
4035
+ up: () => up$100
4015
4036
  });
4016
4037
  /**
4017
4038
  * Org-scope `org_settings` and qualify each glob entry by source.
@@ -4039,7 +4060,7 @@ var _015_org_settings_customer_scoped_exports = /* @__PURE__ */ __exportAll({
4039
4060
  * Idempotent: a re-run on an already-migrated DB sees `customer_id` exists
4040
4061
  * and the list columns are already jsonb, so it is a no-op.
4041
4062
  */
4042
- async function up$93(db) {
4063
+ async function up$100(db) {
4043
4064
  if ((await sql`
4044
4065
  SELECT EXISTS (
4045
4066
  SELECT 1 FROM information_schema.columns
@@ -4164,7 +4185,7 @@ async function up$93(db) {
4164
4185
  await sql`DROP TABLE _org_settings_merged`.execute(db);
4165
4186
  await sql`DROP TABLE _org_settings_stage`.execute(db);
4166
4187
  }
4167
- async function down$93(db) {
4188
+ async function down$100(db) {
4168
4189
  if (!(await sql`
4169
4190
  SELECT EXISTS (
4170
4191
  SELECT 1 FROM information_schema.columns
@@ -4189,8 +4210,8 @@ async function down$93(db) {
4189
4210
  //#endregion
4190
4211
  //#region src/db/migrations/016_org_settings_allow_http_npm.ts
4191
4212
  var _016_org_settings_allow_http_npm_exports = /* @__PURE__ */ __exportAll({
4192
- down: () => down$92,
4193
- up: () => up$92
4213
+ down: () => down$99,
4214
+ up: () => up$99
4194
4215
  });
4195
4216
  /**
4196
4217
  * Add `org_settings.allow_http_npm_registries boolean NOT NULL DEFAULT false`.
@@ -4203,7 +4224,7 @@ var _016_org_settings_allow_http_npm_exports = /* @__PURE__ */ __exportAll({
4203
4224
  *
4204
4225
  * Idempotent: a re-run on a DB that already has the column is a no-op.
4205
4226
  */
4206
- async function up$92(db) {
4227
+ async function up$99(db) {
4207
4228
  if ((await sql`
4208
4229
  SELECT EXISTS (
4209
4230
  SELECT 1 FROM information_schema.columns
@@ -4217,7 +4238,7 @@ async function up$92(db) {
4217
4238
  ADD COLUMN allow_http_npm_registries boolean NOT NULL DEFAULT false
4218
4239
  `.execute(db);
4219
4240
  }
4220
- async function down$92(db) {
4241
+ async function down$99(db) {
4221
4242
  await sql`
4222
4243
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS allow_http_npm_registries
4223
4244
  `.execute(db);
@@ -4225,8 +4246,8 @@ async function down$92(db) {
4225
4246
  //#endregion
4226
4247
  //#region src/db/migrations/017_org_id_widen.ts
4227
4248
  var _017_org_id_widen_exports = /* @__PURE__ */ __exportAll({
4228
- down: () => down$91,
4229
- up: () => up$91
4249
+ down: () => down$98,
4250
+ up: () => up$98
4230
4251
  });
4231
4252
  /**
4232
4253
  * Widen every orchestrator-side `org_id varchar(12)` column to
@@ -4266,17 +4287,17 @@ const ORG_ID_TABLES$1 = [
4266
4287
  "held_runs",
4267
4288
  "scoped_secrets"
4268
4289
  ];
4269
- async function up$91(db) {
4290
+ async function up$98(db) {
4270
4291
  for (const table of ORG_ID_TABLES$1) await sql.raw(`ALTER TABLE public.${table} ALTER COLUMN org_id TYPE varchar(16)`).execute(db);
4271
4292
  }
4272
- async function down$91(db) {
4293
+ async function down$98(db) {
4273
4294
  for (const table of ORG_ID_TABLES$1) await sql.raw(`ALTER TABLE public.${table} ALTER COLUMN org_id TYPE varchar(12)`).execute(db);
4274
4295
  }
4275
4296
  //#endregion
4276
4297
  //#region src/db/migrations/018_org_id_prefix_backfill.ts
4277
4298
  var _018_org_id_prefix_backfill_exports = /* @__PURE__ */ __exportAll({
4278
- down: () => down$90,
4279
- up: () => up$90
4299
+ down: () => down$97,
4300
+ up: () => up$97
4280
4301
  });
4281
4302
  /**
4282
4303
  * Prefix every orchestrator-side tenant string with `org_` to align
@@ -4321,19 +4342,19 @@ const CUSTOMER_ID_TABLES = [
4321
4342
  "workflow_registrations",
4322
4343
  "org_settings"
4323
4344
  ];
4324
- async function up$90(db) {
4345
+ async function up$97(db) {
4325
4346
  for (const table of ORG_ID_TABLES) await sql.raw(`UPDATE public.${table} SET org_id = 'org_' || org_id WHERE org_id <> 'kici-admin' AND org_id NOT LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
4326
4347
  for (const table of CUSTOMER_ID_TABLES) await sql.raw(`UPDATE public.${table} SET customer_id = 'org_' || customer_id WHERE customer_id <> 'kici-admin' AND customer_id NOT LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
4327
4348
  }
4328
- async function down$90(db) {
4349
+ async function down$97(db) {
4329
4350
  for (const table of CUSTOMER_ID_TABLES) await sql.raw(`UPDATE public.${table} SET customer_id = substring(customer_id from 5) WHERE customer_id LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
4330
4351
  for (const table of ORG_ID_TABLES) await sql.raw(`UPDATE public.${table} SET org_id = substring(org_id from 5) WHERE org_id LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
4331
4352
  }
4332
4353
  //#endregion
4333
4354
  //#region src/db/migrations/019_generic_sources_change_notify.ts
4334
4355
  var _019_generic_sources_change_notify_exports = /* @__PURE__ */ __exportAll({
4335
- down: () => down$89,
4336
- up: () => up$89
4356
+ down: () => down$96,
4357
+ up: () => up$96
4337
4358
  });
4338
4359
  /**
4339
4360
  * Add a Postgres trigger on `generic_webhook_sources` that emits
@@ -4356,7 +4377,7 @@ var _019_generic_sources_change_notify_exports = /* @__PURE__ */ __exportAll({
4356
4377
  * (`notify_sources_change()` + `sources_change_trigger`, defined in
4357
4378
  * `001_initial.ts`).
4358
4379
  */
4359
- async function up$89(db) {
4380
+ async function up$96(db) {
4360
4381
  await sql`
4361
4382
  CREATE FUNCTION public.notify_generic_sources_change() RETURNS trigger
4362
4383
  LANGUAGE plpgsql
@@ -4377,15 +4398,15 @@ async function up$89(db) {
4377
4398
  FOR EACH ROW EXECUTE FUNCTION public.notify_generic_sources_change()
4378
4399
  `.execute(db);
4379
4400
  }
4380
- async function down$89(db) {
4401
+ async function down$96(db) {
4381
4402
  await sql`DROP TRIGGER IF EXISTS generic_sources_change_trigger ON public.generic_webhook_sources`.execute(db);
4382
4403
  await sql`DROP FUNCTION IF EXISTS public.notify_generic_sources_change()`.execute(db);
4383
4404
  }
4384
4405
  //#endregion
4385
4406
  //#region src/db/migrations/020_org_settings_dashboard_write_policy.ts
4386
4407
  var _020_org_settings_dashboard_write_policy_exports = /* @__PURE__ */ __exportAll({
4387
- down: () => down$88,
4388
- up: () => up$88
4408
+ down: () => down$95,
4409
+ up: () => up$95
4389
4410
  });
4390
4411
  /**
4391
4412
  * Add `org_settings.dashboard_write_policy jsonb NOT NULL DEFAULT '{}'`.
@@ -4400,7 +4421,7 @@ var _020_org_settings_dashboard_write_policy_exports = /* @__PURE__ */ __exportA
4400
4421
  *
4401
4422
  * Idempotent: a re-run on a DB that already has the column is a no-op.
4402
4423
  */
4403
- async function up$88(db) {
4424
+ async function up$95(db) {
4404
4425
  if ((await sql`
4405
4426
  SELECT EXISTS (
4406
4427
  SELECT 1 FROM information_schema.columns
@@ -4414,7 +4435,7 @@ async function up$88(db) {
4414
4435
  ADD COLUMN dashboard_write_policy jsonb NOT NULL DEFAULT '{}'::jsonb
4415
4436
  `.execute(db);
4416
4437
  }
4417
- async function down$88(db) {
4438
+ async function down$95(db) {
4418
4439
  await sql`
4419
4440
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS dashboard_write_policy
4420
4441
  `.execute(db);
@@ -4422,8 +4443,8 @@ async function down$88(db) {
4422
4443
  //#endregion
4423
4444
  //#region src/db/migrations/021_check_run_tracking.ts
4424
4445
  var _021_check_run_tracking_exports = /* @__PURE__ */ __exportAll({
4425
- down: () => down$87,
4426
- up: () => up$87
4446
+ down: () => down$94,
4447
+ up: () => up$94
4427
4448
  });
4428
4449
  /**
4429
4450
  * Add `check_run_tracking` table for HA-safe check-run state persistence.
@@ -4447,7 +4468,7 @@ var _021_check_run_tracking_exports = /* @__PURE__ */ __exportAll({
4447
4468
  *
4448
4469
  * Idempotent: a re-run on a DB that already has the table is a no-op.
4449
4470
  */
4450
- async function up$87(db) {
4471
+ async function up$94(db) {
4451
4472
  if ((await sql`
4452
4473
  SELECT EXISTS (
4453
4474
  SELECT 1 FROM information_schema.tables
@@ -4478,14 +4499,14 @@ async function up$87(db) {
4478
4499
  WHERE run_id IS NOT NULL
4479
4500
  `.execute(db);
4480
4501
  }
4481
- async function down$87(db) {
4502
+ async function down$94(db) {
4482
4503
  await sql`DROP TABLE IF EXISTS public.check_run_tracking`.execute(db);
4483
4504
  }
4484
4505
  //#endregion
4485
4506
  //#region src/db/migrations/022_scaler_manager_state.ts
4486
4507
  var _022_scaler_manager_state_exports = /* @__PURE__ */ __exportAll({
4487
- down: () => down$86,
4488
- up: () => up$86
4508
+ down: () => down$93,
4509
+ up: () => up$93
4489
4510
  });
4490
4511
  /**
4491
4512
  * Add three tables persisting `ScalerManager` per-coord state:
@@ -4512,7 +4533,7 @@ var _022_scaler_manager_state_exports = /* @__PURE__ */ __exportAll({
4512
4533
  * Idempotent: a re-run on a DB that already has any of these tables
4513
4534
  * leaves the existing one alone.
4514
4535
  */
4515
- async function up$86(db) {
4536
+ async function up$93(db) {
4516
4537
  const tableExists = async (name) => {
4517
4538
  return (await sql`
4518
4539
  SELECT EXISTS (
@@ -4562,7 +4583,7 @@ async function up$86(db) {
4562
4583
  `.execute(db);
4563
4584
  }
4564
4585
  }
4565
- async function down$86(db) {
4586
+ async function down$93(db) {
4566
4587
  await sql`DROP TABLE IF EXISTS public.scaler_reservations`.execute(db);
4567
4588
  await sql`DROP TABLE IF EXISTS public.scaler_agent_jobs`.execute(db);
4568
4589
  await sql`DROP TABLE IF EXISTS public.scaler_spawning_agents`.execute(db);
@@ -4570,8 +4591,8 @@ async function down$86(db) {
4570
4591
  //#endregion
4571
4592
  //#region src/db/migrations/023_dispatch_queue_recovery_deadline.ts
4572
4593
  var _023_dispatch_queue_recovery_deadline_exports = /* @__PURE__ */ __exportAll({
4573
- down: () => down$85,
4574
- up: () => up$85
4594
+ down: () => down$92,
4595
+ up: () => up$92
4575
4596
  });
4576
4597
  /**
4577
4598
  * Add `dispatch_queue.recovery_deadline TIMESTAMPTZ` and
@@ -4595,7 +4616,7 @@ var _023_dispatch_queue_recovery_deadline_exports = /* @__PURE__ */ __exportAll(
4595
4616
  * Idempotent: re-running on a DB that already has either column is a
4596
4617
  * no-op.
4597
4618
  */
4598
- async function up$85(db) {
4619
+ async function up$92(db) {
4599
4620
  const colExists = async (name) => {
4600
4621
  return (await sql`
4601
4622
  SELECT EXISTS (
@@ -4620,7 +4641,7 @@ async function up$85(db) {
4620
4641
  WHERE recovery_deadline IS NOT NULL
4621
4642
  `.execute(db);
4622
4643
  }
4623
- async function down$85(db) {
4644
+ async function down$92(db) {
4624
4645
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_recovery_deadline`.execute(db);
4625
4646
  await sql`
4626
4647
  ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS recovery_agent_id
@@ -4632,8 +4653,8 @@ async function down$85(db) {
4632
4653
  //#endregion
4633
4654
  //#region src/db/migrations/024_dispatch_queue_provisioning_error.ts
4634
4655
  var _024_dispatch_queue_provisioning_error_exports = /* @__PURE__ */ __exportAll({
4635
- down: () => down$84,
4636
- up: () => up$84
4656
+ down: () => down$91,
4657
+ up: () => up$91
4637
4658
  });
4638
4659
  /**
4639
4660
  * Add `dispatch_queue.last_provisioning_error TEXT` recording the most
@@ -4649,7 +4670,7 @@ var _024_dispatch_queue_provisioning_error_exports = /* @__PURE__ */ __exportAll
4649
4670
  *
4650
4671
  * Idempotent: re-running on a DB that already has the column is a no-op.
4651
4672
  */
4652
- async function up$84(db) {
4673
+ async function up$91(db) {
4653
4674
  const colExists = async (name) => {
4654
4675
  return (await sql`
4655
4676
  SELECT EXISTS (
@@ -4665,7 +4686,7 @@ async function up$84(db) {
4665
4686
  ADD COLUMN last_provisioning_error TEXT
4666
4687
  `.execute(db);
4667
4688
  }
4668
- async function down$84(db) {
4689
+ async function down$91(db) {
4669
4690
  await sql`
4670
4691
  ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS last_provisioning_error
4671
4692
  `.execute(db);
@@ -4673,8 +4694,8 @@ async function down$84(db) {
4673
4694
  //#endregion
4674
4695
  //#region src/db/migrations/025_init_failure.ts
4675
4696
  var _025_init_failure_exports = /* @__PURE__ */ __exportAll({
4676
- down: () => down$83,
4677
- up: () => up$83
4697
+ down: () => down$90,
4698
+ up: () => up$90
4678
4699
  });
4679
4700
  /**
4680
4701
  * Add `init_failure jsonb` columns to `execution_runs` and `execution_jobs`.
@@ -4688,7 +4709,7 @@ var _025_init_failure_exports = /* @__PURE__ */ __exportAll({
4688
4709
  * Idempotent: re-running on a DB that already has either column is a no-op
4689
4710
  * for that column.
4690
4711
  */
4691
- async function up$83(db) {
4712
+ async function up$90(db) {
4692
4713
  const colExists = async (table, name) => {
4693
4714
  return (await sql`
4694
4715
  SELECT EXISTS (
@@ -4708,7 +4729,7 @@ async function up$83(db) {
4708
4729
  ADD COLUMN init_failure JSONB DEFAULT NULL
4709
4730
  `.execute(db);
4710
4731
  }
4711
- async function down$83(db) {
4732
+ async function down$90(db) {
4712
4733
  await sql`
4713
4734
  ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS init_failure
4714
4735
  `.execute(db);
@@ -4719,8 +4740,8 @@ async function down$83(db) {
4719
4740
  //#endregion
4720
4741
  //#region src/db/migrations/026_event_log_lockfile_corrupt.ts
4721
4742
  var _026_event_log_lockfile_corrupt_exports = /* @__PURE__ */ __exportAll({
4722
- down: () => down$82,
4723
- up: () => up$82
4743
+ down: () => down$89,
4744
+ up: () => up$89
4724
4745
  });
4725
4746
  /**
4726
4747
  * Extend the event_log.status CHECK constraint with 'lockfile_corrupt' so the
@@ -4729,7 +4750,7 @@ var _026_event_log_lockfile_corrupt_exports = /* @__PURE__ */ __exportAll({
4729
4750
  *
4730
4751
  * Idempotent: the DROP ... IF EXISTS / re-ADD pair re-runs cleanly.
4731
4752
  */
4732
- async function up$82(db) {
4753
+ async function up$89(db) {
4733
4754
  await sql`ALTER TABLE event_log DROP CONSTRAINT IF EXISTS event_log_status_check`.execute(db);
4734
4755
  await sql`
4735
4756
  ALTER TABLE event_log ADD CONSTRAINT event_log_status_check
@@ -4739,7 +4760,7 @@ async function up$82(db) {
4739
4760
  ])))
4740
4761
  `.execute(db);
4741
4762
  }
4742
- async function down$82(db) {
4763
+ async function down$89(db) {
4743
4764
  await sql`ALTER TABLE event_log DROP CONSTRAINT IF EXISTS event_log_status_check`.execute(db);
4744
4765
  await sql`
4745
4766
  ALTER TABLE event_log ADD CONSTRAINT event_log_status_check
@@ -4752,8 +4773,8 @@ async function down$82(db) {
4752
4773
  //#endregion
4753
4774
  //#region src/db/migrations/027_workflow_timeout.ts
4754
4775
  var _027_workflow_timeout_exports = /* @__PURE__ */ __exportAll({
4755
- down: () => down$81,
4756
- up: () => up$81
4776
+ down: () => down$88,
4777
+ up: () => up$88
4757
4778
  });
4758
4779
  /**
4759
4780
  * Add `workflow_timeout_ms integer` to `execution_runs`.
@@ -4771,13 +4792,13 @@ var _027_workflow_timeout_exports = /* @__PURE__ */ __exportAll({
4771
4792
  *
4772
4793
  * Idempotent: re-running on a DB that already has the column is a no-op.
4773
4794
  */
4774
- async function up$81(db) {
4795
+ async function up$88(db) {
4775
4796
  await sql`
4776
4797
  ALTER TABLE public.execution_runs
4777
4798
  ADD COLUMN IF NOT EXISTS workflow_timeout_ms INTEGER DEFAULT NULL
4778
4799
  `.execute(db);
4779
4800
  }
4780
- async function down$81(db) {
4801
+ async function down$88(db) {
4781
4802
  await sql`
4782
4803
  ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS workflow_timeout_ms
4783
4804
  `.execute(db);
@@ -4785,8 +4806,8 @@ async function down$81(db) {
4785
4806
  //#endregion
4786
4807
  //#region src/db/migrations/028_org_settings_user_cache.ts
4787
4808
  var _028_org_settings_user_cache_exports = /* @__PURE__ */ __exportAll({
4788
- down: () => down$80,
4789
- up: () => up$80
4809
+ down: () => down$87,
4810
+ up: () => up$87
4790
4811
  });
4791
4812
  /**
4792
4813
  * Add `org_settings.user_cache_quota_bytes bigint` and
@@ -4805,7 +4826,7 @@ var _028_org_settings_user_cache_exports = /* @__PURE__ */ __exportAll({
4805
4826
  *
4806
4827
  * Idempotent: a re-run on a DB that already has either column skips it.
4807
4828
  */
4808
- async function columnExists$6(db, column) {
4829
+ async function columnExists$11(db, column) {
4809
4830
  return (await sql`
4810
4831
  SELECT EXISTS (
4811
4832
  SELECT 1 FROM information_schema.columns
@@ -4815,17 +4836,17 @@ async function columnExists$6(db, column) {
4815
4836
  ) AS exists
4816
4837
  `.execute(db)).rows[0]?.exists ?? false;
4817
4838
  }
4818
- async function up$80(db) {
4819
- if (!await columnExists$6(db, "user_cache_quota_bytes")) await sql`
4839
+ async function up$87(db) {
4840
+ if (!await columnExists$11(db, "user_cache_quota_bytes")) await sql`
4820
4841
  ALTER TABLE public.org_settings
4821
4842
  ADD COLUMN user_cache_quota_bytes bigint
4822
4843
  `.execute(db);
4823
- if (!await columnExists$6(db, "user_cache_ttl_ms")) await sql`
4844
+ if (!await columnExists$11(db, "user_cache_ttl_ms")) await sql`
4824
4845
  ALTER TABLE public.org_settings
4825
4846
  ADD COLUMN user_cache_ttl_ms bigint
4826
4847
  `.execute(db);
4827
4848
  }
4828
- async function down$80(db) {
4849
+ async function down$87(db) {
4829
4850
  await sql`
4830
4851
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS user_cache_quota_bytes
4831
4852
  `.execute(db);
@@ -4836,8 +4857,8 @@ async function down$80(db) {
4836
4857
  //#endregion
4837
4858
  //#region src/db/migrations/029_dispatch_queue_attempts.ts
4838
4859
  var _029_dispatch_queue_attempts_exports = /* @__PURE__ */ __exportAll({
4839
- down: () => down$79,
4840
- up: () => up$79
4860
+ down: () => down$86,
4861
+ up: () => up$86
4841
4862
  });
4842
4863
  /**
4843
4864
  * Add `dispatch_queue.dispatch_attempts INT NOT NULL DEFAULT 0`.
@@ -4851,7 +4872,7 @@ var _029_dispatch_queue_attempts_exports = /* @__PURE__ */ __exportAll({
4851
4872
  *
4852
4873
  * Idempotent: re-running on a DB that already has the column is a no-op.
4853
4874
  */
4854
- async function up$79(db) {
4875
+ async function up$86(db) {
4855
4876
  if (!((await sql`
4856
4877
  SELECT EXISTS (
4857
4878
  SELECT 1 FROM information_schema.columns
@@ -4864,7 +4885,7 @@ async function up$79(db) {
4864
4885
  ADD COLUMN dispatch_attempts INT NOT NULL DEFAULT 0
4865
4886
  `.execute(db);
4866
4887
  }
4867
- async function down$79(db) {
4888
+ async function down$86(db) {
4868
4889
  await sql`
4869
4890
  ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS dispatch_attempts
4870
4891
  `.execute(db);
@@ -4872,8 +4893,8 @@ async function down$79(db) {
4872
4893
  //#endregion
4873
4894
  //#region src/db/migrations/030_held_runs_env_set_null.ts
4874
4895
  var _030_held_runs_env_set_null_exports = /* @__PURE__ */ __exportAll({
4875
- down: () => down$78,
4876
- up: () => up$78
4896
+ down: () => down$85,
4897
+ up: () => up$85
4877
4898
  });
4878
4899
  /**
4879
4900
  * held_runs.environment_id becomes nullable with ON DELETE SET NULL so
@@ -4884,14 +4905,14 @@ var _030_held_runs_env_set_null_exports = /* @__PURE__ */ __exportAll({
4884
4905
  * Idempotent: dropping the NOT NULL and the constraint are both no-ops on a
4885
4906
  * re-run, and the constraint is re-created with the SET NULL action.
4886
4907
  */
4887
- async function up$78(db) {
4908
+ async function up$85(db) {
4888
4909
  await sql`ALTER TABLE public.held_runs ALTER COLUMN environment_id DROP NOT NULL`.execute(db);
4889
4910
  await sql`ALTER TABLE public.held_runs DROP CONSTRAINT IF EXISTS held_runs_environment_id_fkey`.execute(db);
4890
4911
  await sql`ALTER TABLE public.held_runs
4891
4912
  ADD CONSTRAINT held_runs_environment_id_fkey
4892
4913
  FOREIGN KEY (environment_id) REFERENCES public.environments(id) ON DELETE SET NULL`.execute(db);
4893
4914
  }
4894
- async function down$78(db) {
4915
+ async function down$85(db) {
4895
4916
  await sql`ALTER TABLE public.held_runs DROP CONSTRAINT IF EXISTS held_runs_environment_id_fkey`.execute(db);
4896
4917
  await sql`ALTER TABLE public.held_runs
4897
4918
  ADD CONSTRAINT held_runs_environment_id_fkey
@@ -4901,8 +4922,8 @@ async function down$78(db) {
4901
4922
  //#endregion
4902
4923
  //#region src/db/migrations/031_dispatch_queue_ack_deadline.ts
4903
4924
  var _031_dispatch_queue_ack_deadline_exports = /* @__PURE__ */ __exportAll({
4904
- down: () => down$77,
4905
- up: () => up$77
4925
+ down: () => down$84,
4926
+ up: () => up$84
4906
4927
  });
4907
4928
  /**
4908
4929
  * Add `dispatch_queue.ack_deadline TIMESTAMPTZ` and
@@ -4919,7 +4940,7 @@ var _031_dispatch_queue_ack_deadline_exports = /* @__PURE__ */ __exportAll({
4919
4940
  *
4920
4941
  * Idempotent: re-running on a DB that already has either column is a no-op.
4921
4942
  */
4922
- async function up$77(db) {
4943
+ async function up$84(db) {
4923
4944
  const colExists = async (name) => {
4924
4945
  return (await sql`
4925
4946
  SELECT EXISTS (
@@ -4944,7 +4965,7 @@ async function up$77(db) {
4944
4965
  WHERE ack_deadline IS NOT NULL
4945
4966
  `.execute(db);
4946
4967
  }
4947
- async function down$77(db) {
4968
+ async function down$84(db) {
4948
4969
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_ack_deadline`.execute(db);
4949
4970
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS ack_agent_id`.execute(db);
4950
4971
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS ack_deadline`.execute(db);
@@ -4952,8 +4973,8 @@ async function down$77(db) {
4952
4973
  //#endregion
4953
4974
  //#region src/db/migrations/032_org_settings_dispatch_ack_timeout.ts
4954
4975
  var _032_org_settings_dispatch_ack_timeout_exports = /* @__PURE__ */ __exportAll({
4955
- down: () => down$76,
4956
- up: () => up$76
4976
+ down: () => down$83,
4977
+ up: () => up$83
4957
4978
  });
4958
4979
  /**
4959
4980
  * Add `org_settings.dispatch_ack_timeout_ms BIGINT` (nullable).
@@ -4965,7 +4986,7 @@ var _032_org_settings_dispatch_ack_timeout_exports = /* @__PURE__ */ __exportAll
4965
4986
  *
4966
4987
  * Idempotent: a re-run on a DB that already has the column is a no-op.
4967
4988
  */
4968
- async function up$76(db) {
4989
+ async function up$83(db) {
4969
4990
  if ((await sql`
4970
4991
  SELECT EXISTS (
4971
4992
  SELECT 1 FROM information_schema.columns
@@ -4979,7 +5000,7 @@ async function up$76(db) {
4979
5000
  ADD COLUMN dispatch_ack_timeout_ms BIGINT
4980
5001
  `.execute(db);
4981
5002
  }
4982
- async function down$76(db) {
5003
+ async function down$83(db) {
4983
5004
  await sql`
4984
5005
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS dispatch_ack_timeout_ms
4985
5006
  `.execute(db);
@@ -4987,8 +5008,8 @@ async function down$76(db) {
4987
5008
  //#endregion
4988
5009
  //#region src/db/migrations/033_org_settings_approval.ts
4989
5010
  var _033_org_settings_approval_exports = /* @__PURE__ */ __exportAll({
4990
- down: () => down$75,
4991
- up: () => up$75
5011
+ down: () => down$82,
5012
+ up: () => up$82
4992
5013
  });
4993
5014
  /**
4994
5015
  * Add the two approval-policy columns to `org_settings`:
@@ -5005,7 +5026,7 @@ var _033_org_settings_approval_exports = /* @__PURE__ */ __exportAll({
5005
5026
  * and the orchestrator admin route. Idempotent: a re-run on a DB that already
5006
5027
  * has the columns is a no-op (each column is guarded independently).
5007
5028
  */
5008
- async function up$75(db) {
5029
+ async function up$82(db) {
5009
5030
  const colExists = async (column) => {
5010
5031
  return (await sql`
5011
5032
  SELECT EXISTS (
@@ -5025,7 +5046,7 @@ async function up$75(db) {
5025
5046
  ADD COLUMN allow_self_approval BOOLEAN NOT NULL DEFAULT true
5026
5047
  `.execute(db);
5027
5048
  }
5028
- async function down$75(db) {
5049
+ async function down$82(db) {
5029
5050
  await sql`
5030
5051
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS approval_expiry_seconds
5031
5052
  `.execute(db);
@@ -5036,8 +5057,8 @@ async function down$75(db) {
5036
5057
  //#endregion
5037
5058
  //#region src/db/migrations/034_held_runs_generalize.ts
5038
5059
  var _034_held_runs_generalize_exports = /* @__PURE__ */ __exportAll({
5039
- down: () => down$74,
5040
- up: () => up$74
5060
+ down: () => down$81,
5061
+ up: () => up$81
5041
5062
  });
5042
5063
  /**
5043
5064
  * Generalize `held_runs` from an environment-only hold into the unified
@@ -5059,7 +5080,7 @@ var _034_held_runs_generalize_exports = /* @__PURE__ */ __exportAll({
5059
5080
  * New `held_run_approvals` table: one row per approver decision, FK to
5060
5081
  * `held_runs.id` (uuid) with ON DELETE CASCADE.
5061
5082
  */
5062
- async function up$74(db) {
5083
+ async function up$81(db) {
5063
5084
  const colExists = async (column) => {
5064
5085
  return (await sql`
5065
5086
  SELECT EXISTS (
@@ -5092,7 +5113,7 @@ async function up$74(db) {
5092
5113
  ON public.held_run_approvals USING btree (held_run_id)
5093
5114
  `.execute(db);
5094
5115
  }
5095
- async function down$74(db) {
5116
+ async function down$81(db) {
5096
5117
  await sql`DROP TABLE IF EXISTS public.held_run_approvals`.execute(db);
5097
5118
  await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS approval_requirement`.execute(db);
5098
5119
  await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS trigger_source`.execute(db);
@@ -5102,8 +5123,8 @@ async function down$74(db) {
5102
5123
  //#endregion
5103
5124
  //#region src/db/migrations/035_pending_workflow_contexts.ts
5104
5125
  var _035_pending_workflow_contexts_exports = /* @__PURE__ */ __exportAll({
5105
- down: () => down$73,
5106
- up: () => up$73
5126
+ down: () => down$80,
5127
+ up: () => up$80
5107
5128
  });
5108
5129
  /**
5109
5130
  * Pending workflow dispatch context — backs resume of a workflow whose install
@@ -5112,7 +5133,7 @@ var _035_pending_workflow_contexts_exports = /* @__PURE__ */ __exportAll({
5112
5133
  * wait-timer expiry, concurrency slot free). The row is deleted once the resume
5113
5134
  * dispatch has been kicked off.
5114
5135
  */
5115
- async function up$73(db) {
5136
+ async function up$80(db) {
5116
5137
  await sql`
5117
5138
  CREATE TABLE IF NOT EXISTS public.pending_workflow_contexts (
5118
5139
  run_id text PRIMARY KEY,
@@ -5122,14 +5143,14 @@ async function up$73(db) {
5122
5143
  )
5123
5144
  `.execute(db);
5124
5145
  }
5125
- async function down$73(db) {
5146
+ async function down$80(db) {
5126
5147
  await sql`DROP TABLE IF EXISTS public.pending_workflow_contexts`.execute(db);
5127
5148
  }
5128
5149
  //#endregion
5129
5150
  //#region src/db/migrations/036_attestations.ts
5130
5151
  var _036_attestations_exports = /* @__PURE__ */ __exportAll({
5131
- down: () => down$72,
5132
- up: () => up$72
5152
+ down: () => down$79,
5153
+ up: () => up$79
5133
5154
  });
5134
5155
  /**
5135
5156
  * Add the `attestations` table for build-provenance bundles.
@@ -5142,7 +5163,7 @@ var _036_attestations_exports = /* @__PURE__ */ __exportAll({
5142
5163
  *
5143
5164
  * Idempotent: a re-run on a DB that already has the table is a no-op.
5144
5165
  */
5145
- async function up$72(db) {
5166
+ async function up$79(db) {
5146
5167
  if ((await sql`
5147
5168
  SELECT EXISTS (
5148
5169
  SELECT 1 FROM information_schema.tables
@@ -5168,14 +5189,14 @@ async function up$72(db) {
5168
5189
  ON public.attestations (run_id, job_id)
5169
5190
  `.execute(db);
5170
5191
  }
5171
- async function down$72(db) {
5192
+ async function down$79(db) {
5172
5193
  await sql`DROP TABLE IF EXISTS public.attestations`.execute(db);
5173
5194
  }
5174
5195
  //#endregion
5175
5196
  //#region src/db/migrations/037_generic_sources_provider_type_local.ts
5176
5197
  var _037_generic_sources_provider_type_local_exports = /* @__PURE__ */ __exportAll({
5177
- down: () => down$71,
5178
- up: () => up$71
5198
+ down: () => down$78,
5199
+ up: () => up$78
5179
5200
  });
5180
5201
  /**
5181
5202
  * Replace the `generic_webhook_sources.provider_type` CHECK constraint so it
@@ -5192,7 +5213,7 @@ var _037_generic_sources_provider_type_local_exports = /* @__PURE__ */ __exportA
5192
5213
  * Idempotent: the constraint is dropped IF EXISTS and recreated; the data
5193
5214
  * backfill is a plain UPDATE that is a no-op once no `'internal'` rows remain.
5194
5215
  */
5195
- async function up$71(db) {
5216
+ async function up$78(db) {
5196
5217
  await sql`
5197
5218
  ALTER TABLE public.generic_webhook_sources
5198
5219
  DROP CONSTRAINT IF EXISTS generic_webhook_sources_provider_type_check
@@ -5208,7 +5229,7 @@ async function up$71(db) {
5208
5229
  CHECK (provider_type = ANY (ARRAY['generic'::text, 'local'::text]))
5209
5230
  `.execute(db);
5210
5231
  }
5211
- async function down$71(db) {
5232
+ async function down$78(db) {
5212
5233
  await sql`
5213
5234
  ALTER TABLE public.generic_webhook_sources
5214
5235
  DROP CONSTRAINT IF EXISTS generic_webhook_sources_provider_type_check
@@ -5227,8 +5248,8 @@ async function down$71(db) {
5227
5248
  //#endregion
5228
5249
  //#region src/db/migrations/038_remote_sources.ts
5229
5250
  var _038_remote_sources_exports = /* @__PURE__ */ __exportAll({
5230
- down: () => down$70,
5231
- up: () => up$70
5251
+ down: () => down$77,
5252
+ up: () => up$77
5232
5253
  });
5233
5254
  /**
5234
5255
  * `remote_sources` anchors a Platform-relayed `kici run remote` to its real
@@ -5240,7 +5261,7 @@ var _038_remote_sources_exports = /* @__PURE__ */ __exportAll({
5240
5261
  *
5241
5262
  * Idempotent: a re-run on a DB that already has the table is a no-op.
5242
5263
  */
5243
- async function up$70(db) {
5264
+ async function up$77(db) {
5244
5265
  if ((await sql`
5245
5266
  SELECT EXISTS (
5246
5267
  SELECT 1 FROM information_schema.tables
@@ -5259,14 +5280,14 @@ async function up$70(db) {
5259
5280
  )
5260
5281
  `.execute(db);
5261
5282
  }
5262
- async function down$70(db) {
5283
+ async function down$77(db) {
5263
5284
  await sql`DROP TABLE IF EXISTS public.remote_sources`.execute(db);
5264
5285
  }
5265
5286
  //#endregion
5266
5287
  //#region src/db/migrations/039_host_roster.ts
5267
5288
  var _039_host_roster_exports = /* @__PURE__ */ __exportAll({
5268
- down: () => down$69,
5269
- up: () => up$69
5289
+ down: () => down$76,
5290
+ up: () => up$76
5270
5291
  });
5271
5292
  /**
5272
5293
  * `host_roster` is KiCI's declared inventory: one durable row per agent the
@@ -5283,7 +5304,7 @@ var _039_host_roster_exports = /* @__PURE__ */ __exportAll({
5283
5304
  *
5284
5305
  * Idempotent: a re-run on a DB that already has the table is a no-op.
5285
5306
  */
5286
- async function up$69(db) {
5307
+ async function up$76(db) {
5287
5308
  if ((await sql`
5288
5309
  SELECT EXISTS (
5289
5310
  SELECT 1 FROM information_schema.tables
@@ -5313,14 +5334,14 @@ async function up$69(db) {
5313
5334
  await sql`CREATE INDEX idx_host_roster_reap
5314
5335
  ON public.host_roster (lifecycle_class, last_seen)`.execute(db);
5315
5336
  }
5316
- async function down$69(db) {
5337
+ async function down$76(db) {
5317
5338
  await sql`DROP TABLE IF EXISTS public.host_roster`.execute(db);
5318
5339
  }
5319
5340
  //#endregion
5320
5341
  //#region src/db/migrations/040_runsonall_pin.ts
5321
5342
  var _040_runsonall_pin_exports = /* @__PURE__ */ __exportAll({
5322
- down: () => down$68,
5323
- up: () => up$68
5343
+ down: () => down$75,
5344
+ up: () => up$75
5324
5345
  });
5325
5346
  /**
5326
5347
  * Add the `runsOnAll` host fan-out columns:
@@ -5337,7 +5358,7 @@ var _040_runsonall_pin_exports = /* @__PURE__ */ __exportAll({
5337
5358
  *
5338
5359
  * Idempotent: re-running on a DB that already has any column is a no-op.
5339
5360
  */
5340
- async function colExists$12(db, table, name) {
5361
+ async function colExists$13(db, table, name) {
5341
5362
  return (await sql`
5342
5363
  SELECT EXISTS (
5343
5364
  SELECT 1 FROM information_schema.columns
@@ -5347,18 +5368,18 @@ async function colExists$12(db, table, name) {
5347
5368
  ) AS exists
5348
5369
  `.execute(db)).rows[0]?.exists ?? false;
5349
5370
  }
5350
- async function up$68(db) {
5351
- if (!await colExists$12(db, "dispatch_queue", "pinned_agent_id")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN pinned_agent_id TEXT`.execute(db);
5352
- if (!await colExists$12(db, "execution_jobs", "base_job_name")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN base_job_name TEXT`.execute(db);
5353
- if (!await colExists$12(db, "execution_jobs", "variant_kind")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN variant_kind TEXT`.execute(db);
5354
- if (!await colExists$12(db, "execution_jobs", "variant_label")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN variant_label TEXT`.execute(db);
5371
+ async function up$75(db) {
5372
+ if (!await colExists$13(db, "dispatch_queue", "pinned_agent_id")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN pinned_agent_id TEXT`.execute(db);
5373
+ if (!await colExists$13(db, "execution_jobs", "base_job_name")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN base_job_name TEXT`.execute(db);
5374
+ if (!await colExists$13(db, "execution_jobs", "variant_kind")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN variant_kind TEXT`.execute(db);
5375
+ if (!await colExists$13(db, "execution_jobs", "variant_label")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN variant_label TEXT`.execute(db);
5355
5376
  await sql`
5356
5377
  CREATE INDEX IF NOT EXISTS idx_dispatch_queue_pinned_agent
5357
5378
  ON public.dispatch_queue (pinned_agent_id)
5358
5379
  WHERE pinned_agent_id IS NOT NULL
5359
5380
  `.execute(db);
5360
5381
  }
5361
- async function down$68(db) {
5382
+ async function down$75(db) {
5362
5383
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_pinned_agent`.execute(db);
5363
5384
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS pinned_agent_id`.execute(db);
5364
5385
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS variant_label`.execute(db);
@@ -5368,8 +5389,8 @@ async function down$68(db) {
5368
5389
  //#endregion
5369
5390
  //#region src/db/migrations/041_wave_gated.ts
5370
5391
  var _041_wave_gated_exports = /* @__PURE__ */ __exportAll({
5371
- down: () => down$67,
5372
- up: () => up$67
5392
+ down: () => down$74,
5393
+ up: () => up$74
5373
5394
  });
5374
5395
  /**
5375
5396
  * Add the rolling fan-out wave-gate columns:
@@ -5389,7 +5410,7 @@ var _041_wave_gated_exports = /* @__PURE__ */ __exportAll({
5389
5410
  *
5390
5411
  * Idempotent: re-running on a DB that already has the columns is a no-op.
5391
5412
  */
5392
- async function colExists$11(db, table, name) {
5413
+ async function colExists$12(db, table, name) {
5393
5414
  return (await sql`
5394
5415
  SELECT EXISTS (
5395
5416
  SELECT 1 FROM information_schema.columns
@@ -5399,16 +5420,16 @@ async function colExists$11(db, table, name) {
5399
5420
  ) AS exists
5400
5421
  `.execute(db)).rows[0]?.exists ?? false;
5401
5422
  }
5402
- async function up$67(db) {
5403
- if (!await colExists$11(db, "execution_jobs", "wave_gated")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_gated boolean NOT NULL DEFAULT false`.execute(db);
5404
- if (!await colExists$11(db, "execution_jobs", "wave_max_parallel")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_max_parallel integer`.execute(db);
5405
- if (!await colExists$11(db, "execution_jobs", "wave_fail_fast")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_fail_fast boolean`.execute(db);
5423
+ async function up$74(db) {
5424
+ if (!await colExists$12(db, "execution_jobs", "wave_gated")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_gated boolean NOT NULL DEFAULT false`.execute(db);
5425
+ if (!await colExists$12(db, "execution_jobs", "wave_max_parallel")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_max_parallel integer`.execute(db);
5426
+ if (!await colExists$12(db, "execution_jobs", "wave_fail_fast")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_fail_fast boolean`.execute(db);
5406
5427
  await sql`
5407
5428
  CREATE INDEX IF NOT EXISTS idx_execution_jobs_wave
5408
5429
  ON public.execution_jobs (run_id, base_job_name, wave_gated)
5409
5430
  `.execute(db);
5410
5431
  }
5411
- async function down$67(db) {
5432
+ async function down$74(db) {
5412
5433
  await sql`DROP INDEX IF EXISTS public.idx_execution_jobs_wave`.execute(db);
5413
5434
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS wave_fail_fast`.execute(db);
5414
5435
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS wave_max_parallel`.execute(db);
@@ -5417,8 +5438,8 @@ async function down$67(db) {
5417
5438
  //#endregion
5418
5439
  //#region src/db/migrations/042_dispatch_queue_patterns.ts
5419
5440
  var _042_dispatch_queue_patterns_exports = /* @__PURE__ */ __exportAll({
5420
- down: () => down$66,
5421
- up: () => up$66
5441
+ down: () => down$73,
5442
+ up: () => up$73
5422
5443
  });
5423
5444
  /**
5424
5445
  * Add pattern columns to dispatch_queue. Exact labels stay in runs_on_labels /
@@ -5434,7 +5455,7 @@ var _042_dispatch_queue_patterns_exports = /* @__PURE__ */ __exportAll({
5434
5455
  *
5435
5456
  * Idempotent: re-running on a DB that already has the columns is a no-op.
5436
5457
  */
5437
- async function colExists$10(db, table, name) {
5458
+ async function colExists$11(db, table, name) {
5438
5459
  return (await sql`
5439
5460
  SELECT EXISTS (
5440
5461
  SELECT 1 FROM information_schema.columns
@@ -5444,19 +5465,19 @@ async function colExists$10(db, table, name) {
5444
5465
  ) AS exists
5445
5466
  `.execute(db)).rows[0]?.exists ?? false;
5446
5467
  }
5447
- async function up$66(db) {
5448
- if (!await colExists$10(db, "dispatch_queue", "runs_on_patterns")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN runs_on_patterns jsonb NOT NULL DEFAULT '[]'::jsonb`.execute(db);
5449
- if (!await colExists$10(db, "dispatch_queue", "exclude_patterns")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN exclude_patterns jsonb NOT NULL DEFAULT '[]'::jsonb`.execute(db);
5468
+ async function up$73(db) {
5469
+ if (!await colExists$11(db, "dispatch_queue", "runs_on_patterns")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN runs_on_patterns jsonb NOT NULL DEFAULT '[]'::jsonb`.execute(db);
5470
+ if (!await colExists$11(db, "dispatch_queue", "exclude_patterns")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN exclude_patterns jsonb NOT NULL DEFAULT '[]'::jsonb`.execute(db);
5450
5471
  }
5451
- async function down$66(db) {
5472
+ async function down$73(db) {
5452
5473
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS exclude_patterns`.execute(db);
5453
5474
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS runs_on_patterns`.execute(db);
5454
5475
  }
5455
5476
  //#endregion
5456
5477
  //#region src/db/migrations/043_rerouted_to_peer.ts
5457
5478
  var _043_rerouted_to_peer_exports = /* @__PURE__ */ __exportAll({
5458
- down: () => down$65,
5459
- up: () => up$65
5479
+ down: () => down$72,
5480
+ up: () => up$72
5460
5481
  });
5461
5482
  /**
5462
5483
  * Add a nullable `rerouted_to_peer text` marker to execution_jobs. Non-null
@@ -5467,7 +5488,7 @@ var _043_rerouted_to_peer_exports = /* @__PURE__ */ __exportAll({
5467
5488
  *
5468
5489
  * Idempotent: re-running on a DB that already has the column is a no-op.
5469
5490
  */
5470
- async function colExists$9(db, table, name) {
5491
+ async function colExists$10(db, table, name) {
5471
5492
  return (await sql`
5472
5493
  SELECT EXISTS (
5473
5494
  SELECT 1 FROM information_schema.columns
@@ -5477,17 +5498,17 @@ async function colExists$9(db, table, name) {
5477
5498
  ) AS exists
5478
5499
  `.execute(db)).rows[0]?.exists ?? false;
5479
5500
  }
5480
- async function up$65(db) {
5481
- if (!await colExists$9(db, "execution_jobs", "rerouted_to_peer")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN rerouted_to_peer text`.execute(db);
5501
+ async function up$72(db) {
5502
+ if (!await colExists$10(db, "execution_jobs", "rerouted_to_peer")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN rerouted_to_peer text`.execute(db);
5482
5503
  }
5483
- async function down$65(db) {
5504
+ async function down$72(db) {
5484
5505
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS rerouted_to_peer`.execute(db);
5485
5506
  }
5486
5507
  //#endregion
5487
5508
  //#region src/db/migrations/044_check_mode.ts
5488
5509
  var _044_check_mode_exports = /* @__PURE__ */ __exportAll({
5489
- down: () => down$64,
5490
- up: () => up$64
5510
+ down: () => down$71,
5511
+ up: () => up$71
5491
5512
  });
5492
5513
  /**
5493
5514
  * Add idempotent check-mode columns:
@@ -5504,7 +5525,7 @@ var _044_check_mode_exports = /* @__PURE__ */ __exportAll({
5504
5525
  * All nullable. Idempotent: re-running on a DB that already has the columns is
5505
5526
  * a no-op.
5506
5527
  */
5507
- async function colExists$8(db, table, name) {
5528
+ async function colExists$9(db, table, name) {
5508
5529
  return (await sql`
5509
5530
  SELECT EXISTS (
5510
5531
  SELECT 1 FROM information_schema.columns
@@ -5514,13 +5535,13 @@ async function colExists$8(db, table, name) {
5514
5535
  ) AS exists
5515
5536
  `.execute(db)).rows[0]?.exists ?? false;
5516
5537
  }
5517
- async function up$64(db) {
5518
- if (!await colExists$8(db, "execution_runs", "check_mode")) await sql`ALTER TABLE public.execution_runs ADD COLUMN check_mode text`.execute(db);
5519
- if (!await colExists$8(db, "execution_steps", "check_outcome")) await sql`ALTER TABLE public.execution_steps ADD COLUMN check_outcome text`.execute(db);
5520
- if (!await colExists$8(db, "execution_steps", "drift_summary")) await sql`ALTER TABLE public.execution_steps ADD COLUMN drift_summary text`.execute(db);
5521
- if (!await colExists$8(db, "execution_steps", "drift")) await sql`ALTER TABLE public.execution_steps ADD COLUMN drift jsonb`.execute(db);
5538
+ async function up$71(db) {
5539
+ if (!await colExists$9(db, "execution_runs", "check_mode")) await sql`ALTER TABLE public.execution_runs ADD COLUMN check_mode text`.execute(db);
5540
+ if (!await colExists$9(db, "execution_steps", "check_outcome")) await sql`ALTER TABLE public.execution_steps ADD COLUMN check_outcome text`.execute(db);
5541
+ if (!await colExists$9(db, "execution_steps", "drift_summary")) await sql`ALTER TABLE public.execution_steps ADD COLUMN drift_summary text`.execute(db);
5542
+ if (!await colExists$9(db, "execution_steps", "drift")) await sql`ALTER TABLE public.execution_steps ADD COLUMN drift jsonb`.execute(db);
5522
5543
  }
5523
- async function down$64(db) {
5544
+ async function down$71(db) {
5524
5545
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS drift`.execute(db);
5525
5546
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS drift_summary`.execute(db);
5526
5547
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS check_outcome`.execute(db);
@@ -5529,8 +5550,8 @@ async function down$64(db) {
5529
5550
  //#endregion
5530
5551
  //#region src/db/migrations/045_host_properties.ts
5531
5552
  var _045_host_properties_exports = /* @__PURE__ */ __exportAll({
5532
- down: () => down$63,
5533
- up: () => up$63
5553
+ down: () => down$70,
5554
+ up: () => up$70
5534
5555
  });
5535
5556
  /**
5536
5557
  * Add the typed host-vars dimension to the host roster:
@@ -5544,18 +5565,18 @@ var _045_host_properties_exports = /* @__PURE__ */ __exportAll({
5544
5565
  * Idempotent (`ADD COLUMN IF NOT EXISTS`): re-running on a DB that already has
5545
5566
  * the column is a no-op. Staging data is preserved (additive column).
5546
5567
  */
5547
- async function up$63(db) {
5568
+ async function up$70(db) {
5548
5569
  await sql`ALTER TABLE public.host_roster
5549
5570
  ADD COLUMN IF NOT EXISTS host_properties jsonb NOT NULL DEFAULT '{}'::jsonb`.execute(db);
5550
5571
  }
5551
- async function down$63(db) {
5572
+ async function down$70(db) {
5552
5573
  await sql`ALTER TABLE public.host_roster DROP COLUMN IF EXISTS host_properties`.execute(db);
5553
5574
  }
5554
5575
  //#endregion
5555
5576
  //#region src/db/migrations/046_join_token_consumed_by_instance.ts
5556
5577
  var _046_join_token_consumed_by_instance_exports = /* @__PURE__ */ __exportAll({
5557
- down: () => down$62,
5558
- up: () => up$62
5578
+ down: () => down$69,
5579
+ up: () => up$69
5559
5580
  });
5560
5581
  /**
5561
5582
  * Record the joining peer's instanceId at first consumption of a join token:
@@ -5570,18 +5591,18 @@ var _046_join_token_consumed_by_instance_exports = /* @__PURE__ */ __exportAll({
5570
5591
  * Idempotent (`ADD COLUMN IF NOT EXISTS`): re-running on a DB that already has
5571
5592
  * the column is a no-op. Staging data is preserved (additive nullable column).
5572
5593
  */
5573
- async function up$62(db) {
5594
+ async function up$69(db) {
5574
5595
  await sql`ALTER TABLE public.join_tokens
5575
5596
  ADD COLUMN IF NOT EXISTS consumed_by_instance text`.execute(db);
5576
5597
  }
5577
- async function down$62(db) {
5598
+ async function down$69(db) {
5578
5599
  await sql`ALTER TABLE public.join_tokens DROP COLUMN IF EXISTS consumed_by_instance`.execute(db);
5579
5600
  }
5580
5601
  //#endregion
5581
5602
  //#region src/db/migrations/047_needs_run_on.ts
5582
5603
  var _047_needs_run_on_exports = /* @__PURE__ */ __exportAll({
5583
- down: () => down$61,
5584
- up: () => up$61
5604
+ down: () => down$68,
5605
+ up: () => up$68
5585
5606
  });
5586
5607
  /**
5587
5608
  * Migrate `execution_job_needs` from the binary `if_failed` policy to a
@@ -5606,7 +5627,7 @@ const ALL_TERMINAL_JSON = JSON.stringify([
5606
5627
  "drift_dropped"
5607
5628
  ]);
5608
5629
  const SUCCESS_ONLY_JSON = JSON.stringify(["success"]);
5609
- async function colExists$7(db, table, name) {
5630
+ async function colExists$8(db, table, name) {
5610
5631
  return (await sql`
5611
5632
  SELECT EXISTS (
5612
5633
  SELECT 1 FROM information_schema.columns
@@ -5617,12 +5638,12 @@ async function colExists$7(db, table, name) {
5617
5638
  `.execute(db)).rows[0]?.exists ?? false;
5618
5639
  }
5619
5640
  const SUCCESS_ONLY_DEFAULT = `'${SUCCESS_ONLY_JSON}'`;
5620
- async function up$61(db) {
5621
- if (!await colExists$7(db, "execution_job_needs", "run_on")) await sql`
5641
+ async function up$68(db) {
5642
+ if (!await colExists$8(db, "execution_job_needs", "run_on")) await sql`
5622
5643
  ALTER TABLE public.execution_job_needs
5623
5644
  ADD COLUMN run_on text NOT NULL DEFAULT ${sql.raw(SUCCESS_ONLY_DEFAULT)}
5624
5645
  `.execute(db);
5625
- if (await colExists$7(db, "execution_job_needs", "if_failed")) {
5646
+ if (await colExists$8(db, "execution_job_needs", "if_failed")) {
5626
5647
  await sql`
5627
5648
  UPDATE public.execution_job_needs
5628
5649
  SET run_on = ${ALL_TERMINAL_JSON}
@@ -5636,12 +5657,12 @@ async function up$61(db) {
5636
5657
  await sql`ALTER TABLE public.execution_job_needs DROP COLUMN if_failed`.execute(db);
5637
5658
  }
5638
5659
  }
5639
- async function down$61(db) {
5640
- if (!await colExists$7(db, "execution_job_needs", "if_failed")) await sql`
5660
+ async function down$68(db) {
5661
+ if (!await colExists$8(db, "execution_job_needs", "if_failed")) await sql`
5641
5662
  ALTER TABLE public.execution_job_needs
5642
5663
  ADD COLUMN if_failed text NOT NULL DEFAULT 'skip'
5643
5664
  `.execute(db);
5644
- if (await colExists$7(db, "execution_job_needs", "run_on")) {
5665
+ if (await colExists$8(db, "execution_job_needs", "run_on")) {
5645
5666
  await sql`
5646
5667
  UPDATE public.execution_job_needs
5647
5668
  SET if_failed = CASE WHEN run_on = ${SUCCESS_ONLY_JSON} THEN 'skip' ELSE 'run' END
@@ -5652,8 +5673,8 @@ async function down$61(db) {
5652
5673
  //#endregion
5653
5674
  //#region src/db/migrations/048_host_reboot_pending.ts
5654
5675
  var _048_host_reboot_pending_exports = /* @__PURE__ */ __exportAll({
5655
- down: () => down$60,
5656
- up: () => up$60
5676
+ down: () => down$67,
5677
+ up: () => up$67
5657
5678
  });
5658
5679
  /**
5659
5680
  * Add `host_roster.reboot_pending_until timestamptz NULL` — the persisted
@@ -5670,18 +5691,18 @@ var _048_host_reboot_pending_exports = /* @__PURE__ */ __exportAll({
5670
5691
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
5671
5692
  * preserved.
5672
5693
  */
5673
- async function up$60(db) {
5694
+ async function up$67(db) {
5674
5695
  await sql`ALTER TABLE public.host_roster
5675
5696
  ADD COLUMN IF NOT EXISTS reboot_pending_until timestamptz`.execute(db);
5676
5697
  }
5677
- async function down$60(db) {
5698
+ async function down$67(db) {
5678
5699
  await sql`ALTER TABLE public.host_roster DROP COLUMN IF EXISTS reboot_pending_until`.execute(db);
5679
5700
  }
5680
5701
  //#endregion
5681
5702
  //#region src/db/migrations/049_held_runs_payload.ts
5682
5703
  var _049_held_runs_payload_exports = /* @__PURE__ */ __exportAll({
5683
- down: () => down$59,
5684
- up: () => up$59
5704
+ down: () => down$66,
5705
+ up: () => up$66
5685
5706
  });
5686
5707
  /**
5687
5708
  * Add `held_runs.payload jsonb NULL` — the drift payload captured when a
@@ -5693,18 +5714,18 @@ var _049_held_runs_payload_exports = /* @__PURE__ */ __exportAll({
5693
5714
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
5694
5715
  * preserved.
5695
5716
  */
5696
- async function up$59(db) {
5717
+ async function up$66(db) {
5697
5718
  await sql`ALTER TABLE public.held_runs
5698
5719
  ADD COLUMN IF NOT EXISTS payload jsonb`.execute(db);
5699
5720
  }
5700
- async function down$59(db) {
5721
+ async function down$66(db) {
5701
5722
  await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS payload`.execute(db);
5702
5723
  }
5703
5724
  //#endregion
5704
5725
  //#region src/db/migrations/050_sources_slug.ts
5705
5726
  var _050_sources_slug_exports = /* @__PURE__ */ __exportAll({
5706
- down: () => down$58,
5707
- up: () => up$58
5727
+ down: () => down$65,
5728
+ up: () => up$65
5708
5729
  });
5709
5730
  /**
5710
5731
  * Add `sources.slug TEXT NULL` — the GitHub App slug (the URL-safe identifier
@@ -5719,18 +5740,18 @@ var _050_sources_slug_exports = /* @__PURE__ */ __exportAll({
5719
5740
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
5720
5741
  * preserved.
5721
5742
  */
5722
- async function up$58(db) {
5743
+ async function up$65(db) {
5723
5744
  await sql`ALTER TABLE public.sources
5724
5745
  ADD COLUMN IF NOT EXISTS slug text`.execute(db);
5725
5746
  }
5726
- async function down$58(db) {
5747
+ async function down$65(db) {
5727
5748
  await sql`ALTER TABLE public.sources DROP COLUMN IF EXISTS slug`.execute(db);
5728
5749
  }
5729
5750
  //#endregion
5730
5751
  //#region src/db/migrations/051_binding_host_pattern.ts
5731
5752
  var _051_binding_host_pattern_exports = /* @__PURE__ */ __exportAll({
5732
- down: () => down$57,
5733
- up: () => up$57
5753
+ down: () => down$64,
5754
+ up: () => up$64
5734
5755
  });
5735
5756
  /**
5736
5757
  * Add a per-host dimension to environment secret bindings:
@@ -5746,7 +5767,7 @@ var _051_binding_host_pattern_exports = /* @__PURE__ */ __exportAll({
5746
5767
  * Idempotent: re-running on a DB that already has the column / index is a no-op.
5747
5768
  * Additive — staging data is preserved.
5748
5769
  */
5749
- async function up$57(db) {
5770
+ async function up$64(db) {
5750
5771
  await sql`ALTER TABLE public.environment_bindings
5751
5772
  ADD COLUMN IF NOT EXISTS host_pattern text NOT NULL DEFAULT '**'`.execute(db);
5752
5773
  await sql`ALTER TABLE public.environment_bindings
@@ -5754,7 +5775,7 @@ async function up$57(db) {
5754
5775
  await sql`CREATE UNIQUE INDEX IF NOT EXISTS environment_bindings_env_scope_host_uniq
5755
5776
  ON public.environment_bindings (environment_id, scope_pattern, host_pattern)`.execute(db);
5756
5777
  }
5757
- async function down$57(db) {
5778
+ async function down$64(db) {
5758
5779
  await sql`DROP INDEX IF EXISTS public.environment_bindings_env_scope_host_uniq`.execute(db);
5759
5780
  await sql`ALTER TABLE public.environment_bindings
5760
5781
  DROP COLUMN IF EXISTS host_pattern`.execute(db);
@@ -5764,8 +5785,8 @@ async function down$57(db) {
5764
5785
  //#endregion
5765
5786
  //#region src/db/migrations/052_host_reach_metadata.ts
5766
5787
  var _052_host_reach_metadata_exports = /* @__PURE__ */ __exportAll({
5767
- down: () => down$56,
5768
- up: () => up$56
5788
+ down: () => down$63,
5789
+ up: () => up$63
5769
5790
  });
5770
5791
  /**
5771
5792
  * Add pre-agent reach metadata to the host roster so a declared host (no agent
@@ -5782,14 +5803,14 @@ var _052_host_reach_metadata_exports = /* @__PURE__ */ __exportAll({
5782
5803
  * behaves exactly as before. Idempotent (`ADD COLUMN IF NOT EXISTS`); additive,
5783
5804
  * so staging data is preserved.
5784
5805
  */
5785
- async function up$56(db) {
5806
+ async function up$63(db) {
5786
5807
  await sql`ALTER TABLE public.host_roster
5787
5808
  ADD COLUMN IF NOT EXISTS address text,
5788
5809
  ADD COLUMN IF NOT EXISTS ssh_user text,
5789
5810
  ADD COLUMN IF NOT EXISTS ssh_port integer,
5790
5811
  ADD COLUMN IF NOT EXISTS ssh_key_secret text`.execute(db);
5791
5812
  }
5792
- async function down$56(db) {
5813
+ async function down$63(db) {
5793
5814
  await sql`ALTER TABLE public.host_roster
5794
5815
  DROP COLUMN IF EXISTS address,
5795
5816
  DROP COLUMN IF EXISTS ssh_user,
@@ -5799,8 +5820,8 @@ async function down$56(db) {
5799
5820
  //#endregion
5800
5821
  //#region src/db/migrations/053_agent_token_single_use.ts
5801
5822
  var _053_agent_token_single_use_exports = /* @__PURE__ */ __exportAll({
5802
- down: () => down$55,
5803
- up: () => up$55
5823
+ down: () => down$62,
5824
+ up: () => up$62
5804
5825
  });
5805
5826
  /**
5806
5827
  * Add a single-use marker to agent tokens for the bootstrap (init-runner)
@@ -5815,19 +5836,19 @@ var _053_agent_token_single_use_exports = /* @__PURE__ */ __exportAll({
5815
5836
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
5816
5837
  * preserved.
5817
5838
  */
5818
- async function up$55(db) {
5839
+ async function up$62(db) {
5819
5840
  await sql`ALTER TABLE public.agent_tokens
5820
5841
  ADD COLUMN IF NOT EXISTS consumed_at timestamptz`.execute(db);
5821
5842
  }
5822
- async function down$55(db) {
5843
+ async function down$62(db) {
5823
5844
  await sql`ALTER TABLE public.agent_tokens
5824
5845
  DROP COLUMN IF EXISTS consumed_at`.execute(db);
5825
5846
  }
5826
5847
  //#endregion
5827
5848
  //#region src/db/migrations/054_local_working_tree.ts
5828
5849
  var _054_local_working_tree_exports = /* @__PURE__ */ __exportAll({
5829
- down: () => down$54,
5830
- up: () => up$54
5850
+ down: () => down$61,
5851
+ up: () => up$61
5831
5852
  });
5832
5853
  /**
5833
5854
  * Mark runs that executed an uploaded local working tree (`kici run remote`):
@@ -5840,19 +5861,19 @@ var _054_local_working_tree_exports = /* @__PURE__ */ __exportAll({
5840
5861
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive with a default, so staging
5841
5862
  * data is preserved.
5842
5863
  */
5843
- async function up$54(db) {
5864
+ async function up$61(db) {
5844
5865
  await sql`ALTER TABLE public.execution_runs
5845
5866
  ADD COLUMN IF NOT EXISTS local_working_tree boolean NOT NULL DEFAULT false`.execute(db);
5846
5867
  }
5847
- async function down$54(db) {
5868
+ async function down$61(db) {
5848
5869
  await sql`ALTER TABLE public.execution_runs
5849
5870
  DROP COLUMN IF EXISTS local_working_tree`.execute(db);
5850
5871
  }
5851
5872
  //#endregion
5852
5873
  //#region src/db/migrations/055_agent_token_mandatory_labels.ts
5853
5874
  var _055_agent_token_mandatory_labels_exports = /* @__PURE__ */ __exportAll({
5854
- down: () => down$53,
5855
- up: () => up$53
5875
+ down: () => down$60,
5876
+ up: () => up$60
5856
5877
  });
5857
5878
  /**
5858
5879
  * Add a token-bound mandatory-label taint to agent tokens:
@@ -5868,19 +5889,19 @@ var _055_agent_token_mandatory_labels_exports = /* @__PURE__ */ __exportAll({
5868
5889
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
5869
5890
  * preserved.
5870
5891
  */
5871
- async function up$53(db) {
5892
+ async function up$60(db) {
5872
5893
  await sql`ALTER TABLE public.agent_tokens
5873
5894
  ADD COLUMN IF NOT EXISTS mandatory_labels text`.execute(db);
5874
5895
  }
5875
- async function down$53(db) {
5896
+ async function down$60(db) {
5876
5897
  await sql`ALTER TABLE public.agent_tokens
5877
5898
  DROP COLUMN IF EXISTS mandatory_labels`.execute(db);
5878
5899
  }
5879
5900
  //#endregion
5880
5901
  //#region src/db/migrations/056_execution_jobs_environments.ts
5881
5902
  var _056_execution_jobs_environments_exports = /* @__PURE__ */ __exportAll({
5882
- down: () => down$52,
5883
- up: () => up$52
5903
+ down: () => down$59,
5904
+ up: () => up$59
5884
5905
  });
5885
5906
  /**
5886
5907
  * Add a per-job bound deployment-environment list to `execution_jobs`:
@@ -5895,19 +5916,19 @@ var _056_execution_jobs_environments_exports = /* @__PURE__ */ __exportAll({
5895
5916
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
5896
5917
  * preserved.
5897
5918
  */
5898
- async function up$52(db) {
5919
+ async function up$59(db) {
5899
5920
  await sql`ALTER TABLE public.execution_jobs
5900
5921
  ADD COLUMN IF NOT EXISTS environments text`.execute(db);
5901
5922
  }
5902
- async function down$52(db) {
5923
+ async function down$59(db) {
5903
5924
  await sql`ALTER TABLE public.execution_jobs
5904
5925
  DROP COLUMN IF EXISTS environments`.execute(db);
5905
5926
  }
5906
5927
  //#endregion
5907
5928
  //#region src/db/migrations/057_step_concurrency.ts
5908
5929
  var _057_step_concurrency_exports = /* @__PURE__ */ __exportAll({
5909
- down: () => down$51,
5910
- up: () => up$51
5930
+ down: () => down$58,
5931
+ up: () => up$58
5911
5932
  });
5912
5933
  /**
5913
5934
  * Add parallel step-group concurrency columns to `execution_steps`:
@@ -5920,7 +5941,7 @@ var _057_step_concurrency_exports = /* @__PURE__ */ __exportAll({
5920
5941
  * Both nullable, no backfill. Idempotent: re-running on a DB that already has the
5921
5942
  * columns is a no-op.
5922
5943
  */
5923
- async function colExists$6(db, table, name) {
5944
+ async function colExists$7(db, table, name) {
5924
5945
  return (await sql`
5925
5946
  SELECT EXISTS (
5926
5947
  SELECT 1 FROM information_schema.columns
@@ -5930,19 +5951,19 @@ async function colExists$6(db, table, name) {
5930
5951
  ) AS exists
5931
5952
  `.execute(db)).rows[0]?.exists ?? false;
5932
5953
  }
5933
- async function up$51(db) {
5934
- if (!await colExists$6(db, "execution_steps", "concurrency_kind")) await sql`ALTER TABLE public.execution_steps ADD COLUMN concurrency_kind text`.execute(db);
5935
- if (!await colExists$6(db, "execution_steps", "group_id")) await sql`ALTER TABLE public.execution_steps ADD COLUMN group_id text`.execute(db);
5954
+ async function up$58(db) {
5955
+ if (!await colExists$7(db, "execution_steps", "concurrency_kind")) await sql`ALTER TABLE public.execution_steps ADD COLUMN concurrency_kind text`.execute(db);
5956
+ if (!await colExists$7(db, "execution_steps", "group_id")) await sql`ALTER TABLE public.execution_steps ADD COLUMN group_id text`.execute(db);
5936
5957
  }
5937
- async function down$51(db) {
5958
+ async function down$58(db) {
5938
5959
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS group_id`.execute(db);
5939
5960
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS concurrency_kind`.execute(db);
5940
5961
  }
5941
5962
  //#endregion
5942
5963
  //#region src/db/migrations/058_access_log_agent_label.ts
5943
5964
  var _058_access_log_agent_label_exports = /* @__PURE__ */ __exportAll({
5944
- down: () => down$50,
5945
- up: () => up$50
5965
+ down: () => down$57,
5966
+ up: () => up$57
5946
5967
  });
5947
5968
  /**
5948
5969
  * Add `access_log.agent_label text` — the human-set name of the agent that
@@ -5952,7 +5973,7 @@ var _058_access_log_agent_label_exports = /* @__PURE__ */ __exportAll({
5952
5973
  * the access log by agent. NULL for ordinary human / API-key / system actors.
5953
5974
  * Nullable, no backfill. Idempotent.
5954
5975
  */
5955
- async function colExists$5(db, table, name) {
5976
+ async function colExists$6(db, table, name) {
5956
5977
  return (await sql`
5957
5978
  SELECT EXISTS (
5958
5979
  SELECT 1 FROM information_schema.columns
@@ -5962,17 +5983,17 @@ async function colExists$5(db, table, name) {
5962
5983
  ) AS exists
5963
5984
  `.execute(db)).rows[0]?.exists ?? false;
5964
5985
  }
5965
- async function up$50(db) {
5966
- if (!await colExists$5(db, "access_log", "agent_label")) await sql`ALTER TABLE public.access_log ADD COLUMN agent_label text`.execute(db);
5986
+ async function up$57(db) {
5987
+ if (!await colExists$6(db, "access_log", "agent_label")) await sql`ALTER TABLE public.access_log ADD COLUMN agent_label text`.execute(db);
5967
5988
  }
5968
- async function down$50(db) {
5989
+ async function down$57(db) {
5969
5990
  await sql`ALTER TABLE public.access_log DROP COLUMN IF EXISTS agent_label`.execute(db);
5970
5991
  }
5971
5992
  //#endregion
5972
5993
  //#region src/db/migrations/059_attestation_verdict.ts
5973
5994
  var _059_attestation_verdict_exports = /* @__PURE__ */ __exportAll({
5974
- down: () => down$49,
5975
- up: () => up$49
5995
+ down: () => down$56,
5996
+ up: () => up$56
5976
5997
  });
5977
5998
  /**
5978
5999
  * Add server-side verification verdict columns to `attestations`, plus the
@@ -5989,7 +6010,7 @@ var _059_attestation_verdict_exports = /* @__PURE__ */ __exportAll({
5989
6010
  *
5990
6011
  * Idempotent: guarded on the `verify_status` column's existence.
5991
6012
  */
5992
- async function colExists$4(db, table, name) {
6013
+ async function colExists$5(db, table, name) {
5993
6014
  return (await sql`
5994
6015
  SELECT EXISTS (
5995
6016
  SELECT 1 FROM information_schema.columns
@@ -5999,8 +6020,8 @@ async function colExists$4(db, table, name) {
5999
6020
  ) AS exists
6000
6021
  `.execute(db)).rows[0]?.exists ?? false;
6001
6022
  }
6002
- async function up$49(db) {
6003
- if (await colExists$4(db, "attestations", "verify_status")) return;
6023
+ async function up$56(db) {
6024
+ if (await colExists$5(db, "attestations", "verify_status")) return;
6004
6025
  await sql`
6005
6026
  ALTER TABLE public.attestations
6006
6027
  ADD COLUMN verify_status TEXT NOT NULL DEFAULT 'pending',
@@ -6012,7 +6033,7 @@ async function up$49(db) {
6012
6033
  await sql`CREATE INDEX idx_attestations_verify_status ON public.attestations (verify_status)`.execute(db);
6013
6034
  await sql`CREATE INDEX idx_attestations_created_at ON public.attestations (created_at)`.execute(db);
6014
6035
  }
6015
- async function down$49(db) {
6036
+ async function down$56(db) {
6016
6037
  await sql`DROP INDEX IF EXISTS idx_attestations_created_at`.execute(db);
6017
6038
  await sql`DROP INDEX IF EXISTS idx_attestations_verify_status`.execute(db);
6018
6039
  await sql`DROP INDEX IF EXISTS idx_attestations_subject_name`.execute(db);
@@ -6027,8 +6048,8 @@ async function down$49(db) {
6027
6048
  //#endregion
6028
6049
  //#region src/db/migrations/060_run_trigger_actor.ts
6029
6050
  var _060_run_trigger_actor_exports = /* @__PURE__ */ __exportAll({
6030
- down: () => down$48,
6031
- up: () => up$48
6051
+ down: () => down$55,
6052
+ up: () => up$55
6032
6053
  });
6033
6054
  /**
6034
6055
  * Add the triggering-actor columns to `execution_runs`:
@@ -6046,7 +6067,7 @@ var _060_run_trigger_actor_exports = /* @__PURE__ */ __exportAll({
6046
6067
  * @x" and audit, beyond actor notifications. All nullable, no backfill,
6047
6068
  * idempotent.
6048
6069
  */
6049
- async function colExists$3(db, table, name) {
6070
+ async function colExists$4(db, table, name) {
6050
6071
  return (await sql`
6051
6072
  SELECT EXISTS (
6052
6073
  SELECT 1 FROM information_schema.columns
@@ -6056,12 +6077,12 @@ async function colExists$3(db, table, name) {
6056
6077
  ) AS exists
6057
6078
  `.execute(db)).rows[0]?.exists ?? false;
6058
6079
  }
6059
- async function up$48(db) {
6060
- if (!await colExists$3(db, "execution_runs", "trigger_actor_provider")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_provider text`.execute(db);
6061
- if (!await colExists$3(db, "execution_runs", "trigger_actor_username")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_username text`.execute(db);
6062
- if (!await colExists$3(db, "execution_runs", "trigger_actor_user_id")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_user_id text`.execute(db);
6080
+ async function up$55(db) {
6081
+ if (!await colExists$4(db, "execution_runs", "trigger_actor_provider")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_provider text`.execute(db);
6082
+ if (!await colExists$4(db, "execution_runs", "trigger_actor_username")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_username text`.execute(db);
6083
+ if (!await colExists$4(db, "execution_runs", "trigger_actor_user_id")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_user_id text`.execute(db);
6063
6084
  }
6064
- async function down$48(db) {
6085
+ async function down$55(db) {
6065
6086
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS trigger_actor_provider`.execute(db);
6066
6087
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS trigger_actor_username`.execute(db);
6067
6088
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS trigger_actor_user_id`.execute(db);
@@ -6069,8 +6090,8 @@ async function down$48(db) {
6069
6090
  //#endregion
6070
6091
  //#region src/db/migrations/061_execution_runs_environment_id.ts
6071
6092
  var _061_execution_runs_environment_id_exports = /* @__PURE__ */ __exportAll({
6072
- down: () => down$47,
6073
- up: () => up$47
6093
+ down: () => down$54,
6094
+ up: () => up$54
6074
6095
  });
6075
6096
  /**
6076
6097
  * Add `environment_id` to `execution_runs` so environment run-history can be
@@ -6096,7 +6117,7 @@ var _061_execution_runs_environment_id_exports = /* @__PURE__ */ __exportAll({
6096
6117
  * backfill use `IF NOT EXISTS` / `WHERE environment_id IS NULL` so re-running is
6097
6118
  * a no-op.
6098
6119
  */
6099
- async function colExists$2(db, table, name) {
6120
+ async function colExists$3(db, table, name) {
6100
6121
  return (await sql`
6101
6122
  SELECT EXISTS (
6102
6123
  SELECT 1 FROM information_schema.columns
@@ -6106,8 +6127,8 @@ async function colExists$2(db, table, name) {
6106
6127
  ) AS exists
6107
6128
  `.execute(db)).rows[0]?.exists ?? false;
6108
6129
  }
6109
- async function up$47(db) {
6110
- if (!await colExists$2(db, "execution_runs", "environment_id")) await sql`
6130
+ async function up$54(db) {
6131
+ if (!await colExists$3(db, "execution_runs", "environment_id")) await sql`
6111
6132
  ALTER TABLE public.execution_runs
6112
6133
  ADD COLUMN environment_id uuid
6113
6134
  REFERENCES public.environments(id) ON DELETE SET NULL
@@ -6128,15 +6149,15 @@ async function up$47(db) {
6128
6149
  WHERE e2.type = 'fixed' AND e2.name = er.environment) = 1
6129
6150
  `.execute(db);
6130
6151
  }
6131
- async function down$47(db) {
6152
+ async function down$54(db) {
6132
6153
  await sql`DROP INDEX IF EXISTS idx_execution_runs_environment_id`.execute(db);
6133
6154
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS environment_id`.execute(db);
6134
6155
  }
6135
6156
  //#endregion
6136
6157
  //#region src/db/migrations/062_execution_runs_agent_label.ts
6137
6158
  var _062_execution_runs_agent_label_exports = /* @__PURE__ */ __exportAll({
6138
- down: () => down$46,
6139
- up: () => up$46
6159
+ down: () => down$53,
6160
+ up: () => up$53
6140
6161
  });
6141
6162
  /**
6142
6163
  * Add the agent-provenance columns to `execution_runs`:
@@ -6151,7 +6172,7 @@ var _062_execution_runs_agent_label_exports = /* @__PURE__ */ __exportAll({
6151
6172
  * permissions). NULL for ordinary human / webhook / system-driven runs.
6152
6173
  * Nullable, no backfill, idempotent.
6153
6174
  */
6154
- async function colExists$1(db, table, name) {
6175
+ async function colExists$2(db, table, name) {
6155
6176
  return (await sql`
6156
6177
  SELECT EXISTS (
6157
6178
  SELECT 1 FROM information_schema.columns
@@ -6161,19 +6182,19 @@ async function colExists$1(db, table, name) {
6161
6182
  ) AS exists
6162
6183
  `.execute(db)).rows[0]?.exists ?? false;
6163
6184
  }
6164
- async function up$46(db) {
6165
- if (!await colExists$1(db, "execution_runs", "triggered_by_agent_label")) await sql`ALTER TABLE public.execution_runs ADD COLUMN triggered_by_agent_label text`.execute(db);
6166
- if (!await colExists$1(db, "execution_runs", "cancelled_by_agent_label")) await sql`ALTER TABLE public.execution_runs ADD COLUMN cancelled_by_agent_label text`.execute(db);
6185
+ async function up$53(db) {
6186
+ if (!await colExists$2(db, "execution_runs", "triggered_by_agent_label")) await sql`ALTER TABLE public.execution_runs ADD COLUMN triggered_by_agent_label text`.execute(db);
6187
+ if (!await colExists$2(db, "execution_runs", "cancelled_by_agent_label")) await sql`ALTER TABLE public.execution_runs ADD COLUMN cancelled_by_agent_label text`.execute(db);
6167
6188
  }
6168
- async function down$46(db) {
6189
+ async function down$53(db) {
6169
6190
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS triggered_by_agent_label`.execute(db);
6170
6191
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS cancelled_by_agent_label`.execute(db);
6171
6192
  }
6172
6193
  //#endregion
6173
6194
  //#region src/db/migrations/063_access_log_agent_label_index.ts
6174
6195
  var _063_access_log_agent_label_index_exports = /* @__PURE__ */ __exportAll({
6175
- down: () => down$45,
6176
- up: () => up$45
6196
+ down: () => down$52,
6197
+ up: () => up$52
6177
6198
  });
6178
6199
  /**
6179
6200
  * Index `access_log.agent_label` (column added by migration 058) so the
@@ -6181,17 +6202,17 @@ var _063_access_log_agent_label_index_exports = /* @__PURE__ */ __exportAll({
6181
6202
  * the dashboard "agent name" filter) does an indexed exact-match lookup
6182
6203
  * instead of a scan. Idempotent.
6183
6204
  */
6184
- async function up$45(db) {
6205
+ async function up$52(db) {
6185
6206
  await sql`CREATE INDEX IF NOT EXISTS access_log_agent_label_idx ON public.access_log (agent_label)`.execute(db);
6186
6207
  }
6187
- async function down$45(db) {
6208
+ async function down$52(db) {
6188
6209
  await sql`DROP INDEX IF EXISTS access_log_agent_label_idx`.execute(db);
6189
6210
  }
6190
6211
  //#endregion
6191
6212
  //#region src/db/migrations/064_execution_jobs_skipped_environments.ts
6192
6213
  var _064_execution_jobs_skipped_environments_exports = /* @__PURE__ */ __exportAll({
6193
- down: () => down$44,
6194
- up: () => up$44
6214
+ down: () => down$51,
6215
+ up: () => up$51
6195
6216
  });
6196
6217
  /**
6197
6218
  * Add the test-run skipped-environment columns to `execution_jobs`:
@@ -6206,13 +6227,13 @@ var _064_execution_jobs_skipped_environments_exports = /* @__PURE__ */ __exportA
6206
6227
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
6207
6228
  * preserved.
6208
6229
  */
6209
- async function up$44(db) {
6230
+ async function up$51(db) {
6210
6231
  await sql`ALTER TABLE public.execution_jobs
6211
6232
  ADD COLUMN IF NOT EXISTS skipped_environments text`.execute(db);
6212
6233
  await sql`ALTER TABLE public.execution_jobs
6213
6234
  ADD COLUMN IF NOT EXISTS env_warning text`.execute(db);
6214
6235
  }
6215
- async function down$44(db) {
6236
+ async function down$51(db) {
6216
6237
  await sql`ALTER TABLE public.execution_jobs
6217
6238
  DROP COLUMN IF EXISTS skipped_environments`.execute(db);
6218
6239
  await sql`ALTER TABLE public.execution_jobs
@@ -6221,8 +6242,8 @@ async function down$44(db) {
6221
6242
  //#endregion
6222
6243
  //#region src/db/migrations/065_pending_attestations.ts
6223
6244
  var _065_pending_attestations_exports = /* @__PURE__ */ __exportAll({
6224
- down: () => down$43,
6225
- up: () => up$43
6245
+ down: () => down$50,
6246
+ up: () => up$50
6226
6247
  });
6227
6248
  /**
6228
6249
  * Add the `pending_attestations` deferred-attestation outbox and an idempotency
@@ -6242,7 +6263,7 @@ var _065_pending_attestations_exports = /* @__PURE__ */ __exportAll({
6242
6263
  *
6243
6264
  * Idempotent: guarded on table existence.
6244
6265
  */
6245
- async function up$43(db) {
6266
+ async function up$50(db) {
6246
6267
  if ((await sql`
6247
6268
  SELECT EXISTS (
6248
6269
  SELECT 1 FROM information_schema.tables
@@ -6281,15 +6302,15 @@ async function up$43(db) {
6281
6302
  ON public.attestations (run_id, job_id, subject_digest)
6282
6303
  `.execute(db);
6283
6304
  }
6284
- async function down$43(db) {
6305
+ async function down$50(db) {
6285
6306
  await sql`DROP INDEX IF EXISTS uq_attestations_run_job_subject`.execute(db);
6286
6307
  await sql`DROP TABLE IF EXISTS public.pending_attestations`.execute(db);
6287
6308
  }
6288
6309
  //#endregion
6289
6310
  //#region src/db/migrations/066_pending_attestations_rejected.ts
6290
6311
  var _066_pending_attestations_rejected_exports = /* @__PURE__ */ __exportAll({
6291
- down: () => down$42,
6292
- up: () => up$42
6312
+ down: () => down$49,
6313
+ up: () => up$49
6293
6314
  });
6294
6315
  /**
6295
6316
  * Add `rejected_at` to `pending_attestations`: the terminal-rejection marker for
@@ -6300,21 +6321,21 @@ var _066_pending_attestations_rejected_exports = /* @__PURE__ */ __exportAll({
6300
6321
  *
6301
6322
  * Idempotent: guarded on column existence.
6302
6323
  */
6303
- async function up$42(db) {
6304
- if (await columnExists$5(db, "pending_attestations", "rejected_at")) return;
6324
+ async function up$49(db) {
6325
+ if (await columnExists$10(db, "pending_attestations", "rejected_at")) return;
6305
6326
  await sql`
6306
6327
  ALTER TABLE public.pending_attestations
6307
6328
  ADD COLUMN rejected_at TIMESTAMPTZ
6308
6329
  `.execute(db);
6309
6330
  }
6310
- async function down$42(db) {
6311
- if (!await columnExists$5(db, "pending_attestations", "rejected_at")) return;
6331
+ async function down$49(db) {
6332
+ if (!await columnExists$10(db, "pending_attestations", "rejected_at")) return;
6312
6333
  await sql`
6313
6334
  ALTER TABLE public.pending_attestations
6314
6335
  DROP COLUMN rejected_at
6315
6336
  `.execute(db);
6316
6337
  }
6317
- async function columnExists$5(db, table, column) {
6338
+ async function columnExists$10(db, table, column) {
6318
6339
  return (await sql`
6319
6340
  SELECT EXISTS (
6320
6341
  SELECT 1 FROM information_schema.columns
@@ -6325,8 +6346,8 @@ async function columnExists$5(db, table, column) {
6325
6346
  //#endregion
6326
6347
  //#region src/db/migrations/067_environments_to_contexts.ts
6327
6348
  var _067_environments_to_contexts_exports = /* @__PURE__ */ __exportAll({
6328
- down: () => down$41,
6329
- up: () => up$41
6349
+ down: () => down$48,
6350
+ up: () => up$48
6330
6351
  });
6331
6352
  /**
6332
6353
  * Rename the named-policy object from "environment" to "context" across the
@@ -6360,7 +6381,7 @@ var _067_environments_to_contexts_exports = /* @__PURE__ */ __exportAll({
6360
6381
  * columns automatically (Postgres references them by identity, not name), so
6361
6382
  * only the one hand-named index above needs an explicit rename.
6362
6383
  */
6363
- async function up$41(db) {
6384
+ async function up$48(db) {
6364
6385
  await sql`ALTER TABLE public.environments RENAME TO contexts`.execute(db);
6365
6386
  await sql`ALTER TABLE public.environment_bindings RENAME TO context_bindings`.execute(db);
6366
6387
  await sql`ALTER TABLE public.environment_variables RENAME TO context_variables`.execute(db);
@@ -6379,7 +6400,7 @@ async function up$41(db) {
6379
6400
  await sql`ALTER TABLE public.held_runs ALTER COLUMN queue_type SET DEFAULT 'context'`.execute(db);
6380
6401
  await sql`ALTER TABLE public.held_runs ALTER COLUMN trigger_source SET DEFAULT 'context'`.execute(db);
6381
6402
  }
6382
- async function down$41(db) {
6403
+ async function down$48(db) {
6383
6404
  await sql`ALTER TABLE public.held_runs ALTER COLUMN trigger_source SET DEFAULT 'environment'`.execute(db);
6384
6405
  await sql`ALTER TABLE public.held_runs ALTER COLUMN queue_type SET DEFAULT 'environment'`.execute(db);
6385
6406
  await sql`UPDATE public.held_runs SET trigger_source = 'environment' WHERE trigger_source = 'context'`.execute(db);
@@ -6401,8 +6422,8 @@ async function down$41(db) {
6401
6422
  //#endregion
6402
6423
  //#region src/db/migrations/068_request_idempotency.ts
6403
6424
  var _068_request_idempotency_exports = /* @__PURE__ */ __exportAll({
6404
- down: () => down$40,
6405
- up: () => up$40
6425
+ down: () => down$47,
6426
+ up: () => up$47
6406
6427
  });
6407
6428
  /**
6408
6429
  * Add the `request_idempotency` claim table: a `request_id`-keyed record that
@@ -6417,12 +6438,12 @@ var _068_request_idempotency_exports = /* @__PURE__ */ __exportAll({
6417
6438
  *
6418
6439
  * Idempotent: guarded on table existence.
6419
6440
  */
6420
- async function up$40(db) {
6441
+ async function up$47(db) {
6421
6442
  if (await tableExists$3(db, "request_idempotency")) return;
6422
6443
  await db.schema.createTable("request_idempotency").addColumn("request_id", "text", (c) => c.primaryKey()).addColumn("new_run_id", "text", (c) => c.notNull()).addColumn("created_at", "timestamptz", (c) => c.notNull().defaultTo(sql`now()`)).execute();
6423
6444
  await db.schema.createIndex("idx_request_idempotency_created_at").on("request_idempotency").column("created_at").execute();
6424
6445
  }
6425
- async function down$40(db) {
6446
+ async function down$47(db) {
6426
6447
  await db.schema.dropTable("request_idempotency").ifExists().execute();
6427
6448
  }
6428
6449
  async function tableExists$3(db, table) {
@@ -6436,8 +6457,8 @@ async function tableExists$3(db, table) {
6436
6457
  //#endregion
6437
6458
  //#region src/db/migrations/069_reroute_tunables.ts
6438
6459
  var _069_reroute_tunables_exports = /* @__PURE__ */ __exportAll({
6439
- down: () => down$39,
6440
- up: () => up$39
6460
+ down: () => down$46,
6461
+ up: () => up$46
6441
6462
  });
6442
6463
  /**
6443
6464
  * Add the three reroute-tunable columns to `org_settings` (all nullable):
@@ -6456,12 +6477,12 @@ var _069_reroute_tunables_exports = /* @__PURE__ */ __exportAll({
6456
6477
  * Idempotent: each column add is guarded on column existence, so a re-run on a
6457
6478
  * DB that already has a column is a no-op for that column.
6458
6479
  */
6459
- async function up$39(db) {
6480
+ async function up$46(db) {
6460
6481
  await addColumnIfMissing(db, "reroute_spawn_window_ms", "BIGINT");
6461
6482
  await addColumnIfMissing(db, "reroute_ack_timeout_ms", "BIGINT");
6462
6483
  await addColumnIfMissing(db, "reroute_max_hops", "INTEGER");
6463
6484
  }
6464
- async function down$39(db) {
6485
+ async function down$46(db) {
6465
6486
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS reroute_spawn_window_ms`.execute(db);
6466
6487
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS reroute_ack_timeout_ms`.execute(db);
6467
6488
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS reroute_max_hops`.execute(db);
@@ -6480,8 +6501,8 @@ async function addColumnIfMissing(db, column, type) {
6480
6501
  //#endregion
6481
6502
  //#region src/db/migrations/070_execution_runs_failure_class.ts
6482
6503
  var _070_execution_runs_failure_class_exports = /* @__PURE__ */ __exportAll({
6483
- down: () => down$38,
6484
- up: () => up$38
6504
+ down: () => down$45,
6505
+ up: () => up$45
6485
6506
  });
6486
6507
  /**
6487
6508
  * Add `execution_runs.failure_class` — the reason a terminal run failed
@@ -6492,7 +6513,7 @@ var _070_execution_runs_failure_class_exports = /* @__PURE__ */ __exportAll({
6492
6513
  * like `status`. NULL for success / not-yet-terminal runs. Nullable, no backfill,
6493
6514
  * idempotent.
6494
6515
  */
6495
- async function colExists(db, table, name) {
6516
+ async function colExists$1(db, table, name) {
6496
6517
  return (await sql`
6497
6518
  SELECT EXISTS (
6498
6519
  SELECT 1 FROM information_schema.columns
@@ -6502,17 +6523,17 @@ async function colExists(db, table, name) {
6502
6523
  ) AS exists
6503
6524
  `.execute(db)).rows[0]?.exists ?? false;
6504
6525
  }
6505
- async function up$38(db) {
6506
- if (!await colExists(db, "execution_runs", "failure_class")) await sql`ALTER TABLE public.execution_runs ADD COLUMN failure_class text`.execute(db);
6526
+ async function up$45(db) {
6527
+ if (!await colExists$1(db, "execution_runs", "failure_class")) await sql`ALTER TABLE public.execution_runs ADD COLUMN failure_class text`.execute(db);
6507
6528
  }
6508
- async function down$38(db) {
6529
+ async function down$45(db) {
6509
6530
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS failure_class`.execute(db);
6510
6531
  }
6511
6532
  //#endregion
6512
6533
  //#region src/db/migrations/071_batch_accumulation.ts
6513
6534
  var _071_batch_accumulation_exports = /* @__PURE__ */ __exportAll({
6514
- down: () => down$37,
6515
- up: () => up$37
6535
+ down: () => down$44,
6536
+ up: () => up$44
6516
6537
  });
6517
6538
  /**
6518
6539
  * Add the batch-accumulation tables that back the `workflows_failed_batch`
@@ -6536,7 +6557,7 @@ var _071_batch_accumulation_exports = /* @__PURE__ */ __exportAll({
6536
6557
  *
6537
6558
  * Idempotent: guarded on table existence.
6538
6559
  */
6539
- async function up$37(db) {
6560
+ async function up$44(db) {
6540
6561
  if ((await sql`
6541
6562
  SELECT EXISTS (
6542
6563
  SELECT 1 FROM information_schema.tables
@@ -6581,15 +6602,15 @@ async function up$37(db) {
6581
6602
  ON public.batch_accumulation_items (window_id)
6582
6603
  `.execute(db);
6583
6604
  }
6584
- async function down$37(db) {
6605
+ async function down$44(db) {
6585
6606
  await sql`DROP TABLE IF EXISTS public.batch_accumulation_items`.execute(db);
6586
6607
  await sql`DROP TABLE IF EXISTS public.batch_accumulation_windows`.execute(db);
6587
6608
  }
6588
6609
  //#endregion
6589
6610
  //#region src/db/migrations/072_dispatch_queue_run_id_index.ts
6590
6611
  var _072_dispatch_queue_run_id_index_exports = /* @__PURE__ */ __exportAll({
6591
- down: () => down$36,
6592
- up: () => up$36
6612
+ down: () => down$43,
6613
+ up: () => up$43
6593
6614
  });
6594
6615
  /**
6595
6616
  * Add `idx_dispatch_queue_run_id` on `dispatch_queue (run_id)`.
@@ -6602,20 +6623,20 @@ var _072_dispatch_queue_run_id_index_exports = /* @__PURE__ */ __exportAll({
6602
6623
  *
6603
6624
  * Idempotent: `IF NOT EXISTS` makes a re-run a no-op.
6604
6625
  */
6605
- async function up$36(db) {
6626
+ async function up$43(db) {
6606
6627
  await sql`
6607
6628
  CREATE INDEX IF NOT EXISTS idx_dispatch_queue_run_id
6608
6629
  ON public.dispatch_queue (run_id)
6609
6630
  `.execute(db);
6610
6631
  }
6611
- async function down$36(db) {
6632
+ async function down$43(db) {
6612
6633
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_run_id`.execute(db);
6613
6634
  }
6614
6635
  //#endregion
6615
6636
  //#region src/db/migrations/073_org_settings_ingest_concurrency.ts
6616
6637
  var _073_org_settings_ingest_concurrency_exports = /* @__PURE__ */ __exportAll({
6617
- down: () => down$35,
6618
- up: () => up$35
6638
+ down: () => down$42,
6639
+ up: () => up$42
6619
6640
  });
6620
6641
  /**
6621
6642
  * Add `org_settings.ingest_max_concurrency BIGINT` (nullable).
@@ -6626,7 +6647,7 @@ var _073_org_settings_ingest_concurrency_exports = /* @__PURE__ */ __exportAll({
6626
6647
  *
6627
6648
  * Idempotent: a re-run on a DB that already has the column is a no-op.
6628
6649
  */
6629
- async function up$35(db) {
6650
+ async function up$42(db) {
6630
6651
  if ((await sql`
6631
6652
  SELECT EXISTS (
6632
6653
  SELECT 1 FROM information_schema.columns
@@ -6640,7 +6661,7 @@ async function up$35(db) {
6640
6661
  ADD COLUMN ingest_max_concurrency BIGINT
6641
6662
  `.execute(db);
6642
6663
  }
6643
- async function down$35(db) {
6664
+ async function down$42(db) {
6644
6665
  await sql`
6645
6666
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS ingest_max_concurrency
6646
6667
  `.execute(db);
@@ -6648,8 +6669,8 @@ async function down$35(db) {
6648
6669
  //#endregion
6649
6670
  //#region src/db/migrations/074_normalize_zero_concurrency_limit.ts
6650
6671
  var _074_normalize_zero_concurrency_limit_exports = /* @__PURE__ */ __exportAll({
6651
- down: () => down$34,
6652
- up: () => up$34
6672
+ down: () => down$41,
6673
+ up: () => up$41
6653
6674
  });
6654
6675
  /**
6655
6676
  * Normalize degenerate context concurrency limits. A `concurrency_limit` of 0
@@ -6660,15 +6681,15 @@ var _074_normalize_zero_concurrency_limit_exports = /* @__PURE__ */ __exportAll(
6660
6681
  * Idempotent; down() is a no-op (a normalized 0 cannot — and should not — be
6661
6682
  * restored).
6662
6683
  */
6663
- async function up$34(db) {
6684
+ async function up$41(db) {
6664
6685
  await sql`UPDATE public.contexts SET concurrency_limit = NULL WHERE concurrency_limit <= 0`.execute(db);
6665
6686
  }
6666
- async function down$34(_db) {}
6687
+ async function down$41(_db) {}
6667
6688
  //#endregion
6668
6689
  //#region src/db/migrations/075_ingest_overflow_buffer.ts
6669
6690
  var _075_ingest_overflow_buffer_exports = /* @__PURE__ */ __exportAll({
6670
- down: () => down$33,
6671
- up: () => up$33
6691
+ down: () => down$40,
6692
+ up: () => up$40
6672
6693
  });
6673
6694
  /**
6674
6695
  * Durable overflow buffer for shed webhook-ingest deliveries.
@@ -6682,7 +6703,7 @@ var _075_ingest_overflow_buffer_exports = /* @__PURE__ */ __exportAll({
6682
6703
  *
6683
6704
  * Idempotent: a re-run on a DB that already has the table is a no-op.
6684
6705
  */
6685
- async function up$33(db) {
6706
+ async function up$40(db) {
6686
6707
  if ((await sql`
6687
6708
  SELECT EXISTS (
6688
6709
  SELECT 1 FROM information_schema.tables
@@ -6715,14 +6736,14 @@ async function up$33(db) {
6715
6736
  ON public.ingest_overflow_buffer (delivery_id)
6716
6737
  `.execute(db);
6717
6738
  }
6718
- async function down$33(db) {
6739
+ async function down$40(db) {
6719
6740
  await sql`DROP TABLE IF EXISTS public.ingest_overflow_buffer`.execute(db);
6720
6741
  }
6721
6742
  //#endregion
6722
6743
  //#region src/db/migrations/076_artifacts.ts
6723
6744
  var _076_artifacts_exports = /* @__PURE__ */ __exportAll({
6724
- down: () => down$32,
6725
- up: () => up$32
6745
+ down: () => down$39,
6746
+ up: () => up$39
6726
6747
  });
6727
6748
  /**
6728
6749
  * Add the `artifacts` table for user-facing build artifacts and the per-org
@@ -6739,7 +6760,7 @@ var _076_artifacts_exports = /* @__PURE__ */ __exportAll({
6739
6760
  *
6740
6761
  * Idempotent: a re-run on a DB that already has the table / columns is a no-op.
6741
6762
  */
6742
- async function up$32(db) {
6763
+ async function up$39(db) {
6743
6764
  if (!(await sql`
6744
6765
  SELECT EXISTS (
6745
6766
  SELECT 1 FROM information_schema.tables
@@ -6775,7 +6796,7 @@ async function up$32(db) {
6775
6796
  ADD COLUMN IF NOT EXISTS artifact_ttl_ms BIGINT
6776
6797
  `.execute(db);
6777
6798
  }
6778
- async function down$32(db) {
6799
+ async function down$39(db) {
6779
6800
  await sql`DROP TABLE IF EXISTS public.artifacts`.execute(db);
6780
6801
  await sql`
6781
6802
  ALTER TABLE public.org_settings
@@ -6786,8 +6807,8 @@ async function down$32(db) {
6786
6807
  //#endregion
6787
6808
  //#region src/db/migrations/077_backup_runs.ts
6788
6809
  var _077_backup_runs_exports = /* @__PURE__ */ __exportAll({
6789
- down: () => down$31,
6790
- up: () => up$31
6810
+ down: () => down$38,
6811
+ up: () => up$38
6791
6812
  });
6792
6813
  /**
6793
6814
  * Add the `backup_runs` table: one row per successful `kici-admin db backup`,
@@ -6798,12 +6819,12 @@ var _077_backup_runs_exports = /* @__PURE__ */ __exportAll({
6798
6819
  *
6799
6820
  * Idempotent: guarded on table existence.
6800
6821
  */
6801
- async function up$31(db) {
6822
+ async function up$38(db) {
6802
6823
  if (await tableExists$2(db, "backup_runs")) return;
6803
6824
  await db.schema.createTable("backup_runs").addColumn("id", "bigserial", (c) => c.primaryKey()).addColumn("created_at", "timestamptz", (c) => c.notNull().defaultTo(sql`now()`)).addColumn("dump_path", "text", (c) => c.notNull()).addColumn("byte_size", "bigint", (c) => c.notNull()).addColumn("secret_key_version", "integer").addColumn("pg_server_version", "text", (c) => c.notNull()).addColumn("migrations_hash", "text", (c) => c.notNull()).addColumn("hostname", "text", (c) => c.notNull()).execute();
6804
6825
  await db.schema.createIndex("idx_backup_runs_created_at").on("backup_runs").column("created_at").execute();
6805
6826
  }
6806
- async function down$31(db) {
6827
+ async function down$38(db) {
6807
6828
  await db.schema.dropTable("backup_runs").ifExists().execute();
6808
6829
  }
6809
6830
  async function tableExists$2(db, table) {
@@ -6817,8 +6838,8 @@ async function tableExists$2(db, table) {
6817
6838
  //#endregion
6818
6839
  //#region src/db/migrations/078_org_settings_backup_staleness.ts
6819
6840
  var _078_org_settings_backup_staleness_exports = /* @__PURE__ */ __exportAll({
6820
- down: () => down$30,
6821
- up: () => up$30
6841
+ down: () => down$37,
6842
+ up: () => up$37
6822
6843
  });
6823
6844
  /**
6824
6845
  * Add the nullable `org_settings.backup_staleness_warn_hours INTEGER` column:
@@ -6828,7 +6849,7 @@ var _078_org_settings_backup_staleness_exports = /* @__PURE__ */ __exportAll({
6828
6849
  *
6829
6850
  * Idempotent: guarded on column existence.
6830
6851
  */
6831
- async function up$30(db) {
6852
+ async function up$37(db) {
6832
6853
  if ((await sql`
6833
6854
  SELECT EXISTS (
6834
6855
  SELECT 1 FROM information_schema.columns
@@ -6842,7 +6863,7 @@ async function up$30(db) {
6842
6863
  ADD COLUMN backup_staleness_warn_hours INTEGER
6843
6864
  `.execute(db);
6844
6865
  }
6845
- async function down$30(db) {
6866
+ async function down$37(db) {
6846
6867
  await sql`
6847
6868
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS backup_staleness_warn_hours
6848
6869
  `.execute(db);
@@ -6850,8 +6871,8 @@ async function down$30(db) {
6850
6871
  //#endregion
6851
6872
  //#region src/db/migrations/079_org_settings_scaler_spawn_timeout.ts
6852
6873
  var _079_org_settings_scaler_spawn_timeout_exports = /* @__PURE__ */ __exportAll({
6853
- down: () => down$29,
6854
- up: () => up$29
6874
+ down: () => down$36,
6875
+ up: () => up$36
6855
6876
  });
6856
6877
  /**
6857
6878
  * Add `org_settings.scaler_spawn_timeout_ms BIGINT` (nullable).
@@ -6863,7 +6884,7 @@ var _079_org_settings_scaler_spawn_timeout_exports = /* @__PURE__ */ __exportAll
6863
6884
  *
6864
6885
  * Idempotent: a re-run on a DB that already has the column is a no-op.
6865
6886
  */
6866
- async function up$29(db) {
6887
+ async function up$36(db) {
6867
6888
  if ((await sql`
6868
6889
  SELECT EXISTS (
6869
6890
  SELECT 1 FROM information_schema.columns
@@ -6877,7 +6898,7 @@ async function up$29(db) {
6877
6898
  ADD COLUMN scaler_spawn_timeout_ms BIGINT
6878
6899
  `.execute(db);
6879
6900
  }
6880
- async function down$29(db) {
6901
+ async function down$36(db) {
6881
6902
  await sql`
6882
6903
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS scaler_spawn_timeout_ms
6883
6904
  `.execute(db);
@@ -6885,8 +6906,8 @@ async function down$29(db) {
6885
6906
  //#endregion
6886
6907
  //#region src/db/migrations/080_cluster_settings.ts
6887
6908
  var _080_cluster_settings_exports = /* @__PURE__ */ __exportAll({
6888
- down: () => down$28,
6889
- up: () => up$28
6909
+ down: () => down$35,
6910
+ up: () => up$35
6890
6911
  });
6891
6912
  /**
6892
6913
  * Create `cluster_settings`: a single-row (id='default') table of fleet-wide
@@ -6901,7 +6922,7 @@ var _080_cluster_settings_exports = /* @__PURE__ */ __exportAll({
6901
6922
  *
6902
6923
  * Idempotent: a re-run on a DB that already has the table is a no-op.
6903
6924
  */
6904
- async function up$28(db) {
6925
+ async function up$35(db) {
6905
6926
  if ((await sql`
6906
6927
  SELECT EXISTS (
6907
6928
  SELECT 1 FROM information_schema.tables
@@ -6925,14 +6946,14 @@ async function up$28(db) {
6925
6946
  )
6926
6947
  `.execute(db);
6927
6948
  }
6928
- async function down$28(db) {
6949
+ async function down$35(db) {
6929
6950
  await sql`DROP TABLE IF EXISTS public.cluster_settings`.execute(db);
6930
6951
  }
6931
6952
  //#endregion
6932
6953
  //#region src/db/migrations/081_org_settings_queue_timeout.ts
6933
6954
  var _081_org_settings_queue_timeout_exports = /* @__PURE__ */ __exportAll({
6934
- down: () => down$27,
6935
- up: () => up$27
6955
+ down: () => down$34,
6956
+ up: () => up$34
6936
6957
  });
6937
6958
  /**
6938
6959
  * Add `org_settings.queue_timeout_ms BIGINT` (nullable).
@@ -6949,7 +6970,7 @@ var _081_org_settings_queue_timeout_exports = /* @__PURE__ */ __exportAll({
6949
6970
  *
6950
6971
  * Idempotent: a re-run on a DB that already has the column is a no-op.
6951
6972
  */
6952
- async function up$27(db) {
6973
+ async function up$34(db) {
6953
6974
  if ((await sql`
6954
6975
  SELECT EXISTS (
6955
6976
  SELECT 1 FROM information_schema.columns
@@ -6963,7 +6984,7 @@ async function up$27(db) {
6963
6984
  ADD COLUMN queue_timeout_ms BIGINT
6964
6985
  `.execute(db);
6965
6986
  }
6966
- async function down$27(db) {
6987
+ async function down$34(db) {
6967
6988
  await sql`
6968
6989
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS queue_timeout_ms
6969
6990
  `.execute(db);
@@ -6971,8 +6992,8 @@ async function down$27(db) {
6971
6992
  //#endregion
6972
6993
  //#region src/db/migrations/082_host_s3_reachable.ts
6973
6994
  var _082_host_s3_reachable_exports = /* @__PURE__ */ __exportAll({
6974
- down: () => down$26,
6975
- up: () => up$26
6995
+ down: () => down$33,
6996
+ up: () => up$33
6976
6997
  });
6977
6998
  /**
6978
6999
  * Add `host_roster.s3_reachable BOOLEAN` (nullable).
@@ -6986,7 +7007,7 @@ var _082_host_s3_reachable_exports = /* @__PURE__ */ __exportAll({
6986
7007
  *
6987
7008
  * Idempotent: a re-run on a DB that already has the column is a no-op.
6988
7009
  */
6989
- async function up$26(db) {
7010
+ async function up$33(db) {
6990
7011
  if ((await sql`
6991
7012
  SELECT EXISTS (
6992
7013
  SELECT 1 FROM information_schema.columns
@@ -7000,7 +7021,7 @@ async function up$26(db) {
7000
7021
  ADD COLUMN s3_reachable BOOLEAN
7001
7022
  `.execute(db);
7002
7023
  }
7003
- async function down$26(db) {
7024
+ async function down$33(db) {
7004
7025
  await sql`
7005
7026
  ALTER TABLE public.host_roster DROP COLUMN IF EXISTS s3_reachable
7006
7027
  `.execute(db);
@@ -7008,8 +7029,8 @@ async function down$26(db) {
7008
7029
  //#endregion
7009
7030
  //#region src/db/migrations/083_org_settings_artifact_caps.ts
7010
7031
  var _083_org_settings_artifact_caps_exports = /* @__PURE__ */ __exportAll({
7011
- down: () => down$25,
7012
- up: () => up$25
7032
+ down: () => down$32,
7033
+ up: () => up$32
7013
7034
  });
7014
7035
  /**
7015
7036
  * Add `org_settings.artifact_max_bytes` + `artifact_max_per_run` (both nullable
@@ -7025,7 +7046,7 @@ var _083_org_settings_artifact_caps_exports = /* @__PURE__ */ __exportAll({
7025
7046
  * Idempotent: guarded on column existence; a re-run on a DB that already has a
7026
7047
  * column is a no-op.
7027
7048
  */
7028
- async function up$25(db) {
7049
+ async function up$32(db) {
7029
7050
  for (const col of ["artifact_max_bytes", "artifact_max_per_run"]) {
7030
7051
  if ((await sql`
7031
7052
  SELECT EXISTS (
@@ -7038,15 +7059,15 @@ async function up$25(db) {
7038
7059
  await sql`ALTER TABLE public.org_settings ADD COLUMN ${sql.ref(col)} BIGINT`.execute(db);
7039
7060
  }
7040
7061
  }
7041
- async function down$25(db) {
7062
+ async function down$32(db) {
7042
7063
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS artifact_max_bytes`.execute(db);
7043
7064
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS artifact_max_per_run`.execute(db);
7044
7065
  }
7045
7066
  //#endregion
7046
7067
  //#region src/db/migrations/084_orchestrator_signing_keys.ts
7047
7068
  var _084_orchestrator_signing_keys_exports = /* @__PURE__ */ __exportAll({
7048
- down: () => down$24,
7049
- up: () => up$24
7069
+ down: () => down$31,
7070
+ up: () => up$31
7050
7071
  });
7051
7072
  /**
7052
7073
  * Add the `orchestrator_signing_keys` table: the cluster-scoped, long-lived
@@ -7064,12 +7085,12 @@ var _084_orchestrator_signing_keys_exports = /* @__PURE__ */ __exportAll({
7064
7085
  *
7065
7086
  * Idempotent: guarded on table existence.
7066
7087
  */
7067
- async function up$24(db) {
7088
+ async function up$31(db) {
7068
7089
  if (await tableExists$1(db, "orchestrator_signing_keys")) return;
7069
7090
  await db.schema.createTable("orchestrator_signing_keys").addColumn("kid", "text", (c) => c.primaryKey()).addColumn("public_jwk", "jsonb", (c) => c.notNull()).addColumn("encrypted_private_jwk", "text").addColumn("key_version", "integer", (c) => c.notNull().defaultTo(1)).addColumn("alg", "text", (c) => c.notNull()).addColumn("signer_kind", "text", (c) => c.notNull()).addColumn("key_ref", "text").addColumn("status", "text", (c) => c.notNull().defaultTo("active")).addColumn("revocation_reason", "text").addColumn("created_at", "timestamptz", (c) => c.notNull().defaultTo(sql`now()`)).addColumn("activated_at", "timestamptz").addColumn("retired_at", "timestamptz").addColumn("revoked_at", "timestamptz").execute();
7070
7091
  await db.schema.createIndex("idx_orch_signing_keys_status").on("orchestrator_signing_keys").column("status").execute();
7071
7092
  }
7072
- async function down$24(db) {
7093
+ async function down$31(db) {
7073
7094
  await db.schema.dropTable("orchestrator_signing_keys").ifExists().execute();
7074
7095
  }
7075
7096
  async function tableExists$1(db, table) {
@@ -7083,8 +7104,8 @@ async function tableExists$1(db, table) {
7083
7104
  //#endregion
7084
7105
  //#region src/db/migrations/085_cluster_settings_reroute_flap_grace_ms.ts
7085
7106
  var _085_cluster_settings_reroute_flap_grace_ms_exports = /* @__PURE__ */ __exportAll({
7086
- down: () => down$23,
7087
- up: () => up$23
7107
+ down: () => down$30,
7108
+ up: () => up$30
7088
7109
  });
7089
7110
  /**
7090
7111
  * Add `cluster_settings.reroute_flap_grace_ms` (nullable BIGINT).
@@ -7094,7 +7115,7 @@ var _085_cluster_settings_reroute_flap_grace_ms_exports = /* @__PURE__ */ __expo
7094
7115
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7095
7116
  * the column is a no-op.
7096
7117
  */
7097
- async function up$23(db) {
7118
+ async function up$30(db) {
7098
7119
  if ((await sql`
7099
7120
  SELECT EXISTS (
7100
7121
  SELECT 1 FROM information_schema.columns
@@ -7105,14 +7126,14 @@ async function up$23(db) {
7105
7126
  `.execute(db)).rows[0]?.exists) return;
7106
7127
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN reroute_flap_grace_ms BIGINT`.execute(db);
7107
7128
  }
7108
- async function down$23(db) {
7129
+ async function down$30(db) {
7109
7130
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS reroute_flap_grace_ms`.execute(db);
7110
7131
  }
7111
7132
  //#endregion
7112
7133
  //#region src/db/migrations/086_cluster_settings_max_fanout_hosts.ts
7113
7134
  var _086_cluster_settings_max_fanout_hosts_exports = /* @__PURE__ */ __exportAll({
7114
- down: () => down$22,
7115
- up: () => up$22
7135
+ down: () => down$29,
7136
+ up: () => up$29
7116
7137
  });
7117
7138
  /**
7118
7139
  * Add `cluster_settings.max_fanout_hosts` (nullable INTEGER).
@@ -7122,7 +7143,7 @@ var _086_cluster_settings_max_fanout_hosts_exports = /* @__PURE__ */ __exportAll
7122
7143
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7123
7144
  * the column is a no-op.
7124
7145
  */
7125
- async function up$22(db) {
7146
+ async function up$29(db) {
7126
7147
  if ((await sql`
7127
7148
  SELECT EXISTS (
7128
7149
  SELECT 1 FROM information_schema.columns
@@ -7133,14 +7154,14 @@ async function up$22(db) {
7133
7154
  `.execute(db)).rows[0]?.exists) return;
7134
7155
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN max_fanout_hosts INTEGER`.execute(db);
7135
7156
  }
7136
- async function down$22(db) {
7157
+ async function down$29(db) {
7137
7158
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS max_fanout_hosts`.execute(db);
7138
7159
  }
7139
7160
  //#endregion
7140
7161
  //#region src/db/migrations/087_cluster_settings_event_router_rate_limit.ts
7141
7162
  var _087_cluster_settings_event_router_rate_limit_exports = /* @__PURE__ */ __exportAll({
7142
- down: () => down$21,
7143
- up: () => up$21
7163
+ down: () => down$28,
7164
+ up: () => up$28
7144
7165
  });
7145
7166
  /**
7146
7167
  * Add `cluster_settings.event_router_rate_limit_per_workflow_per_minute` (nullable INTEGER).
@@ -7150,7 +7171,7 @@ var _087_cluster_settings_event_router_rate_limit_exports = /* @__PURE__ */ __ex
7150
7171
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7151
7172
  * the column is a no-op.
7152
7173
  */
7153
- async function up$21(db) {
7174
+ async function up$28(db) {
7154
7175
  if ((await sql`
7155
7176
  SELECT EXISTS (
7156
7177
  SELECT 1 FROM information_schema.columns
@@ -7161,14 +7182,14 @@ async function up$21(db) {
7161
7182
  `.execute(db)).rows[0]?.exists) return;
7162
7183
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN event_router_rate_limit_per_workflow_per_minute INTEGER`.execute(db);
7163
7184
  }
7164
- async function down$21(db) {
7185
+ async function down$28(db) {
7165
7186
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS event_router_rate_limit_per_workflow_per_minute`.execute(db);
7166
7187
  }
7167
7188
  //#endregion
7168
7189
  //#region src/db/migrations/088_cluster_settings_cache_max_tarball_bytes.ts
7169
7190
  var _088_cluster_settings_cache_max_tarball_bytes_exports = /* @__PURE__ */ __exportAll({
7170
- down: () => down$20,
7171
- up: () => up$20
7191
+ down: () => down$27,
7192
+ up: () => up$27
7172
7193
  });
7173
7194
  /**
7174
7195
  * Add `cluster_settings.cache_max_tarball_bytes` (nullable BIGINT).
@@ -7178,7 +7199,7 @@ var _088_cluster_settings_cache_max_tarball_bytes_exports = /* @__PURE__ */ __ex
7178
7199
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7179
7200
  * the column is a no-op.
7180
7201
  */
7181
- async function up$20(db) {
7202
+ async function up$27(db) {
7182
7203
  if ((await sql`
7183
7204
  SELECT EXISTS (
7184
7205
  SELECT 1 FROM information_schema.columns
@@ -7189,14 +7210,14 @@ async function up$20(db) {
7189
7210
  `.execute(db)).rows[0]?.exists) return;
7190
7211
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN cache_max_tarball_bytes BIGINT`.execute(db);
7191
7212
  }
7192
- async function down$20(db) {
7213
+ async function down$27(db) {
7193
7214
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS cache_max_tarball_bytes`.execute(db);
7194
7215
  }
7195
7216
  //#endregion
7196
7217
  //#region src/db/migrations/089_cluster_settings_cache_ttl_days.ts
7197
7218
  var _089_cluster_settings_cache_ttl_days_exports = /* @__PURE__ */ __exportAll({
7198
- down: () => down$19,
7199
- up: () => up$19
7219
+ down: () => down$26,
7220
+ up: () => up$26
7200
7221
  });
7201
7222
  /**
7202
7223
  * Add `cluster_settings.cache_ttl_days` (nullable INTEGER).
@@ -7206,7 +7227,7 @@ var _089_cluster_settings_cache_ttl_days_exports = /* @__PURE__ */ __exportAll({
7206
7227
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7207
7228
  * the column is a no-op.
7208
7229
  */
7209
- async function up$19(db) {
7230
+ async function up$26(db) {
7210
7231
  if ((await sql`
7211
7232
  SELECT EXISTS (
7212
7233
  SELECT 1 FROM information_schema.columns
@@ -7217,14 +7238,14 @@ async function up$19(db) {
7217
7238
  `.execute(db)).rows[0]?.exists) return;
7218
7239
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN cache_ttl_days INTEGER`.execute(db);
7219
7240
  }
7220
- async function down$19(db) {
7241
+ async function down$26(db) {
7221
7242
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS cache_ttl_days`.execute(db);
7222
7243
  }
7223
7244
  //#endregion
7224
7245
  //#region src/db/migrations/090_cluster_settings_concurrency_wait_timeout_ms.ts
7225
7246
  var _090_cluster_settings_concurrency_wait_timeout_ms_exports = /* @__PURE__ */ __exportAll({
7226
- down: () => down$18,
7227
- up: () => up$18
7247
+ down: () => down$25,
7248
+ up: () => up$25
7228
7249
  });
7229
7250
  /**
7230
7251
  * Add `cluster_settings.concurrency_wait_timeout_ms` (nullable BIGINT).
@@ -7234,7 +7255,7 @@ var _090_cluster_settings_concurrency_wait_timeout_ms_exports = /* @__PURE__ */
7234
7255
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7235
7256
  * the column is a no-op.
7236
7257
  */
7237
- async function up$18(db) {
7258
+ async function up$25(db) {
7238
7259
  if ((await sql`
7239
7260
  SELECT EXISTS (
7240
7261
  SELECT 1 FROM information_schema.columns
@@ -7245,14 +7266,14 @@ async function up$18(db) {
7245
7266
  `.execute(db)).rows[0]?.exists) return;
7246
7267
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN concurrency_wait_timeout_ms BIGINT`.execute(db);
7247
7268
  }
7248
- async function down$18(db) {
7269
+ async function down$25(db) {
7249
7270
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS concurrency_wait_timeout_ms`.execute(db);
7250
7271
  }
7251
7272
  //#endregion
7252
7273
  //#region src/db/migrations/091_cluster_settings_agent_token_ttl_ms.ts
7253
7274
  var _091_cluster_settings_agent_token_ttl_ms_exports = /* @__PURE__ */ __exportAll({
7254
- down: () => down$17,
7255
- up: () => up$17
7275
+ down: () => down$24,
7276
+ up: () => up$24
7256
7277
  });
7257
7278
  /**
7258
7279
  * Add `cluster_settings.agent_token_ttl_ms` (nullable BIGINT).
@@ -7262,7 +7283,7 @@ var _091_cluster_settings_agent_token_ttl_ms_exports = /* @__PURE__ */ __exportA
7262
7283
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7263
7284
  * the column is a no-op.
7264
7285
  */
7265
- async function up$17(db) {
7286
+ async function up$24(db) {
7266
7287
  if ((await sql`
7267
7288
  SELECT EXISTS (
7268
7289
  SELECT 1 FROM information_schema.columns
@@ -7273,14 +7294,14 @@ async function up$17(db) {
7273
7294
  `.execute(db)).rows[0]?.exists) return;
7274
7295
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN agent_token_ttl_ms BIGINT`.execute(db);
7275
7296
  }
7276
- async function down$17(db) {
7297
+ async function down$24(db) {
7277
7298
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS agent_token_ttl_ms`.execute(db);
7278
7299
  }
7279
7300
  //#endregion
7280
7301
  //#region src/db/migrations/092_cluster_settings_version.ts
7281
7302
  var _092_cluster_settings_version_exports = /* @__PURE__ */ __exportAll({
7282
- down: () => down$16,
7283
- up: () => up$16
7303
+ down: () => down$23,
7304
+ up: () => up$23
7284
7305
  });
7285
7306
  /**
7286
7307
  * Add `cluster_settings.version` (monotonic BIGINT, bumped on each settings
@@ -7294,7 +7315,7 @@ var _092_cluster_settings_version_exports = /* @__PURE__ */ __exportAll({
7294
7315
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7295
7316
  * the column is a no-op.
7296
7317
  */
7297
- async function up$16(db) {
7318
+ async function up$23(db) {
7298
7319
  if ((await sql`
7299
7320
  SELECT EXISTS (
7300
7321
  SELECT 1 FROM information_schema.columns
@@ -7305,14 +7326,14 @@ async function up$16(db) {
7305
7326
  `.execute(db)).rows[0]?.exists) return;
7306
7327
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN version BIGINT NOT NULL DEFAULT 0`.execute(db);
7307
7328
  }
7308
- async function down$16(db) {
7329
+ async function down$23(db) {
7309
7330
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS version`.execute(db);
7310
7331
  }
7311
7332
  //#endregion
7312
7333
  //#region src/db/migrations/093_org_settings_sandbox_allowlist.ts
7313
7334
  var _093_org_settings_sandbox_allowlist_exports = /* @__PURE__ */ __exportAll({
7314
- down: () => down$15,
7315
- up: () => up$15
7335
+ down: () => down$22,
7336
+ up: () => up$22
7316
7337
  });
7317
7338
  /**
7318
7339
  * Add the per-org container-sandbox escape-hatch allow-list to `org_settings`:
@@ -7330,7 +7351,7 @@ var _093_org_settings_sandbox_allowlist_exports = /* @__PURE__ */ __exportAll({
7330
7351
  *
7331
7352
  * Idempotent: a re-run on a DB that already has a column skips that column.
7332
7353
  */
7333
- async function columnExists$4(db, column) {
7354
+ async function columnExists$9(db, column) {
7334
7355
  return (await sql`
7335
7356
  SELECT EXISTS (
7336
7357
  SELECT 1 FROM information_schema.columns
@@ -7340,17 +7361,17 @@ async function columnExists$4(db, column) {
7340
7361
  ) AS exists
7341
7362
  `.execute(db)).rows[0]?.exists ?? false;
7342
7363
  }
7343
- async function up$15(db) {
7344
- if (!await columnExists$4(db, "sandbox_allowed_capabilities")) await sql`
7364
+ async function up$22(db) {
7365
+ if (!await columnExists$9(db, "sandbox_allowed_capabilities")) await sql`
7345
7366
  ALTER TABLE public.org_settings
7346
7367
  ADD COLUMN sandbox_allowed_capabilities TEXT[]
7347
7368
  `.execute(db);
7348
- if (!await columnExists$4(db, "sandbox_allow_host_network")) await sql`
7369
+ if (!await columnExists$9(db, "sandbox_allow_host_network")) await sql`
7349
7370
  ALTER TABLE public.org_settings
7350
7371
  ADD COLUMN sandbox_allow_host_network BOOLEAN
7351
7372
  `.execute(db);
7352
7373
  }
7353
- async function down$15(db) {
7374
+ async function down$22(db) {
7354
7375
  await sql`
7355
7376
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS sandbox_allowed_capabilities
7356
7377
  `.execute(db);
@@ -7361,8 +7382,8 @@ async function down$15(db) {
7361
7382
  //#endregion
7362
7383
  //#region src/db/migrations/094_dashboard_encryption_keys.ts
7363
7384
  var _094_dashboard_encryption_keys_exports = /* @__PURE__ */ __exportAll({
7364
- down: () => down$14,
7365
- up: () => up$14
7385
+ down: () => down$21,
7386
+ up: () => up$21
7366
7387
  });
7367
7388
  /**
7368
7389
  * Add the `dashboard_encryption_keys` table: the cluster-scoped, long-lived
@@ -7381,12 +7402,12 @@ var _094_dashboard_encryption_keys_exports = /* @__PURE__ */ __exportAll({
7381
7402
  *
7382
7403
  * Idempotent: guarded on table existence.
7383
7404
  */
7384
- async function up$14(db) {
7405
+ async function up$21(db) {
7385
7406
  if (await tableExists(db, "dashboard_encryption_keys")) return;
7386
7407
  await db.schema.createTable("dashboard_encryption_keys").addColumn("kid", "text", (c) => c.primaryKey()).addColumn("public_jwk", "jsonb", (c) => c.notNull()).addColumn("encrypted_private_key", "text", (c) => c.notNull()).addColumn("status", "text", (c) => c.notNull().defaultTo("active")).addColumn("revocation_reason", "text").addColumn("created_at", "timestamptz", (c) => c.notNull().defaultTo(sql`now()`)).addColumn("activated_at", "timestamptz").addColumn("revoked_at", "timestamptz").execute();
7387
7408
  await db.schema.createIndex("idx_dashboard_encryption_keys_status").on("dashboard_encryption_keys").column("status").execute();
7388
7409
  }
7389
- async function down$14(db) {
7410
+ async function down$21(db) {
7390
7411
  await db.schema.dropTable("dashboard_encryption_keys").ifExists().execute();
7391
7412
  }
7392
7413
  async function tableExists(db, table) {
@@ -7400,8 +7421,8 @@ async function tableExists(db, table) {
7400
7421
  //#endregion
7401
7422
  //#region src/db/migrations/095_dashboard_write_policy_tristate.ts
7402
7423
  var _095_dashboard_write_policy_tristate_exports = /* @__PURE__ */ __exportAll({
7403
- down: () => down$13,
7404
- up: () => up$13
7424
+ down: () => down$20,
7425
+ up: () => up$20
7405
7426
  });
7406
7427
  /**
7407
7428
  * Migrate stored `org_settings.dashboard_write_policy` JSONB from the legacy
@@ -7419,7 +7440,7 @@ var _095_dashboard_write_policy_tristate_exports = /* @__PURE__ */ __exportAll({
7419
7440
  * Pure SQL rewrite: for each row, rebuild the object keeping only non-`true`
7420
7441
  * entries and mapping `false` → `'disabled'`, leaving existing string values.
7421
7442
  */
7422
- async function up$13(db) {
7443
+ async function up$20(db) {
7423
7444
  await sql`
7424
7445
  UPDATE org_settings
7425
7446
  SET dashboard_write_policy = COALESCE(
@@ -7446,12 +7467,12 @@ async function up$13(db) {
7446
7467
  )
7447
7468
  `.execute(db);
7448
7469
  }
7449
- async function down$13() {}
7470
+ async function down$20() {}
7450
7471
  //#endregion
7451
7472
  //#region src/db/migrations/096_multi_schedule_cron_last_fired.ts
7452
7473
  var _096_multi_schedule_cron_last_fired_exports = /* @__PURE__ */ __exportAll({
7453
- down: () => down$12,
7454
- up: () => up$12
7474
+ down: () => down$19,
7475
+ up: () => up$19
7455
7476
  });
7456
7477
  /**
7457
7478
  * Track cron last-fired per (registration, schedule) instead of per
@@ -7466,7 +7487,7 @@ var _096_multi_schedule_cron_last_fired_exports = /* @__PURE__ */ __exportAll({
7466
7487
  *
7467
7488
  * Idempotent: re-running on an already-migrated DB skips each step.
7468
7489
  */
7469
- async function columnExists$3(db, column) {
7490
+ async function columnExists$8(db, column) {
7470
7491
  return (await sql`
7471
7492
  SELECT EXISTS (
7472
7493
  SELECT 1 FROM information_schema.columns
@@ -7486,8 +7507,8 @@ async function primaryKeyColumns(db) {
7486
7507
  ORDER BY a.attnum
7487
7508
  `.execute(db)).rows.map((row) => row.attname);
7488
7509
  }
7489
- async function up$12(db) {
7490
- if (!await columnExists$3(db, "schedule_key")) await sql`ALTER TABLE public.cron_last_fired ADD COLUMN schedule_key text`.execute(db);
7510
+ async function up$19(db) {
7511
+ if (!await columnExists$8(db, "schedule_key")) await sql`ALTER TABLE public.cron_last_fired ADD COLUMN schedule_key text`.execute(db);
7491
7512
  await sql`
7492
7513
  UPDATE public.cron_last_fired clf
7493
7514
  SET schedule_key = k.key
@@ -7513,7 +7534,7 @@ async function up$12(db) {
7513
7534
  `.execute(db);
7514
7535
  }
7515
7536
  }
7516
- async function down$12(db) {
7537
+ async function down$19(db) {
7517
7538
  await sql`
7518
7539
  DELETE FROM public.cron_last_fired a
7519
7540
  USING public.cron_last_fired b
@@ -7525,13 +7546,13 @@ async function down$12(db) {
7525
7546
  ALTER TABLE public.cron_last_fired
7526
7547
  ADD CONSTRAINT cron_last_fired_pkey PRIMARY KEY (registration_id)
7527
7548
  `.execute(db);
7528
- if (await columnExists$3(db, "schedule_key")) await sql`ALTER TABLE public.cron_last_fired DROP COLUMN schedule_key`.execute(db);
7549
+ if (await columnExists$8(db, "schedule_key")) await sql`ALTER TABLE public.cron_last_fired DROP COLUMN schedule_key`.execute(db);
7529
7550
  }
7530
7551
  //#endregion
7531
7552
  //#region src/db/migrations/097_execution_runs_pr_number.ts
7532
7553
  var _097_execution_runs_pr_number_exports = /* @__PURE__ */ __exportAll({
7533
- down: () => down$11,
7534
- up: () => up$11
7554
+ down: () => down$18,
7555
+ up: () => up$18
7535
7556
  });
7536
7557
  /**
7537
7558
  * Add `pr_number INTEGER NULL` to `execution_runs`.
@@ -7544,7 +7565,7 @@ var _097_execution_runs_pr_number_exports = /* @__PURE__ */ __exportAll({
7544
7565
  *
7545
7566
  * Idempotent: a re-run on a DB that already has the column is a no-op.
7546
7567
  */
7547
- async function columnExists$2(db, column) {
7568
+ async function columnExists$7(db, column) {
7548
7569
  return (await sql`
7549
7570
  SELECT EXISTS (
7550
7571
  SELECT 1 FROM information_schema.columns
@@ -7554,13 +7575,13 @@ async function columnExists$2(db, column) {
7554
7575
  ) AS exists
7555
7576
  `.execute(db)).rows[0]?.exists ?? false;
7556
7577
  }
7557
- async function up$11(db) {
7558
- if (!await columnExists$2(db, "pr_number")) await sql`
7578
+ async function up$18(db) {
7579
+ if (!await columnExists$7(db, "pr_number")) await sql`
7559
7580
  ALTER TABLE public.execution_runs
7560
7581
  ADD COLUMN pr_number INTEGER
7561
7582
  `.execute(db);
7562
7583
  }
7563
- async function down$11(db) {
7584
+ async function down$18(db) {
7564
7585
  await sql`
7565
7586
  ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS pr_number
7566
7587
  `.execute(db);
@@ -7568,8 +7589,8 @@ async function down$11(db) {
7568
7589
  //#endregion
7569
7590
  //#region src/db/migrations/098_execution_runs_customer_id.ts
7570
7591
  var _098_execution_runs_customer_id_exports = /* @__PURE__ */ __exportAll({
7571
- down: () => down$10,
7572
- up: () => up$10
7592
+ down: () => down$17,
7593
+ up: () => up$17
7573
7594
  });
7574
7595
  /**
7575
7596
  * Denormalize the owning org onto `execution_runs` so the concurrency-gate
@@ -7587,7 +7608,7 @@ var _098_execution_runs_customer_id_exports = /* @__PURE__ */ __exportAll({
7587
7608
  *
7588
7609
  * Idempotent: re-running skips the column when it already exists.
7589
7610
  */
7590
- async function columnExists$1(db, column) {
7611
+ async function columnExists$6(db, column) {
7591
7612
  return (await sql`
7592
7613
  SELECT EXISTS (
7593
7614
  SELECT 1 FROM information_schema.columns
@@ -7597,8 +7618,8 @@ async function columnExists$1(db, column) {
7597
7618
  ) AS exists
7598
7619
  `.execute(db)).rows[0]?.exists ?? false;
7599
7620
  }
7600
- async function up$10(db) {
7601
- if (!await columnExists$1(db, "customer_id")) {
7621
+ async function up$17(db) {
7622
+ if (!await columnExists$6(db, "customer_id")) {
7602
7623
  await sql`
7603
7624
  ALTER TABLE public.execution_runs
7604
7625
  ADD COLUMN customer_id TEXT NOT NULL DEFAULT '__default__'
@@ -7621,7 +7642,7 @@ async function up$10(db) {
7621
7642
  ON public.execution_runs (customer_id, context)
7622
7643
  `.execute(db);
7623
7644
  }
7624
- async function down$10(db) {
7645
+ async function down$17(db) {
7625
7646
  await sql`DROP INDEX IF EXISTS execution_runs_customer_id_context_idx`.execute(db);
7626
7647
  await sql`
7627
7648
  ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS customer_id
@@ -7630,8 +7651,8 @@ async function down$10(db) {
7630
7651
  //#endregion
7631
7652
  //#region src/db/migrations/099_cluster_settings_dashboard_verified_issuer.ts
7632
7653
  var _099_cluster_settings_dashboard_verified_issuer_exports = /* @__PURE__ */ __exportAll({
7633
- down: () => down$9,
7634
- up: () => up$9
7654
+ down: () => down$16,
7655
+ up: () => up$16
7635
7656
  });
7636
7657
  /**
7637
7658
  * Add `cluster_settings.dashboard_verified_issuer` (nullable text).
@@ -7650,7 +7671,7 @@ var _099_cluster_settings_dashboard_verified_issuer_exports = /* @__PURE__ */ __
7650
7671
  * Idempotent: guarded on column existence; a re-run on a DB that already has the
7651
7672
  * column is a no-op.
7652
7673
  */
7653
- async function up$9(db) {
7674
+ async function up$16(db) {
7654
7675
  if ((await sql`
7655
7676
  SELECT EXISTS (
7656
7677
  SELECT 1 FROM information_schema.columns
@@ -7661,14 +7682,14 @@ async function up$9(db) {
7661
7682
  `.execute(db)).rows[0]?.exists) return;
7662
7683
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN dashboard_verified_issuer TEXT`.execute(db);
7663
7684
  }
7664
- async function down$9(db) {
7685
+ async function down$16(db) {
7665
7686
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS dashboard_verified_issuer`.execute(db);
7666
7687
  }
7667
7688
  //#endregion
7668
7689
  //#region src/db/migrations/100_held_runs_hold_type_vocabulary.ts
7669
7690
  var _100_held_runs_hold_type_vocabulary_exports = /* @__PURE__ */ __exportAll({
7670
- down: () => down$8,
7671
- up: () => up$8
7691
+ down: () => down$15,
7692
+ up: () => up$15
7672
7693
  });
7673
7694
  /**
7674
7695
  * Realign `held_runs.hold_type` onto the engine's `HoldType` vocabulary.
@@ -7687,7 +7708,7 @@ var _100_held_runs_hold_type_vocabulary_exports = /* @__PURE__ */ __exportAll({
7687
7708
  *
7688
7709
  * Idempotent: a second run matches no rows.
7689
7710
  */
7690
- async function up$8(db) {
7711
+ async function up$15(db) {
7691
7712
  await sql`UPDATE public.held_runs SET hold_type = 'reviewer' WHERE hold_type = 'approval'`.execute(db);
7692
7713
  await sql`UPDATE public.held_runs SET hold_type = 'timer' WHERE hold_type = 'wait_timer'`.execute(db);
7693
7714
  }
@@ -7701,15 +7722,15 @@ async function up$8(db) {
7701
7722
  * `wait_timer` alone, so leaving those rows spelled `timer` would strand them
7702
7723
  * in the expire-and-fail path.
7703
7724
  */
7704
- async function down$8(db) {
7725
+ async function down$15(db) {
7705
7726
  await sql`UPDATE public.held_runs SET hold_type = 'approval' WHERE hold_type = 'reviewer'`.execute(db);
7706
7727
  await sql`UPDATE public.held_runs SET hold_type = 'wait_timer' WHERE hold_type = 'timer'`.execute(db);
7707
7728
  }
7708
7729
  //#endregion
7709
7730
  //#region src/db/migrations/101_contexts_hold_expiry_drop_default.ts
7710
7731
  var _101_contexts_hold_expiry_drop_default_exports = /* @__PURE__ */ __exportAll({
7711
- down: () => down$7,
7712
- up: () => up$7
7732
+ down: () => down$14,
7733
+ up: () => up$14
7713
7734
  });
7714
7735
  /**
7715
7736
  * Give the context hold expiry a single default, and retire the stored zeroes.
@@ -7730,7 +7751,7 @@ var _101_contexts_hold_expiry_drop_default_exports = /* @__PURE__ */ __exportAll
7730
7751
  * Idempotent: dropping an absent default is a no-op and the UPDATE matches no
7731
7752
  * rows on a second run.
7732
7753
  */
7733
- async function up$7(db) {
7754
+ async function up$14(db) {
7734
7755
  await sql`ALTER TABLE public.contexts ALTER COLUMN hold_expiry_seconds DROP DEFAULT`.execute(db);
7735
7756
  await sql`UPDATE public.contexts SET hold_expiry_seconds = NULL WHERE hold_expiry_seconds = 0`.execute(db);
7736
7757
  }
@@ -7742,14 +7763,14 @@ async function up$7(db) {
7742
7763
  * back to `0` would resume cancelling every hold on its context — so a
7743
7764
  * rollback keeps them on the fallback rather than re-breaking them.
7744
7765
  */
7745
- async function down$7(db) {
7766
+ async function down$14(db) {
7746
7767
  await sql`ALTER TABLE public.contexts ALTER COLUMN hold_expiry_seconds SET DEFAULT 86400`.execute(db);
7747
7768
  }
7748
7769
  //#endregion
7749
7770
  //#region src/db/migrations/102_dispatch_queue_agent_id.ts
7750
7771
  var _102_dispatch_queue_agent_id_exports = /* @__PURE__ */ __exportAll({
7751
- down: () => down$6,
7752
- up: () => up$6
7772
+ down: () => down$13,
7773
+ up: () => up$13
7753
7774
  });
7754
7775
  /**
7755
7776
  * Add `dispatch_queue.agent_id` (nullable text).
@@ -7767,7 +7788,7 @@ var _102_dispatch_queue_agent_id_exports = /* @__PURE__ */ __exportAll({
7767
7788
  * Idempotent: guarded on column existence; a re-run on a DB that already has the
7768
7789
  * column is a no-op.
7769
7790
  */
7770
- async function up$6(db) {
7791
+ async function up$13(db) {
7771
7792
  if ((await sql`
7772
7793
  SELECT EXISTS (
7773
7794
  SELECT 1 FROM information_schema.columns
@@ -7778,14 +7799,14 @@ async function up$6(db) {
7778
7799
  `.execute(db)).rows[0]?.exists) return;
7779
7800
  await sql`ALTER TABLE public.dispatch_queue ADD COLUMN agent_id TEXT`.execute(db);
7780
7801
  }
7781
- async function down$6(db) {
7802
+ async function down$13(db) {
7782
7803
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS agent_id`.execute(db);
7783
7804
  }
7784
7805
  //#endregion
7785
7806
  //#region src/db/migrations/103_cluster_settings_ownership_db_check_timeout_ms.ts
7786
7807
  var _103_cluster_settings_ownership_db_check_timeout_ms_exports = /* @__PURE__ */ __exportAll({
7787
- down: () => down$5,
7788
- up: () => up$5
7808
+ down: () => down$12,
7809
+ up: () => up$12
7789
7810
  });
7790
7811
  /**
7791
7812
  * Add `cluster_settings.ownership_db_check_timeout_ms` (nullable bigint).
@@ -7803,7 +7824,7 @@ var _103_cluster_settings_ownership_db_check_timeout_ms_exports = /* @__PURE__ *
7803
7824
  * Idempotent: guarded on column existence; a re-run on a DB that already has the
7804
7825
  * column is a no-op.
7805
7826
  */
7806
- async function up$5(db) {
7827
+ async function up$12(db) {
7807
7828
  if ((await sql`
7808
7829
  SELECT EXISTS (
7809
7830
  SELECT 1 FROM information_schema.columns
@@ -7814,14 +7835,14 @@ async function up$5(db) {
7814
7835
  `.execute(db)).rows[0]?.exists) return;
7815
7836
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN ownership_db_check_timeout_ms BIGINT`.execute(db);
7816
7837
  }
7817
- async function down$5(db) {
7838
+ async function down$12(db) {
7818
7839
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS ownership_db_check_timeout_ms`.execute(db);
7819
7840
  }
7820
7841
  //#endregion
7821
7842
  //#region src/db/migrations/104_check_run_terminal_sent.ts
7822
7843
  var _104_check_run_terminal_sent_exports = /* @__PURE__ */ __exportAll({
7823
- down: () => down$4,
7824
- up: () => up$4
7844
+ down: () => down$11,
7845
+ up: () => up$11
7825
7846
  });
7826
7847
  /**
7827
7848
  * Add `check_run_tracking.terminal_sent_at` (nullable timestamptz).
@@ -7841,149 +7862,467 @@ var _104_check_run_terminal_sent_exports = /* @__PURE__ */ __exportAll({
7841
7862
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7842
7863
  * the column is a no-op.
7843
7864
  */
7844
- async function up$4(db) {
7845
- if ((await sql`
7865
+ async function up$11(db) {
7866
+ if ((await sql`
7867
+ SELECT EXISTS (
7868
+ SELECT 1 FROM information_schema.columns
7869
+ WHERE table_schema = 'public'
7870
+ AND table_name = 'check_run_tracking'
7871
+ AND column_name = 'terminal_sent_at'
7872
+ ) AS exists
7873
+ `.execute(db)).rows[0]?.exists) return;
7874
+ await sql`ALTER TABLE public.check_run_tracking ADD COLUMN terminal_sent_at TIMESTAMPTZ`.execute(db);
7875
+ }
7876
+ async function down$11(db) {
7877
+ await sql`ALTER TABLE public.check_run_tracking DROP COLUMN IF EXISTS terminal_sent_at`.execute(db);
7878
+ }
7879
+ //#endregion
7880
+ //#region src/db/migrations/105_org_trust_policy.ts
7881
+ var _105_org_trust_policy_exports = /* @__PURE__ */ __exportAll({
7882
+ down: () => down$10,
7883
+ up: () => up$10
7884
+ });
7885
+ /**
7886
+ * Create `org_trust_policy` — the orchestrator's cache of the Platform-owned org
7887
+ * trust policy pushed on `trust_policy.update`.
7888
+ *
7889
+ * A dedicated table rather than `org_settings` columns, because this is
7890
+ * Platform-owned policy the orchestrator consumes, not operator-owned config the
7891
+ * operator tunes. `source` records which of the two wrote the row so the admin
7892
+ * surface can present a Platform-managed policy as read-only.
7893
+ *
7894
+ * Persisting rather than caching in memory is deliberate: a security policy that
7895
+ * silently reverts to a default across a restart is worse than one that is never
7896
+ * applied.
7897
+ *
7898
+ * Idempotent: guarded by IF NOT EXISTS, so a re-run is a no-op.
7899
+ */
7900
+ async function up$10(db) {
7901
+ await sql`
7902
+ CREATE TABLE IF NOT EXISTS public.org_trust_policy (
7903
+ customer_id TEXT PRIMARY KEY,
7904
+ fork_policy TEXT NOT NULL,
7905
+ unknown_contributor_policy TEXT NOT NULL,
7906
+ workflow_change_policy TEXT NOT NULL,
7907
+ approval_expiry_hours INTEGER NOT NULL,
7908
+ source TEXT NOT NULL,
7909
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
7910
+ )
7911
+ `.execute(db);
7912
+ }
7913
+ async function down$10(db) {
7914
+ await sql`DROP TABLE IF EXISTS public.org_trust_policy`.execute(db);
7915
+ }
7916
+ //#endregion
7917
+ //#region src/db/migrations/106_cluster_settings_check_run_tracking_ttl_days.ts
7918
+ var _106_cluster_settings_check_run_tracking_ttl_days_exports = /* @__PURE__ */ __exportAll({
7919
+ down: () => down$9,
7920
+ up: () => up$9
7921
+ });
7922
+ /**
7923
+ * Add `cluster_settings.check_run_tracking_ttl_days` (nullable integer).
7924
+ *
7925
+ * Retention window for `check_run_tracking` rows. The hourly cleanup sweep
7926
+ * deletes rows untouched for longer than this; 0 disables the sweep.
7927
+ *
7928
+ * Cluster-global (the sweep runs once per fleet on the cleanup tick, with no
7929
+ * tenant in scope at the read site), so it lives on `cluster_settings` rather
7930
+ * than `org_settings`. NULL means the orchestrator's own configured default
7931
+ * applies.
7932
+ *
7933
+ * Idempotent: guarded on column existence; a re-run on a database that already
7934
+ * has the column is a no-op.
7935
+ */
7936
+ async function up$9(db) {
7937
+ if ((await sql`
7938
+ SELECT EXISTS (
7939
+ SELECT 1 FROM information_schema.columns
7940
+ WHERE table_schema = 'public'
7941
+ AND table_name = 'cluster_settings'
7942
+ AND column_name = 'check_run_tracking_ttl_days'
7943
+ ) AS exists
7944
+ `.execute(db)).rows[0]?.exists) return;
7945
+ await sql`ALTER TABLE public.cluster_settings ADD COLUMN check_run_tracking_ttl_days INTEGER`.execute(db);
7946
+ }
7947
+ async function down$9(db) {
7948
+ await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS check_run_tracking_ttl_days`.execute(db);
7949
+ }
7950
+ //#endregion
7951
+ //#region src/db/migrations/107_check_run_tracking_updated_at_index.ts
7952
+ var _107_check_run_tracking_updated_at_index_exports = /* @__PURE__ */ __exportAll({
7953
+ down: () => down$8,
7954
+ up: () => up$8
7955
+ });
7956
+ /**
7957
+ * Add `idx_check_run_tracking_updated_at` on `check_run_tracking (updated_at)`.
7958
+ *
7959
+ * `CheckRunTrackingStore.pruneStale` — the hourly retention sweep — filters
7960
+ * `WHERE updated_at < now() - <window>`. The table already carries two indexes
7961
+ * — the primary key on `(provider, owner, repo, sha, check_name)` and the
7962
+ * partial `idx_check_run_tracking_run_id` — but `updated_at` leads neither, so
7963
+ * that predicate can use neither and without this index every sweep
7964
+ * sequentially scans the whole table. The scan
7965
+ * is worst exactly where it hurts: a deployment that accumulated rows before
7966
+ * retention existed has the largest table and gets the scan hourly, on every
7967
+ * coordinator, since the cleanup tick is not leader-gated.
7968
+ *
7969
+ * Mirrors `idx_dispatch_queue_run_id` (migration 072) and
7970
+ * `idx_request_idempotency_created_at` (migration 068), both of which exist to
7971
+ * index a TTL sweep's prune predicate.
7972
+ *
7973
+ * Idempotent: `IF NOT EXISTS` makes a re-run a no-op.
7974
+ */
7975
+ async function up$8(db) {
7976
+ await sql`
7977
+ CREATE INDEX IF NOT EXISTS idx_check_run_tracking_updated_at
7978
+ ON public.check_run_tracking (updated_at)
7979
+ `.execute(db);
7980
+ }
7981
+ async function down$8(db) {
7982
+ await sql`DROP INDEX IF EXISTS public.idx_check_run_tracking_updated_at`.execute(db);
7983
+ }
7984
+ //#endregion
7985
+ //#region src/db/migrations/108_unroutable_fast_fail.ts
7986
+ var _108_unroutable_fast_fail_exports = /* @__PURE__ */ __exportAll({
7987
+ down: () => down$7,
7988
+ up: () => up$7
7989
+ });
7990
+ /**
7991
+ * Fast-fail support for jobs nothing in the fleet can run.
7992
+ *
7993
+ * Three additive, nullable columns:
7994
+ *
7995
+ * - `cluster_settings.unroutable_grace_ms` — how long a job may stay
7996
+ * continuously unroutable before it is terminalized. NULL means the
7997
+ * orchestrator's configured default applies; 0 disables fast-fail and leaves
7998
+ * the `queue_timeout_ms` backstop as the only path.
7999
+ * - `dispatch_queue.unroutable_since` — when the job first read unroutable.
8000
+ * Persisted rather than in-memory so a restart mid-grace resumes the same
8001
+ * clock instead of resetting it; an orchestrator that bounces every 90s must
8002
+ * not be able to keep a genuinely dead job alive forever. Cleared the moment
8003
+ * the job reads routable again.
8004
+ * - `execution_jobs.routing_reason` — the operator-facing reason, visible while
8005
+ * the job is still queued. Cleared on recovery.
8006
+ *
8007
+ * Idempotent: each column is guarded on existence, so a re-run is a no-op.
8008
+ */
8009
+ async function columnExists$5(db, table, column) {
8010
+ return (await sql`
8011
+ SELECT EXISTS (
8012
+ SELECT 1 FROM information_schema.columns
8013
+ WHERE table_schema = 'public'
8014
+ AND table_name = ${table}
8015
+ AND column_name = ${column}
8016
+ ) AS exists
8017
+ `.execute(db)).rows[0]?.exists === true;
8018
+ }
8019
+ async function up$7(db) {
8020
+ if (!await columnExists$5(db, "cluster_settings", "unroutable_grace_ms")) await sql`ALTER TABLE public.cluster_settings ADD COLUMN unroutable_grace_ms INTEGER`.execute(db);
8021
+ if (!await columnExists$5(db, "dispatch_queue", "unroutable_since")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN unroutable_since TIMESTAMPTZ`.execute(db);
8022
+ if (!await columnExists$5(db, "execution_jobs", "routing_reason")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN routing_reason TEXT`.execute(db);
8023
+ }
8024
+ async function down$7(db) {
8025
+ await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS routing_reason`.execute(db);
8026
+ await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS unroutable_since`.execute(db);
8027
+ await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS unroutable_grace_ms`.execute(db);
8028
+ }
8029
+ //#endregion
8030
+ //#region src/db/migrations/109_cluster_settings_cache_knobs.ts
8031
+ var _109_cluster_settings_cache_knobs_exports = /* @__PURE__ */ __exportAll({
8032
+ down: () => down$6,
8033
+ up: () => up$6
8034
+ });
8035
+ /**
8036
+ * Cluster-global cache tunables for the lock-file cache and the Tier-1
8037
+ * content-requirements cache.
8038
+ *
8039
+ * Six additive, nullable columns. NULL means the orchestrator's configured
8040
+ * default applies (the `KICI_LOCKFILE_CACHE_*` / `KICI_CONTENT_CACHE_*` env
8041
+ * vars stay as the cluster-wide defaults). Sizes and TTLs are structural to the
8042
+ * underlying LRU, so a change takes effect at the next orchestrator restart.
8043
+ *
8044
+ * BIGINT rather than INTEGER: a byte ceiling defaults to 64 MiB and the TTLs are
8045
+ * in milliseconds, so both leave INTEGER range as soon as an operator raises
8046
+ * them.
8047
+ *
8048
+ * Idempotent: each column is guarded on existence, so a re-run is a no-op.
8049
+ */
8050
+ async function columnExists$4(db, table, column) {
8051
+ return (await sql`
8052
+ SELECT EXISTS (
8053
+ SELECT 1 FROM information_schema.columns
8054
+ WHERE table_schema = 'public'
8055
+ AND table_name = ${table}
8056
+ AND column_name = ${column}
8057
+ ) AS exists
8058
+ `.execute(db)).rows[0]?.exists === true;
8059
+ }
8060
+ const COLUMNS$2 = [
8061
+ "lockfile_cache_max",
8062
+ "lockfile_cache_max_bytes",
8063
+ "lockfile_cache_ttl_ms",
8064
+ "content_cache_max",
8065
+ "content_cache_max_bytes",
8066
+ "content_cache_ttl_ms"
8067
+ ];
8068
+ async function up$6(db) {
8069
+ for (const column of COLUMNS$2) if (!await columnExists$4(db, "cluster_settings", column)) await sql`ALTER TABLE public.cluster_settings ADD COLUMN ${sql.ref(column)} BIGINT`.execute(db);
8070
+ }
8071
+ async function down$6(db) {
8072
+ for (const column of COLUMNS$2) await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS ${sql.ref(column)}`.execute(db);
8073
+ }
8074
+ //#endregion
8075
+ //#region src/db/migrations/110_cluster_settings_global_eval_knobs.ts
8076
+ var _110_cluster_settings_global_eval_knobs_exports = /* @__PURE__ */ __exportAll({
8077
+ down: () => down$5,
8078
+ up: () => up$5
8079
+ });
8080
+ /**
8081
+ * Cluster-global tunables for the Tier-2 global eval round — the pre-run job
8082
+ * that evaluates each candidate global workflow's `filter` and generators on one
8083
+ * shared checkout of the source and workflow repos.
8084
+ *
8085
+ * Three additive, nullable columns. NULL means the orchestrator's configured
8086
+ * default applies (the `KICI_GLOBAL_EVAL_*` env vars stay as the cluster-wide
8087
+ * defaults). The two budgets are read per round and shipped to the agent in the
8088
+ * round's job config, so a change lands on the next push; `global_eval_cache_max`
8089
+ * sizes an LRU built once at boot and therefore applies at the next restart.
8090
+ *
8091
+ * BIGINT rather than INTEGER: the budgets are in milliseconds, so an operator
8092
+ * raising one leaves INTEGER range with a single generous value.
8093
+ *
8094
+ * Idempotent: each column is guarded on existence, so a re-run is a no-op.
8095
+ */
8096
+ async function columnExists$3(db, table, column) {
8097
+ return (await sql`
8098
+ SELECT EXISTS (
8099
+ SELECT 1 FROM information_schema.columns
8100
+ WHERE table_schema = 'public'
8101
+ AND table_name = ${table}
8102
+ AND column_name = ${column}
8103
+ ) AS exists
8104
+ `.execute(db)).rows[0]?.exists === true;
8105
+ }
8106
+ const COLUMNS$1 = [
8107
+ "global_eval_round_timeout_ms",
8108
+ "global_eval_candidate_timeout_ms",
8109
+ "global_eval_cache_max"
8110
+ ];
8111
+ async function up$5(db) {
8112
+ for (const column of COLUMNS$1) if (!await columnExists$3(db, "cluster_settings", column)) await sql`ALTER TABLE public.cluster_settings ADD COLUMN ${sql.ref(column)} BIGINT`.execute(db);
8113
+ }
8114
+ async function down$5(db) {
8115
+ for (const column of COLUMNS$1) await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS ${sql.ref(column)}`.execute(db);
8116
+ }
8117
+ //#endregion
8118
+ //#region src/db/migrations/111_cluster_settings_global_eval_wait.ts
8119
+ var _111_cluster_settings_global_eval_wait_exports = /* @__PURE__ */ __exportAll({
8120
+ down: () => down$4,
8121
+ up: () => up$4
8122
+ });
8123
+ /**
8124
+ * Cluster-global ceiling on how long webhook processing waits for a Tier-2
8125
+ * global eval round to settle.
8126
+ *
8127
+ * One additive, nullable column. NULL means the orchestrator's configured
8128
+ * default applies (`KICI_GLOBAL_EVAL_WAIT_TIMEOUT_MS` stays the cluster-wide
8129
+ * default). It is read fresh per round and applies orchestrator-side — unlike
8130
+ * the two agent budgets, which are shipped inside the round's job config — so a
8131
+ * change lands on the next push.
8132
+ *
8133
+ * BIGINT rather than INTEGER: the value is in milliseconds, so an operator
8134
+ * raising it leaves INTEGER range with a single generous value.
8135
+ *
8136
+ * Idempotent: the column is guarded on existence, so a re-run is a no-op.
8137
+ */
8138
+ async function columnExists$2(db, table, column) {
8139
+ return (await sql`
7846
8140
  SELECT EXISTS (
7847
8141
  SELECT 1 FROM information_schema.columns
7848
8142
  WHERE table_schema = 'public'
7849
- AND table_name = 'check_run_tracking'
7850
- AND column_name = 'terminal_sent_at'
8143
+ AND table_name = ${table}
8144
+ AND column_name = ${column}
7851
8145
  ) AS exists
7852
- `.execute(db)).rows[0]?.exists) return;
7853
- await sql`ALTER TABLE public.check_run_tracking ADD COLUMN terminal_sent_at TIMESTAMPTZ`.execute(db);
8146
+ `.execute(db)).rows[0]?.exists === true;
8147
+ }
8148
+ const COLUMNS = ["global_eval_wait_timeout_ms"];
8149
+ async function up$4(db) {
8150
+ for (const column of COLUMNS) if (!await columnExists$2(db, "cluster_settings", column)) await sql`ALTER TABLE public.cluster_settings ADD COLUMN ${sql.ref(column)} BIGINT`.execute(db);
7854
8151
  }
7855
8152
  async function down$4(db) {
7856
- await sql`ALTER TABLE public.check_run_tracking DROP COLUMN IF EXISTS terminal_sent_at`.execute(db);
8153
+ for (const column of COLUMNS) await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS ${sql.ref(column)}`.execute(db);
7857
8154
  }
7858
8155
  //#endregion
7859
- //#region src/db/migrations/105_org_trust_policy.ts
7860
- var _105_org_trust_policy_exports = /* @__PURE__ */ __exportAll({
8156
+ //#region src/db/migrations/112_execution_runs_workflow_repo.ts
8157
+ var _112_execution_runs_workflow_repo_exports = /* @__PURE__ */ __exportAll({
7861
8158
  down: () => down$3,
7862
8159
  up: () => up$3
7863
8160
  });
7864
8161
  /**
7865
- * Create `org_trust_policy` the orchestrator's cache of the Platform-owned org
7866
- * trust policy pushed on `trust_policy.update`.
8162
+ * Record which repository DEFINED the workflow a run executed.
7867
8163
  *
7868
- * A dedicated table rather than `org_settings` columns, because this is
7869
- * Platform-owned policy the orchestrator consumes, not operator-owned config the
7870
- * operator tunes. `source` records which of the two wrote the row so the admin
7871
- * surface can present a Platform-managed policy as read-only.
8164
+ * `execution_runs.repo_identifier` is the repository the run acted on. For an
8165
+ * organization-wide workflow dispatched against another repository those are
8166
+ * two different repositories: `repo_identifier` holds the source repository
8167
+ * that emitted the event, while the workflow itself was authored elsewhere and
8168
+ * travels only per job in `jobConfig.workflowRepoIdentifier` — which lives in
8169
+ * `dispatch_queue.job_config` and is pruned once the run's queue rows age out.
7872
8170
  *
7873
- * Persisting rather than caching in memory is deliberate: a security policy that
7874
- * silently reverts to a default across a restart is worse than one that is never
7875
- * applied.
8171
+ * So the run row alone could not answer "which repository defines this
8172
+ * workflow", and the rerun path read `repo_identifier` as the answer: it
8173
+ * re-fetched the source repository's lock file and either failed with a
8174
+ * misleading force-push message or, on a same-named workflow, silently ran the
8175
+ * source repository's workflow instead.
7876
8176
  *
7877
- * Idempotent: guarded by IF NOT EXISTS, so a re-run is a no-op.
8177
+ * Nullable and unbackfilled by design: a null means "the run acted on the
8178
+ * repository that defines its workflow", which is true of every per-repository
8179
+ * run and of every row written before this column existed.
8180
+ *
8181
+ * Idempotent: guarded on the column's existence, so re-running is a no-op.
7878
8182
  */
8183
+ async function colExists(db, table, name) {
8184
+ return (await sql`
8185
+ SELECT EXISTS (
8186
+ SELECT 1 FROM information_schema.columns
8187
+ WHERE table_schema = 'public'
8188
+ AND table_name = ${table}
8189
+ AND column_name = ${name}
8190
+ ) AS exists
8191
+ `.execute(db)).rows[0]?.exists ?? false;
8192
+ }
7879
8193
  async function up$3(db) {
7880
- await sql`
7881
- CREATE TABLE IF NOT EXISTS public.org_trust_policy (
7882
- customer_id TEXT PRIMARY KEY,
7883
- fork_policy TEXT NOT NULL,
7884
- unknown_contributor_policy TEXT NOT NULL,
7885
- workflow_change_policy TEXT NOT NULL,
7886
- approval_expiry_hours INTEGER NOT NULL,
7887
- source TEXT NOT NULL,
7888
- updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
7889
- )
7890
- `.execute(db);
8194
+ if (!await colExists(db, "execution_runs", "workflow_repo_identifier")) await sql`
8195
+ ALTER TABLE public.execution_runs
8196
+ ADD COLUMN workflow_repo_identifier text
8197
+ `.execute(db);
7891
8198
  }
7892
8199
  async function down$3(db) {
7893
- await sql`DROP TABLE IF EXISTS public.org_trust_policy`.execute(db);
8200
+ await sql`
8201
+ ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS workflow_repo_identifier
8202
+ `.execute(db);
7894
8203
  }
7895
8204
  //#endregion
7896
- //#region src/db/migrations/106_cluster_settings_check_run_tracking_ttl_days.ts
7897
- var _106_cluster_settings_check_run_tracking_ttl_days_exports = /* @__PURE__ */ __exportAll({
8205
+ //#region src/db/migrations/113_execution_runs_workflow_repo_index.ts
8206
+ var _113_execution_runs_workflow_repo_index_exports = /* @__PURE__ */ __exportAll({
7898
8207
  down: () => down$2,
7899
8208
  up: () => up$2
7900
8209
  });
7901
8210
  /**
7902
- * Add `cluster_settings.check_run_tracking_ttl_days` (nullable integer).
7903
- *
7904
- * Retention window for `check_run_tracking` rows. The hourly cleanup sweep
7905
- * deletes rows untouched for longer than this; 0 disables the sweep.
7906
- *
7907
- * Cluster-global (the sweep runs once per fleet on the cleanup tick, with no
7908
- * tenant in scope at the read site), so it lives on `cluster_settings` rather
7909
- * than `org_settings`. NULL means the orchestrator's own configured default
7910
- * applies.
8211
+ * Add the partial index `idx_execution_runs_workflow_repo` on
8212
+ * `execution_runs (workflow_repo_identifier) WHERE workflow_repo_identifier IS NOT NULL`.
8213
+ *
8214
+ * Matching a workflow registration to its runs keys on the repository that
8215
+ * DEFINES the workflow — `workflow_repo_identifier ?? repo_identifier` — which
8216
+ * the orchestrator expresses as
8217
+ * `workflow_repo_identifier IN (…) OR (workflow_repo_identifier IS NULL AND repo_identifier IN (…))`
8218
+ * (`registration/registration-run-match.ts`). The second arm rides
8219
+ * `idx_execution_runs_repo` from migration 001; the first arm had no index at
8220
+ * all, because migration 112 added the column without one. A planner cannot
8221
+ * use an index for only half a disjunction, so the whole predicate degraded to
8222
+ * a sequential scan over a table that grows with every run — on
8223
+ * `dashboard.registrations.list`, which runs its grouped MAX on every list
8224
+ * request.
8225
+ *
8226
+ * With both arms indexed the planner can BitmapOr them.
8227
+ *
8228
+ * Partial by design, and the partiality is what makes it cheap: the column is
8229
+ * non-null only for a cross-repository organization-wide run, a small minority
8230
+ * of rows, so the index stays a fraction of the table's size and skips every
8231
+ * per-repository run. It also matches the predicate exactly — the first arm
8232
+ * can never match a NULL row, since `NULL IN (…)` is never true.
7911
8233
  *
7912
- * Idempotent: guarded on column existence; a re-run on a database that already
7913
- * has the column is a no-op.
8234
+ * Idempotent: `IF NOT EXISTS` makes a re-run a no-op.
7914
8235
  */
7915
8236
  async function up$2(db) {
7916
- if ((await sql`
7917
- SELECT EXISTS (
7918
- SELECT 1 FROM information_schema.columns
7919
- WHERE table_schema = 'public'
7920
- AND table_name = 'cluster_settings'
7921
- AND column_name = 'check_run_tracking_ttl_days'
7922
- ) AS exists
7923
- `.execute(db)).rows[0]?.exists) return;
7924
- await sql`ALTER TABLE public.cluster_settings ADD COLUMN check_run_tracking_ttl_days INTEGER`.execute(db);
8237
+ await sql`
8238
+ CREATE INDEX IF NOT EXISTS idx_execution_runs_workflow_repo
8239
+ ON public.execution_runs (workflow_repo_identifier)
8240
+ WHERE workflow_repo_identifier IS NOT NULL
8241
+ `.execute(db);
7925
8242
  }
7926
8243
  async function down$2(db) {
7927
- await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS check_run_tracking_ttl_days`.execute(db);
8244
+ await sql`DROP INDEX IF EXISTS public.idx_execution_runs_workflow_repo`.execute(db);
7928
8245
  }
7929
8246
  //#endregion
7930
- //#region src/db/migrations/107_check_run_tracking_updated_at_index.ts
7931
- var _107_check_run_tracking_updated_at_index_exports = /* @__PURE__ */ __exportAll({
8247
+ //#region src/db/migrations/114_ingest_queue_claim.ts
8248
+ var _114_ingest_queue_claim_exports = /* @__PURE__ */ __exportAll({
7932
8249
  down: () => down$1,
7933
8250
  up: () => up$1
7934
8251
  });
7935
8252
  /**
7936
- * Add `idx_check_run_tracking_updated_at` on `check_run_tracking (updated_at)`.
8253
+ * Claim bookkeeping for the durable ingest queue.
7937
8254
  *
7938
- * `CheckRunTrackingStore.pruneStale` the hourly retention sweep — filters
7939
- * `WHERE updated_at < now() - <window>`. The table already carries two indexes
7940
- * — the primary key on `(provider, owner, repo, sha, check_name)` and the
7941
- * partial `idx_check_run_tracking_run_id` — but `updated_at` leads neither, so
7942
- * that predicate can use neither and without this index every sweep
7943
- * sequentially scans the whole table. The scan
7944
- * is worst exactly where it hurts: a deployment that accumulated rows before
7945
- * retention existed has the largest table and gets the scan hourly, on every
7946
- * coordinator, since the cleanup tick is not leader-gated.
8255
+ * Two additive, nullable columns:
7947
8256
  *
7948
- * Mirrors `idx_dispatch_queue_run_id` (migration 072) and
7949
- * `idx_request_idempotency_created_at` (migration 068), both of which exist to
7950
- * index a TTL sweep's prune predicate.
8257
+ * - `ingest_overflow_buffer.claimed_at` when a row moved `buffered` →
8258
+ * `replaying`. A worker that dies mid-pipeline leaves its row in `replaying`
8259
+ * with nothing to move it back, so the drain pass reclaims a row whose claim
8260
+ * is older than the timeout below. The claim clock has to be its own column:
8261
+ * `captured_at` orders the FIFO drain, so an old row picked up first would
8262
+ * read as instantly stale and be reclaimed out from under a live worker.
8263
+ * - `cluster_settings.ingest_overflow_claim_timeout_ms` — how long a claim may
8264
+ * stand before the drain pass reclaims it. NULL means the orchestrator's
8265
+ * configured default applies. It must exceed the longest a single delivery's
8266
+ * pipeline can legitimately run (a build phase alone is capped at
8267
+ * `cacheBuildTimeoutMs`), or a reclaim would re-run work still in flight.
7951
8268
  *
7952
- * Idempotent: `IF NOT EXISTS` makes a re-run a no-op.
8269
+ * Idempotent: each column is guarded on existence, so a re-run is a no-op.
7953
8270
  */
8271
+ async function columnExists$1(db, table, column) {
8272
+ return (await sql`
8273
+ SELECT EXISTS (
8274
+ SELECT 1 FROM information_schema.columns
8275
+ WHERE table_schema = 'public'
8276
+ AND table_name = ${table}
8277
+ AND column_name = ${column}
8278
+ ) AS exists
8279
+ `.execute(db)).rows[0]?.exists === true;
8280
+ }
7954
8281
  async function up$1(db) {
7955
- await sql`
7956
- CREATE INDEX IF NOT EXISTS idx_check_run_tracking_updated_at
7957
- ON public.check_run_tracking (updated_at)
7958
- `.execute(db);
8282
+ if (!await columnExists$1(db, "ingest_overflow_buffer", "claimed_at")) await sql`ALTER TABLE public.ingest_overflow_buffer ADD COLUMN claimed_at TIMESTAMPTZ`.execute(db);
8283
+ if (!await columnExists$1(db, "cluster_settings", "ingest_overflow_claim_timeout_ms")) await sql`
8284
+ ALTER TABLE public.cluster_settings ADD COLUMN ingest_overflow_claim_timeout_ms INTEGER
8285
+ `.execute(db);
7959
8286
  }
7960
8287
  async function down$1(db) {
7961
- await sql`DROP INDEX IF EXISTS public.idx_check_run_tracking_updated_at`.execute(db);
8288
+ await sql`
8289
+ ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS ingest_overflow_claim_timeout_ms
8290
+ `.execute(db);
8291
+ await sql`
8292
+ ALTER TABLE public.ingest_overflow_buffer DROP COLUMN IF EXISTS claimed_at
8293
+ `.execute(db);
7962
8294
  }
7963
8295
  //#endregion
7964
- //#region src/db/migrations/108_unroutable_fast_fail.ts
7965
- var _108_unroutable_fast_fail_exports = /* @__PURE__ */ __exportAll({
8296
+ //#region src/db/migrations/115_global_workflows_cluster_switch.ts
8297
+ var _115_global_workflows_cluster_switch_exports = /* @__PURE__ */ __exportAll({
7966
8298
  down: () => down,
7967
8299
  up: () => up
7968
8300
  });
7969
8301
  /**
7970
- * Fast-fail support for jobs nothing in the fleet can run.
8302
+ * Move the global-workflows master switch from `org_settings` to
8303
+ * `cluster_settings`.
7971
8304
  *
7972
- * Three additive, nullable columns:
8305
+ * The switch decides whether any repo may register or dispatch a global
8306
+ * workflow — a workflow defined in one repo that runs against events emitted by
8307
+ * other repos in the org, optionally with elevated access to source-repo
8308
+ * secrets. That is an operator-held decision, so it belongs on the fleet-wide
8309
+ * row an operator reaches through `kici-admin cluster-settings`, not on a
8310
+ * per-org row an org admin can flip from the dashboard.
7973
8311
  *
7974
- * - `cluster_settings.unroutable_grace_ms` how long a job may stay
7975
- * continuously unroutable before it is terminalized. NULL means the
7976
- * orchestrator's configured default applies; 0 disables fast-fail and leaves
7977
- * the `queue_timeout_ms` backstop as the only path.
7978
- * - `dispatch_queue.unroutable_since` — when the job first read unroutable.
7979
- * Persisted rather than in-memory so a restart mid-grace resumes the same
7980
- * clock instead of resetting it; an orchestrator that bounces every 90s must
7981
- * not be able to keep a genuinely dead job alive forever. Cleared the moment
7982
- * the job reads routable again.
7983
- * - `execution_jobs.routing_reason` — the operator-facing reason, visible while
7984
- * the job is still queued. Cleared on recovery.
8312
+ * Deliberately NOT back-filled. Copying `EXISTS(SELECT 1 FROM org_settings
8313
+ * WHERE global_workflows_enabled)` into the new column would silently carry a
8314
+ * per-org opt-in forward into a fleet-wide one — enabling globals for orgs
8315
+ * whose operator never chose it. The new column starts NULL, which resolves to
8316
+ * the orchestrator's configured default (`KICI_GLOBAL_WORKFLOWS_ENABLED`,
8317
+ * default false), so global workflows are off until an operator opts in:
7985
8318
  *
7986
- * Idempotent: each column is guarded on existence, so a re-run is a no-op.
8319
+ * kici-admin cluster-settings set --global-workflows-enabled true
8320
+ *
8321
+ * BOOLEAN and nullable, matching the `NULL ⇒ configured default` contract every
8322
+ * other `cluster_settings` knob follows.
8323
+ *
8324
+ * Idempotent: the add is guarded on existence and the drop uses IF EXISTS, so a
8325
+ * re-run is a no-op.
7987
8326
  */
7988
8327
  async function columnExists(db, table, column) {
7989
8328
  return (await sql`
@@ -7996,14 +8335,20 @@ async function columnExists(db, table, column) {
7996
8335
  `.execute(db)).rows[0]?.exists === true;
7997
8336
  }
7998
8337
  async function up(db) {
7999
- if (!await columnExists(db, "cluster_settings", "unroutable_grace_ms")) await sql`ALTER TABLE public.cluster_settings ADD COLUMN unroutable_grace_ms INTEGER`.execute(db);
8000
- if (!await columnExists(db, "dispatch_queue", "unroutable_since")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN unroutable_since TIMESTAMPTZ`.execute(db);
8001
- if (!await columnExists(db, "execution_jobs", "routing_reason")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN routing_reason TEXT`.execute(db);
8338
+ if (!await columnExists(db, "cluster_settings", "global_workflows_enabled")) await sql`ALTER TABLE public.cluster_settings ADD COLUMN global_workflows_enabled BOOLEAN`.execute(db);
8339
+ await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS global_workflows_enabled`.execute(db);
8002
8340
  }
8341
+ /**
8342
+ * Restores the org column with its original NOT NULL DEFAULT false. A rollback
8343
+ * cannot recover the per-org values the up-migration dropped — they are gone —
8344
+ * so every org comes back at the opt-in default.
8345
+ */
8003
8346
  async function down(db) {
8004
- await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS routing_reason`.execute(db);
8005
- await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS unroutable_since`.execute(db);
8006
- await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS unroutable_grace_ms`.execute(db);
8347
+ if (!await columnExists(db, "org_settings", "global_workflows_enabled")) await sql`
8348
+ ALTER TABLE public.org_settings
8349
+ ADD COLUMN global_workflows_enabled BOOLEAN NOT NULL DEFAULT false
8350
+ `.execute(db);
8351
+ await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS global_workflows_enabled`.execute(db);
8007
8352
  }
8008
8353
  //#endregion
8009
8354
  //#region src/db/migration-provider.ts
@@ -8117,7 +8462,14 @@ function createMigrationProvider() {
8117
8462
  "105_org_trust_policy": _105_org_trust_policy_exports,
8118
8463
  "106_cluster_settings_check_run_tracking_ttl_days": _106_cluster_settings_check_run_tracking_ttl_days_exports,
8119
8464
  "107_check_run_tracking_updated_at_index": _107_check_run_tracking_updated_at_index_exports,
8120
- "108_unroutable_fast_fail": _108_unroutable_fast_fail_exports
8465
+ "108_unroutable_fast_fail": _108_unroutable_fast_fail_exports,
8466
+ "109_cluster_settings_cache_knobs": _109_cluster_settings_cache_knobs_exports,
8467
+ "110_cluster_settings_global_eval_knobs": _110_cluster_settings_global_eval_knobs_exports,
8468
+ "111_cluster_settings_global_eval_wait": _111_cluster_settings_global_eval_wait_exports,
8469
+ "112_execution_runs_workflow_repo": _112_execution_runs_workflow_repo_exports,
8470
+ "113_execution_runs_workflow_repo_index": _113_execution_runs_workflow_repo_index_exports,
8471
+ "114_ingest_queue_claim": _114_ingest_queue_claim_exports,
8472
+ "115_global_workflows_cluster_switch": _115_global_workflows_cluster_switch_exports
8121
8473
  };
8122
8474
  } };
8123
8475
  }
@@ -9034,7 +9386,13 @@ const UniversalGitPayloadPathsSchema = z.object({
9034
9386
  /** Path to the `modified` files array on a push event. */
9035
9387
  commitsModified: z.string().min(1),
9036
9388
  /** Path to the `removed` files array on a push event. */
9037
- commitsRemoved: z.string().min(1)
9389
+ commitsRemoved: z.string().min(1),
9390
+ /**
9391
+ * Path to the head commit's message on a push event. Optional so a stored
9392
+ * config written before this field stays valid; when unset, a `commitMessage`
9393
+ * trigger filter is INDETERMINATE and the workflow does not run.
9394
+ */
9395
+ commitMessage: z.string().min(1).optional()
9038
9396
  });
9039
9397
  /**
9040
9398
  * Header-to-event-name mapping. Most forges send an `X-Event-Type`-style
@@ -9133,7 +9491,8 @@ const UNIVERSAL_GIT_PRESETS = {
9133
9491
  defaultBranch: "$.repository.default_branch",
9134
9492
  commitsAdded: "$.commits[*].added[*]",
9135
9493
  commitsModified: "$.commits[*].modified[*]",
9136
- commitsRemoved: "$.commits[*].removed[*]"
9494
+ commitsRemoved: "$.commits[*].removed[*]",
9495
+ commitMessage: "$.head_commit.message"
9137
9496
  },
9138
9497
  eventMapping: {
9139
9498
  push: ["push"],
@@ -9149,7 +9508,8 @@ const UNIVERSAL_GIT_PRESETS = {
9149
9508
  defaultBranch: "$.repository.default_branch",
9150
9509
  commitsAdded: "$.commits[*].added[*]",
9151
9510
  commitsModified: "$.commits[*].modified[*]",
9152
- commitsRemoved: "$.commits[*].removed[*]"
9511
+ commitsRemoved: "$.commits[*].removed[*]",
9512
+ commitMessage: "$.head_commit.message"
9153
9513
  },
9154
9514
  eventMapping: {
9155
9515
  push: ["push"],
@@ -9165,7 +9525,8 @@ const UNIVERSAL_GIT_PRESETS = {
9165
9525
  defaultBranch: "$.repository.default_branch",
9166
9526
  commitsAdded: "$.commits[*].added[*]",
9167
9527
  commitsModified: "$.commits[*].modified[*]",
9168
- commitsRemoved: "$.commits[*].removed[*]"
9528
+ commitsRemoved: "$.commits[*].removed[*]",
9529
+ commitMessage: "$.commits[-1:].message"
9169
9530
  },
9170
9531
  eventMapping: {
9171
9532
  push: ["push"],
@@ -9181,7 +9542,8 @@ const UNIVERSAL_GIT_PRESETS = {
9181
9542
  defaultBranch: "$.project.default_branch",
9182
9543
  commitsAdded: "$.commits[*].added[*]",
9183
9544
  commitsModified: "$.commits[*].modified[*]",
9184
- commitsRemoved: "$.commits[*].removed[*]"
9545
+ commitsRemoved: "$.commits[*].removed[*]",
9546
+ commitMessage: "$.commits[-1:].message"
9185
9547
  },
9186
9548
  eventMapping: {
9187
9549
  push: ["Push Hook", "push"],
@@ -9197,7 +9559,8 @@ const UNIVERSAL_GIT_PRESETS = {
9197
9559
  defaultBranch: "$.repository.default_branch",
9198
9560
  commitsAdded: "$.commits[*].added[*]",
9199
9561
  commitsModified: "$.commits[*].modified[*]",
9200
- commitsRemoved: "$.commits[*].removed[*]"
9562
+ commitsRemoved: "$.commits[*].removed[*]",
9563
+ commitMessage: "$.head_commit.message"
9201
9564
  },
9202
9565
  eventMapping: {
9203
9566
  push: ["push"],
@@ -10131,6 +10494,21 @@ function parseLocalConfig(s) {
10131
10494
  const parsed = LocalSourceConfigSchema.safeParse(raw);
10132
10495
  return parsed.success ? parsed.data : null;
10133
10496
  }
10497
+ /**
10498
+ * Read a local source's stored config over whichever transport the caller is
10499
+ * already on — direct DB when `--database-url` / KICI_DATABASE_URL is in play,
10500
+ * otherwise the admin API. Used to preserve `repoBasePath` when only the clone
10501
+ * base is being changed; returns null when the id names no local source.
10502
+ */
10503
+ async function readLocalSourceConfig(id, databaseUrl, getClient) {
10504
+ const dbUrl = resolveDirectDbUrl$9(databaseUrl);
10505
+ if (dbUrl) {
10506
+ const row = await withGenericManager(dbUrl, (mgr) => mgr.getById(id));
10507
+ return row ? parseLocalConfig(row) : null;
10508
+ }
10509
+ const { source } = await getClient().getGenericSource(id);
10510
+ return parseLocalConfig(source);
10511
+ }
10134
10512
  function safeParse(value) {
10135
10513
  try {
10136
10514
  return JSON.parse(value);
@@ -10676,17 +11054,26 @@ function registerSourceCommands(program, getClient) {
10676
11054
  try {
10677
11055
  const data = {};
10678
11056
  if (opts.name) data.name = opts.name;
10679
- if (opts.path !== void 0) {
10680
- if (!path.isAbsolute(opts.path)) {
10681
- console.error(`Error: --path must be an absolute path: ${opts.path}`);
11057
+ if (opts.path !== void 0 || opts.cloneUrlBase !== void 0) {
11058
+ let repoBasePath = opts.path;
11059
+ if (repoBasePath === void 0) {
11060
+ const existing = await readLocalSourceConfig(id, opts.databaseUrl, getClient);
11061
+ if (!existing) {
11062
+ console.error(`Error: no local source with id ${id}`);
11063
+ process.exit(1);
11064
+ }
11065
+ repoBasePath = existing.repoBasePath;
11066
+ }
11067
+ if (!path.isAbsolute(repoBasePath)) {
11068
+ console.error(`Error: --path must be an absolute path: ${repoBasePath}`);
10682
11069
  process.exit(1);
10683
11070
  }
10684
- const localConfig = { repoBasePath: opts.path };
11071
+ const localConfig = { repoBasePath };
10685
11072
  if (opts.cloneUrlBase) localConfig.cloneUrlBase = opts.cloneUrlBase;
10686
11073
  data.localConfig = localConfig;
10687
11074
  }
10688
11075
  if (Object.keys(data).length === 0) {
10689
- console.error("Error: no fields to update. Provide --path and/or --name.");
11076
+ console.error("Error: no fields to update. Provide --path, --name, and/or --clone-url-base.");
10690
11077
  process.exit(1);
10691
11078
  }
10692
11079
  const dbUrl = resolveDirectDbUrl$9(opts.databaseUrl);
@@ -11320,6 +11707,23 @@ function registerRunsCommands(program, getClient) {
11320
11707
  process.exit(1);
11321
11708
  }
11322
11709
  });
11710
+ runs.command("logs <runId>").description("Print a page of a step log (dogfooded via /api/v1/admin/runs/:runId/jobs/:jobId/steps/:i/logs)").requiredOption("--job <jobId>", "Job id (the dispatch_queue row id for an eval round)").option("--step <n>", "Step index (default 0)", "0").option("--limit <n>", "Max lines to return (default 500, server caps at 2000)", "500").option("--cursor <c>", "Line-offset cursor from a previous page").option("--json", "Emit raw JSON instead of plain lines").action(async (runId, opts) => {
11711
+ try {
11712
+ const params = new URLSearchParams({ limit: String(opts.limit) });
11713
+ if (opts.cursor) params.set("cursor", String(opts.cursor));
11714
+ const path = `/api/v1/admin/runs/${encodeURIComponent(runId)}/jobs/${encodeURIComponent(String(opts.job))}/steps/${encodeURIComponent(String(opts.step))}/logs?${params.toString()}`;
11715
+ const response = await getClient().get(path);
11716
+ if (opts.json) {
11717
+ console.log(JSON.stringify(response, null, 2));
11718
+ return;
11719
+ }
11720
+ for (const line of response.lines) console.log(line.value);
11721
+ if (response.nextCursor) console.error(`(more: re-run with --cursor ${response.nextCursor})`);
11722
+ } catch (err) {
11723
+ console.error(`Error: ${toErrorMessage(err)}`);
11724
+ process.exit(1);
11725
+ }
11726
+ });
11323
11727
  runs.command("ephemeral-key <runId>").description("Show whether the run-ephemeral key has been scrubbed yet").option("--json", "Emit raw JSON instead of plain text").action(async (runId, opts) => {
11324
11728
  try {
11325
11729
  const response = await getClient().getRunEphemeralKey(runId);
@@ -11489,6 +11893,13 @@ const baseSchema = z.object({
11489
11893
  lockfileCacheMax: z.coerce.number().default(500),
11490
11894
  lockfileCacheTtlMs: z.coerce.number().default(36e5),
11491
11895
  lockfileCacheMaxBytes: z.coerce.number().default(64 * 1024 * 1024),
11896
+ contentCacheMax: z.coerce.number().default(500),
11897
+ contentCacheTtlMs: z.coerce.number().default(36e5),
11898
+ contentCacheMaxBytes: z.coerce.number().default(64 * 1024 * 1024),
11899
+ globalEvalRoundTimeoutMs: z.coerce.number().default(12e4),
11900
+ globalEvalCandidateTimeoutMs: z.coerce.number().default(2e4),
11901
+ globalEvalCacheMax: z.coerce.number().default(500),
11902
+ globalEvalWaitTimeoutMs: z.coerce.number().default(24e4),
11492
11903
  queueMaxDepth: z.coerce.number().default(1e3),
11493
11904
  queueTimeoutMs: z.coerce.number().default(36e5),
11494
11905
  /**
@@ -11498,6 +11909,15 @@ const baseSchema = z.object({
11498
11909
  */
11499
11910
  unroutableGraceMs: z.coerce.number().default(12e4),
11500
11911
  /**
11912
+ * Fleet-wide default for the global-workflows master switch. Cluster default;
11913
+ * the live value is the `global_workflows_enabled` cluster setting, and NULL
11914
+ * there means this value applies.
11915
+ *
11916
+ * Defaults to false: a global workflow runs against events from repos other
11917
+ * than the one that defines it, so it is opt-in by the operator.
11918
+ */
11919
+ globalWorkflowsEnabled: z.union([z.boolean(), z.string()]).default(false).transform((v) => typeof v === "boolean" ? v : v === "true"),
11920
+ /**
11501
11921
  * Operator-facing backpressure warning threshold for the dispatch queue.
11502
11922
  * When pending-queue depth stays at or above this value for at least two
11503
11923
  * consecutive refresher ticks (~10s), the orchestrator emits a
@@ -11525,6 +11945,7 @@ const baseSchema = z.object({
11525
11945
  ingestOverflowReplayIntervalMs: z.coerce.number().int().min(1).default(2e3),
11526
11946
  ingestOverflowReplayBatch: z.coerce.number().int().min(1).default(50),
11527
11947
  ingestOverflowMaxAttempts: z.coerce.number().int().min(1).default(10),
11948
+ ingestOverflowClaimTimeoutMs: z.coerce.number().int().min(6e4).default(9e5),
11528
11949
  rerouteSpawnWindowMs: z.coerce.number().int().min(1e3).default(9e4),
11529
11950
  rerouteAckTimeoutMs: z.coerce.number().int().min(1e3).default(15e3),
11530
11951
  rerouteMaxHops: z.coerce.number().int().min(1).default(3),
@@ -11851,9 +12272,17 @@ const envDef = defineEnv({
11851
12272
  lockfileCacheMax: "KICI_LOCKFILE_CACHE_MAX",
11852
12273
  lockfileCacheTtlMs: "KICI_LOCKFILE_CACHE_TTL_MS",
11853
12274
  lockfileCacheMaxBytes: "KICI_LOCKFILE_CACHE_MAX_BYTES",
12275
+ contentCacheMax: "KICI_CONTENT_CACHE_MAX",
12276
+ contentCacheTtlMs: "KICI_CONTENT_CACHE_TTL_MS",
12277
+ contentCacheMaxBytes: "KICI_CONTENT_CACHE_MAX_BYTES",
12278
+ globalEvalRoundTimeoutMs: "KICI_GLOBAL_EVAL_ROUND_TIMEOUT_MS",
12279
+ globalEvalCandidateTimeoutMs: "KICI_GLOBAL_EVAL_CANDIDATE_TIMEOUT_MS",
12280
+ globalEvalCacheMax: "KICI_GLOBAL_EVAL_CACHE_MAX",
12281
+ globalEvalWaitTimeoutMs: "KICI_GLOBAL_EVAL_WAIT_TIMEOUT_MS",
11854
12282
  queueMaxDepth: "KICI_QUEUE_MAX_DEPTH",
11855
12283
  queueTimeoutMs: "KICI_QUEUE_TIMEOUT_MS",
11856
12284
  unroutableGraceMs: "KICI_UNROUTABLE_GRACE_MS",
12285
+ globalWorkflowsEnabled: "KICI_GLOBAL_WORKFLOWS_ENABLED",
11857
12286
  queueBackpressureThreshold: "KICI_QUEUE_BACKPRESSURE_THRESHOLD",
11858
12287
  workerConcurrency: "KICI_WORKER_CONCURRENCY",
11859
12288
  concurrencyWaitTimeoutMs: "KICI_CONCURRENCY_WAIT_TIMEOUT_MS",
@@ -11873,6 +12302,7 @@ const envDef = defineEnv({
11873
12302
  ingestOverflowReplayIntervalMs: "KICI_INGEST_OVERFLOW_REPLAY_INTERVAL_MS",
11874
12303
  ingestOverflowReplayBatch: "KICI_INGEST_OVERFLOW_REPLAY_BATCH",
11875
12304
  ingestOverflowMaxAttempts: "KICI_INGEST_OVERFLOW_MAX_ATTEMPTS",
12305
+ ingestOverflowClaimTimeoutMs: "KICI_INGEST_OVERFLOW_CLAIM_TIMEOUT_MS",
11876
12306
  rerouteSpawnWindowMs: "KICI_REROUTE_SPAWN_WINDOW_MS",
11877
12307
  rerouteAckTimeoutMs: "KICI_REROUTE_ACK_TIMEOUT_MS",
11878
12308
  rerouteMaxHops: "KICI_REROUTE_MAX_HOPS",
@@ -13469,6 +13899,27 @@ var DashboardEncryptionKeyRepo = class {
13469
13899
  //#endregion
13470
13900
  //#region src/cluster/cluster-settings-reader.ts
13471
13901
  const logger$9 = createLogger({ prefix: "orch:cluster-settings" });
13902
+ /**
13903
+ * Ceiling for the three LRU entry-count knobs — `lockfile_cache_max`,
13904
+ * `content_cache_max`, and `global_eval_cache_max`.
13905
+ *
13906
+ * This is a boot-safety bound, not a policy preference. The underlying LRU
13907
+ * allocates its index arrays eagerly from `max` — several typed arrays plus the
13908
+ * TTL and size arrays the caches ask for — so the cost is paid at construction
13909
+ * with zero entries cached. Measured on the shipped version: an empty cache at
13910
+ * `max` 5,000,000 costs ~191 MB, and at 5,000,000,000 the constructor throws
13911
+ * `RangeError: Invalid array length`.
13912
+ *
13913
+ * That throw is what makes an unbounded knob dangerous rather than merely
13914
+ * wasteful. All three caches are built inside `bootstrapOrchestrator`, so a bad
13915
+ * stored value crashes the orchestrator before its admin API is listening —
13916
+ * and the admin API is the only way `kici-admin cluster-settings` can reach the
13917
+ * stored value. The knob would brick the very tool needed to un-brick it.
13918
+ *
13919
+ * 100,000 is 200x the shipped default of 500 and costs ~4 MB per empty cache,
13920
+ * so it is far above any plausible operator setting while keeping boot bounded.
13921
+ */
13922
+ const CACHE_MAX_ENTRIES_CEILING = 1e5;
13472
13923
  const DEFAULT_CACHE_TTL_MS = 1e4;
13473
13924
  /**
13474
13925
  * Reads the single cluster_settings row (id='default') once per short TTL
@@ -13575,6 +14026,29 @@ var ClusterSettingsReader = class {
13575
14026
  };
13576
14027
  }
13577
14028
  /**
14029
+ * Resolve a fleet-wide boolean knob without collapsing a read failure into a
14030
+ * default.
14031
+ *
14032
+ * There is deliberately no `getBoolean(column, fallback)` companion. The
14033
+ * security gate that consumes this must tell the reader's outcomes apart
14034
+ * itself: a stored `false` and a NULL both deny today, but they deny for
14035
+ * different reasons, and `{ ok: false }` must deny regardless of what the
14036
+ * configured default happens to be. A convenience wrapper that folded the
14037
+ * failure into the default would be safe only for as long as that default
14038
+ * stayed `false`. A caller that only needs a display value (the dashboard
14039
+ * status badge) folds `{ ok: false }` into the default explicitly at its own
14040
+ * site, where getting it wrong misreports a badge rather than opening a gate.
14041
+ */
14042
+ async tryGetBoolean(column) {
14043
+ const { row, readable } = await this.loadSnapshot();
14044
+ if (!readable) return { ok: false };
14045
+ const value = row?.[column];
14046
+ return {
14047
+ ok: true,
14048
+ value: typeof value === "boolean" ? value : null
14049
+ };
14050
+ }
14051
+ /**
13578
14052
  * The cluster_settings row version last seen in the cache (0 if never loaded).
13579
14053
  *
13580
14054
  * Synchronous — never awaits a DB read — so the heartbeat timer can read it
@@ -18145,6 +18619,31 @@ function registerLogsCommand(parent) {
18145
18619
  //#endregion
18146
18620
  //#region src/agent-packaging/node-binary.ts
18147
18621
  /**
18622
+ * Fetch a Node dist URL, retrying transient failures. The runtime download is a
18623
+ * bootstrap-critical step on a box that may have flaky egress (a fresh customer
18624
+ * host, a CDN blip); a single bare `fetch` turns any transient connect/DNS/5xx
18625
+ * hiccup into an opaque `fetch failed` that aborts the whole packaging run. We
18626
+ * retry connection-level throws and 5xx responses with exponential backoff, and
18627
+ * fold the underlying `cause` (e.g. `connect ETIMEDOUT …`, `UND_ERR_…`) into the
18628
+ * final error so a genuine failure is diagnosable instead of a bare message.
18629
+ */
18630
+ async function fetchNodeDist(url, attempts = 4) {
18631
+ let lastErr;
18632
+ for (let attempt = 1; attempt <= attempts; attempt++) {
18633
+ try {
18634
+ const resp = await fetch(url);
18635
+ if (resp.ok) return resp;
18636
+ if (resp.status < 500 || attempt === attempts) throw new Error(`Failed to fetch ${url}: HTTP ${resp.status}`);
18637
+ lastErr = /* @__PURE__ */ new Error(`HTTP ${resp.status}`);
18638
+ } catch (err) {
18639
+ lastErr = err;
18640
+ if (attempt === attempts) throw new Error(`Failed to fetch ${url} after ${attempts} attempts: ${JSON.stringify(serializeError(err))}`);
18641
+ }
18642
+ await setTimeout$1(Math.min(500 * 2 ** (attempt - 1), 4e3));
18643
+ }
18644
+ throw new Error(`Failed to fetch ${url}: ${JSON.stringify(serializeError(lastErr))}`);
18645
+ }
18646
+ /**
18148
18647
  * Download + SHASUMS256-verify the Node runtime for a glibc-Linux platform and
18149
18648
  * vendor `node` + `npm` into the payload.
18150
18649
  *
@@ -18164,13 +18663,10 @@ async function downloadNodeBinary(opts) {
18164
18663
  const base = (opts.nodeMirror ?? "https://nodejs.org/dist").replace(/\/$/, "");
18165
18664
  const filename = `node-v${opts.version}-${nodeOs}-${nodeArch}.tar.gz`;
18166
18665
  const dir = `v${opts.version}`;
18167
- const shaResp = await fetch(`${base}/${dir}/SHASUMS256.txt`);
18168
- if (!shaResp.ok) throw new Error(`Failed to fetch SHASUMS256.txt: ${shaResp.status}`);
18169
- const shaLine = (await shaResp.text()).split("\n").find((l) => l.endsWith(filename));
18666
+ const shaLine = (await (await fetchNodeDist(`${base}/${dir}/SHASUMS256.txt`)).text()).split("\n").find((l) => l.endsWith(filename));
18170
18667
  if (!shaLine) throw new Error(`No SHA-256 entry for ${filename} in SHASUMS256.txt`);
18171
18668
  const expected = shaLine.trim().split(/\s+/)[0];
18172
- const archiveResp = await fetch(`${base}/${dir}/${filename}`);
18173
- if (!archiveResp.ok) throw new Error(`Failed to download ${filename}: ${archiveResp.status}`);
18669
+ const archiveResp = await fetchNodeDist(`${base}/${dir}/${filename}`);
18174
18670
  const buf = Buffer.from(await archiveResp.arrayBuffer());
18175
18671
  const actual = createHash("sha256").update(buf).digest("hex");
18176
18672
  if (actual !== expected) throw new Error(`SHA-256 mismatch for ${filename}:\n expected ${expected}\n actual ${actual}`);
@@ -18402,7 +18898,7 @@ async function refreshAgentPackages(storage, version, opts, deps) {
18402
18898
  const ALL_PLATFORMS = AgentPlatform.options;
18403
18899
  /** The orchestrator's own version (single-version invariant) = the packaged agent version. */
18404
18900
  function resolveKiciVersion() {
18405
- return "0.3.0";
18901
+ return "0.5.0";
18406
18902
  }
18407
18903
  /** Parse the --platform value: default set | single | CSV | `all`. */
18408
18904
  function parsePlatforms(raw) {
@@ -20036,7 +20532,7 @@ function formatSettings$1(s, format) {
20036
20532
  if (format === "json") return JSON.stringify(s, null, 2);
20037
20533
  const lines = [];
20038
20534
  lines.push(`Customer/org id: ${s.customerId}`);
20039
- lines.push(`Enabled: ${s.enabled}`);
20535
+ lines.push(`Enabled (cluster-wide): ${s.enabled}`);
20040
20536
  lines.push(`Allowed authors: ${s.allowedRepos === null ? "(any repo)" : formatList(s.allowedRepos)}`);
20041
20537
  lines.push(`Denied source repos: ${s.deniedRepos === null ? "(none)" : formatList(s.deniedRepos)}`);
20042
20538
  lines.push(`Elevated authors: ${s.elevatedRepos === null ? "(none)" : formatList(s.elevatedRepos)}`);
@@ -20094,24 +20590,6 @@ function registerOrgSettingsCommands(program, getClient) {
20094
20590
  process.exit(1);
20095
20591
  }
20096
20592
  });
20097
- gw.command("set-enabled <value>").description("Toggle the master enable switch (true|false)").option("--customer-id <id>", "Customer / org id (alias: --org)").option("--org <id>", "Alias for --customer-id").option("--format <format>", "Output format: json|table", "table").action(async (value, opts) => {
20098
- const enabled = value === "true" ? true : value === "false" ? false : void 0;
20099
- if (enabled === void 0) {
20100
- console.error("Error: value must be \"true\" or \"false\"");
20101
- process.exit(1);
20102
- }
20103
- const customerId = resolveCustomerId(opts);
20104
- try {
20105
- const settings = await patchSettings$1(getClient(), {
20106
- customerId,
20107
- enabled
20108
- });
20109
- console.log(formatSettings$1(settings, opts.format));
20110
- } catch (err) {
20111
- console.error(`Error: ${toErrorMessage(err)}`);
20112
- process.exit(1);
20113
- }
20114
- });
20115
20593
  registerListMutators(gw, getClient, "allow", "allowedRepos");
20116
20594
  registerListMutators(gw, getClient, "deny", "deniedRepos");
20117
20595
  registerListMutators(gw, getClient, "elevate", "elevatedRepos");
@@ -20787,7 +21265,7 @@ function resolveCustomerId(opts) {
20787
21265
  function label(prefix) {
20788
21266
  if (prefix === "allow") return "workflow-author allow-list";
20789
21267
  if (prefix === "deny") return "source-repo deny-list";
20790
- return "elevated-access list";
21268
+ return "elevated-access list (DEPRECATED: not enforced, removed at v1.0.0)";
20791
21269
  }
20792
21270
  /** Legacy boolean sugar for --op / --enabled: true→permissive, false→disabled. */
20793
21271
  function parseStateToken(token) {
@@ -21045,6 +21523,75 @@ const KNOBS$1 = [
21045
21523
  flag: "unroutable-grace-ms",
21046
21524
  min: 0,
21047
21525
  label: "Unroutable fast-fail grace (ms)"
21526
+ },
21527
+ {
21528
+ field: "ingestOverflowClaimTimeoutMs",
21529
+ flag: "ingest-overflow-claim-timeout-ms",
21530
+ min: 6e4,
21531
+ label: "Ingest queue claim timeout (ms)"
21532
+ },
21533
+ {
21534
+ field: "lockfileCacheMax",
21535
+ flag: "lockfile-cache-max",
21536
+ min: 1,
21537
+ max: CACHE_MAX_ENTRIES_CEILING,
21538
+ label: "Lock-file cache max entries"
21539
+ },
21540
+ {
21541
+ field: "lockfileCacheMaxBytes",
21542
+ flag: "lockfile-cache-max-bytes",
21543
+ min: 1024,
21544
+ label: "Lock-file cache max bytes"
21545
+ },
21546
+ {
21547
+ field: "lockfileCacheTtlMs",
21548
+ flag: "lockfile-cache-ttl-ms",
21549
+ min: 1e3,
21550
+ label: "Lock-file cache TTL (ms)"
21551
+ },
21552
+ {
21553
+ field: "contentCacheMax",
21554
+ flag: "content-cache-max",
21555
+ min: 1,
21556
+ max: CACHE_MAX_ENTRIES_CEILING,
21557
+ label: "Content cache max entries"
21558
+ },
21559
+ {
21560
+ field: "contentCacheMaxBytes",
21561
+ flag: "content-cache-max-bytes",
21562
+ min: 1024,
21563
+ label: "Content cache max bytes"
21564
+ },
21565
+ {
21566
+ field: "contentCacheTtlMs",
21567
+ flag: "content-cache-ttl-ms",
21568
+ min: 1e3,
21569
+ label: "Content cache TTL (ms)"
21570
+ },
21571
+ {
21572
+ field: "globalEvalRoundTimeoutMs",
21573
+ flag: "global-eval-round-timeout-ms",
21574
+ min: 1e3,
21575
+ label: "Global eval round timeout (ms)"
21576
+ },
21577
+ {
21578
+ field: "globalEvalCandidateTimeoutMs",
21579
+ flag: "global-eval-candidate-timeout-ms",
21580
+ min: 1e3,
21581
+ label: "Global eval candidate timeout (ms)"
21582
+ },
21583
+ {
21584
+ field: "globalEvalCacheMax",
21585
+ flag: "global-eval-cache-max",
21586
+ min: 1,
21587
+ max: CACHE_MAX_ENTRIES_CEILING,
21588
+ label: "Global eval round-result cache max entries"
21589
+ },
21590
+ {
21591
+ field: "globalEvalWaitTimeoutMs",
21592
+ flag: "global-eval-wait-timeout-ms",
21593
+ min: 1e3,
21594
+ label: "Global eval wait timeout (ms)"
21048
21595
  }
21049
21596
  ];
21050
21597
  /** The cluster-global text knobs. */
@@ -21055,6 +21602,11 @@ const STRING_KNOBS = [{
21055
21602
  expects: "an absolute http(s) URL",
21056
21603
  validate: (v) => /^https?:\/\/[^\s]+$/.test(v)
21057
21604
  }];
21605
+ const BOOLEAN_KNOBS = [{
21606
+ field: "globalWorkflowsEnabled",
21607
+ flag: "global-workflows-enabled",
21608
+ label: "Global workflows enabled"
21609
+ }];
21058
21610
  /** Map a Commander long-flag (`--foo-bar`) to its camelCase option key. */
21059
21611
  function optionKey(flag) {
21060
21612
  return flag.replace(/-([a-z])/g, (_m, c) => c.toUpperCase());
@@ -21062,9 +21614,17 @@ function optionKey(flag) {
21062
21614
  function formatSettings(s, format) {
21063
21615
  if (format === "json") return JSON.stringify(s, null, 2);
21064
21616
  const lines = [];
21065
- const labels = [...KNOBS$1, ...STRING_KNOBS].map((k) => k.label);
21617
+ const labels = [
21618
+ ...KNOBS$1,
21619
+ ...STRING_KNOBS,
21620
+ ...BOOLEAN_KNOBS
21621
+ ].map((k) => k.label);
21066
21622
  const width = Math.max(...labels.map((l) => l.length)) + 2;
21067
- for (const knob of [...KNOBS$1, ...STRING_KNOBS]) {
21623
+ for (const knob of [
21624
+ ...KNOBS$1,
21625
+ ...STRING_KNOBS,
21626
+ ...BOOLEAN_KNOBS
21627
+ ]) {
21068
21628
  const value = s[knob.field];
21069
21629
  const shown = value === null || value === void 0 ? "(cluster default)" : String(value);
21070
21630
  lines.push(`${(knob.label + ":").padEnd(width)} ${shown}`);
@@ -21077,11 +21637,17 @@ async function fetchSettings(client) {
21077
21637
  async function patchSettings(client, body) {
21078
21638
  return (await client.patch("/api/v1/admin/cluster-settings", body)).settings;
21079
21639
  }
21080
- /** Parse an integer CLI flag with a minimum, exiting with an error on failure. */
21081
- function parseKnobValue(flag, value, min) {
21640
+ /**
21641
+ * Parse an integer CLI flag against its knob's bounds, exiting on failure.
21642
+ *
21643
+ * `max` is optional because most knobs have no meaningful ceiling; the ones
21644
+ * that do carry a hard boot-safety bound (see {@link KnobSpec.max}).
21645
+ */
21646
+ function parseKnobValue(flag, value, min, max) {
21082
21647
  const n = Number(value);
21083
- if (!Number.isInteger(n) || n < min) {
21084
- console.error(`Error: --${flag} must be an integer >= ${min}`);
21648
+ const bounds = max === void 0 ? `>= ${min}` : `between ${min} and ${max}`;
21649
+ if (!Number.isInteger(n) || n < min || max !== void 0 && n > max) {
21650
+ console.error(`Error: --${flag} must be an integer ${bounds}`);
21085
21651
  process.exit(1);
21086
21652
  }
21087
21653
  return n;
@@ -21095,26 +21661,80 @@ function parseStringKnobValue(knob, value) {
21095
21661
  }
21096
21662
  return trimmed;
21097
21663
  }
21664
+ /**
21665
+ * Parse a boolean CLI flag, exiting on failure.
21666
+ *
21667
+ * Accepts only the exact strings `true` and `false`. A permissive parser (any
21668
+ * non-empty string is true) would read `--global-workflows-enabled no` as an
21669
+ * enable, which for this knob turns a typo into a security posture change.
21670
+ */
21671
+ function parseBooleanKnobValue(knob, value) {
21672
+ const trimmed = value.trim();
21673
+ if (trimmed !== "true" && trimmed !== "false") {
21674
+ console.error(`Error: --${knob.flag} must be true or false`);
21675
+ process.exit(1);
21676
+ }
21677
+ return trimmed === "true";
21678
+ }
21098
21679
  /** Assemble the PATCH body from provided `set` flags (exits if none given). */
21099
21680
  function buildClusterPatch(opts) {
21100
21681
  const patch = {};
21101
21682
  for (const knob of KNOBS$1) {
21102
21683
  const raw = opts[optionKey(knob.flag)];
21103
- if (raw !== void 0) patch[knob.field] = parseKnobValue(knob.flag, raw, knob.min);
21684
+ if (raw !== void 0) patch[knob.field] = parseKnobValue(knob.flag, raw, knob.min, knob.max);
21104
21685
  }
21105
21686
  for (const knob of STRING_KNOBS) {
21106
21687
  const raw = opts[optionKey(knob.flag)];
21107
21688
  if (raw !== void 0) patch[knob.field] = parseStringKnobValue(knob, raw);
21108
21689
  }
21690
+ for (const knob of BOOLEAN_KNOBS) {
21691
+ const raw = opts[optionKey(knob.flag)];
21692
+ if (raw !== void 0) patch[knob.field] = parseBooleanKnobValue(knob, raw);
21693
+ }
21109
21694
  if (Object.keys(patch).length === 0) {
21110
21695
  console.error(`Error: pass at least one knob flag (e.g. --${KNOBS$1[0].flag} <value>)`);
21111
21696
  process.exit(1);
21112
21697
  }
21113
21698
  return patch;
21114
21699
  }
21700
+ /**
21701
+ * Warn when only one of the two ordered global-eval timeouts is being set.
21702
+ *
21703
+ * The orchestrator's wait ceiling must exceed the agent's round budget — the
21704
+ * agent's budget starts only once the round job is RUNNING, so a lower ceiling
21705
+ * fires on every round that merely waited for a free agent, failing every round
21706
+ * silently. The server rejects the pair outright when BOTH effective values are
21707
+ * stored, but it cannot compare against a column left NULL: NULL means "the
21708
+ * orchestrator's configured default applies", and the route does not know that
21709
+ * number. Setting one alone is exactly that blind spot, so warn here.
21710
+ *
21711
+ * Returns the lines rather than printing them so the check is unit-testable.
21712
+ */
21713
+ function unpairedEvalTimeoutWarnings(patch) {
21714
+ const setting = (v) => typeof v === "number";
21715
+ const round = patch.globalEvalRoundTimeoutMs;
21716
+ const warnings = [];
21717
+ const wait = patch.globalEvalWaitTimeoutMs;
21718
+ if (setting(wait) !== setting(round)) {
21719
+ const which = setting(wait) ? "wait timeout" : "round timeout";
21720
+ const other = setting(wait) ? "--global-eval-round-timeout-ms" : "--global-eval-wait-timeout-ms";
21721
+ warnings.push(`Warning: setting the global eval ${which} alone. The wait timeout must stay greater than the round timeout, or every round fails. Check ${other} with \`kici-admin cluster-settings show\`.`);
21722
+ }
21723
+ const candidate = patch.globalEvalCandidateTimeoutMs;
21724
+ if (setting(candidate) !== setting(round)) {
21725
+ const which = setting(candidate) ? "candidate timeout" : "round timeout";
21726
+ const other = setting(candidate) ? "--global-eval-round-timeout-ms" : "--global-eval-candidate-timeout-ms";
21727
+ warnings.push(`Warning: setting the global eval ${which} alone. The candidate timeout must stay less than the round timeout, or one workflow can suppress every other in its round. Check ${other} with \`kici-admin cluster-settings show\`.`);
21728
+ }
21729
+ return warnings;
21730
+ }
21115
21731
  /** Build the reset PATCH body: all knobs → null, or just the flagged ones. */
21116
21732
  function buildClusterReset(opts) {
21117
- const all = [...KNOBS$1, ...STRING_KNOBS];
21733
+ const all = [
21734
+ ...KNOBS$1,
21735
+ ...STRING_KNOBS,
21736
+ ...BOOLEAN_KNOBS
21737
+ ];
21118
21738
  const flagged = all.filter((k) => opts[optionKey(k.flag)]);
21119
21739
  const target = flagged.length > 0 ? flagged : all;
21120
21740
  const patch = {};
@@ -21164,10 +21784,15 @@ function registerClusterSettingsCommands(program, getClient) {
21164
21784
  }
21165
21785
  });
21166
21786
  const setCmd = cs.command("set").description("Set one or more cluster-global tunables. At least one knob flag required.").option("--format <format>", "Output format: json|table", "table");
21167
- for (const knob of KNOBS$1) setCmd.option(`--${knob.flag} <value>`, `${knob.label} (integer >= ${knob.min})`);
21787
+ for (const knob of KNOBS$1) {
21788
+ const bounds = knob.max === void 0 ? `integer >= ${knob.min}` : `integer ${knob.min}-${knob.max}`;
21789
+ setCmd.option(`--${knob.flag} <value>`, `${knob.label} (${bounds})`);
21790
+ }
21168
21791
  for (const knob of STRING_KNOBS) setCmd.option(`--${knob.flag} <value>`, `${knob.label} (${knob.expects})`);
21792
+ for (const knob of BOOLEAN_KNOBS) setCmd.option(`--${knob.flag} <value>`, `${knob.label} (true|false)`);
21169
21793
  setCmd.action(async (opts) => {
21170
21794
  const patch = buildClusterPatch(opts);
21795
+ for (const line of unpairedEvalTimeoutWarnings(patch)) console.warn(line);
21171
21796
  try {
21172
21797
  const updated = await patchSettings(getClient(), patch);
21173
21798
  console.log(formatSettings(updated, opts.format ?? "table"));
@@ -21182,7 +21807,11 @@ function registerClusterSettingsCommands(program, getClient) {
21182
21807
  }
21183
21808
  });
21184
21809
  const resetCmd = cs.command("reset").description("Clear cluster-global overrides (all, or the named knobs) back to cluster defaults").option("--format <format>", "Output format: json|table", "table");
21185
- for (const knob of [...KNOBS$1, ...STRING_KNOBS]) resetCmd.option(`--${knob.flag}`, `Clear only ${knob.label}`);
21810
+ for (const knob of [
21811
+ ...KNOBS$1,
21812
+ ...STRING_KNOBS,
21813
+ ...BOOLEAN_KNOBS
21814
+ ]) resetCmd.option(`--${knob.flag}`, `Clear only ${knob.label}`);
21186
21815
  resetCmd.action(async (opts) => {
21187
21816
  const patch = buildClusterReset(opts);
21188
21817
  try {