@kici-dev/orchestrator 0.1.26 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/app.d.ts +13 -4
  2. package/dist/approvals/apply-decision.d.ts +1 -1
  3. package/dist/approvals/step-approval-bridge.d.ts +1 -1
  4. package/dist/cache/pending-inits.d.ts +4 -4
  5. package/dist/cli/api-client.d.ts +29 -4
  6. package/dist/cli/commands/context.d.ts +25 -0
  7. package/dist/cli/commands/debug-bundle.d.ts +1 -1
  8. package/dist/cli/commands/variable.d.ts +6 -6
  9. package/dist/cli/service/windows.d.ts +6 -0
  10. package/dist/cli.js +526 -340
  11. package/dist/config.d.ts +16 -0
  12. package/dist/contexts/binding-store.d.ts +36 -0
  13. package/dist/contexts/context-store.d.ts +87 -0
  14. package/dist/{environments → contexts}/held-runs.d.ts +15 -15
  15. package/dist/{environments → contexts}/index.d.ts +1 -1
  16. package/dist/contexts/protection/aggregate.d.ts +43 -0
  17. package/dist/contexts/protection/branch-gate.d.ts +5 -0
  18. package/dist/contexts/protection/concurrency-gate.d.ts +7 -0
  19. package/dist/{environments → contexts}/protection/pipeline.d.ts +3 -3
  20. package/dist/contexts/protection/reviewer-gate.d.ts +7 -0
  21. package/dist/{environments → contexts}/protection/satisfiability.d.ts +21 -21
  22. package/dist/contexts/protection/trust-gate.d.ts +7 -0
  23. package/dist/contexts/protection/wait-timer-gate.d.ts +7 -0
  24. package/dist/contexts/variable-store.d.ts +39 -0
  25. package/dist/dashboard/attestation-filters.d.ts +10 -8
  26. package/dist/dashboard/handler.d.ts +28 -2
  27. package/dist/db/migrations/067_environments_to_contexts.d.ts +36 -0
  28. package/dist/db/migrations/068_request_idempotency.d.ts +17 -0
  29. package/dist/db/types.d.ts +78 -59
  30. package/dist/github-app-name-refresher/github-app-name-refresher.d.ts +1 -1
  31. package/dist/index.js +21 -6
  32. package/dist/metrics/prometheus.d.ts +2 -0
  33. package/dist/oidc/id-token-claims.d.ts +63 -0
  34. package/dist/oidc/jwt.d.ts +15 -0
  35. package/dist/oidc/local-dev-signer.d.ts +31 -0
  36. package/dist/oidc/local-mint.d.ts +77 -0
  37. package/dist/oidc/oidc-mint-registration.d.ts +49 -0
  38. package/dist/pipeline/decorating-secret-resolver.d.ts +4 -4
  39. package/dist/pipeline/dispatch-matched-workflow.d.ts +3 -3
  40. package/dist/pipeline/inline-eval.d.ts +2 -2
  41. package/dist/pipeline/install-secrets-resolver.d.ts +13 -13
  42. package/dist/pipeline/{job-environments.d.ts → job-contexts.d.ts} +23 -23
  43. package/dist/pipeline/manual-schedule.d.ts +8 -1
  44. package/dist/pipeline/processor.d.ts +6 -6
  45. package/dist/pipeline/request-idempotency.d.ts +28 -0
  46. package/dist/pipeline/rerun.d.ts +8 -0
  47. package/dist/pipeline/resume-workflow.d.ts +1 -1
  48. package/dist/pipeline/test-pipeline.d.ts +2 -2
  49. package/dist/provenance/trust-root.d.ts +7 -0
  50. package/dist/provider-registry.d.ts +8 -0
  51. package/dist/providers/local/index.d.ts +1 -0
  52. package/dist/providers/local/local-source-config.d.ts +1 -0
  53. package/dist/reporting/execution-tracker.d.ts +17 -7
  54. package/dist/reporting/run-aggregator.d.ts +5 -5
  55. package/dist/routes/admin-contexts.d.ts +47 -0
  56. package/dist/routes/admin-registrations.d.ts +2 -2
  57. package/dist/routes/github-webhook.d.ts +2 -2
  58. package/dist/secrets/context-secret-resolver.d.ts +30 -0
  59. package/dist/secrets/index.d.ts +1 -1
  60. package/dist/secrets/pg-secret-store.d.ts +3 -3
  61. package/dist/secrets/rbac.d.ts +1 -1
  62. package/dist/secrets/secret-resolver.d.ts +19 -19
  63. package/dist/security/comment-handler.d.ts +1 -1
  64. package/dist/server.js +1770 -1196
  65. package/dist/stale-detector/stale-run-detector.d.ts +1 -1
  66. package/dist/standalone.js +1649 -747
  67. package/dist/storage/blob-routes.d.ts +16 -0
  68. package/dist/ws/{dashboard-env-handler.d.ts → dashboard-context-handler.d.ts} +15 -15
  69. package/dist/ws/oidc-token-relay.d.ts +6 -0
  70. package/installer-image-digests.json +3 -3
  71. package/package.json +4 -4
  72. package/sbom.spdx.json +50 -50
  73. package/dist/cli/commands/environment.d.ts +0 -25
  74. package/dist/environments/binding-store.d.ts +0 -36
  75. package/dist/environments/environment-store.d.ts +0 -87
  76. package/dist/environments/protection/aggregate.d.ts +0 -43
  77. package/dist/environments/protection/branch-gate.d.ts +0 -5
  78. package/dist/environments/protection/concurrency-gate.d.ts +0 -7
  79. package/dist/environments/protection/reviewer-gate.d.ts +0 -7
  80. package/dist/environments/protection/trust-gate.d.ts +0 -7
  81. package/dist/environments/protection/wait-timer-gate.d.ts +0 -7
  82. package/dist/environments/variable-store.d.ts +0 -39
  83. package/dist/routes/admin-environments.d.ts +0 -47
package/dist/cli.js CHANGED
@@ -5,8 +5,8 @@ import * as path$1 from "node:path";
5
5
  import path, { dirname, join, resolve } from "node:path";
6
6
  import * as fs$1 from "node:fs";
7
7
  import fs, { chmodSync, closeSync, createReadStream, createWriteStream, existsSync, mkdtempSync, openSync, promises, readFileSync, realpathSync, statSync, unwatchFile, watchFile, writeFileSync } from "node:fs";
8
- import { Command } from "commander";
9
- import { BaseColdStore, ChunkLru, addLogsToArchive, chunkObjectKey, clearDispatchQueueDirect, computeChunkId, computeMigrationsHash, createDb, createDbRole, createEnvironmentTemplateDirect, createLogger, createPool, createReadOnlyDbUser, createS3Client, decodeChunk, deleteEnvironmentDirect, dropAndCreateDatabase, emitKiciEventDirect, encodeKeySegment, ensureDatabase, formatBytes, formatUptime, isSchemaCurrent, listEnvironmentsDirect, listExecutionRunsDirect, listQueueDirect, listRegistrationsDirect, maskDatabaseUrl, parseDatabaseUrl, parseManifest, prunePeerCredentialsDirect, purgeEnvironmentsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, registerWorkflowManualDirect, resetRaftStateDirect, seedEnvironmentBindingDirect, seedEnvironmentDirect, setEnvironmentPolicyDirect, setEnvironmentSecretDirect, sha256, showEnvironmentDirect, showExecutionRunDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, tablePrefix, toErrorMessage } from "@kici-dev/shared";
8
+ import { Command, Option } from "commander";
9
+ import { BaseColdStore, ChunkLru, addLogsToArchive, chunkObjectKey, clearDispatchQueueDirect, computeChunkId, computeMigrationsHash, createContextTemplateDirect, createDb, createDbRole, createLogger, createPool, createReadOnlyDbUser, createS3Client, decodeChunk, deleteContextDirect, dropAndCreateDatabase, emitKiciEventDirect, encodeKeySegment, ensureDatabase, formatBytes, formatUptime, isSchemaCurrent, listContextsDirect, listExecutionRunsDirect, listQueueDirect, listRegistrationsDirect, maskDatabaseUrl, parseDatabaseUrl, parseManifest, prunePeerCredentialsDirect, purgeContextsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, registerWorkflowManualDirect, resetRaftStateDirect, seedContextBindingDirect, seedContextDirect, setContextPolicyDirect, setContextSecretDirect, sha256, showContextDirect, showExecutionRunDirect, showQueueEntryDirect, showRegistrationDirect, storeMigrationContentHash, tablePrefix, toErrorMessage } from "@kici-dev/shared";
10
10
  import crypto, { createDecipheriv, createHash, createHmac, hkdfSync, randomBytes, randomUUID } from "node:crypto";
11
11
  import { createInterface } from "node:readline";
12
12
  import { KICI_AGENT_ENV_PREFIX, KNOWN_ROLES, PRIVILEGED_ROOT_LABEL, ScalerBackendType, ScalerEventType, TERMINAL_JOB_STATES, TERMINAL_RUN_STATES, WS_MAX_PAYLOAD_BYTES, accessLogWarmSqlCase, attestationVerifyStatusSchema, getAccessLogColdDays, getSecretAuditLogColdDays, matcherSatisfiedBy, minAccessLogWarmDays, minSecretAuditLogWarmDays, parseHostPropertyAssignments, scalerAgentLabels, secretAuditLogWarmSqlCase } from "@kici-dev/engine";
@@ -180,20 +180,35 @@ var AdminApiClient = class {
180
180
  async deleteSecret(orgId, scope, key) {
181
181
  return this.request("DELETE", `/api/v1/admin/secrets/${encodeURIComponent(orgId)}/${encodeURIComponent(scope)}/${encodeURIComponent(key)}`);
182
182
  }
183
- async listVariables(orgId, environment) {
183
+ /**
184
+ * Create (or upsert) a deployment context. `allowLocalExecution` lets
185
+ * CLI-initiated / local runs resolve secrets through this context.
186
+ */
187
+ async createContext(data) {
188
+ return this.request("POST", `/api/v1/admin/contexts`, data);
189
+ }
190
+ /**
191
+ * Bind a scope pattern to a context so its scoped secrets resolve at dispatch.
192
+ * `hostPattern` defaults to `**` (every host) server-side.
193
+ */
194
+ async bindContext(data) {
195
+ const { name, ...body } = data;
196
+ return this.request("POST", `/api/v1/admin/contexts/${encodeURIComponent(name)}/bind`, body);
197
+ }
198
+ async listVariables(orgId, context) {
184
199
  const params = new URLSearchParams({ orgId });
185
- return this.request("GET", `/api/v1/admin/environments/${encodeURIComponent(environment)}/variables?${params}`);
200
+ return this.request("GET", `/api/v1/admin/contexts/${encodeURIComponent(context)}/variables?${params}`);
186
201
  }
187
- async setVariable(orgId, environment, key, value, locked) {
202
+ async setVariable(orgId, context, key, value, locked) {
188
203
  const params = new URLSearchParams({ orgId });
189
- return this.request("PUT", `/api/v1/admin/environments/${encodeURIComponent(environment)}/variables/${encodeURIComponent(key)}?${params}`, {
204
+ return this.request("PUT", `/api/v1/admin/contexts/${encodeURIComponent(context)}/variables/${encodeURIComponent(key)}?${params}`, {
190
205
  value,
191
206
  locked
192
207
  });
193
208
  }
194
- async deleteVariable(orgId, environment, key) {
209
+ async deleteVariable(orgId, context, key) {
195
210
  const params = new URLSearchParams({ orgId });
196
- return this.request("DELETE", `/api/v1/admin/environments/${encodeURIComponent(environment)}/variables/${encodeURIComponent(key)}?${params}`);
211
+ return this.request("DELETE", `/api/v1/admin/contexts/${encodeURIComponent(context)}/variables/${encodeURIComponent(key)}?${params}`);
197
212
  }
198
213
  async rotateKey() {
199
214
  return this.request("POST", "/api/v1/admin/rotate-key");
@@ -631,23 +646,23 @@ function registerSecretCommands(program, getClient) {
631
646
  process.exit(1);
632
647
  }
633
648
  });
634
- sec.command("set [orgId] [scope] [key]").description("Set a secret value. Positional form: \"set <orgId> <scope> <key>\". Sugar form (environment scope): \"set --org <id> --environment <env> --key <k>\". Value comes from one of: --prompt (default on TTY), --from-stdin (default on pipe), --from-file <path>, --from-env <VAR>, --value <plaintext> (discouraged).").option("--value <value>", "Secret value via argv (visible in shell history; prefer --prompt)").option("--org <orgId>", "Org ID (use with --environment + --key; mutually exclusive with positional form)").option("--environment <name>", "Environment scope — sugar for positional <scope>. Requires --org and --key.").option("--key <key>", "Secret key name (use with --org + --environment)").option("--prompt", "Interactive no-echo prompt (requires TTY)").option("--from-stdin", "Read value from piped stdin until EOF").option("--from-file <path>", "Read value from a file (trailing newline trimmed)").option("--from-env <var>", "Read value from a named environment variable").option("--no-trim", "When reading --from-file, keep the trailing newline (default: trim once)").option("--confirm-fingerprint <sha256hex>", "Refuse the write unless SHA-256(value) matches this 64-hex string").option("--dry-run", "Parse + validate the value, print fingerprint + length, do not write").option("--database-url <url>", "Direct-DB mode: write encrypted_value verbatim to scoped_secrets (offline; skips HTTP + encryption)").action(async (posOrgId, posScope, posKey, opts) => {
649
+ sec.command("set [orgId] [scope] [key]").description("Set a secret value. Positional form: \"set <orgId> <scope> <key>\". Sugar form (context scope): \"set --org <id> --context <env> --key <k>\". Value comes from one of: --prompt (default on TTY), --from-stdin (default on pipe), --from-file <path>, --from-env <VAR>, --value <plaintext> (discouraged).").option("--value <value>", "Secret value via argv (visible in shell history; prefer --prompt)").option("--org <orgId>", "Org ID (use with --context + --key; mutually exclusive with positional form)").option("--context <name>", "Context scope — sugar for positional <scope>. Requires --org and --key.").option("--key <key>", "Secret key name (use with --org + --context)").option("--prompt", "Interactive no-echo prompt (requires TTY)").option("--from-stdin", "Read value from piped stdin until EOF").option("--from-file <path>", "Read value from a file (trailing newline trimmed)").option("--from-env <var>", "Read value from a named environment variable").option("--no-trim", "When reading --from-file, keep the trailing newline (default: trim once)").option("--confirm-fingerprint <sha256hex>", "Refuse the write unless SHA-256(value) matches this 64-hex string").option("--dry-run", "Parse + validate the value, print fingerprint + length, do not write").option("--database-url <url>", "Direct-DB mode: write encrypted_value verbatim to scoped_secrets (offline; skips HTTP + encryption)").action(async (posOrgId, posScope, posKey, opts) => {
635
650
  try {
636
651
  const hasPositional = Boolean(posOrgId || posScope || posKey);
637
- const hasSugar = Boolean(opts.org || opts.environment || opts.key);
638
- if (hasPositional && hasSugar) throw new Error("Cannot mix positional <orgId> <scope> <key> form with --org/--environment/--key flags. Pick one.");
652
+ const hasSugar = Boolean(opts.org || opts.context || opts.key);
653
+ if (hasPositional && hasSugar) throw new Error("Cannot mix positional <orgId> <scope> <key> form with --org/--context/--key flags. Pick one.");
639
654
  let orgId;
640
655
  let scope;
641
656
  let key;
642
657
  if (hasSugar) {
643
- if (!opts.org) throw new Error("--org is required when using --environment sugar form");
644
- if (!opts.environment) throw new Error("--environment is required in sugar form (use --environment <name>)");
645
- if (!opts.key) throw new Error("--key is required when using --environment sugar form");
658
+ if (!opts.org) throw new Error("--org is required when using --context sugar form");
659
+ if (!opts.context) throw new Error("--context is required in sugar form (use --context <name>)");
660
+ if (!opts.key) throw new Error("--key is required when using --context sugar form");
646
661
  orgId = opts.org;
647
- scope = opts.environment;
662
+ scope = opts.context;
648
663
  key = opts.key;
649
664
  } else {
650
- if (!posOrgId || !posScope || !posKey) throw new Error("Missing arguments: supply either <orgId> <scope> <key> positionally, or --org + --environment + --key.");
665
+ if (!posOrgId || !posScope || !posKey) throw new Error("Missing arguments: supply either <orgId> <scope> <key> positionally, or --org + --context + --key.");
651
666
  orgId = posOrgId;
652
667
  scope = posScope;
653
668
  key = posKey;
@@ -659,9 +674,9 @@ function registerSecretCommands(program, getClient) {
659
674
  }
660
675
  const dbUrl = resolveDirectDbUrl$9(opts.databaseUrl);
661
676
  if (dbUrl) {
662
- await setEnvironmentSecretDirect(dbUrl, {
677
+ await setContextSecretDirect(dbUrl, {
663
678
  orgId,
664
- environment: scope,
679
+ context: scope,
665
680
  key,
666
681
  encryptedValue: value
667
682
  });
@@ -1590,8 +1605,8 @@ var init_client = __esmMin((() => {
1590
1605
  //#region src/db/migrations/001_initial.ts
1591
1606
  init_client();
1592
1607
  var _001_initial_exports = /* @__PURE__ */ __exportAll({
1593
- down: () => down$65,
1594
- up: () => up$65
1608
+ down: () => down$67,
1609
+ up: () => up$67
1595
1610
  });
1596
1611
  /**
1597
1612
  * Squashed initial migration -- creates the complete Orchestrator database schema.
@@ -2283,7 +2298,7 @@ const DDL_STATEMENTS = [
2283
2298
  `ALTER TABLE ONLY public.held_runs
2284
2299
  ADD CONSTRAINT held_runs_environment_id_fkey FOREIGN KEY (environment_id) REFERENCES public.environments(id);`
2285
2300
  ];
2286
- async function up$65(db) {
2301
+ async function up$67(db) {
2287
2302
  for (const stmt of DDL_STATEMENTS) await sql.raw(stmt).execute(db);
2288
2303
  await sql`
2289
2304
  INSERT INTO cluster_meta (key, value)
@@ -2305,7 +2320,7 @@ async function up$65(db) {
2305
2320
  * Rollback drops everything created above. Uses CASCADE on table drops to cut
2306
2321
  * through the FK graph without relying on exact topological order.
2307
2322
  */
2308
- async function down$65(db) {
2323
+ async function down$67(db) {
2309
2324
  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);
2310
2325
  for (const table of [
2311
2326
  "workflow_registrations",
@@ -2352,8 +2367,8 @@ async function down$65(db) {
2352
2367
  //#endregion
2353
2368
  //#region src/db/migrations/002_config_versions_key_version.ts
2354
2369
  var _002_config_versions_key_version_exports = /* @__PURE__ */ __exportAll({
2355
- down: () => down$64,
2356
- up: () => up$64
2370
+ down: () => down$66,
2371
+ up: () => up$66
2357
2372
  });
2358
2373
  /**
2359
2374
  * Add key_version column to config_versions so that sensitive-field encryption
@@ -2367,13 +2382,13 @@ var _002_config_versions_key_version_exports = /* @__PURE__ */ __exportAll({
2367
2382
  * No index is needed: rotation does a full-table scan; reads are by
2368
2383
  * `version` primary key and never filter on `key_version`.
2369
2384
  */
2370
- async function up$64(db) {
2385
+ async function up$66(db) {
2371
2386
  await sql`
2372
2387
  ALTER TABLE public.config_versions
2373
2388
  ADD COLUMN key_version integer NOT NULL DEFAULT 1
2374
2389
  `.execute(db);
2375
2390
  }
2376
- async function down$64(db) {
2391
+ async function down$66(db) {
2377
2392
  await sql`
2378
2393
  ALTER TABLE public.config_versions
2379
2394
  DROP COLUMN key_version
@@ -2382,8 +2397,8 @@ async function down$64(db) {
2382
2397
  //#endregion
2383
2398
  //#region src/db/migrations/003_access_log.ts
2384
2399
  var _003_access_log_exports = /* @__PURE__ */ __exportAll({
2385
- down: () => down$63,
2386
- up: () => up$63
2400
+ down: () => down$65,
2401
+ up: () => up$65
2387
2402
  });
2388
2403
  /**
2389
2404
  * Access log: one row per read or orchestrator-admin mutation attributable
@@ -2407,7 +2422,7 @@ var _003_access_log_exports = /* @__PURE__ */ __exportAll({
2407
2422
  * Retention is TTL-based via expires_at; packages/orchestrator/src/queue/
2408
2423
  * cleanup.ts picks up the prune pass.
2409
2424
  */
2410
- async function up$63(db) {
2425
+ async function up$65(db) {
2411
2426
  await sql`
2412
2427
  CREATE TABLE public.access_log (
2413
2428
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
@@ -2445,28 +2460,28 @@ async function up$63(db) {
2445
2460
  ON public.access_log (actor_type, actor_id, created_at DESC)
2446
2461
  `.execute(db);
2447
2462
  }
2448
- async function down$63(db) {
2463
+ async function down$65(db) {
2449
2464
  await sql`DROP TABLE IF EXISTS public.access_log`.execute(db);
2450
2465
  }
2451
2466
  //#endregion
2452
2467
  //#region src/db/migrations/004_rename_bundle_to_source.ts
2453
2468
  var _004_rename_bundle_to_source_exports = /* @__PURE__ */ __exportAll({
2454
- down: () => down$62,
2455
- up: () => up$62
2469
+ down: () => down$64,
2470
+ up: () => up$64
2456
2471
  });
2457
- async function up$62(db) {
2472
+ async function up$64(db) {
2458
2473
  await db.schema.alterTable("dispatch_queue").renameColumn("bundle_url", "source_tar_url").execute();
2459
2474
  await db.schema.alterTable("dispatch_queue").renameColumn("bundle_hash", "source_tar_hash").execute();
2460
2475
  }
2461
- async function down$62(db) {
2476
+ async function down$64(db) {
2462
2477
  await db.schema.alterTable("dispatch_queue").renameColumn("source_tar_url", "bundle_url").execute();
2463
2478
  await db.schema.alterTable("dispatch_queue").renameColumn("source_tar_hash", "bundle_hash").execute();
2464
2479
  }
2465
2480
  //#endregion
2466
2481
  //#region src/db/migrations/005_cold_store_chunk_counter.ts
2467
2482
  var _005_cold_store_chunk_counter_exports = /* @__PURE__ */ __exportAll({
2468
- down: () => down$61,
2469
- up: () => up$61
2483
+ down: () => down$63,
2484
+ up: () => up$63
2470
2485
  });
2471
2486
  /**
2472
2487
  * Cold-store chunk counter table.
@@ -2483,7 +2498,7 @@ var _005_cold_store_chunk_counter_exports = /* @__PURE__ */ __exportAll({
2483
2498
  *
2484
2499
  * sections 5 and 8.
2485
2500
  */
2486
- async function up$61(db) {
2501
+ async function up$63(db) {
2487
2502
  await sql`
2488
2503
  CREATE TABLE public.cold_store_chunk_counts (
2489
2504
  db TEXT NOT NULL,
@@ -2501,14 +2516,14 @@ async function up$61(db) {
2501
2516
  ON public.cold_store_chunk_counts (db, table_name)
2502
2517
  `.execute(db);
2503
2518
  }
2504
- async function down$61(db) {
2519
+ async function down$63(db) {
2505
2520
  await sql`DROP TABLE IF EXISTS public.cold_store_chunk_counts`.execute(db);
2506
2521
  }
2507
2522
  //#endregion
2508
2523
  //#region src/db/migrations/006_runs_jobs_steps_archived_at.ts
2509
2524
  var _006_runs_jobs_steps_archived_at_exports = /* @__PURE__ */ __exportAll({
2510
- down: () => down$60,
2511
- up: () => up$60
2525
+ down: () => down$62,
2526
+ up: () => up$62
2512
2527
  });
2513
2528
  /**
2514
2529
  * `execution_runs` / `execution_jobs` / `execution_steps` cold-store
@@ -2544,7 +2559,7 @@ var _006_runs_jobs_steps_archived_at_exports = /* @__PURE__ */ __exportAll({
2544
2559
  * - `idx_execution_jobs_routing_key_created (routing_key, created_at)`
2545
2560
  * - `idx_execution_steps_routing_key_created (routing_key, created_at)`
2546
2561
  */
2547
- async function up$60(db) {
2562
+ async function up$62(db) {
2548
2563
  await sql`
2549
2564
  ALTER TABLE public.execution_runs
2550
2565
  ADD COLUMN archived_at TIMESTAMPTZ NULL,
@@ -2589,7 +2604,7 @@ async function up$60(db) {
2589
2604
  ON public.execution_steps (routing_key, created_at)
2590
2605
  `.execute(db);
2591
2606
  }
2592
- async function down$60(db) {
2607
+ async function down$62(db) {
2593
2608
  await sql`DROP INDEX IF EXISTS public.idx_execution_steps_routing_key_created`.execute(db);
2594
2609
  await sql`
2595
2610
  ALTER TABLE public.execution_steps
@@ -2614,8 +2629,8 @@ async function down$60(db) {
2614
2629
  //#endregion
2615
2630
  //#region src/db/migrations/007_audit_logs_archived_at.ts
2616
2631
  var _007_audit_logs_archived_at_exports = /* @__PURE__ */ __exportAll({
2617
- down: () => down$59,
2618
- up: () => up$59
2632
+ down: () => down$61,
2633
+ up: () => up$61
2619
2634
  });
2620
2635
  /**
2621
2636
  * `secret_audit_log` and `access_log` cold-store schema additions, plus
@@ -2655,7 +2670,7 @@ var _007_audit_logs_archived_at_exports = /* @__PURE__ */ __exportAll({
2655
2670
  * `down()` would not have meaningful retention bounds. Acceptable for
2656
2671
  * staging.
2657
2672
  */
2658
- async function up$59(db) {
2673
+ async function up$61(db) {
2659
2674
  await sql`
2660
2675
  ALTER TABLE public.secret_audit_log
2661
2676
  ADD COLUMN archived_at TIMESTAMPTZ NULL,
@@ -2676,7 +2691,7 @@ async function up$59(db) {
2676
2691
  DROP COLUMN IF EXISTS expires_at
2677
2692
  `.execute(db);
2678
2693
  }
2679
- async function down$59(db) {
2694
+ async function down$61(db) {
2680
2695
  await sql`
2681
2696
  ALTER TABLE public.access_log
2682
2697
  ADD COLUMN expires_at TIMESTAMPTZ NOT NULL DEFAULT (now() + INTERVAL '90 days')
@@ -2704,8 +2719,8 @@ async function down$59(db) {
2704
2719
  //#endregion
2705
2720
  //#region src/db/migrations/008_event_log_archived_at.ts
2706
2721
  var _008_event_log_archived_at_exports = /* @__PURE__ */ __exportAll({
2707
- down: () => down$58,
2708
- up: () => up$58
2722
+ down: () => down$60,
2723
+ up: () => up$60
2709
2724
  });
2710
2725
  /**
2711
2726
  * `event_log` cold-store schema additions plus removal of the
@@ -2743,7 +2758,7 @@ var _008_event_log_archived_at_exports = /* @__PURE__ */ __exportAll({
2743
2758
  * — best effort; rows inserted between `up()` and a hypothetical
2744
2759
  * `down()` would not have meaningful retention bounds.
2745
2760
  */
2746
- async function up$58(db) {
2761
+ async function up$60(db) {
2747
2762
  await sql`
2748
2763
  ALTER TABLE public.event_log
2749
2764
  ADD COLUMN archived_at TIMESTAMPTZ NULL,
@@ -2759,7 +2774,7 @@ async function up$58(db) {
2759
2774
  DROP COLUMN IF EXISTS expires_at
2760
2775
  `.execute(db);
2761
2776
  }
2762
- async function down$58(db) {
2777
+ async function down$60(db) {
2763
2778
  await sql`
2764
2779
  ALTER TABLE public.event_log
2765
2780
  ADD COLUMN expires_at TIMESTAMPTZ NOT NULL DEFAULT (now() + INTERVAL '30 days')
@@ -2778,8 +2793,8 @@ async function down$58(db) {
2778
2793
  //#endregion
2779
2794
  //#region src/db/migrations/009_access_log_trigram.ts
2780
2795
  var _009_access_log_trigram_exports = /* @__PURE__ */ __exportAll({
2781
- down: () => down$57,
2782
- up: () => up$57
2796
+ down: () => down$59,
2797
+ up: () => up$59
2783
2798
  });
2784
2799
  /**
2785
2800
  * Trigram (pg_trgm) index on access_log.error_message for the federated
@@ -2792,7 +2807,7 @@ var _009_access_log_trigram_exports = /* @__PURE__ */ __exportAll({
2792
2807
  * EXISTS` are both safe to re-run. No CONCURRENTLY because Kysely runs
2793
2808
  * migrations inside a transaction; the lock is brief on a sampled table.
2794
2809
  */
2795
- async function up$57(db) {
2810
+ async function up$59(db) {
2796
2811
  await sql`CREATE EXTENSION IF NOT EXISTS pg_trgm`.execute(db);
2797
2812
  await sql`
2798
2813
  CREATE INDEX IF NOT EXISTS access_log_error_message_trgm_idx
@@ -2801,14 +2816,14 @@ async function up$57(db) {
2801
2816
  WHERE error_message IS NOT NULL
2802
2817
  `.execute(db);
2803
2818
  }
2804
- async function down$57(db) {
2819
+ async function down$59(db) {
2805
2820
  await sql`DROP INDEX IF EXISTS public.access_log_error_message_trgm_idx`.execute(db);
2806
2821
  }
2807
2822
  //#endregion
2808
2823
  //#region src/db/migrations/010_cold_store_chunks.ts
2809
2824
  var _010_cold_store_chunks_exports = /* @__PURE__ */ __exportAll({
2810
- down: () => down$56,
2811
- up: () => up$56
2825
+ down: () => down$58,
2826
+ up: () => up$58
2812
2827
  });
2813
2828
  /**
2814
2829
  * Cold-store chunk index — Phase 2 (cold-store purge).
@@ -2840,7 +2855,7 @@ var _010_cold_store_chunks_exports = /* @__PURE__ */ __exportAll({
2840
2855
  * forever. Adapters that don't opt into per-bucket archival via
2841
2856
  * `coldTtlDays` don't insert here either.
2842
2857
  */
2843
- async function up$56(db) {
2858
+ async function up$58(db) {
2844
2859
  await sql`
2845
2860
  CREATE TABLE public.cold_store_chunks (
2846
2861
  db TEXT NOT NULL,
@@ -2867,14 +2882,14 @@ async function up$56(db) {
2867
2882
  ON public.cold_store_chunks (db, table_name, tenant_id, archived_at DESC)
2868
2883
  `.execute(db);
2869
2884
  }
2870
- async function down$56(db) {
2885
+ async function down$58(db) {
2871
2886
  await sql`DROP TABLE IF EXISTS public.cold_store_chunks`.execute(db);
2872
2887
  }
2873
2888
  //#endregion
2874
2889
  //#region src/db/migrations/011_drop_source_secrets_notify.ts
2875
2890
  var _011_drop_source_secrets_notify_exports = /* @__PURE__ */ __exportAll({
2876
- down: () => down$55,
2877
- up: () => up$55
2891
+ down: () => down$57,
2892
+ up: () => up$57
2878
2893
  });
2879
2894
  /**
2880
2895
  * Drop the `source_secrets_change_trigger` and the
@@ -2893,11 +2908,11 @@ var _011_drop_source_secrets_notify_exports = /* @__PURE__ */ __exportAll({
2893
2908
  * in `001_initial.ts`. They wake up no consumer until the `WebhookSecretManager`
2894
2909
  * is restored, so this migration is safe to roll back.
2895
2910
  */
2896
- async function up$55(db) {
2911
+ async function up$57(db) {
2897
2912
  await sql`DROP TRIGGER IF EXISTS source_secrets_change_trigger ON public.scoped_secrets`.execute(db);
2898
2913
  await sql`DROP FUNCTION IF EXISTS public.notify_source_secrets_change() CASCADE`.execute(db);
2899
2914
  }
2900
- async function down$55(db) {
2915
+ async function down$57(db) {
2901
2916
  await sql`
2902
2917
  CREATE OR REPLACE FUNCTION public.notify_source_secrets_change() RETURNS trigger
2903
2918
  LANGUAGE plpgsql
@@ -2936,8 +2951,8 @@ async function down$55(db) {
2936
2951
  //#endregion
2937
2952
  //#region src/db/migrations/012_peer_credentials_active_uniq.ts
2938
2953
  var _012_peer_credentials_active_uniq_exports = /* @__PURE__ */ __exportAll({
2939
- down: () => down$54,
2940
- up: () => up$54
2954
+ down: () => down$56,
2955
+ up: () => up$56
2941
2956
  });
2942
2957
  /**
2943
2958
  * Add a partial unique index on `peer_credentials (instance_id) WHERE
@@ -2963,7 +2978,7 @@ var _012_peer_credentials_active_uniq_exports = /* @__PURE__ */ __exportAll({
2963
2978
  * `down()` only drops the index; it does NOT undo the dedupe (there's no
2964
2979
  * safe way to recreate revoked rows, and the dedupe is monotonic).
2965
2980
  */
2966
- async function up$54(db) {
2981
+ async function up$56(db) {
2967
2982
  await sql`
2968
2983
  UPDATE public.peer_credentials
2969
2984
  SET revoked_at = NOW()
@@ -2981,14 +2996,14 @@ async function up$54(db) {
2981
2996
  WHERE revoked_at IS NULL
2982
2997
  `.execute(db);
2983
2998
  }
2984
- async function down$54(db) {
2999
+ async function down$56(db) {
2985
3000
  await sql`DROP INDEX IF EXISTS public.peer_credentials_active_uniq`.execute(db);
2986
3001
  }
2987
3002
  //#endregion
2988
3003
  //#region src/db/migrations/013_execution_log_bytes.ts
2989
3004
  var _013_execution_log_bytes_exports = /* @__PURE__ */ __exportAll({
2990
- down: () => down$53,
2991
- up: () => up$53
3005
+ down: () => down$55,
3006
+ up: () => up$55
2992
3007
  });
2993
3008
  /**
2994
3009
  * Add `log_bytes BIGINT NOT NULL DEFAULT 0` columns to `execution_runs` and
@@ -3007,7 +3022,7 @@ var _013_execution_log_bytes_exports = /* @__PURE__ */ __exportAll({
3007
3022
  *
3008
3023
  * Idempotent (`ADD COLUMN IF NOT EXISTS`).
3009
3024
  */
3010
- async function up$53(db) {
3025
+ async function up$55(db) {
3011
3026
  await sql`
3012
3027
  ALTER TABLE public.execution_runs
3013
3028
  ADD COLUMN IF NOT EXISTS log_bytes BIGINT NOT NULL DEFAULT 0
@@ -3017,15 +3032,15 @@ async function up$53(db) {
3017
3032
  ADD COLUMN IF NOT EXISTS log_bytes BIGINT NOT NULL DEFAULT 0
3018
3033
  `.execute(db);
3019
3034
  }
3020
- async function down$53(db) {
3035
+ async function down$55(db) {
3021
3036
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS log_bytes`.execute(db);
3022
3037
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS log_bytes`.execute(db);
3023
3038
  }
3024
3039
  //#endregion
3025
3040
  //#region src/db/migrations/014_kici_events_lease_retry.ts
3026
3041
  var _014_kici_events_lease_retry_exports = /* @__PURE__ */ __exportAll({
3027
- down: () => down$52,
3028
- up: () => up$52
3042
+ down: () => down$54,
3043
+ up: () => up$54
3029
3044
  });
3030
3045
  /**
3031
3046
  * Add lease + retry + DLQ columns to `kici_events` so the EventRouter can
@@ -3059,7 +3074,7 @@ var _014_kici_events_lease_retry_exports = /* @__PURE__ */ __exportAll({
3059
3074
  *
3060
3075
  * Idempotent (`ADD COLUMN IF NOT EXISTS` + `CREATE INDEX IF NOT EXISTS`).
3061
3076
  */
3062
- async function up$52(db) {
3077
+ async function up$54(db) {
3063
3078
  await sql`
3064
3079
  ALTER TABLE public.kici_events
3065
3080
  ADD COLUMN IF NOT EXISTS claimed_at TIMESTAMPTZ,
@@ -3090,7 +3105,7 @@ async function up$52(db) {
3090
3105
  WHERE dlq_at IS NOT NULL
3091
3106
  `.execute(db);
3092
3107
  }
3093
- async function down$52(db) {
3108
+ async function down$54(db) {
3094
3109
  await sql`DROP INDEX IF EXISTS public.idx_kici_events_dlq`.execute(db);
3095
3110
  await sql`DROP INDEX IF EXISTS public.idx_kici_events_lease_expired`.execute(db);
3096
3111
  await sql`DROP INDEX IF EXISTS public.idx_kici_events_retry_due`.execute(db);
@@ -3108,8 +3123,8 @@ async function down$52(db) {
3108
3123
  //#endregion
3109
3124
  //#region src/db/migrations/015_org_settings_customer_scoped.ts
3110
3125
  var _015_org_settings_customer_scoped_exports = /* @__PURE__ */ __exportAll({
3111
- down: () => down$51,
3112
- up: () => up$51
3126
+ down: () => down$53,
3127
+ up: () => up$53
3113
3128
  });
3114
3129
  /**
3115
3130
  * Org-scope `org_settings` and qualify each glob entry by source.
@@ -3137,7 +3152,7 @@ var _015_org_settings_customer_scoped_exports = /* @__PURE__ */ __exportAll({
3137
3152
  * Idempotent: a re-run on an already-migrated DB sees `customer_id` exists
3138
3153
  * and the list columns are already jsonb, so it is a no-op.
3139
3154
  */
3140
- async function up$51(db) {
3155
+ async function up$53(db) {
3141
3156
  if ((await sql`
3142
3157
  SELECT EXISTS (
3143
3158
  SELECT 1 FROM information_schema.columns
@@ -3262,7 +3277,7 @@ async function up$51(db) {
3262
3277
  await sql`DROP TABLE _org_settings_merged`.execute(db);
3263
3278
  await sql`DROP TABLE _org_settings_stage`.execute(db);
3264
3279
  }
3265
- async function down$51(db) {
3280
+ async function down$53(db) {
3266
3281
  if (!(await sql`
3267
3282
  SELECT EXISTS (
3268
3283
  SELECT 1 FROM information_schema.columns
@@ -3287,8 +3302,8 @@ async function down$51(db) {
3287
3302
  //#endregion
3288
3303
  //#region src/db/migrations/016_org_settings_allow_http_npm.ts
3289
3304
  var _016_org_settings_allow_http_npm_exports = /* @__PURE__ */ __exportAll({
3290
- down: () => down$50,
3291
- up: () => up$50
3305
+ down: () => down$52,
3306
+ up: () => up$52
3292
3307
  });
3293
3308
  /**
3294
3309
  * Add `org_settings.allow_http_npm_registries boolean NOT NULL DEFAULT false`.
@@ -3301,7 +3316,7 @@ var _016_org_settings_allow_http_npm_exports = /* @__PURE__ */ __exportAll({
3301
3316
  *
3302
3317
  * Idempotent: a re-run on a DB that already has the column is a no-op.
3303
3318
  */
3304
- async function up$50(db) {
3319
+ async function up$52(db) {
3305
3320
  if ((await sql`
3306
3321
  SELECT EXISTS (
3307
3322
  SELECT 1 FROM information_schema.columns
@@ -3315,7 +3330,7 @@ async function up$50(db) {
3315
3330
  ADD COLUMN allow_http_npm_registries boolean NOT NULL DEFAULT false
3316
3331
  `.execute(db);
3317
3332
  }
3318
- async function down$50(db) {
3333
+ async function down$52(db) {
3319
3334
  await sql`
3320
3335
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS allow_http_npm_registries
3321
3336
  `.execute(db);
@@ -3323,8 +3338,8 @@ async function down$50(db) {
3323
3338
  //#endregion
3324
3339
  //#region src/db/migrations/017_org_id_widen.ts
3325
3340
  var _017_org_id_widen_exports = /* @__PURE__ */ __exportAll({
3326
- down: () => down$49,
3327
- up: () => up$49
3341
+ down: () => down$51,
3342
+ up: () => up$51
3328
3343
  });
3329
3344
  /**
3330
3345
  * Widen every orchestrator-side `org_id varchar(12)` column to
@@ -3364,17 +3379,17 @@ const ORG_ID_TABLES$1 = [
3364
3379
  "held_runs",
3365
3380
  "scoped_secrets"
3366
3381
  ];
3367
- async function up$49(db) {
3382
+ async function up$51(db) {
3368
3383
  for (const table of ORG_ID_TABLES$1) await sql.raw(`ALTER TABLE public.${table} ALTER COLUMN org_id TYPE varchar(16)`).execute(db);
3369
3384
  }
3370
- async function down$49(db) {
3385
+ async function down$51(db) {
3371
3386
  for (const table of ORG_ID_TABLES$1) await sql.raw(`ALTER TABLE public.${table} ALTER COLUMN org_id TYPE varchar(12)`).execute(db);
3372
3387
  }
3373
3388
  //#endregion
3374
3389
  //#region src/db/migrations/018_org_id_prefix_backfill.ts
3375
3390
  var _018_org_id_prefix_backfill_exports = /* @__PURE__ */ __exportAll({
3376
- down: () => down$48,
3377
- up: () => up$48
3391
+ down: () => down$50,
3392
+ up: () => up$50
3378
3393
  });
3379
3394
  /**
3380
3395
  * Prefix every orchestrator-side tenant string with `org_` to align
@@ -3419,19 +3434,19 @@ const CUSTOMER_ID_TABLES = [
3419
3434
  "workflow_registrations",
3420
3435
  "org_settings"
3421
3436
  ];
3422
- async function up$48(db) {
3437
+ async function up$50(db) {
3423
3438
  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);
3424
3439
  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);
3425
3440
  }
3426
- async function down$48(db) {
3441
+ async function down$50(db) {
3427
3442
  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);
3428
3443
  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);
3429
3444
  }
3430
3445
  //#endregion
3431
3446
  //#region src/db/migrations/019_generic_sources_change_notify.ts
3432
3447
  var _019_generic_sources_change_notify_exports = /* @__PURE__ */ __exportAll({
3433
- down: () => down$47,
3434
- up: () => up$47
3448
+ down: () => down$49,
3449
+ up: () => up$49
3435
3450
  });
3436
3451
  /**
3437
3452
  * Add a Postgres trigger on `generic_webhook_sources` that emits
@@ -3454,7 +3469,7 @@ var _019_generic_sources_change_notify_exports = /* @__PURE__ */ __exportAll({
3454
3469
  * (`notify_sources_change()` + `sources_change_trigger`, defined in
3455
3470
  * `001_initial.ts`).
3456
3471
  */
3457
- async function up$47(db) {
3472
+ async function up$49(db) {
3458
3473
  await sql`
3459
3474
  CREATE FUNCTION public.notify_generic_sources_change() RETURNS trigger
3460
3475
  LANGUAGE plpgsql
@@ -3475,15 +3490,15 @@ async function up$47(db) {
3475
3490
  FOR EACH ROW EXECUTE FUNCTION public.notify_generic_sources_change()
3476
3491
  `.execute(db);
3477
3492
  }
3478
- async function down$47(db) {
3493
+ async function down$49(db) {
3479
3494
  await sql`DROP TRIGGER IF EXISTS generic_sources_change_trigger ON public.generic_webhook_sources`.execute(db);
3480
3495
  await sql`DROP FUNCTION IF EXISTS public.notify_generic_sources_change()`.execute(db);
3481
3496
  }
3482
3497
  //#endregion
3483
3498
  //#region src/db/migrations/020_org_settings_dashboard_write_policy.ts
3484
3499
  var _020_org_settings_dashboard_write_policy_exports = /* @__PURE__ */ __exportAll({
3485
- down: () => down$46,
3486
- up: () => up$46
3500
+ down: () => down$48,
3501
+ up: () => up$48
3487
3502
  });
3488
3503
  /**
3489
3504
  * Add `org_settings.dashboard_write_policy jsonb NOT NULL DEFAULT '{}'`.
@@ -3498,7 +3513,7 @@ var _020_org_settings_dashboard_write_policy_exports = /* @__PURE__ */ __exportA
3498
3513
  *
3499
3514
  * Idempotent: a re-run on a DB that already has the column is a no-op.
3500
3515
  */
3501
- async function up$46(db) {
3516
+ async function up$48(db) {
3502
3517
  if ((await sql`
3503
3518
  SELECT EXISTS (
3504
3519
  SELECT 1 FROM information_schema.columns
@@ -3512,7 +3527,7 @@ async function up$46(db) {
3512
3527
  ADD COLUMN dashboard_write_policy jsonb NOT NULL DEFAULT '{}'::jsonb
3513
3528
  `.execute(db);
3514
3529
  }
3515
- async function down$46(db) {
3530
+ async function down$48(db) {
3516
3531
  await sql`
3517
3532
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS dashboard_write_policy
3518
3533
  `.execute(db);
@@ -3520,8 +3535,8 @@ async function down$46(db) {
3520
3535
  //#endregion
3521
3536
  //#region src/db/migrations/021_check_run_tracking.ts
3522
3537
  var _021_check_run_tracking_exports = /* @__PURE__ */ __exportAll({
3523
- down: () => down$45,
3524
- up: () => up$45
3538
+ down: () => down$47,
3539
+ up: () => up$47
3525
3540
  });
3526
3541
  /**
3527
3542
  * Add `check_run_tracking` table for HA-safe check-run state persistence.
@@ -3545,7 +3560,7 @@ var _021_check_run_tracking_exports = /* @__PURE__ */ __exportAll({
3545
3560
  *
3546
3561
  * Idempotent: a re-run on a DB that already has the table is a no-op.
3547
3562
  */
3548
- async function up$45(db) {
3563
+ async function up$47(db) {
3549
3564
  if ((await sql`
3550
3565
  SELECT EXISTS (
3551
3566
  SELECT 1 FROM information_schema.tables
@@ -3576,14 +3591,14 @@ async function up$45(db) {
3576
3591
  WHERE run_id IS NOT NULL
3577
3592
  `.execute(db);
3578
3593
  }
3579
- async function down$45(db) {
3594
+ async function down$47(db) {
3580
3595
  await sql`DROP TABLE IF EXISTS public.check_run_tracking`.execute(db);
3581
3596
  }
3582
3597
  //#endregion
3583
3598
  //#region src/db/migrations/022_scaler_manager_state.ts
3584
3599
  var _022_scaler_manager_state_exports = /* @__PURE__ */ __exportAll({
3585
- down: () => down$44,
3586
- up: () => up$44
3600
+ down: () => down$46,
3601
+ up: () => up$46
3587
3602
  });
3588
3603
  /**
3589
3604
  * Add three tables persisting `ScalerManager` per-coord state:
@@ -3610,7 +3625,7 @@ var _022_scaler_manager_state_exports = /* @__PURE__ */ __exportAll({
3610
3625
  * Idempotent: a re-run on a DB that already has any of these tables
3611
3626
  * leaves the existing one alone.
3612
3627
  */
3613
- async function up$44(db) {
3628
+ async function up$46(db) {
3614
3629
  const tableExists = async (name) => {
3615
3630
  return (await sql`
3616
3631
  SELECT EXISTS (
@@ -3660,7 +3675,7 @@ async function up$44(db) {
3660
3675
  `.execute(db);
3661
3676
  }
3662
3677
  }
3663
- async function down$44(db) {
3678
+ async function down$46(db) {
3664
3679
  await sql`DROP TABLE IF EXISTS public.scaler_reservations`.execute(db);
3665
3680
  await sql`DROP TABLE IF EXISTS public.scaler_agent_jobs`.execute(db);
3666
3681
  await sql`DROP TABLE IF EXISTS public.scaler_spawning_agents`.execute(db);
@@ -3668,8 +3683,8 @@ async function down$44(db) {
3668
3683
  //#endregion
3669
3684
  //#region src/db/migrations/023_dispatch_queue_recovery_deadline.ts
3670
3685
  var _023_dispatch_queue_recovery_deadline_exports = /* @__PURE__ */ __exportAll({
3671
- down: () => down$43,
3672
- up: () => up$43
3686
+ down: () => down$45,
3687
+ up: () => up$45
3673
3688
  });
3674
3689
  /**
3675
3690
  * Add `dispatch_queue.recovery_deadline TIMESTAMPTZ` and
@@ -3693,7 +3708,7 @@ var _023_dispatch_queue_recovery_deadline_exports = /* @__PURE__ */ __exportAll(
3693
3708
  * Idempotent: re-running on a DB that already has either column is a
3694
3709
  * no-op.
3695
3710
  */
3696
- async function up$43(db) {
3711
+ async function up$45(db) {
3697
3712
  const colExists = async (name) => {
3698
3713
  return (await sql`
3699
3714
  SELECT EXISTS (
@@ -3718,7 +3733,7 @@ async function up$43(db) {
3718
3733
  WHERE recovery_deadline IS NOT NULL
3719
3734
  `.execute(db);
3720
3735
  }
3721
- async function down$43(db) {
3736
+ async function down$45(db) {
3722
3737
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_recovery_deadline`.execute(db);
3723
3738
  await sql`
3724
3739
  ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS recovery_agent_id
@@ -3730,8 +3745,8 @@ async function down$43(db) {
3730
3745
  //#endregion
3731
3746
  //#region src/db/migrations/024_dispatch_queue_provisioning_error.ts
3732
3747
  var _024_dispatch_queue_provisioning_error_exports = /* @__PURE__ */ __exportAll({
3733
- down: () => down$42,
3734
- up: () => up$42
3748
+ down: () => down$44,
3749
+ up: () => up$44
3735
3750
  });
3736
3751
  /**
3737
3752
  * Add `dispatch_queue.last_provisioning_error TEXT` recording the most
@@ -3747,7 +3762,7 @@ var _024_dispatch_queue_provisioning_error_exports = /* @__PURE__ */ __exportAll
3747
3762
  *
3748
3763
  * Idempotent: re-running on a DB that already has the column is a no-op.
3749
3764
  */
3750
- async function up$42(db) {
3765
+ async function up$44(db) {
3751
3766
  const colExists = async (name) => {
3752
3767
  return (await sql`
3753
3768
  SELECT EXISTS (
@@ -3763,7 +3778,7 @@ async function up$42(db) {
3763
3778
  ADD COLUMN last_provisioning_error TEXT
3764
3779
  `.execute(db);
3765
3780
  }
3766
- async function down$42(db) {
3781
+ async function down$44(db) {
3767
3782
  await sql`
3768
3783
  ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS last_provisioning_error
3769
3784
  `.execute(db);
@@ -3771,8 +3786,8 @@ async function down$42(db) {
3771
3786
  //#endregion
3772
3787
  //#region src/db/migrations/025_init_failure.ts
3773
3788
  var _025_init_failure_exports = /* @__PURE__ */ __exportAll({
3774
- down: () => down$41,
3775
- up: () => up$41
3789
+ down: () => down$43,
3790
+ up: () => up$43
3776
3791
  });
3777
3792
  /**
3778
3793
  * Add `init_failure jsonb` columns to `execution_runs` and `execution_jobs`.
@@ -3786,7 +3801,7 @@ var _025_init_failure_exports = /* @__PURE__ */ __exportAll({
3786
3801
  * Idempotent: re-running on a DB that already has either column is a no-op
3787
3802
  * for that column.
3788
3803
  */
3789
- async function up$41(db) {
3804
+ async function up$43(db) {
3790
3805
  const colExists = async (table, name) => {
3791
3806
  return (await sql`
3792
3807
  SELECT EXISTS (
@@ -3806,7 +3821,7 @@ async function up$41(db) {
3806
3821
  ADD COLUMN init_failure JSONB DEFAULT NULL
3807
3822
  `.execute(db);
3808
3823
  }
3809
- async function down$41(db) {
3824
+ async function down$43(db) {
3810
3825
  await sql`
3811
3826
  ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS init_failure
3812
3827
  `.execute(db);
@@ -3817,8 +3832,8 @@ async function down$41(db) {
3817
3832
  //#endregion
3818
3833
  //#region src/db/migrations/026_event_log_lockfile_corrupt.ts
3819
3834
  var _026_event_log_lockfile_corrupt_exports = /* @__PURE__ */ __exportAll({
3820
- down: () => down$40,
3821
- up: () => up$40
3835
+ down: () => down$42,
3836
+ up: () => up$42
3822
3837
  });
3823
3838
  /**
3824
3839
  * Extend the event_log.status CHECK constraint with 'lockfile_corrupt' so the
@@ -3827,7 +3842,7 @@ var _026_event_log_lockfile_corrupt_exports = /* @__PURE__ */ __exportAll({
3827
3842
  *
3828
3843
  * Idempotent: the DROP ... IF EXISTS / re-ADD pair re-runs cleanly.
3829
3844
  */
3830
- async function up$40(db) {
3845
+ async function up$42(db) {
3831
3846
  await sql`ALTER TABLE event_log DROP CONSTRAINT IF EXISTS event_log_status_check`.execute(db);
3832
3847
  await sql`
3833
3848
  ALTER TABLE event_log ADD CONSTRAINT event_log_status_check
@@ -3837,7 +3852,7 @@ async function up$40(db) {
3837
3852
  ])))
3838
3853
  `.execute(db);
3839
3854
  }
3840
- async function down$40(db) {
3855
+ async function down$42(db) {
3841
3856
  await sql`ALTER TABLE event_log DROP CONSTRAINT IF EXISTS event_log_status_check`.execute(db);
3842
3857
  await sql`
3843
3858
  ALTER TABLE event_log ADD CONSTRAINT event_log_status_check
@@ -3850,8 +3865,8 @@ async function down$40(db) {
3850
3865
  //#endregion
3851
3866
  //#region src/db/migrations/027_workflow_timeout.ts
3852
3867
  var _027_workflow_timeout_exports = /* @__PURE__ */ __exportAll({
3853
- down: () => down$39,
3854
- up: () => up$39
3868
+ down: () => down$41,
3869
+ up: () => up$41
3855
3870
  });
3856
3871
  /**
3857
3872
  * Add `workflow_timeout_ms integer` to `execution_runs`.
@@ -3869,13 +3884,13 @@ var _027_workflow_timeout_exports = /* @__PURE__ */ __exportAll({
3869
3884
  *
3870
3885
  * Idempotent: re-running on a DB that already has the column is a no-op.
3871
3886
  */
3872
- async function up$39(db) {
3887
+ async function up$41(db) {
3873
3888
  await sql`
3874
3889
  ALTER TABLE public.execution_runs
3875
3890
  ADD COLUMN IF NOT EXISTS workflow_timeout_ms INTEGER DEFAULT NULL
3876
3891
  `.execute(db);
3877
3892
  }
3878
- async function down$39(db) {
3893
+ async function down$41(db) {
3879
3894
  await sql`
3880
3895
  ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS workflow_timeout_ms
3881
3896
  `.execute(db);
@@ -3883,8 +3898,8 @@ async function down$39(db) {
3883
3898
  //#endregion
3884
3899
  //#region src/db/migrations/028_org_settings_user_cache.ts
3885
3900
  var _028_org_settings_user_cache_exports = /* @__PURE__ */ __exportAll({
3886
- down: () => down$38,
3887
- up: () => up$38
3901
+ down: () => down$40,
3902
+ up: () => up$40
3888
3903
  });
3889
3904
  /**
3890
3905
  * Add `org_settings.user_cache_quota_bytes bigint` and
@@ -3913,7 +3928,7 @@ async function columnExists$1(db, column) {
3913
3928
  ) AS exists
3914
3929
  `.execute(db)).rows[0]?.exists ?? false;
3915
3930
  }
3916
- async function up$38(db) {
3931
+ async function up$40(db) {
3917
3932
  if (!await columnExists$1(db, "user_cache_quota_bytes")) await sql`
3918
3933
  ALTER TABLE public.org_settings
3919
3934
  ADD COLUMN user_cache_quota_bytes bigint
@@ -3923,7 +3938,7 @@ async function up$38(db) {
3923
3938
  ADD COLUMN user_cache_ttl_ms bigint
3924
3939
  `.execute(db);
3925
3940
  }
3926
- async function down$38(db) {
3941
+ async function down$40(db) {
3927
3942
  await sql`
3928
3943
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS user_cache_quota_bytes
3929
3944
  `.execute(db);
@@ -3934,8 +3949,8 @@ async function down$38(db) {
3934
3949
  //#endregion
3935
3950
  //#region src/db/migrations/029_dispatch_queue_attempts.ts
3936
3951
  var _029_dispatch_queue_attempts_exports = /* @__PURE__ */ __exportAll({
3937
- down: () => down$37,
3938
- up: () => up$37
3952
+ down: () => down$39,
3953
+ up: () => up$39
3939
3954
  });
3940
3955
  /**
3941
3956
  * Add `dispatch_queue.dispatch_attempts INT NOT NULL DEFAULT 0`.
@@ -3949,7 +3964,7 @@ var _029_dispatch_queue_attempts_exports = /* @__PURE__ */ __exportAll({
3949
3964
  *
3950
3965
  * Idempotent: re-running on a DB that already has the column is a no-op.
3951
3966
  */
3952
- async function up$37(db) {
3967
+ async function up$39(db) {
3953
3968
  if (!((await sql`
3954
3969
  SELECT EXISTS (
3955
3970
  SELECT 1 FROM information_schema.columns
@@ -3962,7 +3977,7 @@ async function up$37(db) {
3962
3977
  ADD COLUMN dispatch_attempts INT NOT NULL DEFAULT 0
3963
3978
  `.execute(db);
3964
3979
  }
3965
- async function down$37(db) {
3980
+ async function down$39(db) {
3966
3981
  await sql`
3967
3982
  ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS dispatch_attempts
3968
3983
  `.execute(db);
@@ -3970,8 +3985,8 @@ async function down$37(db) {
3970
3985
  //#endregion
3971
3986
  //#region src/db/migrations/030_held_runs_env_set_null.ts
3972
3987
  var _030_held_runs_env_set_null_exports = /* @__PURE__ */ __exportAll({
3973
- down: () => down$36,
3974
- up: () => up$36
3988
+ down: () => down$38,
3989
+ up: () => up$38
3975
3990
  });
3976
3991
  /**
3977
3992
  * held_runs.environment_id becomes nullable with ON DELETE SET NULL so
@@ -3982,14 +3997,14 @@ var _030_held_runs_env_set_null_exports = /* @__PURE__ */ __exportAll({
3982
3997
  * Idempotent: dropping the NOT NULL and the constraint are both no-ops on a
3983
3998
  * re-run, and the constraint is re-created with the SET NULL action.
3984
3999
  */
3985
- async function up$36(db) {
4000
+ async function up$38(db) {
3986
4001
  await sql`ALTER TABLE public.held_runs ALTER COLUMN environment_id DROP NOT NULL`.execute(db);
3987
4002
  await sql`ALTER TABLE public.held_runs DROP CONSTRAINT IF EXISTS held_runs_environment_id_fkey`.execute(db);
3988
4003
  await sql`ALTER TABLE public.held_runs
3989
4004
  ADD CONSTRAINT held_runs_environment_id_fkey
3990
4005
  FOREIGN KEY (environment_id) REFERENCES public.environments(id) ON DELETE SET NULL`.execute(db);
3991
4006
  }
3992
- async function down$36(db) {
4007
+ async function down$38(db) {
3993
4008
  await sql`ALTER TABLE public.held_runs DROP CONSTRAINT IF EXISTS held_runs_environment_id_fkey`.execute(db);
3994
4009
  await sql`ALTER TABLE public.held_runs
3995
4010
  ADD CONSTRAINT held_runs_environment_id_fkey
@@ -3999,8 +4014,8 @@ async function down$36(db) {
3999
4014
  //#endregion
4000
4015
  //#region src/db/migrations/031_dispatch_queue_ack_deadline.ts
4001
4016
  var _031_dispatch_queue_ack_deadline_exports = /* @__PURE__ */ __exportAll({
4002
- down: () => down$35,
4003
- up: () => up$35
4017
+ down: () => down$37,
4018
+ up: () => up$37
4004
4019
  });
4005
4020
  /**
4006
4021
  * Add `dispatch_queue.ack_deadline TIMESTAMPTZ` and
@@ -4017,7 +4032,7 @@ var _031_dispatch_queue_ack_deadline_exports = /* @__PURE__ */ __exportAll({
4017
4032
  *
4018
4033
  * Idempotent: re-running on a DB that already has either column is a no-op.
4019
4034
  */
4020
- async function up$35(db) {
4035
+ async function up$37(db) {
4021
4036
  const colExists = async (name) => {
4022
4037
  return (await sql`
4023
4038
  SELECT EXISTS (
@@ -4042,7 +4057,7 @@ async function up$35(db) {
4042
4057
  WHERE ack_deadline IS NOT NULL
4043
4058
  `.execute(db);
4044
4059
  }
4045
- async function down$35(db) {
4060
+ async function down$37(db) {
4046
4061
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_ack_deadline`.execute(db);
4047
4062
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS ack_agent_id`.execute(db);
4048
4063
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS ack_deadline`.execute(db);
@@ -4050,8 +4065,8 @@ async function down$35(db) {
4050
4065
  //#endregion
4051
4066
  //#region src/db/migrations/032_org_settings_dispatch_ack_timeout.ts
4052
4067
  var _032_org_settings_dispatch_ack_timeout_exports = /* @__PURE__ */ __exportAll({
4053
- down: () => down$34,
4054
- up: () => up$34
4068
+ down: () => down$36,
4069
+ up: () => up$36
4055
4070
  });
4056
4071
  /**
4057
4072
  * Add `org_settings.dispatch_ack_timeout_ms BIGINT` (nullable).
@@ -4063,7 +4078,7 @@ var _032_org_settings_dispatch_ack_timeout_exports = /* @__PURE__ */ __exportAll
4063
4078
  *
4064
4079
  * Idempotent: a re-run on a DB that already has the column is a no-op.
4065
4080
  */
4066
- async function up$34(db) {
4081
+ async function up$36(db) {
4067
4082
  if ((await sql`
4068
4083
  SELECT EXISTS (
4069
4084
  SELECT 1 FROM information_schema.columns
@@ -4077,7 +4092,7 @@ async function up$34(db) {
4077
4092
  ADD COLUMN dispatch_ack_timeout_ms BIGINT
4078
4093
  `.execute(db);
4079
4094
  }
4080
- async function down$34(db) {
4095
+ async function down$36(db) {
4081
4096
  await sql`
4082
4097
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS dispatch_ack_timeout_ms
4083
4098
  `.execute(db);
@@ -4085,8 +4100,8 @@ async function down$34(db) {
4085
4100
  //#endregion
4086
4101
  //#region src/db/migrations/033_org_settings_approval.ts
4087
4102
  var _033_org_settings_approval_exports = /* @__PURE__ */ __exportAll({
4088
- down: () => down$33,
4089
- up: () => up$33
4103
+ down: () => down$35,
4104
+ up: () => up$35
4090
4105
  });
4091
4106
  /**
4092
4107
  * Add the two approval-policy columns to `org_settings`:
@@ -4103,7 +4118,7 @@ var _033_org_settings_approval_exports = /* @__PURE__ */ __exportAll({
4103
4118
  * and the orchestrator admin route. Idempotent: a re-run on a DB that already
4104
4119
  * has the columns is a no-op (each column is guarded independently).
4105
4120
  */
4106
- async function up$33(db) {
4121
+ async function up$35(db) {
4107
4122
  const colExists = async (column) => {
4108
4123
  return (await sql`
4109
4124
  SELECT EXISTS (
@@ -4123,7 +4138,7 @@ async function up$33(db) {
4123
4138
  ADD COLUMN allow_self_approval BOOLEAN NOT NULL DEFAULT true
4124
4139
  `.execute(db);
4125
4140
  }
4126
- async function down$33(db) {
4141
+ async function down$35(db) {
4127
4142
  await sql`
4128
4143
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS approval_expiry_seconds
4129
4144
  `.execute(db);
@@ -4134,8 +4149,8 @@ async function down$33(db) {
4134
4149
  //#endregion
4135
4150
  //#region src/db/migrations/034_held_runs_generalize.ts
4136
4151
  var _034_held_runs_generalize_exports = /* @__PURE__ */ __exportAll({
4137
- down: () => down$32,
4138
- up: () => up$32
4152
+ down: () => down$34,
4153
+ up: () => up$34
4139
4154
  });
4140
4155
  /**
4141
4156
  * Generalize `held_runs` from an environment-only hold into the unified
@@ -4157,7 +4172,7 @@ var _034_held_runs_generalize_exports = /* @__PURE__ */ __exportAll({
4157
4172
  * New `held_run_approvals` table: one row per approver decision, FK to
4158
4173
  * `held_runs.id` (uuid) with ON DELETE CASCADE.
4159
4174
  */
4160
- async function up$32(db) {
4175
+ async function up$34(db) {
4161
4176
  const colExists = async (column) => {
4162
4177
  return (await sql`
4163
4178
  SELECT EXISTS (
@@ -4190,7 +4205,7 @@ async function up$32(db) {
4190
4205
  ON public.held_run_approvals USING btree (held_run_id)
4191
4206
  `.execute(db);
4192
4207
  }
4193
- async function down$32(db) {
4208
+ async function down$34(db) {
4194
4209
  await sql`DROP TABLE IF EXISTS public.held_run_approvals`.execute(db);
4195
4210
  await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS approval_requirement`.execute(db);
4196
4211
  await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS trigger_source`.execute(db);
@@ -4200,8 +4215,8 @@ async function down$32(db) {
4200
4215
  //#endregion
4201
4216
  //#region src/db/migrations/035_pending_workflow_contexts.ts
4202
4217
  var _035_pending_workflow_contexts_exports = /* @__PURE__ */ __exportAll({
4203
- down: () => down$31,
4204
- up: () => up$31
4218
+ down: () => down$33,
4219
+ up: () => up$33
4205
4220
  });
4206
4221
  /**
4207
4222
  * Pending workflow dispatch context — backs resume of a workflow whose install
@@ -4210,7 +4225,7 @@ var _035_pending_workflow_contexts_exports = /* @__PURE__ */ __exportAll({
4210
4225
  * wait-timer expiry, concurrency slot free). The row is deleted once the resume
4211
4226
  * dispatch has been kicked off.
4212
4227
  */
4213
- async function up$31(db) {
4228
+ async function up$33(db) {
4214
4229
  await sql`
4215
4230
  CREATE TABLE IF NOT EXISTS public.pending_workflow_contexts (
4216
4231
  run_id text PRIMARY KEY,
@@ -4220,14 +4235,14 @@ async function up$31(db) {
4220
4235
  )
4221
4236
  `.execute(db);
4222
4237
  }
4223
- async function down$31(db) {
4238
+ async function down$33(db) {
4224
4239
  await sql`DROP TABLE IF EXISTS public.pending_workflow_contexts`.execute(db);
4225
4240
  }
4226
4241
  //#endregion
4227
4242
  //#region src/db/migrations/036_attestations.ts
4228
4243
  var _036_attestations_exports = /* @__PURE__ */ __exportAll({
4229
- down: () => down$30,
4230
- up: () => up$30
4244
+ down: () => down$32,
4245
+ up: () => up$32
4231
4246
  });
4232
4247
  /**
4233
4248
  * Add the `attestations` table for build-provenance bundles.
@@ -4240,7 +4255,7 @@ var _036_attestations_exports = /* @__PURE__ */ __exportAll({
4240
4255
  *
4241
4256
  * Idempotent: a re-run on a DB that already has the table is a no-op.
4242
4257
  */
4243
- async function up$30(db) {
4258
+ async function up$32(db) {
4244
4259
  if ((await sql`
4245
4260
  SELECT EXISTS (
4246
4261
  SELECT 1 FROM information_schema.tables
@@ -4266,14 +4281,14 @@ async function up$30(db) {
4266
4281
  ON public.attestations (run_id, job_id)
4267
4282
  `.execute(db);
4268
4283
  }
4269
- async function down$30(db) {
4284
+ async function down$32(db) {
4270
4285
  await sql`DROP TABLE IF EXISTS public.attestations`.execute(db);
4271
4286
  }
4272
4287
  //#endregion
4273
4288
  //#region src/db/migrations/037_generic_sources_provider_type_local.ts
4274
4289
  var _037_generic_sources_provider_type_local_exports = /* @__PURE__ */ __exportAll({
4275
- down: () => down$29,
4276
- up: () => up$29
4290
+ down: () => down$31,
4291
+ up: () => up$31
4277
4292
  });
4278
4293
  /**
4279
4294
  * Replace the `generic_webhook_sources.provider_type` CHECK constraint so it
@@ -4290,7 +4305,7 @@ var _037_generic_sources_provider_type_local_exports = /* @__PURE__ */ __exportA
4290
4305
  * Idempotent: the constraint is dropped IF EXISTS and recreated; the data
4291
4306
  * backfill is a plain UPDATE that is a no-op once no `'internal'` rows remain.
4292
4307
  */
4293
- async function up$29(db) {
4308
+ async function up$31(db) {
4294
4309
  await sql`
4295
4310
  ALTER TABLE public.generic_webhook_sources
4296
4311
  DROP CONSTRAINT IF EXISTS generic_webhook_sources_provider_type_check
@@ -4306,7 +4321,7 @@ async function up$29(db) {
4306
4321
  CHECK (provider_type = ANY (ARRAY['generic'::text, 'local'::text]))
4307
4322
  `.execute(db);
4308
4323
  }
4309
- async function down$29(db) {
4324
+ async function down$31(db) {
4310
4325
  await sql`
4311
4326
  ALTER TABLE public.generic_webhook_sources
4312
4327
  DROP CONSTRAINT IF EXISTS generic_webhook_sources_provider_type_check
@@ -4325,8 +4340,8 @@ async function down$29(db) {
4325
4340
  //#endregion
4326
4341
  //#region src/db/migrations/038_remote_sources.ts
4327
4342
  var _038_remote_sources_exports = /* @__PURE__ */ __exportAll({
4328
- down: () => down$28,
4329
- up: () => up$28
4343
+ down: () => down$30,
4344
+ up: () => up$30
4330
4345
  });
4331
4346
  /**
4332
4347
  * `remote_sources` anchors a Platform-relayed `kici run remote` to its real
@@ -4338,7 +4353,7 @@ var _038_remote_sources_exports = /* @__PURE__ */ __exportAll({
4338
4353
  *
4339
4354
  * Idempotent: a re-run on a DB that already has the table is a no-op.
4340
4355
  */
4341
- async function up$28(db) {
4356
+ async function up$30(db) {
4342
4357
  if ((await sql`
4343
4358
  SELECT EXISTS (
4344
4359
  SELECT 1 FROM information_schema.tables
@@ -4357,14 +4372,14 @@ async function up$28(db) {
4357
4372
  )
4358
4373
  `.execute(db);
4359
4374
  }
4360
- async function down$28(db) {
4375
+ async function down$30(db) {
4361
4376
  await sql`DROP TABLE IF EXISTS public.remote_sources`.execute(db);
4362
4377
  }
4363
4378
  //#endregion
4364
4379
  //#region src/db/migrations/039_host_roster.ts
4365
4380
  var _039_host_roster_exports = /* @__PURE__ */ __exportAll({
4366
- down: () => down$27,
4367
- up: () => up$27
4381
+ down: () => down$29,
4382
+ up: () => up$29
4368
4383
  });
4369
4384
  /**
4370
4385
  * `host_roster` is KiCI's declared inventory: one durable row per agent the
@@ -4381,7 +4396,7 @@ var _039_host_roster_exports = /* @__PURE__ */ __exportAll({
4381
4396
  *
4382
4397
  * Idempotent: a re-run on a DB that already has the table is a no-op.
4383
4398
  */
4384
- async function up$27(db) {
4399
+ async function up$29(db) {
4385
4400
  if ((await sql`
4386
4401
  SELECT EXISTS (
4387
4402
  SELECT 1 FROM information_schema.tables
@@ -4411,14 +4426,14 @@ async function up$27(db) {
4411
4426
  await sql`CREATE INDEX idx_host_roster_reap
4412
4427
  ON public.host_roster (lifecycle_class, last_seen)`.execute(db);
4413
4428
  }
4414
- async function down$27(db) {
4429
+ async function down$29(db) {
4415
4430
  await sql`DROP TABLE IF EXISTS public.host_roster`.execute(db);
4416
4431
  }
4417
4432
  //#endregion
4418
4433
  //#region src/db/migrations/040_runsonall_pin.ts
4419
4434
  var _040_runsonall_pin_exports = /* @__PURE__ */ __exportAll({
4420
- down: () => down$26,
4421
- up: () => up$26
4435
+ down: () => down$28,
4436
+ up: () => up$28
4422
4437
  });
4423
4438
  /**
4424
4439
  * Add the `runsOnAll` host fan-out columns:
@@ -4445,7 +4460,7 @@ async function colExists$11(db, table, name) {
4445
4460
  ) AS exists
4446
4461
  `.execute(db)).rows[0]?.exists ?? false;
4447
4462
  }
4448
- async function up$26(db) {
4463
+ async function up$28(db) {
4449
4464
  if (!await colExists$11(db, "dispatch_queue", "pinned_agent_id")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN pinned_agent_id TEXT`.execute(db);
4450
4465
  if (!await colExists$11(db, "execution_jobs", "base_job_name")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN base_job_name TEXT`.execute(db);
4451
4466
  if (!await colExists$11(db, "execution_jobs", "variant_kind")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN variant_kind TEXT`.execute(db);
@@ -4456,7 +4471,7 @@ async function up$26(db) {
4456
4471
  WHERE pinned_agent_id IS NOT NULL
4457
4472
  `.execute(db);
4458
4473
  }
4459
- async function down$26(db) {
4474
+ async function down$28(db) {
4460
4475
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_pinned_agent`.execute(db);
4461
4476
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS pinned_agent_id`.execute(db);
4462
4477
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS variant_label`.execute(db);
@@ -4466,8 +4481,8 @@ async function down$26(db) {
4466
4481
  //#endregion
4467
4482
  //#region src/db/migrations/041_wave_gated.ts
4468
4483
  var _041_wave_gated_exports = /* @__PURE__ */ __exportAll({
4469
- down: () => down$25,
4470
- up: () => up$25
4484
+ down: () => down$27,
4485
+ up: () => up$27
4471
4486
  });
4472
4487
  /**
4473
4488
  * Add the rolling fan-out wave-gate columns:
@@ -4497,7 +4512,7 @@ async function colExists$10(db, table, name) {
4497
4512
  ) AS exists
4498
4513
  `.execute(db)).rows[0]?.exists ?? false;
4499
4514
  }
4500
- async function up$25(db) {
4515
+ async function up$27(db) {
4501
4516
  if (!await colExists$10(db, "execution_jobs", "wave_gated")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_gated boolean NOT NULL DEFAULT false`.execute(db);
4502
4517
  if (!await colExists$10(db, "execution_jobs", "wave_max_parallel")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_max_parallel integer`.execute(db);
4503
4518
  if (!await colExists$10(db, "execution_jobs", "wave_fail_fast")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_fail_fast boolean`.execute(db);
@@ -4506,7 +4521,7 @@ async function up$25(db) {
4506
4521
  ON public.execution_jobs (run_id, base_job_name, wave_gated)
4507
4522
  `.execute(db);
4508
4523
  }
4509
- async function down$25(db) {
4524
+ async function down$27(db) {
4510
4525
  await sql`DROP INDEX IF EXISTS public.idx_execution_jobs_wave`.execute(db);
4511
4526
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS wave_fail_fast`.execute(db);
4512
4527
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS wave_max_parallel`.execute(db);
@@ -4515,8 +4530,8 @@ async function down$25(db) {
4515
4530
  //#endregion
4516
4531
  //#region src/db/migrations/042_dispatch_queue_patterns.ts
4517
4532
  var _042_dispatch_queue_patterns_exports = /* @__PURE__ */ __exportAll({
4518
- down: () => down$24,
4519
- up: () => up$24
4533
+ down: () => down$26,
4534
+ up: () => up$26
4520
4535
  });
4521
4536
  /**
4522
4537
  * Add pattern columns to dispatch_queue. Exact labels stay in runs_on_labels /
@@ -4542,19 +4557,19 @@ async function colExists$9(db, table, name) {
4542
4557
  ) AS exists
4543
4558
  `.execute(db)).rows[0]?.exists ?? false;
4544
4559
  }
4545
- async function up$24(db) {
4560
+ async function up$26(db) {
4546
4561
  if (!await colExists$9(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);
4547
4562
  if (!await colExists$9(db, "dispatch_queue", "exclude_patterns")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN exclude_patterns jsonb NOT NULL DEFAULT '[]'::jsonb`.execute(db);
4548
4563
  }
4549
- async function down$24(db) {
4564
+ async function down$26(db) {
4550
4565
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS exclude_patterns`.execute(db);
4551
4566
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS runs_on_patterns`.execute(db);
4552
4567
  }
4553
4568
  //#endregion
4554
4569
  //#region src/db/migrations/043_rerouted_to_peer.ts
4555
4570
  var _043_rerouted_to_peer_exports = /* @__PURE__ */ __exportAll({
4556
- down: () => down$23,
4557
- up: () => up$23
4571
+ down: () => down$25,
4572
+ up: () => up$25
4558
4573
  });
4559
4574
  /**
4560
4575
  * Add a nullable `rerouted_to_peer text` marker to execution_jobs. Non-null
@@ -4575,17 +4590,17 @@ async function colExists$8(db, table, name) {
4575
4590
  ) AS exists
4576
4591
  `.execute(db)).rows[0]?.exists ?? false;
4577
4592
  }
4578
- async function up$23(db) {
4593
+ async function up$25(db) {
4579
4594
  if (!await colExists$8(db, "execution_jobs", "rerouted_to_peer")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN rerouted_to_peer text`.execute(db);
4580
4595
  }
4581
- async function down$23(db) {
4596
+ async function down$25(db) {
4582
4597
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS rerouted_to_peer`.execute(db);
4583
4598
  }
4584
4599
  //#endregion
4585
4600
  //#region src/db/migrations/044_check_mode.ts
4586
4601
  var _044_check_mode_exports = /* @__PURE__ */ __exportAll({
4587
- down: () => down$22,
4588
- up: () => up$22
4602
+ down: () => down$24,
4603
+ up: () => up$24
4589
4604
  });
4590
4605
  /**
4591
4606
  * Add idempotent check-mode columns:
@@ -4612,13 +4627,13 @@ async function colExists$7(db, table, name) {
4612
4627
  ) AS exists
4613
4628
  `.execute(db)).rows[0]?.exists ?? false;
4614
4629
  }
4615
- async function up$22(db) {
4630
+ async function up$24(db) {
4616
4631
  if (!await colExists$7(db, "execution_runs", "check_mode")) await sql`ALTER TABLE public.execution_runs ADD COLUMN check_mode text`.execute(db);
4617
4632
  if (!await colExists$7(db, "execution_steps", "check_outcome")) await sql`ALTER TABLE public.execution_steps ADD COLUMN check_outcome text`.execute(db);
4618
4633
  if (!await colExists$7(db, "execution_steps", "drift_summary")) await sql`ALTER TABLE public.execution_steps ADD COLUMN drift_summary text`.execute(db);
4619
4634
  if (!await colExists$7(db, "execution_steps", "drift")) await sql`ALTER TABLE public.execution_steps ADD COLUMN drift jsonb`.execute(db);
4620
4635
  }
4621
- async function down$22(db) {
4636
+ async function down$24(db) {
4622
4637
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS drift`.execute(db);
4623
4638
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS drift_summary`.execute(db);
4624
4639
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS check_outcome`.execute(db);
@@ -4627,8 +4642,8 @@ async function down$22(db) {
4627
4642
  //#endregion
4628
4643
  //#region src/db/migrations/045_host_properties.ts
4629
4644
  var _045_host_properties_exports = /* @__PURE__ */ __exportAll({
4630
- down: () => down$21,
4631
- up: () => up$21
4645
+ down: () => down$23,
4646
+ up: () => up$23
4632
4647
  });
4633
4648
  /**
4634
4649
  * Add the typed host-vars dimension to the host roster:
@@ -4642,18 +4657,18 @@ var _045_host_properties_exports = /* @__PURE__ */ __exportAll({
4642
4657
  * Idempotent (`ADD COLUMN IF NOT EXISTS`): re-running on a DB that already has
4643
4658
  * the column is a no-op. Staging data is preserved (additive column).
4644
4659
  */
4645
- async function up$21(db) {
4660
+ async function up$23(db) {
4646
4661
  await sql`ALTER TABLE public.host_roster
4647
4662
  ADD COLUMN IF NOT EXISTS host_properties jsonb NOT NULL DEFAULT '{}'::jsonb`.execute(db);
4648
4663
  }
4649
- async function down$21(db) {
4664
+ async function down$23(db) {
4650
4665
  await sql`ALTER TABLE public.host_roster DROP COLUMN IF EXISTS host_properties`.execute(db);
4651
4666
  }
4652
4667
  //#endregion
4653
4668
  //#region src/db/migrations/046_join_token_consumed_by_instance.ts
4654
4669
  var _046_join_token_consumed_by_instance_exports = /* @__PURE__ */ __exportAll({
4655
- down: () => down$20,
4656
- up: () => up$20
4670
+ down: () => down$22,
4671
+ up: () => up$22
4657
4672
  });
4658
4673
  /**
4659
4674
  * Record the joining peer's instanceId at first consumption of a join token:
@@ -4668,18 +4683,18 @@ var _046_join_token_consumed_by_instance_exports = /* @__PURE__ */ __exportAll({
4668
4683
  * Idempotent (`ADD COLUMN IF NOT EXISTS`): re-running on a DB that already has
4669
4684
  * the column is a no-op. Staging data is preserved (additive nullable column).
4670
4685
  */
4671
- async function up$20(db) {
4686
+ async function up$22(db) {
4672
4687
  await sql`ALTER TABLE public.join_tokens
4673
4688
  ADD COLUMN IF NOT EXISTS consumed_by_instance text`.execute(db);
4674
4689
  }
4675
- async function down$20(db) {
4690
+ async function down$22(db) {
4676
4691
  await sql`ALTER TABLE public.join_tokens DROP COLUMN IF EXISTS consumed_by_instance`.execute(db);
4677
4692
  }
4678
4693
  //#endregion
4679
4694
  //#region src/db/migrations/047_needs_run_on.ts
4680
4695
  var _047_needs_run_on_exports = /* @__PURE__ */ __exportAll({
4681
- down: () => down$19,
4682
- up: () => up$19
4696
+ down: () => down$21,
4697
+ up: () => up$21
4683
4698
  });
4684
4699
  /**
4685
4700
  * Migrate `execution_job_needs` from the binary `if_failed` policy to a
@@ -4715,7 +4730,7 @@ async function colExists$6(db, table, name) {
4715
4730
  `.execute(db)).rows[0]?.exists ?? false;
4716
4731
  }
4717
4732
  const SUCCESS_ONLY_DEFAULT = `'${SUCCESS_ONLY_JSON}'`;
4718
- async function up$19(db) {
4733
+ async function up$21(db) {
4719
4734
  if (!await colExists$6(db, "execution_job_needs", "run_on")) await sql`
4720
4735
  ALTER TABLE public.execution_job_needs
4721
4736
  ADD COLUMN run_on text NOT NULL DEFAULT ${sql.raw(SUCCESS_ONLY_DEFAULT)}
@@ -4734,7 +4749,7 @@ async function up$19(db) {
4734
4749
  await sql`ALTER TABLE public.execution_job_needs DROP COLUMN if_failed`.execute(db);
4735
4750
  }
4736
4751
  }
4737
- async function down$19(db) {
4752
+ async function down$21(db) {
4738
4753
  if (!await colExists$6(db, "execution_job_needs", "if_failed")) await sql`
4739
4754
  ALTER TABLE public.execution_job_needs
4740
4755
  ADD COLUMN if_failed text NOT NULL DEFAULT 'skip'
@@ -4750,8 +4765,8 @@ async function down$19(db) {
4750
4765
  //#endregion
4751
4766
  //#region src/db/migrations/048_host_reboot_pending.ts
4752
4767
  var _048_host_reboot_pending_exports = /* @__PURE__ */ __exportAll({
4753
- down: () => down$18,
4754
- up: () => up$18
4768
+ down: () => down$20,
4769
+ up: () => up$20
4755
4770
  });
4756
4771
  /**
4757
4772
  * Add `host_roster.reboot_pending_until timestamptz NULL` — the persisted
@@ -4768,18 +4783,18 @@ var _048_host_reboot_pending_exports = /* @__PURE__ */ __exportAll({
4768
4783
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
4769
4784
  * preserved.
4770
4785
  */
4771
- async function up$18(db) {
4786
+ async function up$20(db) {
4772
4787
  await sql`ALTER TABLE public.host_roster
4773
4788
  ADD COLUMN IF NOT EXISTS reboot_pending_until timestamptz`.execute(db);
4774
4789
  }
4775
- async function down$18(db) {
4790
+ async function down$20(db) {
4776
4791
  await sql`ALTER TABLE public.host_roster DROP COLUMN IF EXISTS reboot_pending_until`.execute(db);
4777
4792
  }
4778
4793
  //#endregion
4779
4794
  //#region src/db/migrations/049_held_runs_payload.ts
4780
4795
  var _049_held_runs_payload_exports = /* @__PURE__ */ __exportAll({
4781
- down: () => down$17,
4782
- up: () => up$17
4796
+ down: () => down$19,
4797
+ up: () => up$19
4783
4798
  });
4784
4799
  /**
4785
4800
  * Add `held_runs.payload jsonb NULL` — the drift payload captured when a
@@ -4791,18 +4806,18 @@ var _049_held_runs_payload_exports = /* @__PURE__ */ __exportAll({
4791
4806
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
4792
4807
  * preserved.
4793
4808
  */
4794
- async function up$17(db) {
4809
+ async function up$19(db) {
4795
4810
  await sql`ALTER TABLE public.held_runs
4796
4811
  ADD COLUMN IF NOT EXISTS payload jsonb`.execute(db);
4797
4812
  }
4798
- async function down$17(db) {
4813
+ async function down$19(db) {
4799
4814
  await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS payload`.execute(db);
4800
4815
  }
4801
4816
  //#endregion
4802
4817
  //#region src/db/migrations/050_sources_slug.ts
4803
4818
  var _050_sources_slug_exports = /* @__PURE__ */ __exportAll({
4804
- down: () => down$16,
4805
- up: () => up$16
4819
+ down: () => down$18,
4820
+ up: () => up$18
4806
4821
  });
4807
4822
  /**
4808
4823
  * Add `sources.slug TEXT NULL` — the GitHub App slug (the URL-safe identifier
@@ -4817,18 +4832,18 @@ var _050_sources_slug_exports = /* @__PURE__ */ __exportAll({
4817
4832
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
4818
4833
  * preserved.
4819
4834
  */
4820
- async function up$16(db) {
4835
+ async function up$18(db) {
4821
4836
  await sql`ALTER TABLE public.sources
4822
4837
  ADD COLUMN IF NOT EXISTS slug text`.execute(db);
4823
4838
  }
4824
- async function down$16(db) {
4839
+ async function down$18(db) {
4825
4840
  await sql`ALTER TABLE public.sources DROP COLUMN IF EXISTS slug`.execute(db);
4826
4841
  }
4827
4842
  //#endregion
4828
4843
  //#region src/db/migrations/051_binding_host_pattern.ts
4829
4844
  var _051_binding_host_pattern_exports = /* @__PURE__ */ __exportAll({
4830
- down: () => down$15,
4831
- up: () => up$15
4845
+ down: () => down$17,
4846
+ up: () => up$17
4832
4847
  });
4833
4848
  /**
4834
4849
  * Add a per-host dimension to environment secret bindings:
@@ -4844,7 +4859,7 @@ var _051_binding_host_pattern_exports = /* @__PURE__ */ __exportAll({
4844
4859
  * Idempotent: re-running on a DB that already has the column / index is a no-op.
4845
4860
  * Additive — staging data is preserved.
4846
4861
  */
4847
- async function up$15(db) {
4862
+ async function up$17(db) {
4848
4863
  await sql`ALTER TABLE public.environment_bindings
4849
4864
  ADD COLUMN IF NOT EXISTS host_pattern text NOT NULL DEFAULT '**'`.execute(db);
4850
4865
  await sql`ALTER TABLE public.environment_bindings
@@ -4852,7 +4867,7 @@ async function up$15(db) {
4852
4867
  await sql`CREATE UNIQUE INDEX IF NOT EXISTS environment_bindings_env_scope_host_uniq
4853
4868
  ON public.environment_bindings (environment_id, scope_pattern, host_pattern)`.execute(db);
4854
4869
  }
4855
- async function down$15(db) {
4870
+ async function down$17(db) {
4856
4871
  await sql`DROP INDEX IF EXISTS public.environment_bindings_env_scope_host_uniq`.execute(db);
4857
4872
  await sql`ALTER TABLE public.environment_bindings
4858
4873
  DROP COLUMN IF EXISTS host_pattern`.execute(db);
@@ -4862,8 +4877,8 @@ async function down$15(db) {
4862
4877
  //#endregion
4863
4878
  //#region src/db/migrations/052_host_reach_metadata.ts
4864
4879
  var _052_host_reach_metadata_exports = /* @__PURE__ */ __exportAll({
4865
- down: () => down$14,
4866
- up: () => up$14
4880
+ down: () => down$16,
4881
+ up: () => up$16
4867
4882
  });
4868
4883
  /**
4869
4884
  * Add pre-agent reach metadata to the host roster so a declared host (no agent
@@ -4880,14 +4895,14 @@ var _052_host_reach_metadata_exports = /* @__PURE__ */ __exportAll({
4880
4895
  * behaves exactly as before. Idempotent (`ADD COLUMN IF NOT EXISTS`); additive,
4881
4896
  * so staging data is preserved.
4882
4897
  */
4883
- async function up$14(db) {
4898
+ async function up$16(db) {
4884
4899
  await sql`ALTER TABLE public.host_roster
4885
4900
  ADD COLUMN IF NOT EXISTS address text,
4886
4901
  ADD COLUMN IF NOT EXISTS ssh_user text,
4887
4902
  ADD COLUMN IF NOT EXISTS ssh_port integer,
4888
4903
  ADD COLUMN IF NOT EXISTS ssh_key_secret text`.execute(db);
4889
4904
  }
4890
- async function down$14(db) {
4905
+ async function down$16(db) {
4891
4906
  await sql`ALTER TABLE public.host_roster
4892
4907
  DROP COLUMN IF EXISTS address,
4893
4908
  DROP COLUMN IF EXISTS ssh_user,
@@ -4897,8 +4912,8 @@ async function down$14(db) {
4897
4912
  //#endregion
4898
4913
  //#region src/db/migrations/053_agent_token_single_use.ts
4899
4914
  var _053_agent_token_single_use_exports = /* @__PURE__ */ __exportAll({
4900
- down: () => down$13,
4901
- up: () => up$13
4915
+ down: () => down$15,
4916
+ up: () => up$15
4902
4917
  });
4903
4918
  /**
4904
4919
  * Add a single-use marker to agent tokens for the bootstrap (init-runner)
@@ -4913,19 +4928,19 @@ var _053_agent_token_single_use_exports = /* @__PURE__ */ __exportAll({
4913
4928
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
4914
4929
  * preserved.
4915
4930
  */
4916
- async function up$13(db) {
4931
+ async function up$15(db) {
4917
4932
  await sql`ALTER TABLE public.agent_tokens
4918
4933
  ADD COLUMN IF NOT EXISTS consumed_at timestamptz`.execute(db);
4919
4934
  }
4920
- async function down$13(db) {
4935
+ async function down$15(db) {
4921
4936
  await sql`ALTER TABLE public.agent_tokens
4922
4937
  DROP COLUMN IF EXISTS consumed_at`.execute(db);
4923
4938
  }
4924
4939
  //#endregion
4925
4940
  //#region src/db/migrations/054_local_working_tree.ts
4926
4941
  var _054_local_working_tree_exports = /* @__PURE__ */ __exportAll({
4927
- down: () => down$12,
4928
- up: () => up$12
4942
+ down: () => down$14,
4943
+ up: () => up$14
4929
4944
  });
4930
4945
  /**
4931
4946
  * Mark runs that executed an uploaded local working tree (`kici run remote`):
@@ -4938,19 +4953,19 @@ var _054_local_working_tree_exports = /* @__PURE__ */ __exportAll({
4938
4953
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive with a default, so staging
4939
4954
  * data is preserved.
4940
4955
  */
4941
- async function up$12(db) {
4956
+ async function up$14(db) {
4942
4957
  await sql`ALTER TABLE public.execution_runs
4943
4958
  ADD COLUMN IF NOT EXISTS local_working_tree boolean NOT NULL DEFAULT false`.execute(db);
4944
4959
  }
4945
- async function down$12(db) {
4960
+ async function down$14(db) {
4946
4961
  await sql`ALTER TABLE public.execution_runs
4947
4962
  DROP COLUMN IF EXISTS local_working_tree`.execute(db);
4948
4963
  }
4949
4964
  //#endregion
4950
4965
  //#region src/db/migrations/055_agent_token_mandatory_labels.ts
4951
4966
  var _055_agent_token_mandatory_labels_exports = /* @__PURE__ */ __exportAll({
4952
- down: () => down$11,
4953
- up: () => up$11
4967
+ down: () => down$13,
4968
+ up: () => up$13
4954
4969
  });
4955
4970
  /**
4956
4971
  * Add a token-bound mandatory-label taint to agent tokens:
@@ -4966,19 +4981,19 @@ var _055_agent_token_mandatory_labels_exports = /* @__PURE__ */ __exportAll({
4966
4981
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
4967
4982
  * preserved.
4968
4983
  */
4969
- async function up$11(db) {
4984
+ async function up$13(db) {
4970
4985
  await sql`ALTER TABLE public.agent_tokens
4971
4986
  ADD COLUMN IF NOT EXISTS mandatory_labels text`.execute(db);
4972
4987
  }
4973
- async function down$11(db) {
4988
+ async function down$13(db) {
4974
4989
  await sql`ALTER TABLE public.agent_tokens
4975
4990
  DROP COLUMN IF EXISTS mandatory_labels`.execute(db);
4976
4991
  }
4977
4992
  //#endregion
4978
4993
  //#region src/db/migrations/056_execution_jobs_environments.ts
4979
4994
  var _056_execution_jobs_environments_exports = /* @__PURE__ */ __exportAll({
4980
- down: () => down$10,
4981
- up: () => up$10
4995
+ down: () => down$12,
4996
+ up: () => up$12
4982
4997
  });
4983
4998
  /**
4984
4999
  * Add a per-job bound deployment-environment list to `execution_jobs`:
@@ -4993,19 +5008,19 @@ var _056_execution_jobs_environments_exports = /* @__PURE__ */ __exportAll({
4993
5008
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
4994
5009
  * preserved.
4995
5010
  */
4996
- async function up$10(db) {
5011
+ async function up$12(db) {
4997
5012
  await sql`ALTER TABLE public.execution_jobs
4998
5013
  ADD COLUMN IF NOT EXISTS environments text`.execute(db);
4999
5014
  }
5000
- async function down$10(db) {
5015
+ async function down$12(db) {
5001
5016
  await sql`ALTER TABLE public.execution_jobs
5002
5017
  DROP COLUMN IF EXISTS environments`.execute(db);
5003
5018
  }
5004
5019
  //#endregion
5005
5020
  //#region src/db/migrations/057_step_concurrency.ts
5006
5021
  var _057_step_concurrency_exports = /* @__PURE__ */ __exportAll({
5007
- down: () => down$9,
5008
- up: () => up$9
5022
+ down: () => down$11,
5023
+ up: () => up$11
5009
5024
  });
5010
5025
  /**
5011
5026
  * Add parallel step-group concurrency columns to `execution_steps`:
@@ -5028,19 +5043,19 @@ async function colExists$5(db, table, name) {
5028
5043
  ) AS exists
5029
5044
  `.execute(db)).rows[0]?.exists ?? false;
5030
5045
  }
5031
- async function up$9(db) {
5046
+ async function up$11(db) {
5032
5047
  if (!await colExists$5(db, "execution_steps", "concurrency_kind")) await sql`ALTER TABLE public.execution_steps ADD COLUMN concurrency_kind text`.execute(db);
5033
5048
  if (!await colExists$5(db, "execution_steps", "group_id")) await sql`ALTER TABLE public.execution_steps ADD COLUMN group_id text`.execute(db);
5034
5049
  }
5035
- async function down$9(db) {
5050
+ async function down$11(db) {
5036
5051
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS group_id`.execute(db);
5037
5052
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS concurrency_kind`.execute(db);
5038
5053
  }
5039
5054
  //#endregion
5040
5055
  //#region src/db/migrations/058_access_log_agent_label.ts
5041
5056
  var _058_access_log_agent_label_exports = /* @__PURE__ */ __exportAll({
5042
- down: () => down$8,
5043
- up: () => up$8
5057
+ down: () => down$10,
5058
+ up: () => up$10
5044
5059
  });
5045
5060
  /**
5046
5061
  * Add `access_log.agent_label text` — the human-set name of the agent that
@@ -5060,17 +5075,17 @@ async function colExists$4(db, table, name) {
5060
5075
  ) AS exists
5061
5076
  `.execute(db)).rows[0]?.exists ?? false;
5062
5077
  }
5063
- async function up$8(db) {
5078
+ async function up$10(db) {
5064
5079
  if (!await colExists$4(db, "access_log", "agent_label")) await sql`ALTER TABLE public.access_log ADD COLUMN agent_label text`.execute(db);
5065
5080
  }
5066
- async function down$8(db) {
5081
+ async function down$10(db) {
5067
5082
  await sql`ALTER TABLE public.access_log DROP COLUMN IF EXISTS agent_label`.execute(db);
5068
5083
  }
5069
5084
  //#endregion
5070
5085
  //#region src/db/migrations/059_attestation_verdict.ts
5071
5086
  var _059_attestation_verdict_exports = /* @__PURE__ */ __exportAll({
5072
- down: () => down$7,
5073
- up: () => up$7
5087
+ down: () => down$9,
5088
+ up: () => up$9
5074
5089
  });
5075
5090
  /**
5076
5091
  * Add server-side verification verdict columns to `attestations`, plus the
@@ -5097,7 +5112,7 @@ async function colExists$3(db, table, name) {
5097
5112
  ) AS exists
5098
5113
  `.execute(db)).rows[0]?.exists ?? false;
5099
5114
  }
5100
- async function up$7(db) {
5115
+ async function up$9(db) {
5101
5116
  if (await colExists$3(db, "attestations", "verify_status")) return;
5102
5117
  await sql`
5103
5118
  ALTER TABLE public.attestations
@@ -5110,7 +5125,7 @@ async function up$7(db) {
5110
5125
  await sql`CREATE INDEX idx_attestations_verify_status ON public.attestations (verify_status)`.execute(db);
5111
5126
  await sql`CREATE INDEX idx_attestations_created_at ON public.attestations (created_at)`.execute(db);
5112
5127
  }
5113
- async function down$7(db) {
5128
+ async function down$9(db) {
5114
5129
  await sql`DROP INDEX IF EXISTS idx_attestations_created_at`.execute(db);
5115
5130
  await sql`DROP INDEX IF EXISTS idx_attestations_verify_status`.execute(db);
5116
5131
  await sql`DROP INDEX IF EXISTS idx_attestations_subject_name`.execute(db);
@@ -5125,8 +5140,8 @@ async function down$7(db) {
5125
5140
  //#endregion
5126
5141
  //#region src/db/migrations/060_run_trigger_actor.ts
5127
5142
  var _060_run_trigger_actor_exports = /* @__PURE__ */ __exportAll({
5128
- down: () => down$6,
5129
- up: () => up$6
5143
+ down: () => down$8,
5144
+ up: () => up$8
5130
5145
  });
5131
5146
  /**
5132
5147
  * Add the triggering-actor columns to `execution_runs`:
@@ -5154,12 +5169,12 @@ async function colExists$2(db, table, name) {
5154
5169
  ) AS exists
5155
5170
  `.execute(db)).rows[0]?.exists ?? false;
5156
5171
  }
5157
- async function up$6(db) {
5172
+ async function up$8(db) {
5158
5173
  if (!await colExists$2(db, "execution_runs", "trigger_actor_provider")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_provider text`.execute(db);
5159
5174
  if (!await colExists$2(db, "execution_runs", "trigger_actor_username")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_username text`.execute(db);
5160
5175
  if (!await colExists$2(db, "execution_runs", "trigger_actor_user_id")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_user_id text`.execute(db);
5161
5176
  }
5162
- async function down$6(db) {
5177
+ async function down$8(db) {
5163
5178
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS trigger_actor_provider`.execute(db);
5164
5179
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS trigger_actor_username`.execute(db);
5165
5180
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS trigger_actor_user_id`.execute(db);
@@ -5167,8 +5182,8 @@ async function down$6(db) {
5167
5182
  //#endregion
5168
5183
  //#region src/db/migrations/061_execution_runs_environment_id.ts
5169
5184
  var _061_execution_runs_environment_id_exports = /* @__PURE__ */ __exportAll({
5170
- down: () => down$5,
5171
- up: () => up$5
5185
+ down: () => down$7,
5186
+ up: () => up$7
5172
5187
  });
5173
5188
  /**
5174
5189
  * Add `environment_id` to `execution_runs` so environment run-history can be
@@ -5204,7 +5219,7 @@ async function colExists$1(db, table, name) {
5204
5219
  ) AS exists
5205
5220
  `.execute(db)).rows[0]?.exists ?? false;
5206
5221
  }
5207
- async function up$5(db) {
5222
+ async function up$7(db) {
5208
5223
  if (!await colExists$1(db, "execution_runs", "environment_id")) await sql`
5209
5224
  ALTER TABLE public.execution_runs
5210
5225
  ADD COLUMN environment_id uuid
@@ -5226,15 +5241,15 @@ async function up$5(db) {
5226
5241
  WHERE e2.type = 'fixed' AND e2.name = er.environment) = 1
5227
5242
  `.execute(db);
5228
5243
  }
5229
- async function down$5(db) {
5244
+ async function down$7(db) {
5230
5245
  await sql`DROP INDEX IF EXISTS idx_execution_runs_environment_id`.execute(db);
5231
5246
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS environment_id`.execute(db);
5232
5247
  }
5233
5248
  //#endregion
5234
5249
  //#region src/db/migrations/062_execution_runs_agent_label.ts
5235
5250
  var _062_execution_runs_agent_label_exports = /* @__PURE__ */ __exportAll({
5236
- down: () => down$4,
5237
- up: () => up$4
5251
+ down: () => down$6,
5252
+ up: () => up$6
5238
5253
  });
5239
5254
  /**
5240
5255
  * Add the agent-provenance columns to `execution_runs`:
@@ -5259,19 +5274,19 @@ async function colExists(db, table, name) {
5259
5274
  ) AS exists
5260
5275
  `.execute(db)).rows[0]?.exists ?? false;
5261
5276
  }
5262
- async function up$4(db) {
5277
+ async function up$6(db) {
5263
5278
  if (!await colExists(db, "execution_runs", "triggered_by_agent_label")) await sql`ALTER TABLE public.execution_runs ADD COLUMN triggered_by_agent_label text`.execute(db);
5264
5279
  if (!await colExists(db, "execution_runs", "cancelled_by_agent_label")) await sql`ALTER TABLE public.execution_runs ADD COLUMN cancelled_by_agent_label text`.execute(db);
5265
5280
  }
5266
- async function down$4(db) {
5281
+ async function down$6(db) {
5267
5282
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS triggered_by_agent_label`.execute(db);
5268
5283
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS cancelled_by_agent_label`.execute(db);
5269
5284
  }
5270
5285
  //#endregion
5271
5286
  //#region src/db/migrations/063_access_log_agent_label_index.ts
5272
5287
  var _063_access_log_agent_label_index_exports = /* @__PURE__ */ __exportAll({
5273
- down: () => down$3,
5274
- up: () => up$3
5288
+ down: () => down$5,
5289
+ up: () => up$5
5275
5290
  });
5276
5291
  /**
5277
5292
  * Index `access_log.agent_label` (column added by migration 058) so the
@@ -5279,17 +5294,17 @@ var _063_access_log_agent_label_index_exports = /* @__PURE__ */ __exportAll({
5279
5294
  * the dashboard "agent name" filter) does an indexed exact-match lookup
5280
5295
  * instead of a scan. Idempotent.
5281
5296
  */
5282
- async function up$3(db) {
5297
+ async function up$5(db) {
5283
5298
  await sql`CREATE INDEX IF NOT EXISTS access_log_agent_label_idx ON public.access_log (agent_label)`.execute(db);
5284
5299
  }
5285
- async function down$3(db) {
5300
+ async function down$5(db) {
5286
5301
  await sql`DROP INDEX IF EXISTS access_log_agent_label_idx`.execute(db);
5287
5302
  }
5288
5303
  //#endregion
5289
5304
  //#region src/db/migrations/064_execution_jobs_skipped_environments.ts
5290
5305
  var _064_execution_jobs_skipped_environments_exports = /* @__PURE__ */ __exportAll({
5291
- down: () => down$2,
5292
- up: () => up$2
5306
+ down: () => down$4,
5307
+ up: () => up$4
5293
5308
  });
5294
5309
  /**
5295
5310
  * Add the test-run skipped-environment columns to `execution_jobs`:
@@ -5304,13 +5319,13 @@ var _064_execution_jobs_skipped_environments_exports = /* @__PURE__ */ __exportA
5304
5319
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
5305
5320
  * preserved.
5306
5321
  */
5307
- async function up$2(db) {
5322
+ async function up$4(db) {
5308
5323
  await sql`ALTER TABLE public.execution_jobs
5309
5324
  ADD COLUMN IF NOT EXISTS skipped_environments text`.execute(db);
5310
5325
  await sql`ALTER TABLE public.execution_jobs
5311
5326
  ADD COLUMN IF NOT EXISTS env_warning text`.execute(db);
5312
5327
  }
5313
- async function down$2(db) {
5328
+ async function down$4(db) {
5314
5329
  await sql`ALTER TABLE public.execution_jobs
5315
5330
  DROP COLUMN IF EXISTS skipped_environments`.execute(db);
5316
5331
  await sql`ALTER TABLE public.execution_jobs
@@ -5319,8 +5334,8 @@ async function down$2(db) {
5319
5334
  //#endregion
5320
5335
  //#region src/db/migrations/065_pending_attestations.ts
5321
5336
  var _065_pending_attestations_exports = /* @__PURE__ */ __exportAll({
5322
- down: () => down$1,
5323
- up: () => up$1
5337
+ down: () => down$3,
5338
+ up: () => up$3
5324
5339
  });
5325
5340
  /**
5326
5341
  * Add the `pending_attestations` deferred-attestation outbox and an idempotency
@@ -5340,7 +5355,7 @@ var _065_pending_attestations_exports = /* @__PURE__ */ __exportAll({
5340
5355
  *
5341
5356
  * Idempotent: guarded on table existence.
5342
5357
  */
5343
- async function up$1(db) {
5358
+ async function up$3(db) {
5344
5359
  if ((await sql`
5345
5360
  SELECT EXISTS (
5346
5361
  SELECT 1 FROM information_schema.tables
@@ -5379,15 +5394,15 @@ async function up$1(db) {
5379
5394
  ON public.attestations (run_id, job_id, subject_digest)
5380
5395
  `.execute(db);
5381
5396
  }
5382
- async function down$1(db) {
5397
+ async function down$3(db) {
5383
5398
  await sql`DROP INDEX IF EXISTS uq_attestations_run_job_subject`.execute(db);
5384
5399
  await sql`DROP TABLE IF EXISTS public.pending_attestations`.execute(db);
5385
5400
  }
5386
5401
  //#endregion
5387
5402
  //#region src/db/migrations/066_pending_attestations_rejected.ts
5388
5403
  var _066_pending_attestations_rejected_exports = /* @__PURE__ */ __exportAll({
5389
- down: () => down,
5390
- up: () => up
5404
+ down: () => down$2,
5405
+ up: () => up$2
5391
5406
  });
5392
5407
  /**
5393
5408
  * Add `rejected_at` to `pending_attestations`: the terminal-rejection marker for
@@ -5398,14 +5413,14 @@ var _066_pending_attestations_rejected_exports = /* @__PURE__ */ __exportAll({
5398
5413
  *
5399
5414
  * Idempotent: guarded on column existence.
5400
5415
  */
5401
- async function up(db) {
5416
+ async function up$2(db) {
5402
5417
  if (await columnExists(db, "pending_attestations", "rejected_at")) return;
5403
5418
  await sql`
5404
5419
  ALTER TABLE public.pending_attestations
5405
5420
  ADD COLUMN rejected_at TIMESTAMPTZ
5406
5421
  `.execute(db);
5407
5422
  }
5408
- async function down(db) {
5423
+ async function down$2(db) {
5409
5424
  if (!await columnExists(db, "pending_attestations", "rejected_at")) return;
5410
5425
  await sql`
5411
5426
  ALTER TABLE public.pending_attestations
@@ -5421,6 +5436,117 @@ async function columnExists(db, table, column) {
5421
5436
  `.execute(db)).rows[0]?.exists ?? false;
5422
5437
  }
5423
5438
  //#endregion
5439
+ //#region src/db/migrations/067_environments_to_contexts.ts
5440
+ var _067_environments_to_contexts_exports = /* @__PURE__ */ __exportAll({
5441
+ down: () => down$1,
5442
+ up: () => up$1
5443
+ });
5444
+ /**
5445
+ * Rename the named-policy object from "environment" to "context" across the
5446
+ * orchestrator schema. Data-preserving rename-in-place (never drop/recreate):
5447
+ *
5448
+ * Tables:
5449
+ * - `environments` → `contexts`
5450
+ * - `environment_bindings` → `context_bindings`
5451
+ * - `environment_variables` → `context_variables`
5452
+ * - `environment_source_overrides` → `context_source_overrides`
5453
+ *
5454
+ * Columns:
5455
+ * - `context_bindings.environment_id` → `context_id`
5456
+ * - `context_variables.environment_id` → `context_id`
5457
+ * - `context_source_overrides.environment_id` → `context_id`
5458
+ * - `held_runs.environment_id` → `context_id`
5459
+ * - `execution_runs.environment` → `context`
5460
+ * - `execution_runs.environment_id` → `context_id`
5461
+ * - `execution_jobs.environments` → `contexts`
5462
+ * - `execution_jobs.skipped_environments` → `skipped_contexts`
5463
+ *
5464
+ * Index:
5465
+ * - `idx_execution_runs_environment_id` → `idx_execution_runs_context_id`
5466
+ *
5467
+ * Held-run enum values + defaults: `held_runs.queue_type` /
5468
+ * `held_runs.trigger_source` default `'environment'` → `'context'` and existing
5469
+ * `'environment'` rows are migrated to `'context'` (the `HeldRunQueueType` value
5470
+ * rename).
5471
+ *
5472
+ * Foreign keys and remaining constraints/indexes follow the renamed tables and
5473
+ * columns automatically (Postgres references them by identity, not name), so
5474
+ * only the one hand-named index above needs an explicit rename.
5475
+ */
5476
+ async function up$1(db) {
5477
+ await sql`ALTER TABLE public.environments RENAME TO contexts`.execute(db);
5478
+ await sql`ALTER TABLE public.environment_bindings RENAME TO context_bindings`.execute(db);
5479
+ await sql`ALTER TABLE public.environment_variables RENAME TO context_variables`.execute(db);
5480
+ await sql`ALTER TABLE public.environment_source_overrides RENAME TO context_source_overrides`.execute(db);
5481
+ await sql`ALTER TABLE public.context_bindings RENAME COLUMN environment_id TO context_id`.execute(db);
5482
+ await sql`ALTER TABLE public.context_variables RENAME COLUMN environment_id TO context_id`.execute(db);
5483
+ await sql`ALTER TABLE public.context_source_overrides RENAME COLUMN environment_id TO context_id`.execute(db);
5484
+ await sql`ALTER TABLE public.held_runs RENAME COLUMN environment_id TO context_id`.execute(db);
5485
+ await sql`ALTER TABLE public.execution_runs RENAME COLUMN environment TO context`.execute(db);
5486
+ await sql`ALTER TABLE public.execution_runs RENAME COLUMN environment_id TO context_id`.execute(db);
5487
+ await sql`ALTER TABLE public.execution_jobs RENAME COLUMN environments TO contexts`.execute(db);
5488
+ await sql`ALTER TABLE public.execution_jobs RENAME COLUMN skipped_environments TO skipped_contexts`.execute(db);
5489
+ await sql`ALTER INDEX IF EXISTS idx_execution_runs_environment_id RENAME TO idx_execution_runs_context_id`.execute(db);
5490
+ await sql`UPDATE public.held_runs SET queue_type = 'context' WHERE queue_type = 'environment'`.execute(db);
5491
+ await sql`UPDATE public.held_runs SET trigger_source = 'context' WHERE trigger_source = 'environment'`.execute(db);
5492
+ await sql`ALTER TABLE public.held_runs ALTER COLUMN queue_type SET DEFAULT 'context'`.execute(db);
5493
+ await sql`ALTER TABLE public.held_runs ALTER COLUMN trigger_source SET DEFAULT 'context'`.execute(db);
5494
+ }
5495
+ async function down$1(db) {
5496
+ await sql`ALTER TABLE public.held_runs ALTER COLUMN trigger_source SET DEFAULT 'environment'`.execute(db);
5497
+ await sql`ALTER TABLE public.held_runs ALTER COLUMN queue_type SET DEFAULT 'environment'`.execute(db);
5498
+ await sql`UPDATE public.held_runs SET trigger_source = 'environment' WHERE trigger_source = 'context'`.execute(db);
5499
+ await sql`UPDATE public.held_runs SET queue_type = 'environment' WHERE queue_type = 'context'`.execute(db);
5500
+ await sql`ALTER INDEX IF EXISTS idx_execution_runs_context_id RENAME TO idx_execution_runs_environment_id`.execute(db);
5501
+ await sql`ALTER TABLE public.execution_jobs RENAME COLUMN skipped_contexts TO skipped_environments`.execute(db);
5502
+ await sql`ALTER TABLE public.execution_jobs RENAME COLUMN contexts TO environments`.execute(db);
5503
+ await sql`ALTER TABLE public.execution_runs RENAME COLUMN context_id TO environment_id`.execute(db);
5504
+ await sql`ALTER TABLE public.execution_runs RENAME COLUMN context TO environment`.execute(db);
5505
+ await sql`ALTER TABLE public.held_runs RENAME COLUMN context_id TO environment_id`.execute(db);
5506
+ await sql`ALTER TABLE public.context_source_overrides RENAME COLUMN context_id TO environment_id`.execute(db);
5507
+ await sql`ALTER TABLE public.context_variables RENAME COLUMN context_id TO environment_id`.execute(db);
5508
+ await sql`ALTER TABLE public.context_bindings RENAME COLUMN context_id TO environment_id`.execute(db);
5509
+ await sql`ALTER TABLE public.context_source_overrides RENAME TO environment_source_overrides`.execute(db);
5510
+ await sql`ALTER TABLE public.context_variables RENAME TO environment_variables`.execute(db);
5511
+ await sql`ALTER TABLE public.context_bindings RENAME TO environment_bindings`.execute(db);
5512
+ await sql`ALTER TABLE public.contexts RENAME TO environments`.execute(db);
5513
+ }
5514
+ //#endregion
5515
+ //#region src/db/migrations/068_request_idempotency.ts
5516
+ var _068_request_idempotency_exports = /* @__PURE__ */ __exportAll({
5517
+ down: () => down,
5518
+ up: () => up
5519
+ });
5520
+ /**
5521
+ * Add the `request_idempotency` claim table: a `request_id`-keyed record that
5522
+ * makes run-minting dashboard requests (`run.rerun.request`,
5523
+ * `run.manual_schedule.request`) idempotent on the Platform `requestId`. HA
5524
+ * coordinator siblings share one orchestrator DB, so when the Platform relay
5525
+ * fails over and re-sends the same request to a sibling, the atomic `INSERT …
5526
+ * ON CONFLICT DO NOTHING` on `request_id` lets exactly one coordinator win —
5527
+ * the loser returns the winner's `new_run_id` instead of minting a second run.
5528
+ * Rows are pruned after 1h (far past the ~10s request budget) by the periodic
5529
+ * cleanup tick.
5530
+ *
5531
+ * Idempotent: guarded on table existence.
5532
+ */
5533
+ async function up(db) {
5534
+ if (await tableExists(db, "request_idempotency")) return;
5535
+ 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();
5536
+ await db.schema.createIndex("idx_request_idempotency_created_at").on("request_idempotency").column("created_at").execute();
5537
+ }
5538
+ async function down(db) {
5539
+ await db.schema.dropTable("request_idempotency").ifExists().execute();
5540
+ }
5541
+ async function tableExists(db, table) {
5542
+ return (await sql`
5543
+ SELECT EXISTS (
5544
+ SELECT 1 FROM information_schema.tables
5545
+ WHERE table_schema = 'public' AND table_name = ${table}
5546
+ ) AS exists
5547
+ `.execute(db)).rows[0]?.exists ?? false;
5548
+ }
5549
+ //#endregion
5424
5550
  //#region src/db/migration-provider.ts
5425
5551
  function createMigrationProvider() {
5426
5552
  return { async getMigrations() {
@@ -5490,7 +5616,9 @@ function createMigrationProvider() {
5490
5616
  "063_access_log_agent_label_index": _063_access_log_agent_label_index_exports,
5491
5617
  "064_execution_jobs_skipped_environments": _064_execution_jobs_skipped_environments_exports,
5492
5618
  "065_pending_attestations": _065_pending_attestations_exports,
5493
- "066_pending_attestations_rejected": _066_pending_attestations_rejected_exports
5619
+ "066_pending_attestations_rejected": _066_pending_attestations_rejected_exports,
5620
+ "067_environments_to_contexts": _067_environments_to_contexts_exports,
5621
+ "068_request_idempotency": _068_request_idempotency_exports
5494
5622
  };
5495
5623
  } };
5496
5624
  }
@@ -6020,7 +6148,16 @@ const LocalSourceConfigSchema = z.object({
6020
6148
  repoBasePath: z.string().min(1).refine((p) => path.isAbsolute(p), { message: "repoBasePath must be an absolute path" }),
6021
6149
  /** Optional network clone base (git:// / http://) for remote agents that do
6022
6150
  * not share the orchestrator's filesystem. When unset, file:// is used. */
6023
- cloneUrlBase: z.string().min(1).optional()
6151
+ cloneUrlBase: z.string().min(1).optional(),
6152
+ /**
6153
+ * In-place profile: the `repoBasePath` IS the operator's real working tree,
6154
+ * so a dispatched run skips the source-pack `__build__` job and each job runs
6155
+ * the tree directly (the agent, under its `KICI_IN_PLACE` profile, uses the
6156
+ * `file://` path as workDir with no clone). Set only by the local dev plane
6157
+ * for a `kici run --local --in-place` run. Only meaningful for `file://`
6158
+ * (no `cloneUrlBase`) local sources on a host-sharing scaler.
6159
+ */
6160
+ inPlace: z.boolean().optional()
6024
6161
  }).strict();
6025
6162
  //#endregion
6026
6163
  //#region src/cli/commands/local-trigger.ts
@@ -7845,6 +7982,9 @@ const baseSchema = z.object({
7845
7982
  secretKeyOld: z.string().optional(),
7846
7983
  secretKeyFileOld: z.string().optional(),
7847
7984
  bootstrapAdminToken: z.string().optional(),
7985
+ independentSecrets: z.enum(["true", "false"]).default("false").transform((v) => v === "true"),
7986
+ independentIdentity: z.enum(["true", "false"]).default("false").transform((v) => v === "true"),
7987
+ devIdentityKeyFile: z.string().optional(),
7848
7988
  pgCustomerSecrets: z.enum(["true", "false"]).default("true").transform((v) => v === "true"),
7849
7989
  agentAuth: z.enum(["token", "none"]).default("token"),
7850
7990
  agentTokenTtlMs: z.coerce.number().default(36e5),
@@ -7885,6 +8025,23 @@ const baseSchema = z.object({
7885
8025
  * unless `KICI_TEST_MODE=1`. Production deployments leave this unset.
7886
8026
  */
7887
8027
  testMintDeferAudience: z.string().optional(),
8028
+ /**
8029
+ * **Test-only.** When set (and `KICI_TEST_MODE=1`), the orchestrator forces
8030
+ * the *initial* agent provenance mint to DEFER for any job whose requested
8031
+ * OIDC `audience` equals this value (same as `testMintDeferAudience`), AND the
8032
+ * retrier's later re-mint to TERMINALLY REJECT it — so an E2E can exercise the
8033
+ * `markRejected` → gauge-exclusion → `--include-rejected` re-arm cycle with a
8034
+ * REAL run. Ignored unless `KICI_TEST_MODE=1`. Production leaves this unset.
8035
+ */
8036
+ testMintRejectAudience: z.string().optional(),
8037
+ /**
8038
+ * **Test-only.** When set (and `KICI_TEST_MODE=1`), `handleRerunRequest`
8039
+ * sleeps this many milliseconds before invoking `onRerun`, so an HA E2E can
8040
+ * make the first coordinator slow enough that the Platform relay fails over
8041
+ * to a sibling — exercising the `requestId` idempotency claim. Ignored unless
8042
+ * `KICI_TEST_MODE=1`. Production deployments leave this unset.
8043
+ */
8044
+ testRerunDelayMs: z.coerce.number().optional(),
7888
8045
  eventLogMaxPayloadBytes: z.coerce.number().default(5 * 1024 * 1024),
7889
8046
  logLevel: z.enum([
7890
8047
  "debug",
@@ -8055,6 +8212,9 @@ const envDef = defineEnv({
8055
8212
  secretKeyOld: "KICI_SECRET_KEY_OLD",
8056
8213
  secretKeyFileOld: "KICI_SECRET_KEY_FILE_OLD",
8057
8214
  bootstrapAdminToken: "KICI_BOOTSTRAP_ADMIN_TOKEN",
8215
+ independentSecrets: "KICI_INDEPENDENT_SECRETS",
8216
+ independentIdentity: "KICI_INDEPENDENT_IDENTITY",
8217
+ devIdentityKeyFile: "KICI_DEV_IDENTITY_KEY_FILE",
8058
8218
  pgCustomerSecrets: "KICI_PG_CUSTOMER_SECRETS",
8059
8219
  agentAuth: "KICI_AGENT_AUTH",
8060
8220
  agentTokenTtlMs: "KICI_AGENT_TOKEN_TTL_MS",
@@ -8075,6 +8235,8 @@ const envDef = defineEnv({
8075
8235
  testMode: "KICI_TEST_MODE",
8076
8236
  testEventFailFirstN: "KICI_TEST_EVENT_FAIL_FIRST_N",
8077
8237
  testMintDeferAudience: "KICI_TEST_MINT_DEFER_AUDIENCE",
8238
+ testMintRejectAudience: "KICI_TEST_MINT_REJECT_AUDIENCE",
8239
+ testRerunDelayMs: "KICI_TEST_RERUN_DELAY_MS",
8078
8240
  eventLogMaxPayloadBytes: "KICI_EVENT_LOG_MAX_PAYLOAD_BYTES",
8079
8241
  logLevel: "KICI_LOG_LEVEL",
8080
8242
  nodeEnv: "NODE_ENV",
@@ -8765,6 +8927,16 @@ function createProvenanceTrustRoot(opts = {}) {
8765
8927
  const ttlMs = opts.ttlMs ?? 5 * 6e4;
8766
8928
  let issuer = opts.issuer ?? null;
8767
8929
  let cache = null;
8930
+ if (opts.staticJwks) {
8931
+ const staticJwks = opts.staticJwks;
8932
+ return {
8933
+ getIssuer: () => issuer,
8934
+ getJwks: async () => staticJwks,
8935
+ setIssuer: (next) => {
8936
+ issuer = next;
8937
+ }
8938
+ };
8939
+ }
8768
8940
  async function fetchJwks() {
8769
8941
  if (!issuer) return null;
8770
8942
  try {
@@ -9643,7 +9815,7 @@ function registerDiagnoseCommand(program, getClient) {
9643
9815
  * Register the debug-bundle command on the CLI program.
9644
9816
  */
9645
9817
  function registerDebugBundleCommand(program, getClient) {
9646
- program.command("debug-bundle").description("Generate a diagnostic debug bundle ZIP for troubleshooting").option("-o, --output <path>", "Output ZIP file path", `kici-debug-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}.zip`).option("--log-dir <path>", "Directory with rotated *.log files to include (defaults to $KICI_LOG_DIR)").option("--log-window <hours>", "Hours of log history to include in the bundle", (value) => parseInt(value, 10), 4).option("--fleet", "Collect logs from every node in the cluster (server-side fan-out)").option("--list", "With --fleet: print the fleet topology and exit (no collection)").option("--json", "With --fleet --list: emit the topology as JSON").option("--pick [selectors]", "With --fleet: comma-separated selectors (id/host*/label:k=v); bare flag opens an interactive picker on a TTY").option("--fleet-timeout <seconds>", "Per-node deadline for --fleet", (value) => parseInt(value, 10), 60).action(async (opts) => {
9818
+ program.command("debug-bundle").description("Generate a diagnostic debug bundle ZIP for troubleshooting").addOption(new Option("-o, --output <path>", "Output ZIP file path").default(`kici-debug-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}.zip`, "kici-debug-<timestamp>.zip")).option("--log-dir <path>", "Directory with rotated *.log files to include (defaults to $KICI_LOG_DIR)").option("--log-window <hours>", "Hours of log history to include in the bundle", (value) => parseInt(value, 10), 4).option("--fleet", "Collect logs from every node in the cluster (server-side fan-out)").option("--list", "With --fleet: print the fleet topology and exit (no collection)").option("--json", "With --fleet --list: emit the topology as JSON").option("--pick [selectors]", "With --fleet: comma-separated selectors (id/host*/label:k=v); bare flag opens an interactive picker on a TTY").option("--fleet-timeout <seconds>", "Per-node deadline for --fleet", (value) => parseInt(value, 10), 60).action(async (opts) => {
9647
9819
  try {
9648
9820
  const client = getClient();
9649
9821
  if (opts.fleet) {
@@ -11186,7 +11358,21 @@ var init_windows = __esmMin((() => {
11186
11358
  init_registry();
11187
11359
  init_platform_detect();
11188
11360
  WindowsServiceManager = class {
11361
+ /**
11362
+ * Check whether a Windows service is currently registered.
11363
+ * `sc.exe query` exits non-zero (execSync throws) when the service does
11364
+ * not exist; exit 0 means it exists (possibly pending-delete).
11365
+ */
11366
+ serviceExists(name) {
11367
+ try {
11368
+ execSync(`sc.exe query ${name}`, { stdio: "pipe" });
11369
+ return true;
11370
+ } catch {
11371
+ return false;
11372
+ }
11373
+ }
11189
11374
  async install(config) {
11375
+ if (this.serviceExists(config.name)) await this.uninstall(config);
11190
11376
  const depMeta = getDepMetadata("shawl");
11191
11377
  const depPath = await ensureDep(depMeta, getCacheDir());
11192
11378
  const shawlExe = path.join(depPath, depMeta.extractPath);
@@ -15179,7 +15365,7 @@ function registerMaintenanceCommands(program, getClient) {
15179
15365
  });
15180
15366
  }
15181
15367
  //#endregion
15182
- //#region src/cli/commands/environment.ts
15368
+ //#region src/cli/commands/context.ts
15183
15369
  function resolveDirectDbUrl$4(explicit) {
15184
15370
  return explicit ?? process.env.KICI_DATABASE_URL ?? null;
15185
15371
  }
@@ -15218,9 +15404,9 @@ function summarizePolicy(env) {
15218
15404
  if (env.minimum_trust) parts.push(`trust=${env.minimum_trust}`);
15219
15405
  return parts.length === 0 ? "-" : parts.join(" ");
15220
15406
  }
15221
- function printEnvironmentTable(rows) {
15407
+ function printContextTable(rows) {
15222
15408
  if (rows.length === 0) {
15223
- console.log("No environments found.");
15409
+ console.log("No contexts found.");
15224
15410
  return;
15225
15411
  }
15226
15412
  const header = [
@@ -15240,8 +15426,8 @@ function printEnvironmentTable(rows) {
15240
15426
  console.log(header.map((h, i) => pad(h, widths[i])).join(" "));
15241
15427
  for (const row of data) console.log(row.map((c, i) => pad(c, widths[i])).join(" "));
15242
15428
  }
15243
- function printShowEnvironment(res) {
15244
- const e = res.environment;
15429
+ function printShowContext(res) {
15430
+ const e = res.context;
15245
15431
  console.log(`id: ${e.id}`);
15246
15432
  console.log(`org: ${e.org_id}`);
15247
15433
  console.log(`name: ${e.name}`);
@@ -15260,9 +15446,9 @@ function printShowEnvironment(res) {
15260
15446
  }
15261
15447
  } else console.log("bindings: none");
15262
15448
  }
15263
- function registerEnvironmentCommands(program, getClient) {
15264
- const env = program.command("environment").description("Environment management (dual-mode)");
15265
- env.command("create").description("Upsert an environment (idempotent by org+name)").requiredOption("--org <id>", "Org ID").requiredOption("--name <name>", "Environment name").option("--type <t>", "Environment type (fixed|glob|template)", "fixed").option("--glob-pattern <pattern>", "Glob pattern matched against declared environment names (required with --type glob)").option("--enabled <bool>", "Enabled flag (true|false)", "true").option("--branch-restrictions <json>", "JSON array of allowed branches (e.g. '[\"main\"]')").option("--required-reviewers <csv>", "CSV of required reviewer user IDs (or empty to clear)").option("--wait-timer <seconds>", "Wait timer before release (seconds)").option("--hold-expiry <seconds>", "Hold expiry TTL (seconds)").option("--minimum-trust <level>", "Minimum trust (known|trusted)").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15449
+ function registerContextCommands(program, getClient) {
15450
+ const env = program.command("context").description("Context management (dual-mode)");
15451
+ env.command("create").description("Upsert a context (idempotent by org+name)").requiredOption("--org <id>", "Org ID").requiredOption("--name <name>", "Context name").option("--type <t>", "Context type (fixed|glob|template)", "fixed").option("--glob-pattern <pattern>", "Glob pattern matched against declared context names (required with --type glob)").option("--enabled <bool>", "Enabled flag (true|false)", "true").option("--branch-restrictions <json>", "JSON array of allowed branches (e.g. '[\"main\"]')").option("--required-reviewers <csv>", "CSV of required reviewer user IDs (or empty to clear)").option("--wait-timer <seconds>", "Wait timer before release (seconds)").option("--hold-expiry <seconds>", "Hold expiry TTL (seconds)").option("--minimum-trust <level>", "Minimum trust (known|trusted)").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15266
15452
  try {
15267
15453
  if (opts.type === "glob" && !opts.globPattern) throw new Error("--type glob requires --glob-pattern <pattern>");
15268
15454
  if (opts.type !== "glob" && opts.globPattern !== void 0) throw new Error("--glob-pattern requires --type glob");
@@ -15284,40 +15470,40 @@ function registerEnvironmentCommands(program, getClient) {
15284
15470
  minimumTrust: opts.minimumTrust
15285
15471
  };
15286
15472
  const dbUrl = resolveDirectDbUrl$4(opts.databaseUrl);
15287
- const result = dbUrl ? await seedEnvironmentDirect(dbUrl, payload) : await getClient().post("/api/v1/admin/environments", payload);
15473
+ const result = dbUrl ? await seedContextDirect(dbUrl, payload) : await getClient().post("/api/v1/admin/contexts", payload);
15288
15474
  if (opts.json) console.log(JSON.stringify(result));
15289
- else console.log(`environment create: envId=${result.envId} created=${result.created}${dbUrl ? " (direct)" : ""}`);
15475
+ else console.log(`context create: envId=${result.envId} created=${result.created}${dbUrl ? " (direct)" : ""}`);
15290
15476
  } catch (err) {
15291
15477
  console.error(`Error: ${toErrorMessage(err)}`);
15292
15478
  process.exit(1);
15293
15479
  }
15294
15480
  });
15295
- env.command("bind").description("Upsert an environment_bindings row (scope_pattern → environment)").requiredOption("--org <id>", "Org ID").requiredOption("--env <name>", "Environment name").requiredOption("--scope <pattern>", "Scope pattern (e.g. \"staging\" or \"aws/prod/**\")").option("--host <pattern>", "Host selector (exact/glob/regex over agentId/host/labels); \"**\" = all hosts", "**").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15481
+ env.command("bind").description("Upsert a context_bindings row (scope_pattern → context)").requiredOption("--org <id>", "Org ID").requiredOption("--env <name>", "Context name").requiredOption("--scope <pattern>", "Scope pattern (e.g. \"staging\" or \"aws/prod/**\")").option("--host <pattern>", "Host selector (exact/glob/regex over agentId/host/labels); \"**\" = all hosts", "**").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15296
15482
  try {
15297
15483
  const dbUrl = resolveDirectDbUrl$4(opts.databaseUrl);
15298
15484
  const payload = {
15299
15485
  orgId: opts.org,
15300
- envName: opts.env,
15486
+ contextName: opts.env,
15301
15487
  scopePattern: opts.scope,
15302
15488
  hostPattern: opts.host
15303
15489
  };
15304
- const result = dbUrl ? await seedEnvironmentBindingDirect(dbUrl, payload) : await getClient().post(`/api/v1/admin/environments/${encodeURIComponent(opts.env)}/bind`, {
15490
+ const result = dbUrl ? await seedContextBindingDirect(dbUrl, payload) : await getClient().post(`/api/v1/admin/contexts/${encodeURIComponent(opts.env)}/bind`, {
15305
15491
  orgId: opts.org,
15306
15492
  scopePattern: opts.scope,
15307
15493
  hostPattern: opts.host
15308
15494
  });
15309
15495
  if (opts.json) console.log(JSON.stringify(result));
15310
- else console.log(`environment bind: created=${result.created}${dbUrl ? " (direct)" : ""}`);
15496
+ else console.log(`context bind: created=${result.created}${dbUrl ? " (direct)" : ""}`);
15311
15497
  } catch (err) {
15312
15498
  console.error(`Error: ${toErrorMessage(err)}`);
15313
15499
  process.exit(1);
15314
15500
  }
15315
15501
  });
15316
- env.command("set-policy").description("Update policy fields on an environment (only provided fields change)").requiredOption("--org <id>", "Org ID").requiredOption("--env <name>", "Environment name").option("--branch-restrictions <json>", "JSON array of allowed branches").option("--required-reviewers <csv>", "CSV of required reviewer user IDs (empty to clear)").option("--wait-timer <seconds>", "Wait timer before release (seconds)").option("--hold-expiry <seconds>", "Hold expiry TTL (seconds)").option("--minimum-trust <level>", "Minimum trust (known|trusted, or \"null\" to clear)").option("--enabled <bool>", "Enabled flag (true|false)").option("--allow-local-execution <bool>", "Allow CLI/test runs to resolve this env (true|false)").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15502
+ env.command("set-policy").description("Update policy fields on a context (only provided fields change)").requiredOption("--org <id>", "Org ID").requiredOption("--env <name>", "Context name").option("--branch-restrictions <json>", "JSON array of allowed branches").option("--required-reviewers <csv>", "CSV of required reviewer user IDs (empty to clear)").option("--wait-timer <seconds>", "Wait timer before release (seconds)").option("--hold-expiry <seconds>", "Hold expiry TTL (seconds)").option("--minimum-trust <level>", "Minimum trust (known|trusted, or \"null\" to clear)").option("--enabled <bool>", "Enabled flag (true|false)").option("--allow-local-execution <bool>", "Allow CLI/test runs to resolve this env (true|false)").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15317
15503
  try {
15318
15504
  const payload = {
15319
15505
  orgId: opts.org,
15320
- envName: opts.env
15506
+ contextName: opts.env
15321
15507
  };
15322
15508
  if (opts.branchRestrictions !== void 0) payload.branchRestrictions = parseJsonOption(opts.branchRestrictions, "--branch-restrictions");
15323
15509
  if (opts.requiredReviewers !== void 0) payload.requiredReviewers = parseCsvOption(opts.requiredReviewers);
@@ -15327,73 +15513,73 @@ function registerEnvironmentCommands(program, getClient) {
15327
15513
  if (opts.enabled !== void 0) payload.enabled = opts.enabled === "false" ? false : true;
15328
15514
  if (opts.allowLocalExecution !== void 0) payload.allowLocalExecution = opts.allowLocalExecution === "false" ? false : true;
15329
15515
  const dbUrl = resolveDirectDbUrl$4(opts.databaseUrl);
15330
- if (dbUrl) await setEnvironmentPolicyDirect(dbUrl, payload);
15331
- else await getClient().patch(`/api/v1/admin/environments/${encodeURIComponent(opts.env)}/policy`, payload);
15516
+ if (dbUrl) await setContextPolicyDirect(dbUrl, payload);
15517
+ else await getClient().patch(`/api/v1/admin/contexts/${encodeURIComponent(opts.env)}/policy`, payload);
15332
15518
  if (opts.json) console.log(JSON.stringify({ updated: true }));
15333
- else console.log(`environment set-policy: updated (env=${opts.env})${dbUrl ? " (direct)" : ""}`);
15519
+ else console.log(`context set-policy: updated (env=${opts.env})${dbUrl ? " (direct)" : ""}`);
15334
15520
  } catch (err) {
15335
15521
  console.error(`Error: ${toErrorMessage(err)}`);
15336
15522
  process.exit(1);
15337
15523
  }
15338
15524
  });
15339
- env.command("list").description("List environments for an org").requiredOption("--org <id>", "Org ID").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15525
+ env.command("list").description("List contexts for an org").requiredOption("--org <id>", "Org ID").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15340
15526
  try {
15341
15527
  const dbUrl = resolveDirectDbUrl$4(opts.databaseUrl);
15342
- const result = dbUrl ? await listEnvironmentsDirect(dbUrl, { orgId: opts.org }) : await getClient().get(`/api/v1/admin/environments?orgId=${encodeURIComponent(opts.org)}`);
15528
+ const result = dbUrl ? await listContextsDirect(dbUrl, { orgId: opts.org }) : await getClient().get(`/api/v1/admin/contexts?orgId=${encodeURIComponent(opts.org)}`);
15343
15529
  if (opts.json) console.log(JSON.stringify(result));
15344
- else printEnvironmentTable(result.environments);
15530
+ else printContextTable(result.contexts);
15345
15531
  } catch (err) {
15346
15532
  console.error(`Error: ${toErrorMessage(err)}`);
15347
15533
  process.exit(1);
15348
15534
  }
15349
15535
  });
15350
- env.command("show").description("Show a single environment with variables + bindings").requiredOption("--org <id>", "Org ID").requiredOption("--name <name>", "Environment name").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15536
+ env.command("show").description("Show a single context with variables + bindings").requiredOption("--org <id>", "Org ID").requiredOption("--name <name>", "Context name").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15351
15537
  try {
15352
15538
  const dbUrl = resolveDirectDbUrl$4(opts.databaseUrl);
15353
- const result = dbUrl ? await showEnvironmentDirect(dbUrl, {
15539
+ const result = dbUrl ? await showContextDirect(dbUrl, {
15354
15540
  orgId: opts.org,
15355
15541
  name: opts.name
15356
- }) : await getClient().get(`/api/v1/admin/environments/${encodeURIComponent(opts.name)}?orgId=${encodeURIComponent(opts.org)}`);
15542
+ }) : await getClient().get(`/api/v1/admin/contexts/${encodeURIComponent(opts.name)}?orgId=${encodeURIComponent(opts.org)}`);
15357
15543
  if (opts.json) console.log(JSON.stringify(result));
15358
- else printShowEnvironment(result);
15544
+ else printShowContext(result);
15359
15545
  } catch (err) {
15360
15546
  console.error(`Error: ${toErrorMessage(err)}`);
15361
15547
  process.exit(1);
15362
15548
  }
15363
15549
  });
15364
- env.command("delete").description("Delete an environment (cascades bindings, variables, overrides; held-run history survives; pending held runs block with a clear error, resolved holds do not)").requiredOption("--org <id>", "Org ID").requiredOption("--name <name>", "Environment name").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15550
+ env.command("delete").description("Delete a context (cascades bindings, variables, overrides; held-run history survives; pending held runs block with a clear error, resolved holds do not)").requiredOption("--org <id>", "Org ID").requiredOption("--name <name>", "Context name").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15365
15551
  try {
15366
15552
  const dbUrl = resolveDirectDbUrl$4(opts.databaseUrl);
15367
15553
  let deleted;
15368
- if (dbUrl) ({deleted} = await deleteEnvironmentDirect(dbUrl, {
15554
+ if (dbUrl) ({deleted} = await deleteContextDirect(dbUrl, {
15369
15555
  orgId: opts.org,
15370
15556
  name: opts.name
15371
15557
  }));
15372
- else deleted = (await getClient().delete(`/api/v1/admin/environments/${encodeURIComponent(opts.name)}?orgId=${encodeURIComponent(opts.org)}`)).deleted;
15373
- if (!deleted) throw new Error(`environment not found (org=${opts.org}, name=${opts.name})`);
15558
+ else deleted = (await getClient().delete(`/api/v1/admin/contexts/${encodeURIComponent(opts.name)}?orgId=${encodeURIComponent(opts.org)}`)).deleted;
15559
+ if (!deleted) throw new Error(`context not found (org=${opts.org}, name=${opts.name})`);
15374
15560
  if (opts.json) console.log(JSON.stringify({ deleted: true }));
15375
- else console.log(`environment delete: deleted=true${dbUrl ? " (direct)" : ""}`);
15561
+ else console.log(`context delete: deleted=true${dbUrl ? " (direct)" : ""}`);
15376
15562
  } catch (err) {
15377
15563
  console.error(`Error: ${toErrorMessage(err)}`);
15378
15564
  process.exit(1);
15379
15565
  }
15380
15566
  });
15381
- env.command("purge").description("Delete all environments (and held runs) for an org — direct-DB break-glass / warm-start reset").option("--database-url <url>", "Use direct DB access (or KICI_DATABASE_URL)").option("--org <id>", "Restrict purge to a single org (omit to purge all orgs)").option("--json", "Emit JSON output").action(async (opts) => {
15567
+ env.command("purge").description("Delete all contexts (and held runs) for an org — direct-DB break-glass / warm-start reset").option("--database-url <url>", "Use direct DB access (or KICI_DATABASE_URL)").option("--org <id>", "Restrict purge to a single org (omit to purge all orgs)").option("--json", "Emit JSON output").action(async (opts) => {
15382
15568
  try {
15383
15569
  const dbUrl = resolveDirectDbUrl$4(opts.databaseUrl);
15384
15570
  if (!dbUrl) {
15385
15571
  console.error("Error: --database-url or KICI_DATABASE_URL is required (direct-DB only)");
15386
15572
  process.exit(1);
15387
15573
  }
15388
- const result = await purgeEnvironmentsDirect(dbUrl, opts.org);
15574
+ const result = await purgeContextsDirect(dbUrl, opts.org);
15389
15575
  if (opts.json) console.log(JSON.stringify(result));
15390
- else console.log(`environment purge: environmentsDeleted=${result.environmentsDeleted} heldRunsDeleted=${result.heldRunsDeleted}` + (opts.org ? ` (org ${opts.org})` : " (all orgs)"));
15576
+ else console.log(`context purge: contextsDeleted=${result.contextsDeleted} heldRunsDeleted=${result.heldRunsDeleted}` + (opts.org ? ` (org ${opts.org})` : " (all orgs)"));
15391
15577
  } catch (err) {
15392
15578
  console.error(`Error: ${toErrorMessage(err)}`);
15393
15579
  process.exit(1);
15394
15580
  }
15395
15581
  });
15396
- env.command("create-template").description("Create or update an environment template + its seed variables").requiredOption("--org <id>", "Org ID").requiredOption("--template <name>", "Template name").option("--type <t>", "Environment type (defaults to \"template\")", "template").option("--branch-restrictions <json>", "JSON array of allowed branches").option("--required-reviewers <csv>", "CSV of required reviewer user IDs").option("--wait-timer <seconds>", "Wait timer (seconds)").option("--hold-expiry <seconds>", "Hold expiry TTL (seconds)").option("--minimum-trust <level>", "Minimum trust (known|trusted)").option("--variables <json>", "JSON object of env variables to seed (e.g. '{\"K\":\"V\"}')").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15582
+ env.command("create-template").description("Create or update a context template + its seed variables").requiredOption("--org <id>", "Org ID").requiredOption("--template <name>", "Template name").option("--type <t>", "Context type (defaults to \"template\")", "template").option("--branch-restrictions <json>", "JSON array of allowed branches").option("--required-reviewers <csv>", "CSV of required reviewer user IDs").option("--wait-timer <seconds>", "Wait timer (seconds)").option("--hold-expiry <seconds>", "Hold expiry TTL (seconds)").option("--minimum-trust <level>", "Minimum trust (known|trusted)").option("--variables <json>", "JSON object of env variables to seed (e.g. '{\"K\":\"V\"}')").option("--database-url <url>", "Use direct DB access instead of HTTP (offline mode)").option("--json", "Emit JSON output").action(async (opts) => {
15397
15583
  try {
15398
15584
  const branchRestrictions = parseJsonOption(opts.branchRestrictions, "--branch-restrictions");
15399
15585
  const requiredReviewers = parseCsvOption(opts.requiredReviewers);
@@ -15413,9 +15599,9 @@ function registerEnvironmentCommands(program, getClient) {
15413
15599
  variables
15414
15600
  };
15415
15601
  const dbUrl = resolveDirectDbUrl$4(opts.databaseUrl);
15416
- const result = dbUrl ? await createEnvironmentTemplateDirect(dbUrl, payload) : await getClient().post("/api/v1/admin/environments/templates", payload);
15602
+ const result = dbUrl ? await createContextTemplateDirect(dbUrl, payload) : await getClient().post("/api/v1/admin/contexts/templates", payload);
15417
15603
  if (opts.json) console.log(JSON.stringify(result));
15418
- else console.log(`environment create-template: envId=${result.envId} created=${result.created} variablesSet=${result.variablesSet}${dbUrl ? " (direct)" : ""}`);
15604
+ else console.log(`context create-template: envId=${result.envId} created=${result.created} variablesSet=${result.variablesSet}${dbUrl ? " (direct)" : ""}`);
15419
15605
  } catch (err) {
15420
15606
  console.error(`Error: ${toErrorMessage(err)}`);
15421
15607
  process.exit(1);
@@ -15425,12 +15611,12 @@ function registerEnvironmentCommands(program, getClient) {
15425
15611
  //#endregion
15426
15612
  //#region src/cli/commands/variable.ts
15427
15613
  function registerVariableCommands(program, getClient) {
15428
- const vr = program.command("variable").description("Manage environment variables");
15429
- vr.command("list <orgId> <environment>").description("List org-level variables in an environment").option("--values", "Print variable values inline (default: keys + locked flag only)").action(async (orgId, environment, opts) => {
15614
+ const vr = program.command("variable").description("Manage context variables");
15615
+ vr.command("list <orgId> <context>").description("List org-level variables in a context").option("--values", "Print variable values inline (default: keys + locked flag only)").action(async (orgId, context, opts) => {
15430
15616
  try {
15431
- const { variables } = await getClient().listVariables(orgId, environment);
15617
+ const { variables } = await getClient().listVariables(orgId, context);
15432
15618
  if (variables.length === 0) {
15433
- console.log("No variables in this environment.");
15619
+ console.log("No variables in this context.");
15434
15620
  return;
15435
15621
  }
15436
15622
  for (const v of variables) {
@@ -15443,12 +15629,12 @@ function registerVariableCommands(program, getClient) {
15443
15629
  process.exit(1);
15444
15630
  }
15445
15631
  });
15446
- vr.command("get <orgId> <environment> <key>").description("Print the value of a single variable").action(async (orgId, environment, key) => {
15632
+ vr.command("get <orgId> <context> <key>").description("Print the value of a single variable").action(async (orgId, context, key) => {
15447
15633
  try {
15448
- const { variables } = await getClient().listVariables(orgId, environment);
15634
+ const { variables } = await getClient().listVariables(orgId, context);
15449
15635
  const match = variables.find((v) => v.key === key);
15450
15636
  if (!match) {
15451
- console.error(`Variable '${key}' not found in environment '${environment}'.`);
15637
+ console.error(`Variable '${key}' not found in context '${context}'.`);
15452
15638
  process.exit(1);
15453
15639
  }
15454
15640
  console.log(match.value);
@@ -15457,31 +15643,31 @@ function registerVariableCommands(program, getClient) {
15457
15643
  process.exit(1);
15458
15644
  }
15459
15645
  });
15460
- vr.command("set <orgId> <environment> <key>").description("Set an environment variable. Value comes from one of: --prompt (default on TTY), --from-stdin (default on pipe), --from-file <path>, --from-env <VAR>, --value <plaintext> (discouraged).").option("--value <value>", "Variable value via argv (visible in shell history)").option("--prompt", "Interactive no-echo prompt (requires TTY)").option("--from-stdin", "Read value from piped stdin until EOF").option("--from-file <path>", "Read value from a file (trailing newline trimmed)").option("--from-env <var>", "Read value from a named environment variable").option("--no-trim", "When reading --from-file, keep the trailing newline (default: trim once)").option("--locked", "Mark the variable as locked (source overrides cannot replace it)").option("--confirm-fingerprint <sha256hex>", "Refuse the write unless SHA-256(value) matches this 64-hex string").option("--dry-run", "Parse + validate the value, print fingerprint + length, do not write").action(async (orgId, environment, key, opts) => {
15646
+ vr.command("set <orgId> <context> <key>").description("Set a context variable. Value comes from one of: --prompt (default on TTY), --from-stdin (default on pipe), --from-file <path>, --from-env <VAR>, --value <plaintext> (discouraged).").option("--value <value>", "Variable value via argv (visible in shell history)").option("--prompt", "Interactive no-echo prompt (requires TTY)").option("--from-stdin", "Read value from piped stdin until EOF").option("--from-file <path>", "Read value from a file (trailing newline trimmed)").option("--from-env <var>", "Read value from a named environment variable").option("--no-trim", "When reading --from-file, keep the trailing newline (default: trim once)").option("--locked", "Mark the variable as locked (source overrides cannot replace it)").option("--confirm-fingerprint <sha256hex>", "Refuse the write unless SHA-256(value) matches this 64-hex string").option("--dry-run", "Parse + validate the value, print fingerprint + length, do not write").action(async (orgId, context, key, opts) => {
15461
15647
  try {
15462
15648
  const { value, source } = await resolveSecretInput(opts);
15463
15649
  if (opts.dryRun) {
15464
- console.log(`[dry-run] would set variable '${key}' in environment '${environment}' for org ${orgId} (${value.length} chars, source=${source}, locked=${Boolean(opts.locked)}, sha256=${fingerprintValue(value)})`);
15650
+ console.log(`[dry-run] would set variable '${key}' in context '${context}' for org ${orgId} (${value.length} chars, source=${source}, locked=${Boolean(opts.locked)}, sha256=${fingerprintValue(value)})`);
15465
15651
  return;
15466
15652
  }
15467
- await getClient().setVariable(orgId, environment, key, value, opts.locked);
15653
+ await getClient().setVariable(orgId, context, key, value, opts.locked);
15468
15654
  const lockTag = opts.locked ? " [locked]" : "";
15469
- console.log(`Variable '${key}' set in environment '${environment}' for org ${orgId}${lockTag}.`);
15655
+ console.log(`Variable '${key}' set in context '${context}' for org ${orgId}${lockTag}.`);
15470
15656
  } catch (err) {
15471
15657
  console.error(`Error: ${toErrorMessage(err)}`);
15472
15658
  process.exit(1);
15473
15659
  }
15474
15660
  });
15475
- vr.command("delete <orgId> <environment> <key>").description("Delete an environment variable").option("--yes", "Skip confirmation prompt").action(async (orgId, environment, key, opts) => {
15661
+ vr.command("delete <orgId> <context> <key>").description("Delete a context variable").option("--yes", "Skip confirmation prompt").action(async (orgId, context, key, opts) => {
15476
15662
  try {
15477
15663
  if (!opts.yes) {
15478
- if (!await confirm$1(`Are you sure you want to delete variable '${key}' from environment '${environment}'?`)) {
15664
+ if (!await confirm$1(`Are you sure you want to delete variable '${key}' from context '${context}'?`)) {
15479
15665
  console.log("Aborted.");
15480
15666
  return;
15481
15667
  }
15482
15668
  }
15483
- await getClient().deleteVariable(orgId, environment, key);
15484
- console.log(`Variable '${key}' deleted from environment '${environment}' for org ${orgId}.`);
15669
+ await getClient().deleteVariable(orgId, context, key);
15670
+ console.log(`Variable '${key}' deleted from context '${context}' for org ${orgId}.`);
15485
15671
  } catch (err) {
15486
15672
  console.error(`Error: ${toErrorMessage(err)}`);
15487
15673
  process.exit(1);
@@ -15620,7 +15806,7 @@ function printRunsTable(runs) {
15620
15806
  r.workflow_name,
15621
15807
  r.status,
15622
15808
  r.routing_key ?? "-",
15623
- r.environment ?? "-",
15809
+ r.context ?? "-",
15624
15810
  String(r.created_at)
15625
15811
  ]);
15626
15812
  const widths = header.map((h, i) => Math.max(h.length, ...rows.map((row) => row[i].length)));
@@ -15637,7 +15823,7 @@ function printRunShow(run, jobs) {
15637
15823
  console.log(`ref: ${run.ref}`);
15638
15824
  console.log(`sha: ${run.sha}`);
15639
15825
  console.log(`routing: ${run.routing_key ?? "-"}`);
15640
- console.log(`env: ${run.environment ?? "-"}`);
15826
+ console.log(`env: ${run.context ?? "-"}`);
15641
15827
  console.log(`created_at: ${run.created_at}`);
15642
15828
  if (run.completed_at) console.log(`completed: ${run.completed_at}`);
15643
15829
  if (run.duration_ms !== null) console.log(`duration: ${run.duration_ms}ms`);
@@ -21296,7 +21482,7 @@ function buildProgram() {
21296
21482
  registerClusterNameCommands(program, getClient);
21297
21483
  registerClusterCommands(program);
21298
21484
  registerMaintenanceCommands(program, getClient);
21299
- registerEnvironmentCommands(program, getClient);
21485
+ registerContextCommands(program, getClient);
21300
21486
  registerVariableCommands(program, getClient);
21301
21487
  registerQueueCommands(program, getClient);
21302
21488
  registerExecutionCommands(program, getClient);