@kici-dev/orchestrator 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.js CHANGED
@@ -135,7 +135,7 @@ var init_verification = __esmMin((() => {}));
135
135
  //#endregion
136
136
  //#region src/webhook/verify-inbound.ts
137
137
  init_verification();
138
- const logger$96 = createLogger({ prefix: "verify-inbound" });
138
+ const logger$97 = createLogger({ prefix: "verify-inbound" });
139
139
  /** Fixed org_id for source secrets in PgSecretStore (matches SourceStore). */
140
140
  const SOURCE_ORG_ID$1 = "__system__";
141
141
  /** Default GitHub-style signature header. */
@@ -151,7 +151,7 @@ async function verifyInboundWebhook(deps, input) {
151
151
  const { routingKey } = input;
152
152
  if (routingKey.startsWith("github:")) return verifyGithub(deps, input);
153
153
  if (routingKey.startsWith("generic:")) return verifyGeneric(deps, input);
154
- logger$96.warn("Unknown routing-key prefix", { routingKey });
154
+ logger$97.warn("Unknown routing-key prefix", { routingKey });
155
155
  return {
156
156
  result: "rejected_unknown_source",
157
157
  reason: `provider not implemented for routing key prefix`
@@ -177,7 +177,7 @@ async function verifyGithub(deps, input) {
177
177
  try {
178
178
  secrets = await getGithubWebhookSecrets(secretStore, source.id);
179
179
  } catch (err) {
180
- logger$96.error("Failed to read webhook secret from PgSecretStore", {
180
+ logger$97.error("Failed to read webhook secret from PgSecretStore", {
181
181
  routingKey,
182
182
  sourceId: source.id,
183
183
  error: toErrorMessage(err)
@@ -227,7 +227,7 @@ async function verifyGeneric(deps, input) {
227
227
  try {
228
228
  config = parseGenericVerificationConfig(source.verification_method, source.verification_config);
229
229
  } catch (err) {
230
- logger$96.error("Malformed verification_config JSON", {
230
+ logger$97.error("Malformed verification_config JSON", {
231
231
  routingKey,
232
232
  method: source.verification_method,
233
233
  error: toErrorMessage(err)
@@ -380,6 +380,15 @@ var init_config$5 = __esmMin((() => {
380
380
  * behavior). Trailing slash optional.
381
381
  */
382
382
  dashboardUrl: z.string().optional(),
383
+ /**
384
+ * Public base URL at which this orchestrator's own webhook ingress is
385
+ * reachable (independent/hybrid self-serve generic webhooks:
386
+ * `<base>/webhook/<customerId>/generic/<sourceId>`). Used by
387
+ * `kici-admin source add` to print a generic source's webhook URL. GitHub-App
388
+ * ingress is Platform-relayed, so GitHub URLs come from the Platform's
389
+ * `source.register.ack`, not this value. Trailing slash optional.
390
+ */
391
+ webhookPublicUrl: z.string().optional(),
383
392
  databaseUrl: z.string().default(""),
384
393
  lockfileCacheMax: z.coerce.number().default(500),
385
394
  lockfileCacheTtlMs: z.coerce.number().default(36e5),
@@ -572,6 +581,7 @@ var init_config$5 = __esmMin((() => {
572
581
  platformUrl: "KICI_PLATFORM_URL",
573
582
  platformToken: "KICI_PLATFORM_TOKEN",
574
583
  dashboardUrl: "KICI_DASHBOARD_URL",
584
+ webhookPublicUrl: "KICI_WEBHOOK_PUBLIC_URL",
575
585
  databaseUrl: "KICI_DATABASE_URL",
576
586
  cacheStorageType: "KICI_STORAGE_TYPE",
577
587
  cacheStoragePath: "KICI_STORAGE_PATH",
@@ -731,9 +741,9 @@ var init_event_buffer = __esmMin((() => {
731
741
  * `rejected_misconfigured` ack. This keeps the WS handler inside its 5 s budget
732
742
  * and prevents a malicious sender from killing the orch process via a bad frame.
733
743
  */
734
- var logger$95, DEFAULT_BUFFER_TTL_MS, RelayBufferRegistry;
744
+ var logger$96, DEFAULT_BUFFER_TTL_MS, RelayBufferRegistry;
735
745
  var init_relay_buffer = __esmMin((() => {
736
- logger$95 = createLogger({ prefix: "relay-buffer" });
746
+ logger$96 = createLogger({ prefix: "relay-buffer" });
737
747
  DEFAULT_BUFFER_TTL_MS = 3e4;
738
748
  RelayBufferRegistry = class {
739
749
  buffers = /* @__PURE__ */ new Map();
@@ -767,7 +777,7 @@ var init_relay_buffer = __esmMin((() => {
767
777
  };
768
778
  const ttl = setTimeout(() => {
769
779
  this.buffers.delete(messageId);
770
- logger$95.warn("Reassembly buffer TTL expired before final chunk", {
780
+ logger$96.warn("Reassembly buffer TTL expired before final chunk", {
771
781
  messageId,
772
782
  deliveryId: meta.deliveryId,
773
783
  receivedChunks: this.buffers.get(messageId)?.expectedSequence ?? 0
@@ -902,11 +912,11 @@ function toSourceRegistrationEntry(source) {
902
912
  subtype: source.subtype
903
913
  };
904
914
  }
905
- var logger$94, PlatformClient$1;
915
+ var logger$95, PlatformClient$1;
906
916
  var init_platform_client = __esmMin((() => {
907
917
  init_event_buffer();
908
918
  init_relay_buffer();
909
- logger$94 = createLogger({ prefix: "platform-client" });
919
+ logger$95 = createLogger({ prefix: "platform-client" });
910
920
  PlatformClient$1 = class {
911
921
  ws = null;
912
922
  _state = "disconnected";
@@ -919,6 +929,12 @@ var init_platform_client = __esmMin((() => {
919
929
  token;
920
930
  onWebhookRelay;
921
931
  providerSources;
932
+ /**
933
+ * Pending `registerSourceAndAwait()` callers, keyed by routing key. Resolved
934
+ * with the Platform-computed webhook URL when the matching
935
+ * `source.register.ack` arrives, or rejected on timeout / disconnect.
936
+ */
937
+ pendingSourceRegistrations = /* @__PURE__ */ new Map();
922
938
  instanceId;
923
939
  clusterName;
924
940
  clusterId;
@@ -961,7 +977,7 @@ var init_platform_client = __esmMin((() => {
961
977
  /**
962
978
  * Returns the cached public alias of the orchestrator's owning org,
963
979
  * or `undefined` if Platform has not supplied one yet. Read by
964
- * `commit-status.ts` when building `details_url`.
980
+ * `check-run-reporter.ts` when building `details_url`.
965
981
  */
966
982
  getOrgPublicAlias() {
967
983
  return this._orgPublicAlias;
@@ -1048,7 +1064,7 @@ var init_platform_client = __esmMin((() => {
1048
1064
  */
1049
1065
  async completeChunkedRelay(messageId, meta, body) {
1050
1066
  if (!this.onVerifyInbound) {
1051
- logger$94.error("Chunked webhook.relay received but no onVerifyInbound configured", {
1067
+ logger$95.error("Chunked webhook.relay received but no onVerifyInbound configured", {
1052
1068
  messageId,
1053
1069
  deliveryId: meta.deliveryId
1054
1070
  });
@@ -1063,7 +1079,7 @@ var init_platform_client = __esmMin((() => {
1063
1079
  }
1064
1080
  const outcome = await this.onVerifyInbound(meta, body);
1065
1081
  if (outcome.result !== "accepted") {
1066
- logger$94.warn("Chunked webhook.relay verify rejected", {
1082
+ logger$95.warn("Chunked webhook.relay verify rejected", {
1067
1083
  messageId,
1068
1084
  deliveryId: meta.deliveryId,
1069
1085
  routingKey: meta.routingKey,
@@ -1084,7 +1100,7 @@ var init_platform_client = __esmMin((() => {
1084
1100
  if (contentType.includes("application/json") || contentType === "") try {
1085
1101
  payload = body.length === 0 ? {} : JSON.parse(body.toString("utf8"));
1086
1102
  } catch (err) {
1087
- logger$94.warn("Accepted webhook body is not valid JSON; rejecting", {
1103
+ logger$95.warn("Accepted webhook body is not valid JSON; rejecting", {
1088
1104
  messageId,
1089
1105
  deliveryId: meta.deliveryId,
1090
1106
  error: toErrorMessage(err)
@@ -1119,7 +1135,7 @@ var init_platform_client = __esmMin((() => {
1119
1135
  ...meta.requestId && { requestId: meta.requestId }
1120
1136
  };
1121
1137
  this.onWebhookRelay(relay).catch((err) => {
1122
- logger$94.error("Error processing chunked webhook relay", {
1138
+ logger$95.error("Error processing chunked webhook relay", {
1123
1139
  messageId,
1124
1140
  deliveryId: meta.deliveryId,
1125
1141
  error: toErrorMessage(err)
@@ -1132,7 +1148,7 @@ var init_platform_client = __esmMin((() => {
1132
1148
  */
1133
1149
  connect() {
1134
1150
  if (this._state !== "disconnected") {
1135
- logger$94.warn("connect() called while not disconnected", { state: this._state });
1151
+ logger$95.warn("connect() called while not disconnected", { state: this._state });
1136
1152
  return;
1137
1153
  }
1138
1154
  this.intentionalDisconnect = false;
@@ -1226,7 +1242,9 @@ var init_platform_client = __esmMin((() => {
1226
1242
  ...this.address !== void 0 && { address: this.address },
1227
1243
  ...this.version && { version: this.version },
1228
1244
  ...this.mode && { mode: this.mode },
1229
- ...this.scalerBackends && { scalerBackends: this.scalerBackends }
1245
+ ...this.scalerBackends && { scalerBackends: this.scalerBackends },
1246
+ ...this.s3LogAccess !== void 0 && { s3LogAccess: this.s3LogAccess },
1247
+ ...this.queueTimeoutMs && { queueTimeoutMs: this.queueTimeoutMs }
1230
1248
  });
1231
1249
  else if (newSources.length === 0 && this.providerSources.length > 0) this.send({
1232
1250
  type: "source.register",
@@ -1245,6 +1263,50 @@ var init_platform_client = __esmMin((() => {
1245
1263
  this.providerSources.length = 0;
1246
1264
  this.providerSources.push(...newSources);
1247
1265
  }
1266
+ /**
1267
+ * Push the full source list to the Platform and resolve with the webhook URL
1268
+ * the Platform computed for `routingKey` (from the `source.register.ack`), or
1269
+ * `null` if the Platform has no public webhook base configured.
1270
+ *
1271
+ * Used by `kici-admin source add` (platform/hybrid mode) to print the URL
1272
+ * synchronously. Passing the **full** source list keeps this on the single
1273
+ * `updateSources` push path — the routing key being newly added means
1274
+ * `updateSources` emits a `source.register` whose ack carries the URL; the
1275
+ * later NOTIFY-driven republish then diffs to a no-op.
1276
+ *
1277
+ * Rejects on timeout or disconnect; the caller degrades to a "(unavailable)"
1278
+ * note rather than fabricating a URL.
1279
+ */
1280
+ registerSourceAndAwait(fullSources, routingKey, timeoutMs = 5e3) {
1281
+ return new Promise((resolve, reject) => {
1282
+ const existing = this.pendingSourceRegistrations.get(routingKey);
1283
+ if (existing) {
1284
+ clearTimeout(existing.timer);
1285
+ existing.reject(/* @__PURE__ */ new Error("superseded by a newer registration"));
1286
+ }
1287
+ const timer = setTimeout(() => {
1288
+ this.pendingSourceRegistrations.delete(routingKey);
1289
+ reject(/* @__PURE__ */ new Error(`timed out waiting for source.register.ack for ${routingKey}`));
1290
+ }, timeoutMs);
1291
+ this.pendingSourceRegistrations.set(routingKey, {
1292
+ resolve,
1293
+ reject,
1294
+ timer
1295
+ });
1296
+ this.updateSources(fullSources);
1297
+ });
1298
+ }
1299
+ /**
1300
+ * Reject every pending `registerSourceAndAwait()` — called on disconnect so a
1301
+ * `source add` issued while the link drops fails fast instead of hanging.
1302
+ */
1303
+ rejectPendingSourceRegistrations(reason) {
1304
+ for (const [, pending] of this.pendingSourceRegistrations) {
1305
+ clearTimeout(pending.timer);
1306
+ pending.reject(new Error(reason));
1307
+ }
1308
+ this.pendingSourceRegistrations.clear();
1309
+ }
1248
1310
  getReconnectDelay() {
1249
1311
  return getReconnectDelay(this.reconnectAttempts, this.maxReconnectDelayMs);
1250
1312
  }
@@ -1259,14 +1321,14 @@ var init_platform_client = __esmMin((() => {
1259
1321
  }
1260
1322
  });
1261
1323
  } catch (err) {
1262
- logger$94.error("Failed to create WebSocket", { error: toErrorMessage(err) });
1324
+ logger$95.error("Failed to create WebSocket", { error: toErrorMessage(err) });
1263
1325
  this._state = "disconnected";
1264
1326
  this.scheduleReconnect();
1265
1327
  return;
1266
1328
  }
1267
1329
  this.ws.on("open", () => {
1268
1330
  this._state = "authenticating";
1269
- logger$94.info("Connected to Platform, sending auth request", { url: this.url });
1331
+ logger$95.info("Connected to Platform, sending auth request", { url: this.url });
1270
1332
  this.ws.send(JSON.stringify({
1271
1333
  type: "auth.request",
1272
1334
  token: this.token,
@@ -1279,16 +1341,17 @@ var init_platform_client = __esmMin((() => {
1279
1341
  });
1280
1342
  this.ws.on("close", (code, reason) => {
1281
1343
  const reasonText = reason.toString();
1282
- logger$94.info("Platform connection closed", {
1344
+ logger$95.info("Platform connection closed", {
1283
1345
  code,
1284
1346
  reason: reasonText
1285
1347
  });
1286
1348
  this._state = "disconnected";
1287
1349
  this.stopHeartbeat();
1350
+ this.rejectPendingSourceRegistrations("Platform connection closed before ack");
1288
1351
  if (!this.intentionalDisconnect) this.scheduleReconnect();
1289
1352
  });
1290
1353
  this.ws.on("error", (err) => {
1291
- logger$94.error("Platform WebSocket error", { error: err.message });
1354
+ logger$95.error("Platform WebSocket error", { error: err.message });
1292
1355
  if (this.ws && this.ws.readyState === WebSocket.OPEN) this.ws.close();
1293
1356
  });
1294
1357
  }
@@ -1297,7 +1360,7 @@ var init_platform_client = __esmMin((() => {
1297
1360
  try {
1298
1361
  raw = JSON.parse(data.toString());
1299
1362
  } catch {
1300
- logger$94.warn("Malformed JSON received from Platform");
1363
+ logger$95.warn("Malformed JSON received from Platform");
1301
1364
  return;
1302
1365
  }
1303
1366
  const parsed = platformToOrchestratorMessageSchema.safeParse(raw);
@@ -1324,11 +1387,11 @@ var init_platform_client = __esmMin((() => {
1324
1387
  this.onJoinRequest(joinParsed.data).then((response) => {
1325
1388
  this.sendRaw(response);
1326
1389
  }).catch((err) => {
1327
- logger$94.error("Error handling join request", { error: toErrorMessage(err) });
1390
+ logger$95.error("Error handling join request", { error: toErrorMessage(err) });
1328
1391
  });
1329
1392
  return;
1330
1393
  }
1331
- logger$94.warn("Invalid message from Platform", { errors: primaryIssues });
1394
+ logger$95.warn("Invalid message from Platform", { errors: primaryIssues });
1332
1395
  }
1333
1396
  /**
1334
1397
  * Dispatch a parsed platform message to the appropriate per-area
@@ -1354,7 +1417,7 @@ var init_platform_client = __esmMin((() => {
1354
1417
  this.handleSourceRegisterAck(msg);
1355
1418
  break;
1356
1419
  case "source.deregister.ack":
1357
- logger$94.info("Source deregistration acknowledged", { removed: msg.removed });
1420
+ logger$95.info("Source deregistration acknowledged", { removed: msg.removed });
1358
1421
  break;
1359
1422
  case "peer.discover":
1360
1423
  this.handlePeerDiscover(msg);
@@ -1363,14 +1426,14 @@ var init_platform_client = __esmMin((() => {
1363
1426
  this.handlePeerUpdate(msg);
1364
1427
  break;
1365
1428
  case "dashboard.run.detail":
1366
- logger$94.debug("Dashboard run detail request received", {
1429
+ logger$95.debug("Dashboard run detail request received", {
1367
1430
  requestId: msg.requestId,
1368
1431
  runId: msg.runId
1369
1432
  });
1370
1433
  this.onDashboardRunDetail?.(msg);
1371
1434
  break;
1372
1435
  case "dashboard.step.logs":
1373
- logger$94.debug("Dashboard step logs request received", {
1436
+ logger$95.debug("Dashboard step logs request received", {
1374
1437
  requestId: msg.requestId,
1375
1438
  runId: msg.runId,
1376
1439
  jobId: msg.jobId,
@@ -1379,7 +1442,7 @@ var init_platform_client = __esmMin((() => {
1379
1442
  this.onDashboardStepLogs?.(msg);
1380
1443
  break;
1381
1444
  case "run.rerun.request":
1382
- logger$94.info("Run rerun request received", {
1445
+ logger$95.info("Run rerun request received", {
1383
1446
  requestId: msg.requestId,
1384
1447
  runId: msg.runId,
1385
1448
  actor: msg.actor
@@ -1387,7 +1450,7 @@ var init_platform_client = __esmMin((() => {
1387
1450
  this.onRunRerun?.(msg);
1388
1451
  break;
1389
1452
  case "run.manual_schedule.request":
1390
- logger$94.info("Manual schedule request received", {
1453
+ logger$95.info("Manual schedule request received", {
1391
1454
  requestId: msg.requestId,
1392
1455
  registrationId: msg.registrationId,
1393
1456
  actor: msg.actor
@@ -1395,7 +1458,7 @@ var init_platform_client = __esmMin((() => {
1395
1458
  this.onManualSchedule?.(msg);
1396
1459
  break;
1397
1460
  case "run.cancel.request":
1398
- logger$94.info("Run cancel request received", {
1461
+ logger$95.info("Run cancel request received", {
1399
1462
  requestId: msg.requestId,
1400
1463
  runId: msg.runId,
1401
1464
  actor: msg.actor
@@ -1403,14 +1466,14 @@ var init_platform_client = __esmMin((() => {
1403
1466
  this.onRunCancel?.(msg);
1404
1467
  break;
1405
1468
  case "dashboard.payload":
1406
- logger$94.debug("Dashboard payload request received", {
1469
+ logger$95.debug("Dashboard payload request received", {
1407
1470
  requestId: msg.requestId,
1408
1471
  runId: msg.runId
1409
1472
  });
1410
1473
  this.onDashboardPayload?.(msg);
1411
1474
  break;
1412
1475
  case "dashboard.orch.logs":
1413
- logger$94.debug("Dashboard orchestration logs request received", {
1476
+ logger$95.debug("Dashboard orchestration logs request received", {
1414
1477
  requestId: msg.requestId,
1415
1478
  runId: msg.runId,
1416
1479
  jobId: msg.jobId
@@ -1418,30 +1481,30 @@ var init_platform_client = __esmMin((() => {
1418
1481
  this.onDashboardOrchLogs?.(msg);
1419
1482
  break;
1420
1483
  case "trust_policy.update":
1421
- logger$94.info("Trust policy updated", { orgId: msg.orgId });
1484
+ logger$95.info("Trust policy updated", { orgId: msg.orgId });
1422
1485
  this.onTrustPolicyUpdate?.(msg);
1423
1486
  break;
1424
1487
  case "stale.checkrun.cleanup":
1425
- logger$94.info("Stale check run cleanup request received", { runCount: msg.runs.length });
1488
+ logger$95.info("Stale check run cleanup request received", { runCount: msg.runs.length });
1426
1489
  this.onStaleCheckrunCleanup?.(msg);
1427
1490
  break;
1428
1491
  case "dashboard.diagnostics":
1429
- logger$94.debug("Dashboard diagnostics request received", { requestId: msg.requestId });
1492
+ logger$95.debug("Dashboard diagnostics request received", { requestId: msg.requestId });
1430
1493
  this.onDashboardDiagnostics?.(msg);
1431
1494
  break;
1432
1495
  case "dashboard.scaler.capacity":
1433
- logger$94.debug("Dashboard scaler capacity request received", { requestId: msg.requestId });
1496
+ logger$95.debug("Dashboard scaler capacity request received", { requestId: msg.requestId });
1434
1497
  this.onDashboardScalerCapacity?.(msg);
1435
1498
  break;
1436
1499
  case "dashboard.scaler.agents":
1437
- logger$94.debug("Dashboard scaler agents request received", {
1500
+ logger$95.debug("Dashboard scaler agents request received", {
1438
1501
  requestId: msg.requestId,
1439
1502
  scalerName: msg.scalerName
1440
1503
  });
1441
1504
  this.onDashboardScalerAgents?.(msg);
1442
1505
  break;
1443
1506
  case "dashboard.access-log.list":
1444
- logger$94.debug("Dashboard access-log list request received", {
1507
+ logger$95.debug("Dashboard access-log list request received", {
1445
1508
  requestId: msg.requestId,
1446
1509
  orgId: msg.orgId
1447
1510
  });
@@ -1487,19 +1550,19 @@ var init_platform_client = __esmMin((() => {
1487
1550
  case "dashboard.backends.test":
1488
1551
  case "dashboard.global-workflows.get":
1489
1552
  case "dashboard.global-workflows.update":
1490
- logger$94.debug("Dashboard environment message received", {
1553
+ logger$95.debug("Dashboard environment message received", {
1491
1554
  type: msg.type,
1492
1555
  requestId: msg.requestId
1493
1556
  });
1494
1557
  this.onDashboardEnvMessage?.(msg);
1495
1558
  break;
1496
1559
  default:
1497
- logger$94.warn("Unknown platform message type", { type: msg.type });
1560
+ logger$95.warn("Unknown platform message type", { type: msg.type });
1498
1561
  break;
1499
1562
  }
1500
1563
  }
1501
1564
  handleAuthSuccess(msg) {
1502
- logger$94.info("Authenticated with Platform", {
1565
+ logger$95.info("Authenticated with Platform", {
1503
1566
  connectionId: msg.connectionId,
1504
1567
  orgPublicAlias: msg.orgPublicAlias
1505
1568
  });
@@ -1521,7 +1584,7 @@ var init_platform_client = __esmMin((() => {
1521
1584
  ...this.s3LogAccess !== void 0 && { s3LogAccess: this.s3LogAccess },
1522
1585
  ...this.queueTimeoutMs && { queueTimeoutMs: this.queueTimeoutMs }
1523
1586
  });
1524
- logger$94.info("Sent source.register", {
1587
+ logger$95.info("Sent source.register", {
1525
1588
  sources: this.providerSources.map((s) => s.routingKey),
1526
1589
  instanceId: this.instanceId,
1527
1590
  scalerBackends: this.scalerBackends ?? null
@@ -1529,7 +1592,7 @@ var init_platform_client = __esmMin((() => {
1529
1592
  this.flushBuffer();
1530
1593
  }
1531
1594
  handleAuthFailure(msg) {
1532
- logger$94.error("Platform auth failed", { reason: msg.reason });
1595
+ logger$95.error("Platform auth failed", { reason: msg.reason });
1533
1596
  if (this.ws && this.ws.readyState === WebSocket.OPEN) this.ws.close(1e3, "Auth failed");
1534
1597
  }
1535
1598
  handleWebhookRelayStart(msg) {
@@ -1547,7 +1610,7 @@ var init_platform_client = __esmMin((() => {
1547
1610
  ...msg.requestId && { requestId: msg.requestId }
1548
1611
  });
1549
1612
  if (startRes.status === "error") {
1550
- logger$94.warn("Rejecting webhook.relay.start", {
1613
+ logger$95.warn("Rejecting webhook.relay.start", {
1551
1614
  messageId: msg.messageId,
1552
1615
  reason: startRes.reason
1553
1616
  });
@@ -1558,7 +1621,7 @@ var init_platform_client = __esmMin((() => {
1558
1621
  result: "rejected_misconfigured",
1559
1622
  reason: startRes.reason
1560
1623
  });
1561
- } else logger$94.info("Webhook relay stream started", {
1624
+ } else logger$95.info("Webhook relay stream started", {
1562
1625
  messageId: msg.messageId,
1563
1626
  deliveryId: msg.deliveryId,
1564
1627
  event: msg.event,
@@ -1570,7 +1633,7 @@ var init_platform_client = __esmMin((() => {
1570
1633
  const applyRes = this.relayBuffer.chunk(msg.messageId, msg.sequence, msg.data, msg.final);
1571
1634
  if (applyRes.status === "pending") return;
1572
1635
  if (applyRes.status === "error") {
1573
- logger$94.warn("Rejecting webhook.relay.chunk", {
1636
+ logger$95.warn("Rejecting webhook.relay.chunk", {
1574
1637
  messageId: msg.messageId,
1575
1638
  sequence: msg.sequence,
1576
1639
  reason: applyRes.reason
@@ -1591,7 +1654,7 @@ var init_platform_client = __esmMin((() => {
1591
1654
  routingKey: meta.routingKey
1592
1655
  }, () => {
1593
1656
  this.completeChunkedRelay(msg.messageId, meta, body).catch((err) => {
1594
- logger$94.error("Error completing chunked relay", {
1657
+ logger$95.error("Error completing chunked relay", {
1595
1658
  messageId: msg.messageId,
1596
1659
  error: toErrorMessage(err)
1597
1660
  });
@@ -1608,10 +1671,18 @@ var init_platform_client = __esmMin((() => {
1608
1671
  handleSourceRegisterAck(msg) {
1609
1672
  const accepted = msg.accepted;
1610
1673
  const rejected = msg.rejected;
1611
- if (accepted.length > 0) logger$94.info("Source registration accepted", { routingKeys: accepted });
1612
- if (rejected.length > 0) logger$94.warn("Source registration rejected", { rejected: rejected.map((r) => `${r.routingKey}: ${r.reason}`) });
1674
+ if (accepted.length > 0) logger$95.info("Source registration accepted", { routingKeys: accepted.map((a) => a.routingKey) });
1675
+ for (const entry of accepted) {
1676
+ const pending = this.pendingSourceRegistrations.get(entry.routingKey);
1677
+ if (pending) {
1678
+ clearTimeout(pending.timer);
1679
+ this.pendingSourceRegistrations.delete(entry.routingKey);
1680
+ pending.resolve(entry.webhookUrl);
1681
+ }
1682
+ }
1683
+ if (rejected.length > 0) logger$95.warn("Source registration rejected", { rejected: rejected.map((r) => `${r.routingKey}: ${r.reason}`) });
1613
1684
  if (msg.peers && msg.peers.length > 0 && this.onPeerDiscover) for (const peer of msg.peers) {
1614
- logger$94.info("Peer discovered via source.register.ack", {
1685
+ logger$95.info("Peer discovered via source.register.ack", {
1615
1686
  connectionId: peer.connectionId,
1616
1687
  instanceId: peer.instanceId,
1617
1688
  address: peer.address,
@@ -1623,7 +1694,7 @@ var init_platform_client = __esmMin((() => {
1623
1694
  }
1624
1695
  handlePeerDiscover(msg) {
1625
1696
  const { peer } = msg;
1626
- logger$94.info("Peer discovered via Platform matchmaker", {
1697
+ logger$95.info("Peer discovered via Platform matchmaker", {
1627
1698
  connectionId: peer.connectionId,
1628
1699
  instanceId: peer.instanceId,
1629
1700
  address: peer.address,
@@ -1633,7 +1704,7 @@ var init_platform_client = __esmMin((() => {
1633
1704
  }
1634
1705
  handlePeerUpdate(msg) {
1635
1706
  if (msg.peers && this.onPeerDiscover) for (const peer of msg.peers) {
1636
- logger$94.info("Peer discovered via peer.update", {
1707
+ logger$95.info("Peer discovered via peer.update", {
1637
1708
  connectionId: peer.connectionId,
1638
1709
  instanceId: peer.instanceId,
1639
1710
  address: peer.address,
@@ -1653,7 +1724,7 @@ var init_platform_client = __esmMin((() => {
1653
1724
  flushBuffer() {
1654
1725
  const messages = this.eventBuffer.flush();
1655
1726
  if (messages.length > 0) {
1656
- logger$94.info("Flushing event buffer", { count: messages.length });
1727
+ logger$95.info("Flushing event buffer", { count: messages.length });
1657
1728
  for (const msg of messages) this.sendDirect(msg);
1658
1729
  }
1659
1730
  }
@@ -1676,7 +1747,7 @@ var init_platform_client = __esmMin((() => {
1676
1747
  this.cancelReconnect();
1677
1748
  const delay = this.getReconnectDelay();
1678
1749
  this.reconnectAttempts++;
1679
- logger$94.info("Scheduling reconnect", {
1750
+ logger$95.info("Scheduling reconnect", {
1680
1751
  attempt: this.reconnectAttempts,
1681
1752
  delayMs: Math.round(delay)
1682
1753
  });
@@ -2035,7 +2106,7 @@ var trust_resolver_exports = /* @__PURE__ */ __exportAll({
2035
2106
  function findIdentityLink(identityLinks, provider, providerUsername, providerUserId) {
2036
2107
  if (providerUserId === void 0 || providerUserId.length === 0) {
2037
2108
  trustMatchRefusedNoIdTotal.add(1, { reason: "event_missing" });
2038
- logger$93.warn("Trust match refused: webhook event has no provider numeric id", {
2109
+ logger$94.warn("Trust match refused: webhook event has no provider numeric id", {
2039
2110
  provider,
2040
2111
  providerUsername
2041
2112
  });
@@ -2047,7 +2118,7 @@ function findIdentityLink(identityLinks, provider, providerUsername, providerUse
2047
2118
  if (byUsername) {
2048
2119
  const reason = byUsername.providerUserId === null || byUsername.providerUserId === void 0 ? "link_missing" : "id_mismatch";
2049
2120
  trustMatchRefusedNoIdTotal.add(1, { reason });
2050
- logger$93.warn("Trust match refused: numeric id missing on link or did not match event", {
2121
+ logger$94.warn("Trust match refused: numeric id missing on link or did not match event", {
2051
2122
  provider,
2052
2123
  providerUsername,
2053
2124
  providerUserId,
@@ -2075,10 +2146,10 @@ function isReadOrHigher(permission) {
2075
2146
  function isCiTrustWriteOrHigher(level) {
2076
2147
  return level === "write" || level === "admin";
2077
2148
  }
2078
- var logger$93, TrustResolver$1;
2149
+ var logger$94, TrustResolver$1;
2079
2150
  var init_trust_resolver = __esmMin((() => {
2080
2151
  init_prometheus();
2081
- logger$93 = createLogger({ prefix: "trust-resolver" });
2152
+ logger$94 = createLogger({ prefix: "trust-resolver" });
2082
2153
  TrustResolver$1 = class {
2083
2154
  constructor(contributorCache) {
2084
2155
  this.contributorCache = contributorCache;
@@ -2208,14 +2279,14 @@ async function handleApprovalComment(params) {
2208
2279
  const { commentBody, commenterUsername, commenterUserId, provider, orgId, identityLinks, orgMemberPermissions, heldRunStore } = params;
2209
2280
  const command = parseKiciCommand(commentBody);
2210
2281
  if (!command) return { handled: false };
2211
- logger$92.info("Processing /kici command", {
2282
+ logger$93.info("Processing /kici command", {
2212
2283
  action: command.action,
2213
2284
  commenter: commenterUsername,
2214
2285
  runId: command.runId
2215
2286
  });
2216
2287
  const identityLink = findIdentityLink(identityLinks, provider, commenterUsername, commenterUserId);
2217
2288
  if (!identityLink) {
2218
- logger$92.info("No identity link for commenter", {
2289
+ logger$93.info("No identity link for commenter", {
2219
2290
  commenter: commenterUsername,
2220
2291
  provider
2221
2292
  });
@@ -2226,7 +2297,7 @@ async function handleApprovalComment(params) {
2226
2297
  }
2227
2298
  const ciTrustLevel = orgMemberPermissions.get(identityLink.userId) ?? "none";
2228
2299
  if (ciTrustLevel !== "write" && ciTrustLevel !== "admin") {
2229
- logger$92.info("Insufficient ci_trust level", {
2300
+ logger$93.info("Insufficient ci_trust level", {
2230
2301
  commenter: commenterUsername,
2231
2302
  userId: identityLink.userId,
2232
2303
  ciTrustLevel
@@ -2238,12 +2309,12 @@ async function handleApprovalComment(params) {
2238
2309
  }
2239
2310
  const pendingHolds = await heldRunStore.listByQueueType(orgId, "security", { status: "pending" });
2240
2311
  if (pendingHolds.length === 0) {
2241
- logger$92.info("No pending security holds found", { orgId });
2312
+ logger$93.info("No pending security holds found", { orgId });
2242
2313
  return { handled: true };
2243
2314
  }
2244
2315
  const targetHolds = command.runId ? pendingHolds.filter((h) => h.run_id === command.runId) : pendingHolds;
2245
2316
  if (targetHolds.length === 0) {
2246
- logger$92.info("No matching security holds found", {
2317
+ logger$93.info("No matching security holds found", {
2247
2318
  orgId,
2248
2319
  runId: command.runId
2249
2320
  });
@@ -2254,14 +2325,14 @@ async function handleApprovalComment(params) {
2254
2325
  for (const hold of targetHolds) try {
2255
2326
  if (approved) {
2256
2327
  await heldRunStore.approveByQueueType(orgId, hold.id, identityLink.userId, "security");
2257
- logger$92.info("Security hold approved", {
2328
+ logger$93.info("Security hold approved", {
2258
2329
  heldRunId: hold.id,
2259
2330
  runId: hold.run_id,
2260
2331
  approvedBy: identityLink.userId
2261
2332
  });
2262
2333
  } else {
2263
2334
  await heldRunStore.reject(orgId, hold.id, `Rejected by ${commenterUsername} via /kici reject`);
2264
- logger$92.info("Security hold rejected", {
2335
+ logger$93.info("Security hold rejected", {
2265
2336
  heldRunId: hold.id,
2266
2337
  runId: hold.run_id,
2267
2338
  rejectedBy: commenterUsername
@@ -2269,7 +2340,7 @@ async function handleApprovalComment(params) {
2269
2340
  }
2270
2341
  processedCount++;
2271
2342
  } catch (err) {
2272
- logger$92.error("Failed to process security hold", {
2343
+ logger$93.error("Failed to process security hold", {
2273
2344
  heldRunId: hold.id,
2274
2345
  action: command.action,
2275
2346
  error: toErrorMessage(err)
@@ -2279,15 +2350,15 @@ async function handleApprovalComment(params) {
2279
2350
  const title = approved ? "Approved" : "Rejected";
2280
2351
  const summary = approved ? `Approved by ${commenterUsername} via /kici approve` : `Rejected by ${commenterUsername} via /kici reject`;
2281
2352
  params.checkStatusPoster.postCheckStatus(params.repoIdentifier, params.commitSha, approved ? "success" : "failure", title, summary, params.credentials).catch((err) => {
2282
- logger$92.warn("Failed to update check status after approval", { error: toErrorMessage(err) });
2353
+ logger$93.warn("Failed to update check status after approval", { error: toErrorMessage(err) });
2283
2354
  });
2284
2355
  }
2285
2356
  return { handled: true };
2286
2357
  }
2287
- var logger$92;
2358
+ var logger$93;
2288
2359
  var init_comment_handler = __esmMin((() => {
2289
2360
  init_trust_resolver();
2290
- logger$92 = createLogger({ prefix: "comment-handler" });
2361
+ logger$93 = createLogger({ prefix: "comment-handler" });
2291
2362
  }));
2292
2363
  //#endregion
2293
2364
  //#region src/registration/extractor.ts
@@ -2381,9 +2452,9 @@ function payloadFromObject$1(payload) {
2381
2452
  function payloadFromRawBody(body) {
2382
2453
  return { raw: Buffer.from(body, "utf-8") };
2383
2454
  }
2384
- var logger$91, EventLogWriter;
2455
+ var logger$92, EventLogWriter;
2385
2456
  var init_event_log$1 = __esmMin((() => {
2386
- logger$91 = createLogger({ prefix: "event-log" });
2457
+ logger$92 = createLogger({ prefix: "event-log" });
2387
2458
  EventLogWriter = class EventLogWriter {
2388
2459
  db;
2389
2460
  logStorage;
@@ -2419,7 +2490,7 @@ var init_event_log$1 = __esmMin((() => {
2419
2490
  if (sizeBytes > this.opts.maxPayloadBytes) {
2420
2491
  payloadOmitted = true;
2421
2492
  payloadOmittedReason = PayloadOmittedReason.enum.size_exceeded;
2422
- logger$91.warn("Webhook payload exceeds soft cap; recording metadata only", {
2493
+ logger$92.warn("Webhook payload exceeds soft cap; recording metadata only", {
2423
2494
  deliveryId: info.deliveryId,
2424
2495
  sizeBytes,
2425
2496
  maxBytes: this.opts.maxPayloadBytes
@@ -2433,7 +2504,7 @@ var init_event_log$1 = __esmMin((() => {
2433
2504
  } catch (err) {
2434
2505
  payloadOmitted = true;
2435
2506
  payloadOmittedReason = PayloadOmittedReason.enum.storage_failed;
2436
- logger$91.error("Failed to upload event-log payload to object storage", {
2507
+ logger$92.error("Failed to upload event-log payload to object storage", {
2437
2508
  deliveryId: info.deliveryId,
2438
2509
  orgId: outcome.orgId,
2439
2510
  error: toErrorMessage(err)
@@ -2470,7 +2541,7 @@ var init_event_log$1 = __esmMin((() => {
2470
2541
  ref: row.ref
2471
2542
  })).execute();
2472
2543
  } catch (err) {
2473
- logger$91.error("Failed to record event_log row", {
2544
+ logger$92.error("Failed to record event_log row", {
2474
2545
  deliveryId: info.deliveryId,
2475
2546
  orgId: outcome.orgId,
2476
2547
  error: toErrorMessage(err)
@@ -3501,7 +3572,7 @@ async function mintCloneTokenForReroute(args) {
3501
3572
  try {
3502
3573
  return await args.bundle.cloneTokenProvider?.createCloneToken(args.repoIdentifier, args.credentials) ?? void 0;
3503
3574
  } catch (err) {
3504
- logger$90.warn("Failed to pre-resolve clone token for cluster reroute, agent may fail clone", {
3575
+ logger$91.warn("Failed to pre-resolve clone token for cluster reroute, agent may fail clone", {
3505
3576
  runId: args.runId,
3506
3577
  workflow: args.workflowName,
3507
3578
  error: toErrorMessage(err)
@@ -3512,7 +3583,7 @@ async function mintCloneTokenForReroute(args) {
3512
3583
  /**
3513
3584
  * Build the wrapped dispatcher, overlay info with effective routing/provider,
3514
3585
  * persist the webhook payload, fire source-location callbacks, and post the
3515
- * pending commit-status check. Pure side-effects + a typed result bag for
3586
+ * pending check-run check. Pure side-effects + a typed result bag for
3516
3587
  * downstream phases.
3517
3588
  */
3518
3589
  async function setupDispatchContext(ctx) {
@@ -3539,14 +3610,14 @@ async function setupDispatchContext(ctx) {
3539
3610
  const backend = deps.logStorage.constructor.name;
3540
3611
  try {
3541
3612
  await deps.logStorage.append(payloadPath, payloadBytes);
3542
- logger$90.info("Stored webhook payload for run", {
3613
+ logger$91.info("Stored webhook payload for run", {
3543
3614
  runId,
3544
3615
  payloadPath,
3545
3616
  bytes: payloadBytes.length,
3546
3617
  logStorageBackend: backend
3547
3618
  });
3548
3619
  } catch (err) {
3549
- logger$90.error("Failed to store webhook payload", {
3620
+ logger$91.error("Failed to store webhook payload", {
3550
3621
  runId,
3551
3622
  payloadPath,
3552
3623
  bytes: payloadBytes.length,
@@ -3563,10 +3634,10 @@ async function setupDispatchContext(ctx) {
3563
3634
  const locs = job.steps.map((s) => s.sourceLocation);
3564
3635
  if (locs.some((l) => l !== void 0)) deps.onSourceLocationsExtracted(workflow.name, job.name, locs);
3565
3636
  }
3566
- if (deps.commitStatusReporter) {
3637
+ if (deps.checkRunReporter) {
3567
3638
  const [owner, repo] = repoIdentifier.split("/");
3568
3639
  const jobNames = workflow.jobs.filter(isLockStaticJob).map((j) => j.name);
3569
- await deps.commitStatusReporter.setPendingAwait({
3640
+ await deps.checkRunReporter.setPendingAwait({
3570
3641
  provider: info.provider,
3571
3642
  owner,
3572
3643
  repo,
@@ -3622,13 +3693,13 @@ async function probeCaches(ctx, setup, contentHash, lockfileHash, targetPlatform
3622
3693
  sourceHit = await deps.sourceCache.has(contentHash);
3623
3694
  if (sourceHit) {
3624
3695
  sourceCacheHitsTotal.add(1);
3625
- logger$90.info("Source cache hit", {
3696
+ logger$91.info("Source cache hit", {
3626
3697
  workflow: workflow.name,
3627
3698
  contentHash
3628
3699
  });
3629
3700
  } else {
3630
3701
  sourceCacheMissesTotal.add(1);
3631
- logger$90.info("Source cache miss", {
3702
+ logger$91.info("Source cache miss", {
3632
3703
  workflow: workflow.name,
3633
3704
  contentHash
3634
3705
  });
@@ -3643,13 +3714,13 @@ async function probeCaches(ctx, setup, contentHash, lockfileHash, targetPlatform
3643
3714
  depHit = await deps.depCache.has(lockfileHash, targetPlatform, targetArch);
3644
3715
  if (depHit) {
3645
3716
  depCacheHitsTotal.add(1);
3646
- logger$90.info("Dep cache hit", {
3717
+ logger$91.info("Dep cache hit", {
3647
3718
  workflow: workflow.name,
3648
3719
  lockfileHash
3649
3720
  });
3650
3721
  } else {
3651
3722
  depCacheMissesTotal.add(1);
3652
- logger$90.info("Dep cache miss", {
3723
+ logger$91.info("Dep cache miss", {
3653
3724
  workflow: workflow.name,
3654
3725
  lockfileHash
3655
3726
  });
@@ -3718,9 +3789,9 @@ async function runBuildJob(args) {
3718
3789
  let rejected = false;
3719
3790
  let error;
3720
3791
  const coalescingKey = `${contentHash || "none"}:${lockfileHash || "none"}`;
3721
- if (deps.commitStatusReporter) {
3792
+ if (deps.checkRunReporter) {
3722
3793
  const [owner, repo] = repoIdentifier.split("/");
3723
- deps.commitStatusReporter.setBuildPending({
3794
+ deps.checkRunReporter.setBuildPending({
3724
3795
  provider: setup.info.provider,
3725
3796
  owner,
3726
3797
  repo,
@@ -3741,7 +3812,7 @@ async function runBuildJob(args) {
3741
3812
  const result = await setup.dispatcher.dispatch(buildJobInput);
3742
3813
  if (result.status === "rejected") {
3743
3814
  const reason = `Build job dispatch rejected: ${result.reason}`;
3744
- logger$90.error(reason, {
3815
+ logger$91.error(reason, {
3745
3816
  runId,
3746
3817
  workflow: workflow.name
3747
3818
  });
@@ -3789,9 +3860,9 @@ async function runBuildJob(args) {
3789
3860
  async function recordBuildFailure(args) {
3790
3861
  const { ctx, setup, buildJobTrackedEarly, err, buildJobId } = args;
3791
3862
  const { deps, workflow, repoIdentifier, credentials, event, ref, runId } = ctx;
3792
- if (deps.commitStatusReporter) {
3863
+ if (deps.checkRunReporter) {
3793
3864
  const [owner, repo] = repoIdentifier.split("/");
3794
- deps.commitStatusReporter.setBuildComplete({
3865
+ deps.checkRunReporter.setBuildComplete({
3795
3866
  provider: setup.info.provider,
3796
3867
  owner,
3797
3868
  repo,
@@ -3809,7 +3880,7 @@ async function recordBuildFailure(args) {
3809
3880
  if (buildJobTrackedEarly) await deps.executionTracker.onBuildFailed(runId);
3810
3881
  else await deps.executionTracker.onBuildFailedBeforeTracking(runId, workflow.name, setup.info.provider, repoIdentifier, event.targetBranch, ref, setup.effectiveDeliveryId, credentials, setup.info.routingKey, buildTriggerEvent(event.type, event.action), extractCommitMessage$1(setup.info.event, setup.info.payload), toErrorMessage(err));
3811
3882
  } catch (cleanupErr) {
3812
- logger$90.warn("Failed to mark run as failed after build error", {
3883
+ logger$91.warn("Failed to mark run as failed after build error", {
3813
3884
  runId,
3814
3885
  error: toErrorMessage(cleanupErr)
3815
3886
  });
@@ -3817,7 +3888,7 @@ async function recordBuildFailure(args) {
3817
3888
  if (buildJobId) try {
3818
3889
  await deps.dispatcher.cancelQueuedJob(buildJobId, `Build failed: ${toErrorMessage(err)}`);
3819
3890
  } catch (cleanupErr) {
3820
- logger$90.warn("Failed to mark build job dispatch_queue row as failed", {
3891
+ logger$91.warn("Failed to mark build job dispatch_queue row as failed", {
3821
3892
  runId,
3822
3893
  buildJobId,
3823
3894
  error: toErrorMessage(cleanupErr)
@@ -3831,9 +3902,9 @@ async function recordBuildFailure(args) {
3831
3902
  async function readPostBuildCacheUrls(args) {
3832
3903
  const { ctx, setup, contentHash, lockfileHash, targetPlatform, targetArch } = args;
3833
3904
  const { deps, workflow, repoIdentifier, credentials, ref, runId } = ctx;
3834
- if (deps.commitStatusReporter) {
3905
+ if (deps.checkRunReporter) {
3835
3906
  const [owner, repo] = repoIdentifier.split("/");
3836
- deps.commitStatusReporter.setBuildComplete({
3907
+ deps.checkRunReporter.setBuildComplete({
3837
3908
  provider: setup.info.provider,
3838
3909
  owner,
3839
3910
  repo,
@@ -3929,7 +4000,7 @@ async function prepareCacheAndBuild(ctx, setup) {
3929
4000
  if (result.error !== void 0) {
3930
4001
  const buildDuration = Number(process.hrtime.bigint() - buildStart) / 1e9;
3931
4002
  buildDurationSeconds.record(buildDuration);
3932
- logger$90.warn("Build failed, skipping execution for workflow", {
4003
+ logger$91.warn("Build failed, skipping execution for workflow", {
3933
4004
  workflow: workflow.name,
3934
4005
  coalescingKey: `${contentHash || "none"}:${lockfileHash || "none"}`,
3935
4006
  error: toErrorMessage(result.error)
@@ -3943,7 +4014,7 @@ async function prepareCacheAndBuild(ctx, setup) {
3943
4014
  });
3944
4015
  if (hasDynamicEntries) {
3945
4016
  buildFailed = true;
3946
- logger$90.info("Build failed but workflow has dynamic entries, continuing with dynamic dispatch", {
4017
+ logger$91.info("Build failed but workflow has dynamic entries, continuing with dynamic dispatch", {
3947
4018
  workflow: workflow.name,
3948
4019
  dynamicEntryCount: dynamicEntries.length
3949
4020
  });
@@ -3989,7 +4060,7 @@ async function prepareCacheAndBuild(ctx, setup) {
3989
4060
  depsHash = depResult.hash;
3990
4061
  }
3991
4062
  }
3992
- if (!contentHash && deps.sourceCache) logger$90.debug("Workflow missing contentHash, agents will compile from source", { workflow: workflow.name });
4063
+ if (!contentHash && deps.sourceCache) logger$91.debug("Workflow missing contentHash, agents will compile from source", { workflow: workflow.name });
3993
4064
  return {
3994
4065
  sourceTarUrl,
3995
4066
  sourceTarHash,
@@ -4017,7 +4088,7 @@ async function resolveWorkflowSecretsAndKey(ctx) {
4017
4088
  const declaredContexts = workflow.contexts ?? [];
4018
4089
  if (declaredContexts.length > 0) {
4019
4090
  if (!deps.secretResolver) {
4020
- logger$90.error("Workflow declares secret contexts but secrets subsystem is not configured (KICI_SECRET_KEY missing)", {
4091
+ logger$91.error("Workflow declares secret contexts but secrets subsystem is not configured (KICI_SECRET_KEY missing)", {
4021
4092
  workflow: workflow.name,
4022
4093
  contexts: declaredContexts
4023
4094
  });
@@ -4036,7 +4107,7 @@ async function resolveWorkflowSecretsAndKey(ctx) {
4036
4107
  resolvedNamespacedSecrets = mergedNamespaced;
4037
4108
  }
4038
4109
  } catch (err) {
4039
- logger$90.error("Secret resolution failed, skipping workflow", {
4110
+ logger$91.error("Secret resolution failed, skipping workflow", {
4040
4111
  workflow: workflow.name,
4041
4112
  error: toErrorMessage(err)
4042
4113
  });
@@ -4054,7 +4125,7 @@ async function resolveWorkflowSecretsAndKey(ctx) {
4054
4125
  public_key: runPublicKeyBase64
4055
4126
  }).execute();
4056
4127
  } catch (err) {
4057
- logger$90.warn("Failed to generate ephemeral key pair for run, secret outputs disabled", {
4128
+ logger$91.warn("Failed to generate ephemeral key pair for run, secret outputs disabled", {
4058
4129
  runId,
4059
4130
  error: toErrorMessage(err)
4060
4131
  });
@@ -4089,7 +4160,7 @@ async function resolveWorkflowInstallSecrets(ctx, secrets) {
4089
4160
  if (deps.db) try {
4090
4161
  allowHttp = (await deps.db.selectFrom("org_settings").select("allow_http_npm_registries").where("customer_id", "=", resolvedOrgId).executeTakeFirst())?.allow_http_npm_registries ?? false;
4091
4162
  } catch (err) {
4092
- logger$90.warn("Failed to read org_settings.allow_http_npm_registries — defaulting to false", {
4163
+ logger$91.warn("Failed to read org_settings.allow_http_npm_registries — defaulting to false", {
4093
4164
  runId,
4094
4165
  workflow: workflow.name,
4095
4166
  error: toErrorMessage(err)
@@ -4113,20 +4184,20 @@ async function resolveWorkflowInstallSecrets(ctx, secrets) {
4113
4184
  protectionContext
4114
4185
  });
4115
4186
  if (result.decision === "reject") {
4116
- logger$90.error("Workflow install-secrets resolution rejected dispatch", {
4187
+ logger$91.error("Workflow install-secrets resolution rejected dispatch", {
4117
4188
  runId,
4118
4189
  workflow: workflow.name,
4119
4190
  reason: result.reason
4120
4191
  });
4121
4192
  return { skipDispatch: true };
4122
4193
  }
4123
- if (result.contributorStripped) logger$90.warn("Skipping registries:/installEnv: resolution for untrusted contributor — install will fail naturally if private deps are required", {
4194
+ if (result.contributorStripped) logger$91.warn("Skipping registries:/installEnv: resolution for untrusted contributor — install will fail naturally if private deps are required", {
4124
4195
  runId,
4125
4196
  workflow: workflow.name,
4126
4197
  contributor: trustResolution?.contributorUsername,
4127
4198
  tier: trustResolution?.tier
4128
4199
  });
4129
- else logger$90.info("Resolved workflow install secrets", {
4200
+ else logger$91.info("Resolved workflow install secrets", {
4130
4201
  runId,
4131
4202
  workflow: workflow.name,
4132
4203
  registryCount: result.npmRegistries?.length ?? 0,
@@ -4242,7 +4313,7 @@ async function applyEnvironmentRulesAndSecrets(args) {
4242
4313
  if (gateResult.action === "reject") {
4243
4314
  jobEnvData.rejected = true;
4244
4315
  jobEnvData.rejectReason = gateResult.reason ?? "Rejected by protection rules";
4245
- logger$90.info("Job rejected by protection rules", {
4316
+ logger$91.info("Job rejected by protection rules", {
4246
4317
  runId,
4247
4318
  workflow: workflow.name,
4248
4319
  job: lockJob.name,
@@ -4263,7 +4334,7 @@ async function applyEnvironmentRulesAndSecrets(args) {
4263
4334
  await deps.heldRunStore.create(resolvedOrgId, heldRunData);
4264
4335
  }
4265
4336
  jobEnvData.held = true;
4266
- logger$90.info("Job held by protection rules", {
4337
+ logger$91.info("Job held by protection rules", {
4267
4338
  runId,
4268
4339
  workflow: workflow.name,
4269
4340
  job: lockJob.name,
@@ -4274,7 +4345,7 @@ async function applyEnvironmentRulesAndSecrets(args) {
4274
4345
  if (gateResult.holdType === "security" && bundle.checkStatusPoster) {
4275
4346
  const holdSummary = buildSecurityHoldSummary("environment_trust", trustResolution?.tier ?? "unknown", trustResolution?.contributorUsername);
4276
4347
  bundle.checkStatusPoster.postCheckStatus(repoIdentifier, ref, "pending", "Held for approval", holdSummary, credentials).catch((err) => {
4277
- logger$90.warn("Failed to post security hold check", {
4348
+ logger$91.warn("Failed to post security hold check", {
4278
4349
  runId,
4279
4350
  job: lockJob.name,
4280
4351
  error: toErrorMessage(err)
@@ -4293,7 +4364,7 @@ async function applyEnvironmentRulesAndSecrets(args) {
4293
4364
  jobEnvData.jobNamespacedSecrets = { [environmentName]: envSecrets };
4294
4365
  }
4295
4366
  } catch (err) {
4296
- logger$90.error("Per-job secret resolution failed", {
4367
+ logger$91.error("Per-job secret resolution failed", {
4297
4368
  runId,
4298
4369
  workflow: workflow.name,
4299
4370
  job: lockJob.name,
@@ -4317,7 +4388,7 @@ async function evaluateJobEnvironments(args) {
4317
4388
  for (const lockJob of buildPrep.staticJobs) {
4318
4389
  const jobEnvData = {};
4319
4390
  const { inlineEnvironmentName, inlineEnv, inlineConcurrencyGroup } = evaluateInlineFields(lockJob, inlinePayload);
4320
- if (inlineEnvironmentName || inlineEnv || inlineConcurrencyGroup) logger$90.debug("Inline evaluation resolved dynamic fields", {
4391
+ if (inlineEnvironmentName || inlineEnv || inlineConcurrencyGroup) logger$91.debug("Inline evaluation resolved dynamic fields", {
4321
4392
  job: lockJob.name,
4322
4393
  environment: !!inlineEnvironmentName,
4323
4394
  env: !!inlineEnv,
@@ -4433,12 +4504,12 @@ function logRoleAwareFailure(failure, flatLabels, runId, workflowName) {
4433
4504
  const roleName = roleLabel.replace("kici:role:", "");
4434
4505
  const platformLabels = flatLabels.filter((l) => l.startsWith("kici:os:") || l.startsWith("kici:arch:")).map((l) => l.split(":").pop());
4435
4506
  const platformDesc = platformLabels.length > 0 ? platformLabels.join(", ") : "any platform";
4436
- logger$90.error(`No ${roleName} available for [${platformDesc}]. Add 'roles: [${roleName}]' to a scaler with matching labels, or use default 'roles: [all]'.`, {
4507
+ logger$91.error(`No ${roleName} available for [${platformDesc}]. Add 'roles: [${roleName}]' to a scaler with matching labels, or use default 'roles: [all]'.`, {
4437
4508
  runId,
4438
4509
  workflow: workflowName,
4439
4510
  job: failure.jobName
4440
4511
  });
4441
- } else logger$90.warn("Job routing failed", {
4512
+ } else logger$91.warn("Job routing failed", {
4442
4513
  runId,
4443
4514
  workflow: workflowName,
4444
4515
  job: failure.jobName,
@@ -4470,7 +4541,7 @@ async function preRegisterNonRootJobs(args) {
4470
4541
  jobName: gatedJob.name,
4471
4542
  runsOnLabels
4472
4543
  });
4473
- logger$90.info("Job gated by needs scheduler (cluster path)", {
4544
+ logger$91.info("Job gated by needs scheduler (cluster path)", {
4474
4545
  runId,
4475
4546
  workflow: workflow.name,
4476
4547
  job: gatedJob.name
@@ -4482,7 +4553,7 @@ async function clusterRouteRootJobs(args) {
4482
4553
  const { ctx, setup, buildPrep, buildJobConfig, rootDispatchableJobs, needsGatedCount, dispatchedJobs, rejectedJobs } = args;
4483
4554
  const { deps, workflow, repoIdentifier, credentials, event, ref, runId, bundle } = ctx;
4484
4555
  if (rootDispatchableJobs.length === 0) {
4485
- logger$90.info("All dispatchable jobs deferred or needs-gated, skipping coordinator routing", {
4556
+ logger$91.info("All dispatchable jobs deferred or needs-gated, skipping coordinator routing", {
4486
4557
  runId,
4487
4558
  workflow: workflow.name,
4488
4559
  needsGated: needsGatedCount
@@ -4530,7 +4601,7 @@ async function clusterRouteRootJobs(args) {
4530
4601
  const routeResult = await Promise.race([deps.coordinator.routeJobs(runCtx, jobsToRoute), new Promise((_, reject) => {
4531
4602
  routeTimeout = setTimeout(() => reject(/* @__PURE__ */ new Error("routeJobs timed out after 30s")), 3e4);
4532
4603
  })]).catch((err) => {
4533
- logger$90.warn("Coordinator routing timed out, dispatching locally", {
4604
+ logger$91.warn("Coordinator routing timed out, dispatching locally", {
4534
4605
  runId,
4535
4606
  workflow: workflow.name,
4536
4607
  error: toErrorMessage(err)
@@ -4573,7 +4644,7 @@ async function clusterRouteRootJobs(args) {
4573
4644
  jobId: syntheticId,
4574
4645
  reason: result.reason
4575
4646
  });
4576
- } else if (result.status === "queued-no-backend") logger$90.warn("Job has no matching backend (cluster fallback), skipping", {
4647
+ } else if (result.status === "queued-no-backend") logger$91.warn("Job has no matching backend (cluster fallback), skipping", {
4577
4648
  runId,
4578
4649
  workflow: workflow.name,
4579
4650
  job: jtr.jobName,
@@ -4603,7 +4674,7 @@ async function clusterRouteRootJobs(args) {
4603
4674
  jobName: rerouted.jobName,
4604
4675
  runsOnLabels: flatLabels
4605
4676
  });
4606
- logger$90.info("Job rerouted to peer", {
4677
+ logger$91.info("Job rerouted to peer", {
4607
4678
  runId,
4608
4679
  workflow: workflow.name,
4609
4680
  job: rerouted.jobName,
@@ -4620,7 +4691,7 @@ async function dispatchSingleOrchPath(args) {
4620
4691
  for (const jobOrFactory of buildPrep.staticJobs) {
4621
4692
  const envData = jobEnvironmentData.get(jobOrFactory.name);
4622
4693
  if (envData?.rejected) {
4623
- logger$90.info("Job skipped (rejected by protection rules)", {
4694
+ logger$91.info("Job skipped (rejected by protection rules)", {
4624
4695
  runId,
4625
4696
  workflow: workflow.name,
4626
4697
  job: jobOrFactory.name,
@@ -4629,7 +4700,7 @@ async function dispatchSingleOrchPath(args) {
4629
4700
  continue;
4630
4701
  }
4631
4702
  if (envData?.held) {
4632
- logger$90.info("Job held by protection rules", {
4703
+ logger$91.info("Job held by protection rules", {
4633
4704
  runId,
4634
4705
  workflow: workflow.name,
4635
4706
  job: jobOrFactory.name
@@ -4659,7 +4730,7 @@ async function dispatchSingleOrchPath(args) {
4659
4730
  jobName: jobOrFactory.name,
4660
4731
  runsOnLabels
4661
4732
  });
4662
- logger$90.info("Job gated by needs scheduler (not dispatched yet)", {
4733
+ logger$91.info("Job gated by needs scheduler (not dispatched yet)", {
4663
4734
  runId,
4664
4735
  workflow: workflow.name,
4665
4736
  job: jobOrFactory.name
@@ -4678,7 +4749,7 @@ async function dispatchSingleOrchPath(args) {
4678
4749
  jobId: syntheticId,
4679
4750
  reason: result.reason
4680
4751
  });
4681
- } else if (result.status === "queued-no-backend") logger$90.warn("Job has no matching backend, skipping execution tracking", {
4752
+ } else if (result.status === "queued-no-backend") logger$91.warn("Job has no matching backend, skipping execution tracking", {
4682
4753
  runId,
4683
4754
  workflow: workflow.name,
4684
4755
  job: jobOrFactory.name,
@@ -4690,7 +4761,7 @@ async function dispatchSingleOrchPath(args) {
4690
4761
  jobName: jobOrFactory.name,
4691
4762
  runsOnLabels
4692
4763
  });
4693
- logger$90.info("Job dispatched", {
4764
+ logger$91.info("Job dispatched", {
4694
4765
  runId,
4695
4766
  workflow: workflow.name,
4696
4767
  job: jobOrFactory.name,
@@ -4710,7 +4781,7 @@ async function dispatchStaticJobs(args) {
4710
4781
  const { ctx, setup, buildPrep, buildJobConfig, jobEnvironmentData, dispatchedJobs, rejectedJobs } = args;
4711
4782
  const { deps, workflow, runId } = ctx;
4712
4783
  if (buildPrep.buildFailed) {
4713
- logger$90.info("Skipping static job dispatch due to build failure", {
4784
+ logger$91.info("Skipping static job dispatch due to build failure", {
4714
4785
  runId,
4715
4786
  workflow: workflow.name,
4716
4787
  staticJobCount: buildPrep.staticJobs.length
@@ -4763,7 +4834,7 @@ async function recordRunStart(args) {
4763
4834
  await deps.executionTracker.addJobsToRun(runId, executionJobs, declaredContexts.length > 0 ? [...declaredContexts] : void 0);
4764
4835
  } else await deps.executionTracker.onExecutionStarted(runId, workflow.name, setup.info.provider, repoIdentifier, event.targetBranch, ref, setup.effectiveDeliveryId, credentials, summarizeDecision(decision), dispatchedJobs, setup.info.routingKey, declaredContexts.length > 0 ? [...declaredContexts] : void 0, buildTriggerEvent(event.type, event.action), extractCommitMessage$1(setup.info.event, setup.info.payload), void 0, void 0, void 0, setup.workflowConcurrency);
4765
4836
  if (runEnvironmentName && deps.db) deps.db.updateTable("execution_runs").set({ environment: runEnvironmentName }).where("run_id", "=", runId).execute().catch((err) => {
4766
- logger$90.error("Failed to set environment on execution run", {
4837
+ logger$91.error("Failed to set environment on execution run", {
4767
4838
  runId,
4768
4839
  environment: runEnvironmentName,
4769
4840
  error: toErrorMessage(err)
@@ -4774,7 +4845,7 @@ async function recordRunStart(args) {
4774
4845
  lock_file_source: lockFileSource,
4775
4846
  contributor_username: trustResolution.contributorUsername
4776
4847
  }).where("run_id", "=", runId).execute().catch((err) => {
4777
- logger$90.error("Failed to set trust context on execution run", {
4848
+ logger$91.error("Failed to set trust context on execution run", {
4778
4849
  runId,
4779
4850
  error: toErrorMessage(err)
4780
4851
  });
@@ -4786,7 +4857,7 @@ async function insertEdgesAndMarkRejected(args) {
4786
4857
  if (deps.db && dispatchedJobs.length > 0) try {
4787
4858
  await insertEdgesForRun(deps.db, runId, staticJobs);
4788
4859
  } catch (err) {
4789
- logger$90.error("Failed to insert needs edges for run", {
4860
+ logger$91.error("Failed to insert needs edges for run", {
4790
4861
  runId,
4791
4862
  error: toErrorMessage(err)
4792
4863
  });
@@ -4794,7 +4865,7 @@ async function insertEdgesAndMarkRejected(args) {
4794
4865
  if (deps.executionTracker && rejectedJobs.length > 0) {
4795
4866
  const now = Date.now();
4796
4867
  for (const { jobId, reason } of rejectedJobs) deps.executionTracker.onJobStatus(runId, jobId, ExecutionJobStatus.enum.failed, now, void 0, { error: reason }).catch((err) => {
4797
- logger$90.error("Failed to mark rejected job as failed", {
4868
+ logger$91.error("Failed to mark rejected job as failed", {
4798
4869
  runId,
4799
4870
  jobId,
4800
4871
  error: toErrorMessage(err)
@@ -4826,7 +4897,7 @@ async function applyInitResultEnvironment(args) {
4826
4897
  jobEnvData.jobNamespacedSecrets = { [initResult.environmentName]: envSecrets };
4827
4898
  }
4828
4899
  } catch (err) {
4829
- logger$90.error("Deferred init: secret resolution failed", {
4900
+ logger$91.error("Deferred init: secret resolution failed", {
4830
4901
  runId,
4831
4902
  job: lockJob.name,
4832
4903
  error: toErrorMessage(err)
@@ -4903,7 +4974,7 @@ async function dispatchExecutionAfterInit(args) {
4903
4974
  jobName: local.jobName,
4904
4975
  runsOnLabels: jobInput.runsOnLabels
4905
4976
  }]).catch((err) => {
4906
- logger$90.error("Failed to add deferred init job to execution tracker", {
4977
+ logger$91.error("Failed to add deferred init job to execution tracker", {
4907
4978
  runId,
4908
4979
  error: toErrorMessage(err)
4909
4980
  });
@@ -4924,13 +4995,13 @@ async function dispatchExecutionAfterInit(args) {
4924
4995
  jobName: lockJob.name,
4925
4996
  runsOnLabels: jobInput.runsOnLabels
4926
4997
  }]).catch((err) => {
4927
- logger$90.error("Failed to add deferred init job to execution tracker", {
4998
+ logger$91.error("Failed to add deferred init job to execution tracker", {
4928
4999
  runId,
4929
5000
  error: toErrorMessage(err)
4930
5001
  });
4931
5002
  });
4932
5003
  }
4933
- logger$90.info("Deferred init job resolved, execution job dispatched", {
5004
+ logger$91.info("Deferred init job resolved, execution job dispatched", {
4934
5005
  runId,
4935
5006
  workflow: workflow.name,
4936
5007
  job: lockJob.name,
@@ -4941,14 +5012,14 @@ function startDeferredInitDispatch(args) {
4941
5012
  const { ctx, setup, buildPrep, buildJobConfig, jobEnvironmentData, deferredInitJobs } = args;
4942
5013
  const { deps, workflow, runId } = ctx;
4943
5014
  if (deferredInitJobs.length === 0 || !deps.pendingInits) return;
4944
- logger$90.info("Starting deferred init dispatch", {
5015
+ logger$91.info("Starting deferred init dispatch", {
4945
5016
  runId,
4946
5017
  count: deferredInitJobs.length
4947
5018
  });
4948
5019
  const pendingInits = deps.pendingInits;
4949
5020
  for (const { lockJob, initJobInput } of deferredInitJobs) (async () => {
4950
5021
  try {
4951
- logger$90.info("Dispatching deferred init job", {
5022
+ logger$91.info("Dispatching deferred init job", {
4952
5023
  runId,
4953
5024
  workflow: workflow.name,
4954
5025
  job: lockJob.name,
@@ -4974,7 +5045,7 @@ function startDeferredInitDispatch(args) {
4974
5045
  lockJob
4975
5046
  });
4976
5047
  } catch (err) {
4977
- logger$90.error("Deferred init job failed", {
5048
+ logger$91.error("Deferred init job failed", {
4978
5049
  runId,
4979
5050
  workflow: workflow.name,
4980
5051
  job: lockJob.name,
@@ -4992,7 +5063,7 @@ async function dispatchEvalJob(args) {
4992
5063
  const { ctx, setup, buildPrep, dynamicEntry } = args;
4993
5064
  const { deps, workflow, repoIdentifier, credentials, event, ref, runId, bundle } = ctx;
4994
5065
  const evalJobName = `__dynamic__${workflow.name}__${dynamicEntry.source.index}`;
4995
- logger$90.info("Dispatching dynamic eval job", {
5066
+ logger$91.info("Dispatching dynamic eval job", {
4996
5067
  runId,
4997
5068
  workflow: workflow.name,
4998
5069
  evalJob: evalJobName,
@@ -5076,7 +5147,7 @@ async function resolveGeneratedJobConfigs(args) {
5076
5147
  };
5077
5148
  }
5078
5149
  } catch (err) {
5079
- logger$90.error("Dynamic job: secret resolution failed", {
5150
+ logger$91.error("Dynamic job: secret resolution failed", {
5080
5151
  runId,
5081
5152
  job: genJob.name,
5082
5153
  error: toErrorMessage(err)
@@ -5116,7 +5187,7 @@ async function resolveGeneratedJobConfigs(args) {
5116
5187
  runsOnLabels: Array.isArray(genJob.runsOn) ? [...genJob.runsOn] : [genJob.runsOn]
5117
5188
  });
5118
5189
  } catch (err) {
5119
- logger$90.error("Failed to resolve secrets for dynamic generated job", {
5190
+ logger$91.error("Failed to resolve secrets for dynamic generated job", {
5120
5191
  runId,
5121
5192
  job: genJob.name,
5122
5193
  error: toErrorMessage(err)
@@ -5173,7 +5244,7 @@ async function gateAndStoreNonRootGeneratedJobs(args) {
5173
5244
  jobName: genJob.name,
5174
5245
  runsOnLabels
5175
5246
  }]);
5176
- logger$90.info("Generated job gated by cross-domain needs", {
5247
+ logger$91.info("Generated job gated by cross-domain needs", {
5177
5248
  runId,
5178
5249
  workflow: workflow.name,
5179
5250
  job: genJob.name,
@@ -5211,13 +5282,13 @@ async function directDispatchGeneratedJobs(args) {
5211
5282
  jobName: genJob.name,
5212
5283
  runsOnLabels
5213
5284
  }]);
5214
- logger$90.info("Dynamic generated job dispatched (direct)", {
5285
+ logger$91.info("Dynamic generated job dispatched (direct)", {
5215
5286
  runId,
5216
5287
  job: genJob.name,
5217
5288
  status: genResult.status
5218
5289
  });
5219
5290
  } catch (err) {
5220
- logger$90.error("Failed to dispatch dynamic generated job", {
5291
+ logger$91.error("Failed to dispatch dynamic generated job", {
5221
5292
  runId,
5222
5293
  job: genJob.name,
5223
5294
  error: toErrorMessage(err)
@@ -5278,7 +5349,7 @@ async function routeRootGeneratedJobs(args) {
5278
5349
  const routeResult = await Promise.race([deps.coordinator.routeJobs(genRunCtx, generatedJobsToRoute), new Promise((_, reject) => {
5279
5350
  genRouteTimeout = setTimeout(() => reject(/* @__PURE__ */ new Error("routeJobs timed out after 60s")), 6e4);
5280
5351
  })]).catch((err) => {
5281
- logger$90.warn("Generated job coordinator routing timed out, falling back to direct dispatch", {
5352
+ logger$91.warn("Generated job coordinator routing timed out, falling back to direct dispatch", {
5282
5353
  runId,
5283
5354
  workflow: workflow.name,
5284
5355
  error: toErrorMessage(err),
@@ -5303,25 +5374,25 @@ async function routeRootGeneratedJobs(args) {
5303
5374
  jobName: local.jobName,
5304
5375
  runsOnLabels: matchingConfig?.runsOnLabels ?? []
5305
5376
  }]).catch((err) => {
5306
- logger$90.error("Failed to add generated job to execution tracker", {
5377
+ logger$91.error("Failed to add generated job to execution tracker", {
5307
5378
  runId,
5308
5379
  job: local.jobName,
5309
5380
  error: toErrorMessage(err)
5310
5381
  });
5311
5382
  });
5312
5383
  }
5313
- for (const rerouted of routeResult.reroutedJobs) logger$90.info("Generated job rerouted to peer", {
5384
+ for (const rerouted of routeResult.reroutedJobs) logger$91.info("Generated job rerouted to peer", {
5314
5385
  runId,
5315
5386
  job: rerouted.jobName,
5316
5387
  peerId: rerouted.peerId
5317
5388
  });
5318
- for (const failed of routeResult.failedJobs) logger$90.error(`Generated job '${failed.jobName}' routing failed: ${failed.reason}. This indicates a capability advertisement mismatch — the peer was selected based on advertised labels but rejected the job.`, {
5389
+ for (const failed of routeResult.failedJobs) logger$91.error(`Generated job '${failed.jobName}' routing failed: ${failed.reason}. This indicates a capability advertisement mismatch — the peer was selected based on advertised labels but rejected the job.`, {
5319
5390
  runId,
5320
5391
  workflow: workflow.name,
5321
5392
  job: failed.jobName,
5322
5393
  reason: failed.reason
5323
5394
  });
5324
- logger$90.info("Generated jobs routed via coordinator", {
5395
+ logger$91.info("Generated jobs routed via coordinator", {
5325
5396
  runId,
5326
5397
  workflow: workflow.name,
5327
5398
  local: routeResult.localJobs.length,
@@ -5334,7 +5405,7 @@ async function setGroupNameAndResolveEdges(args) {
5334
5405
  const { deps, runId } = ctx;
5335
5406
  if (!deps.db || !groupName) return;
5336
5407
  for (const memberName of generatedJobNames) await deps.db.updateTable("execution_jobs").set({ group_name: groupName }).where("run_id", "=", runId).where("job_name", "=", memberName).execute().catch((err) => {
5337
- logger$90.warn("Failed to set group_name on generated job", {
5408
+ logger$91.warn("Failed to set group_name on generated job", {
5338
5409
  runId,
5339
5410
  jobName: memberName,
5340
5411
  groupName,
@@ -5350,7 +5421,7 @@ async function setGroupNameAndResolveEdges(args) {
5350
5421
  });
5351
5422
  if (dependentStaticJobs.length > 0) {
5352
5423
  await resolveGroupEdges(deps.db, runId, groupName, generatedJobNames, dependentStaticJobs);
5353
- logger$90.info("Group edges resolved", {
5424
+ logger$91.info("Group edges resolved", {
5354
5425
  runId,
5355
5426
  groupName,
5356
5427
  members: generatedJobNames.length,
@@ -5408,7 +5479,7 @@ async function detectAndFailCycles(args) {
5408
5479
  if (visited >= allJobRows.length) return { cycle: false };
5409
5480
  const cycleJobs = [...inDegree.entries()].filter(([, d]) => d > 0).map(([n]) => n);
5410
5481
  const cycleTrace = cycleJobs.join(" -> ");
5411
- logger$90.error("Eval-time cycle detected in job graph", {
5482
+ logger$91.error("Eval-time cycle detected in job graph", {
5412
5483
  runId,
5413
5484
  cycleTrace
5414
5485
  });
@@ -5443,7 +5514,7 @@ async function processDynamicEntry(args) {
5443
5514
  dynamicEntry
5444
5515
  });
5445
5516
  const generatedJobs = await deps.pendingDynamics.track(evalJobId);
5446
- logger$90.info("Dynamic eval completed, dispatching generated jobs", {
5517
+ logger$91.info("Dynamic eval completed, dispatching generated jobs", {
5447
5518
  runId,
5448
5519
  workflow: workflow.name,
5449
5520
  generatedCount: generatedJobs.length,
@@ -5490,7 +5561,7 @@ async function processDynamicEntry(args) {
5490
5561
  memberJobNames: generatedJobs.map((j) => j.name)
5491
5562
  });
5492
5563
  } catch (err) {
5493
- logger$90.error("Dynamic eval job failed", {
5564
+ logger$91.error("Dynamic eval job failed", {
5494
5565
  runId,
5495
5566
  workflow: workflow.name,
5496
5567
  sourceIndex: dynamicEntry.source.index,
@@ -5613,7 +5684,7 @@ async function dispatchMatchedWorkflow(ctx) {
5613
5684
  });
5614
5685
  if (buildPrep.dynamicEntries.length > 0 && ctx.deps.pendingDynamics) {
5615
5686
  const hasStaticJobs = buildPrep.staticJobs.length > 0;
5616
- logger$90.info(hasStaticJobs ? "Starting deferred dynamic job dispatch" : "Dynamic-only workflow dispatching eval jobs", {
5687
+ logger$91.info(hasStaticJobs ? "Starting deferred dynamic job dispatch" : "Dynamic-only workflow dispatching eval jobs", {
5617
5688
  runId: ctx.runId,
5618
5689
  workflow: ctx.workflow.name,
5619
5690
  dynamicEntryCount: buildPrep.dynamicEntries.length,
@@ -5637,7 +5708,7 @@ async function dispatchMatchedWorkflow(ctx) {
5637
5708
  }
5638
5709
  return { dispatchedJobCount: dispatchedJobs.length };
5639
5710
  }
5640
- var logger$90;
5711
+ var logger$91;
5641
5712
  var init_dispatch_matched_workflow = __esmMin((() => {
5642
5713
  init_pipeline();
5643
5714
  init_environment_store();
@@ -5647,7 +5718,7 @@ var init_dispatch_matched_workflow = __esmMin((() => {
5647
5718
  init_needs_scheduler();
5648
5719
  init_prometheus();
5649
5720
  init_processor();
5650
- logger$90 = createLogger({ prefix: "pipeline" });
5721
+ logger$91 = createLogger({ prefix: "pipeline" });
5651
5722
  }));
5652
5723
  //#endregion
5653
5724
  //#region src/pipeline/process-webhook.ts
@@ -5702,7 +5773,7 @@ async function recordSkipEventLog(info, deps, resolvedOrgId, status) {
5702
5773
  async function dedupAndResolveProvider(info, deps) {
5703
5774
  const resolvedOrgId = await resolveOrgIdSafe(deps, info.routingKey);
5704
5775
  if (await deps.dedup.exists(info.deliveryId)) {
5705
- logger$89.debug("Duplicate webhook, skipping", { deliveryId: info.deliveryId });
5776
+ logger$90.debug("Duplicate webhook, skipping", { deliveryId: info.deliveryId });
5706
5777
  dedupHitsTotal.add(1);
5707
5778
  await recordSkipEventLog(info, deps, resolvedOrgId, EventLogStatus.enum.duplicate);
5708
5779
  return { status: "skip" };
@@ -5714,7 +5785,7 @@ async function dedupAndResolveProvider(info, deps) {
5714
5785
  });
5715
5786
  const bundle = deps.providerRegistry.getByRoutingKey(info.routingKey);
5716
5787
  if (!bundle) {
5717
- logger$89.debug("Unknown provider, skipping", {
5788
+ logger$90.debug("Unknown provider, skipping", {
5718
5789
  deliveryId: info.deliveryId,
5719
5790
  provider: info.provider,
5720
5791
  routingKey: info.routingKey
@@ -5751,7 +5822,7 @@ function invalidateContributorCacheForEvent(info, deps, bundle) {
5751
5822
  totalDeleted += deps.contributorCache.invalidateByUserInOrg(provider, inv.orgLogin, inv.username);
5752
5823
  break;
5753
5824
  }
5754
- logger$89.info("Invalidated contributor cache entries", {
5825
+ logger$90.info("Invalidated contributor cache entries", {
5755
5826
  deliveryId: info.deliveryId,
5756
5827
  event: info.event,
5757
5828
  action: info.action,
@@ -5766,7 +5837,7 @@ function invalidateContributorCacheForEvent(info, deps, bundle) {
5766
5837
  async function normalizeWebhookEvent(info, deps, bundle, resolvedOrgId) {
5767
5838
  const event = bundle.normalizer.normalizeEvent(info.event, info.action, info.payload);
5768
5839
  if (event) return event;
5769
- logger$89.debug("Unknown event type, skipping", {
5840
+ logger$90.debug("Unknown event type, skipping", {
5770
5841
  deliveryId: info.deliveryId,
5771
5842
  event: info.event
5772
5843
  });
@@ -5787,7 +5858,7 @@ async function gatherCrossSourceCandidates(info, deps, resolvedOrgId, inboundEve
5787
5858
  const remoteVersion = await deps.registrationStore.getVersion();
5788
5859
  await deps.registrationIndex.refreshIfNeeded(remoteVersion);
5789
5860
  } catch (err) {
5790
- logger$89.warn("Cross-source dispatch: registration index refresh failed", {
5861
+ logger$90.warn("Cross-source dispatch: registration index refresh failed", {
5791
5862
  deliveryId: info.deliveryId,
5792
5863
  error: toErrorMessage(err)
5793
5864
  });
@@ -5847,7 +5918,7 @@ async function dispatchOneCrossSourceCandidate(args) {
5847
5918
  const { reg } = candidate;
5848
5919
  const syntheticEvent = buildCrossSourceEvent(info, deps, candidate, inboundEventName);
5849
5920
  if (!syntheticEvent) {
5850
- logger$89.debug("Cross-source repo dispatch: unable to normalize inbound event", {
5921
+ logger$90.debug("Cross-source repo dispatch: unable to normalize inbound event", {
5851
5922
  deliveryId: info.deliveryId,
5852
5923
  registrationId: reg.id,
5853
5924
  routingKey: reg.routingKey,
@@ -5859,7 +5930,7 @@ async function dispatchOneCrossSourceCandidate(args) {
5859
5930
  if (matchedDecisions.length === 0) return 0;
5860
5931
  const crossDedupKey = `${info.deliveryId}:${reg.id}`;
5861
5932
  if (await deps.dedup.exists(crossDedupKey)) {
5862
- logger$89.debug("Cross-source dispatch: composite dedup hit", {
5933
+ logger$90.debug("Cross-source dispatch: composite dedup hit", {
5863
5934
  deliveryId: info.deliveryId,
5864
5935
  registrationId: reg.id
5865
5936
  });
@@ -5868,7 +5939,7 @@ async function dispatchOneCrossSourceCandidate(args) {
5868
5939
  await deps.dedup.mark(crossDedupKey);
5869
5940
  const regBundle = deps.providerRegistry.getByRoutingKey(reg.routingKey);
5870
5941
  if (!regBundle) {
5871
- logger$89.warn("Cross-source dispatch: registration bundle not found", {
5942
+ logger$90.warn("Cross-source dispatch: registration bundle not found", {
5872
5943
  deliveryId: info.deliveryId,
5873
5944
  registrationId: reg.id,
5874
5945
  routingKey: reg.routingKey
@@ -5884,7 +5955,7 @@ async function dispatchOneCrossSourceCandidate(args) {
5884
5955
  token
5885
5956
  };
5886
5957
  } catch (err) {
5887
- logger$89.error("Cross-source dispatch: clone token issuance failed", {
5958
+ logger$90.error("Cross-source dispatch: clone token issuance failed", {
5888
5959
  deliveryId: info.deliveryId,
5889
5960
  registrationId: reg.id,
5890
5961
  routingKey: reg.routingKey,
@@ -5969,7 +6040,7 @@ async function recordCrossSourceCompletion(args) {
5969
6040
  timestamp: Date.now()
5970
6041
  });
5971
6042
  webhooksProcessedTotal.add(1, { result: jobsDispatched > 0 ? "matched" : "skipped" });
5972
- logger$89.info("Cross-source webhook processed", {
6043
+ logger$90.info("Cross-source webhook processed", {
5973
6044
  deliveryId: info.deliveryId,
5974
6045
  inboundEventName,
5975
6046
  registrationsConsidered: candidatesConsidered,
@@ -6004,7 +6075,7 @@ async function dispatchCrossSourceWorkflows(info, deps, event, resolvedOrgId) {
6004
6075
  const candidates = await gatherCrossSourceCandidates(info, deps, resolvedOrgId, inboundEventName);
6005
6076
  crossSourceFanoutSize.record(candidates.length, { event: inboundEventName });
6006
6077
  if (candidates.length === 0) {
6007
- logger$89.debug("Cross-source: no registrations for event, falling through", {
6078
+ logger$90.debug("Cross-source: no registrations for event, falling through", {
6008
6079
  deliveryId: info.deliveryId,
6009
6080
  inboundEventName,
6010
6081
  orgId: resolvedOrgId
@@ -6037,7 +6108,7 @@ async function dispatchCrossSourceWorkflows(info, deps, event, resolvedOrgId) {
6037
6108
  async function extractRepoAndCredentials(info, deps, bundle, resolvedOrgId) {
6038
6109
  const repoIdentifier = bundle.normalizer.extractRepoIdentifier(info.payload);
6039
6110
  if (!repoIdentifier) {
6040
- logger$89.debug("Missing repository info in payload, skipping", { deliveryId: info.deliveryId });
6111
+ logger$90.debug("Missing repository info in payload, skipping", { deliveryId: info.deliveryId });
6041
6112
  webhooksProcessedTotal.add(1, { result: "skipped" });
6042
6113
  await recordSkipEventLog(info, deps, resolvedOrgId, EventLogStatus.enum.received);
6043
6114
  return null;
@@ -6082,7 +6153,7 @@ async function handleApprovalCommentIfPresent(args) {
6082
6153
  credentials
6083
6154
  });
6084
6155
  if (result.handled) {
6085
- logger$89.info("Handled /kici command from comment", {
6156
+ logger$90.info("Handled /kici command from comment", {
6086
6157
  deliveryId: info.deliveryId,
6087
6158
  action: command.action,
6088
6159
  commenter: senderUsername,
@@ -6124,7 +6195,7 @@ async function resolveTrustForPR(args) {
6124
6195
  credentials
6125
6196
  });
6126
6197
  const lockFileSource = selectLockFileSource(isPREvent, trustResolution.tier);
6127
- logger$89.info("Trust tier resolved for PR", {
6198
+ logger$90.info("Trust tier resolved for PR", {
6128
6199
  deliveryId: info.deliveryId,
6129
6200
  sender: event.senderUsername,
6130
6201
  tier: trustResolution.tier,
@@ -6136,7 +6207,7 @@ async function resolveTrustForPR(args) {
6136
6207
  lockFileSource
6137
6208
  };
6138
6209
  } catch (err) {
6139
- logger$89.warn("Trust resolution failed, defaulting to base lock file", {
6210
+ logger$90.warn("Trust resolution failed, defaulting to base lock file", {
6140
6211
  deliveryId: info.deliveryId,
6141
6212
  sender: event.senderUsername,
6142
6213
  error: toErrorMessage(err)
@@ -6161,7 +6232,7 @@ async function resolveTrustForPR(args) {
6161
6232
  */
6162
6233
  async function fetchLockFileWithFallbackPhase(args) {
6163
6234
  const { info, deps, bundle, event, resolvedOrgId, repoIdentifier, credentials, ref, isPREvent, lockFileSource } = args;
6164
- if (!bundle.lockFileFetcher) logger$89.debug("No lock file fetcher available for inbound provider, relying on fallback", { deliveryId: info.deliveryId });
6235
+ if (!bundle.lockFileFetcher) logger$90.debug("No lock file fetcher available for inbound provider, relying on fallback", { deliveryId: info.deliveryId });
6165
6236
  let lockFile;
6166
6237
  let headLockFileForDiff;
6167
6238
  let resolvedFallbackBundle;
@@ -6225,7 +6296,7 @@ async function fetchLockFileWithFallbackPhase(args) {
6225
6296
  if (resolvedFallbackBundle) {
6226
6297
  dispatchBundle = resolvedFallbackBundle;
6227
6298
  dispatchCredentials = resolvedFallbackCredentials ?? credentials;
6228
- logger$89.info("Cross-provider dispatch: using fallback bundle for clone URL + token", {
6299
+ logger$90.info("Cross-provider dispatch: using fallback bundle for clone URL + token", {
6229
6300
  deliveryId: info.deliveryId,
6230
6301
  inboundRoutingKey: info.routingKey,
6231
6302
  fallbackRoutingKey: resolvedFallbackRoutingKey,
@@ -6314,7 +6385,7 @@ async function tryDispatchGlobalsWithoutLockFile(args) {
6314
6385
  if (deps.globalWorkflowPolicy) {
6315
6386
  const sourceCheck = await deps.globalWorkflowPolicy.isSourceRepoAllowed(info.routingKey, repoIdentifier, resolvedOrgId);
6316
6387
  if (!sourceCheck.allowed) {
6317
- logger$89.info("Skipping global workflow dispatch: source repo in deny-list", {
6388
+ logger$90.info("Skipping global workflow dispatch: source repo in deny-list", {
6318
6389
  sourceRepo: repoIdentifier,
6319
6390
  eventRoutingKey: info.routingKey,
6320
6391
  workflowRoutingKey: reg.routingKey,
@@ -6347,7 +6418,7 @@ async function tryDispatchGlobalsWithoutLockFile(args) {
6347
6418
  });
6348
6419
  for (const { lockJobName, input } of inputs) {
6349
6420
  const result = await deps.dispatcher.dispatch(input);
6350
- if (result.status !== "rejected") logger$89.info("Global workflow job dispatched (no lock file path)", {
6421
+ if (result.status !== "rejected") logger$90.info("Global workflow job dispatched (no lock file path)", {
6351
6422
  runId: globalRunId,
6352
6423
  workflow: reg.lockEntry.name,
6353
6424
  job: lockJobName,
@@ -6378,7 +6449,7 @@ function applyWorkflowModificationsAndSecurityHold(args) {
6378
6449
  workflowModifications = detectWorkflowModifications(fullLockFile, headLockFileForDiff);
6379
6450
  if (workflowModifications.length > 0) {
6380
6451
  const tier = trustResolution?.tier ?? "unknown";
6381
- logger$89.info("Workflow modifications detected in PR", {
6452
+ logger$90.info("Workflow modifications detected in PR", {
6382
6453
  deliveryId: info.deliveryId,
6383
6454
  sender: event.senderUsername,
6384
6455
  tier,
@@ -6394,7 +6465,7 @@ function applyWorkflowModificationsAndSecurityHold(args) {
6394
6465
  ...workflowModifications.map((m) => `- **${m.changeType}**: \`${m.workflowName}\``)
6395
6466
  ].join("\n");
6396
6467
  bundle.checkStatusPoster.postCheckStatus(repoIdentifier, ref, "neutral", "Workflow changes detected", modSummary, credentials).catch((err) => {
6397
- logger$89.warn("Failed to post workflow modification check", {
6468
+ logger$90.warn("Failed to post workflow modification check", {
6398
6469
  deliveryId: info.deliveryId,
6399
6470
  error: toErrorMessage(err)
6400
6471
  });
@@ -6404,7 +6475,7 @@ function applyWorkflowModificationsAndSecurityHold(args) {
6404
6475
  if (securityHold && bundle.checkStatusPoster) {
6405
6476
  const holdSummary = buildSecurityHoldSummary(securityHold.reason, trustResolution?.tier ?? "unknown", trustResolution?.contributorUsername);
6406
6477
  bundle.checkStatusPoster.postCheckStatus(repoIdentifier, ref, "pending", "Held for approval", holdSummary, credentials).catch((err) => {
6407
- logger$89.warn("Failed to post security hold check", {
6478
+ logger$90.warn("Failed to post security hold check", {
6408
6479
  deliveryId: info.deliveryId,
6409
6480
  error: toErrorMessage(err)
6410
6481
  });
@@ -6434,7 +6505,7 @@ async function registerWorkflowsOnDefaultBranchPush(args) {
6434
6505
  if (globalWorkflows.length > 0) {
6435
6506
  const permission = await deps.globalWorkflowPolicy.isWorkflowRepoAllowed(info.routingKey, repoIdentifier, resolvedOrgId);
6436
6507
  if (!permission.allowed) {
6437
- logger$89.warn("Skipping global workflow registration: not permitted", {
6508
+ logger$90.warn("Skipping global workflow registration: not permitted", {
6438
6509
  reason: permission.reason,
6439
6510
  repo: repoIdentifier
6440
6511
  });
@@ -6452,7 +6523,7 @@ async function registerWorkflowsOnDefaultBranchPush(args) {
6452
6523
  const newVersion = await deps.registrationStore.bumpVersion();
6453
6524
  await deps.registrationIndex.refreshIfNeeded(newVersion);
6454
6525
  if (deps.cronScheduler) await deps.cronScheduler.refreshCache();
6455
- logger$89.info("Workflow registrations updated", {
6526
+ logger$90.info("Workflow registrations updated", {
6456
6527
  repoIdentifier,
6457
6528
  workflowCount: registerableWorkflows.length,
6458
6529
  registryVersion: newVersion
@@ -6559,7 +6630,7 @@ async function dispatchGlobalWorkflowsForOtherRepos(args) {
6559
6630
  if (deps.globalWorkflowPolicy) {
6560
6631
  const sourceCheck = await deps.globalWorkflowPolicy.isSourceRepoAllowed(info.routingKey, repoIdentifier, resolvedOrgId);
6561
6632
  if (!sourceCheck.allowed) {
6562
- logger$89.info("Skipping global workflow dispatch: source repo in deny-list", {
6633
+ logger$90.info("Skipping global workflow dispatch: source repo in deny-list", {
6563
6634
  sourceRepo: repoIdentifier,
6564
6635
  eventRoutingKey: info.routingKey,
6565
6636
  workflowRoutingKey: reg.routingKey,
@@ -6593,7 +6664,7 @@ async function dispatchGlobalWorkflowsForOtherRepos(args) {
6593
6664
  });
6594
6665
  for (const { lockJobName, input } of inputs) {
6595
6666
  const result = await deps.dispatcher.dispatch(input);
6596
- if (result.status !== "rejected") logger$89.info("Global workflow job dispatched", {
6667
+ if (result.status !== "rejected") logger$90.info("Global workflow job dispatched", {
6597
6668
  runId: globalRunId,
6598
6669
  workflow: reg.lockEntry.name,
6599
6670
  job: lockJobName,
@@ -6631,7 +6702,7 @@ async function forwardTracesAndRecordEventLog(args) {
6631
6702
  webhooksProcessedTotal.add(1, { result: matchedCount > 0 ? "matched" : "skipped" });
6632
6703
  if (deps.webhookPayloadDir) {
6633
6704
  const payloadDir = join(deps.webhookPayloadDir, repoIdentifier, info.deliveryId);
6634
- mkdir(payloadDir, { recursive: true }).then(() => writeFile(join(payloadDir, "payload.json"), JSON.stringify(payload, null, 2))).catch((err) => logger$89.warn("Failed to write webhook payload", { error: String(err) }));
6705
+ mkdir(payloadDir, { recursive: true }).then(() => writeFile(join(payloadDir, "payload.json"), JSON.stringify(payload, null, 2))).catch((err) => logger$90.warn("Failed to write webhook payload", { error: String(err) }));
6635
6706
  }
6636
6707
  if (deps.eventLog) {
6637
6708
  const firstRunId = matchedRunIds[0] ?? null;
@@ -6645,7 +6716,7 @@ async function forwardTracesAndRecordEventLog(args) {
6645
6716
  runId: firstRunId
6646
6717
  });
6647
6718
  }
6648
- logger$89.info("Webhook processed", {
6719
+ logger$90.info("Webhook processed", {
6649
6720
  deliveryId: info.deliveryId,
6650
6721
  event: info.event,
6651
6722
  matchedWorkflows: matchedCount,
@@ -6716,7 +6787,7 @@ async function processWebhook$1(info, deps) {
6716
6787
  lockFileSource: trust.lockFileSource
6717
6788
  });
6718
6789
  if (!lockOutcome.lockFile) {
6719
- logger$89.debug("No lock file found for per-repo matching, checking global workflows", {
6790
+ logger$90.debug("No lock file found for per-repo matching, checking global workflows", {
6720
6791
  deliveryId: info.deliveryId,
6721
6792
  repoIdentifier,
6722
6793
  ref,
@@ -6818,7 +6889,7 @@ async function processWebhook$1(info, deps) {
6818
6889
  ref
6819
6890
  });
6820
6891
  }
6821
- var logger$89;
6892
+ var logger$90;
6822
6893
  var init_process_webhook = __esmMin((() => {
6823
6894
  init_lock_source();
6824
6895
  init_workflow_diff();
@@ -6828,7 +6899,7 @@ var init_process_webhook = __esmMin((() => {
6828
6899
  init_prometheus();
6829
6900
  init_dispatch_matched_workflow();
6830
6901
  init_processor();
6831
- logger$89 = createLogger({ prefix: "pipeline" });
6902
+ logger$90 = createLogger({ prefix: "pipeline" });
6832
6903
  }));
6833
6904
  //#endregion
6834
6905
  //#region src/pipeline/processor.ts
@@ -7014,7 +7085,7 @@ async function resolveLockFileWithFallback(args) {
7014
7085
  };
7015
7086
  const sameTenantRegistrations = registrationIndex.getByOrgAndRepo(customerId, repoIdentifier);
7016
7087
  if (sameTenantRegistrations.length === 0) {
7017
- logger$88.info("Multi-provider fallback: no same-customer registrations for repo", {
7088
+ logger$89.info("Multi-provider fallback: no same-customer registrations for repo", {
7018
7089
  deliveryId,
7019
7090
  inboundRoutingKey,
7020
7091
  customerId,
@@ -7035,7 +7106,7 @@ async function resolveLockFileWithFallback(args) {
7035
7106
  fallbackRoutingKeys.push(reg.routingKey);
7036
7107
  }
7037
7108
  if (fallbackRoutingKeys.length === 0) {
7038
- logger$88.info("Multi-provider fallback: all same-customer registrations share the inbound routingKey", {
7109
+ logger$89.info("Multi-provider fallback: all same-customer registrations share the inbound routingKey", {
7039
7110
  deliveryId,
7040
7111
  inboundRoutingKey,
7041
7112
  customerId,
@@ -7057,7 +7128,7 @@ async function resolveLockFileWithFallback(args) {
7057
7128
  try {
7058
7129
  lockFile = await lockFileCache.get(fallbackBundle.lockFileFetcher, repoIdentifier, ref, fallbackCredentials);
7059
7130
  } catch (err) {
7060
- logger$88.warn("Multi-provider fallback: fetcher threw, continuing", {
7131
+ logger$89.warn("Multi-provider fallback: fetcher threw, continuing", {
7061
7132
  deliveryId,
7062
7133
  inboundRoutingKey,
7063
7134
  fallbackRoutingKey,
@@ -7067,7 +7138,7 @@ async function resolveLockFileWithFallback(args) {
7067
7138
  continue;
7068
7139
  }
7069
7140
  if (lockFile) {
7070
- logger$88.info("Lock file resolved via fallback provider bundle", {
7141
+ logger$89.info("Lock file resolved via fallback provider bundle", {
7071
7142
  deliveryId,
7072
7143
  inboundRoutingKey,
7073
7144
  fallbackRoutingKey,
@@ -7084,7 +7155,7 @@ async function resolveLockFileWithFallback(args) {
7084
7155
  };
7085
7156
  }
7086
7157
  }
7087
- logger$88.info("Multi-provider fallback exhausted without resolving lock file", {
7158
+ logger$89.info("Multi-provider fallback exhausted without resolving lock file", {
7088
7159
  deliveryId,
7089
7160
  inboundRoutingKey,
7090
7161
  customerId,
@@ -7108,7 +7179,7 @@ async function resolveOrgId(db, routingKey) {
7108
7179
  if (source?.customer_id) return source.customer_id;
7109
7180
  const genericSource = await db.selectFrom("generic_webhook_sources").select("customer_id").where("routing_key", "=", routingKey).executeTakeFirst();
7110
7181
  if (genericSource?.customer_id) return genericSource.customer_id;
7111
- logger$88.warn("No customer_id found for routing key, falling back to __default__", { routingKey });
7182
+ logger$89.warn("No customer_id found for routing key, falling back to __default__", { routingKey });
7112
7183
  return "__default__";
7113
7184
  }
7114
7185
  /**
@@ -7230,7 +7301,7 @@ function triggerHasPathFilters(trigger) {
7230
7301
  async function dispatchReadyJob(runId, jobName, dispatcher, executionTracker, coordinator, db) {
7231
7302
  const pendingCtx = await consumePendingJobContext(db, runId, jobName);
7232
7303
  if (!pendingCtx) {
7233
- logger$88.warn("No pending dispatch context for ready job (may have been dispatched already)", {
7304
+ logger$89.warn("No pending dispatch context for ready job (may have been dispatched already)", {
7234
7305
  runId,
7235
7306
  jobName
7236
7307
  });
@@ -7239,13 +7310,13 @@ async function dispatchReadyJob(runId, jobName, dispatcher, executionTracker, co
7239
7310
  try {
7240
7311
  const result = await dispatcher.dispatch(pendingCtx.jobInput);
7241
7312
  if (result.status === "rejected") {
7242
- logger$88.error("Scheduler-dispatched job rejected by dispatcher", {
7313
+ logger$89.error("Scheduler-dispatched job rejected by dispatcher", {
7243
7314
  runId,
7244
7315
  jobName,
7245
7316
  reason: result.reason
7246
7317
  });
7247
7318
  if (executionTracker) await executionTracker.onJobStatus(runId, jobName, ExecutionJobStatus.enum.failed, Date.now(), void 0, { error: `dispatch rejected: ${result.reason}` });
7248
- } else if (result.status === "queued-no-backend") logger$88.warn("Scheduler-dispatched job has no matching backend", {
7319
+ } else if (result.status === "queued-no-backend") logger$89.warn("Scheduler-dispatched job has no matching backend", {
7249
7320
  runId,
7250
7321
  jobName
7251
7322
  });
@@ -7262,14 +7333,14 @@ async function dispatchReadyJob(runId, jobName, dispatcher, executionTracker, co
7262
7333
  ready_at: /* @__PURE__ */ new Date()
7263
7334
  }).where("run_id", "=", runId).where("job_id", "=", result.jobId).execute();
7264
7335
  }
7265
- logger$88.info("Scheduler-dispatched job ready and dispatched", {
7336
+ logger$89.info("Scheduler-dispatched job ready and dispatched", {
7266
7337
  runId,
7267
7338
  jobName,
7268
7339
  jobId: result.jobId
7269
7340
  });
7270
7341
  }
7271
7342
  } catch (err) {
7272
- logger$88.error("Failed to dispatch scheduler-ready job", {
7343
+ logger$89.error("Failed to dispatch scheduler-ready job", {
7273
7344
  runId,
7274
7345
  jobName,
7275
7346
  error: toErrorMessage(err)
@@ -7306,10 +7377,10 @@ function summarizeDecision(decision) {
7306
7377
  checksCount: decision.checks.length
7307
7378
  };
7308
7379
  }
7309
- var logger$88, pendingJobContexts;
7380
+ var logger$89, pendingJobContexts;
7310
7381
  var init_processor = __esmMin((() => {
7311
7382
  init_process_webhook();
7312
- logger$88 = createLogger({ prefix: "pipeline" });
7383
+ logger$89 = createLogger({ prefix: "pipeline" });
7313
7384
  pendingJobContexts = /* @__PURE__ */ new Map();
7314
7385
  }));
7315
7386
  //#endregion
@@ -7325,9 +7396,9 @@ var init_processor = __esmMin((() => {
7325
7396
  * and are not handled here.
7326
7397
  */
7327
7398
  var log_pull_handler_exports = /* @__PURE__ */ __exportAll({ LogPullHandler: () => LogPullHandler$1 });
7328
- var logger$87, LogPullHandler$1;
7399
+ var logger$88, LogPullHandler$1;
7329
7400
  var init_log_pull_handler = __esmMin((() => {
7330
- logger$87 = createLogger({ prefix: "log-pull" });
7401
+ logger$88 = createLogger({ prefix: "log-pull" });
7331
7402
  LogPullHandler$1 = class {
7332
7403
  constructor(deps) {
7333
7404
  this.deps = deps;
@@ -7416,7 +7487,7 @@ var init_log_pull_handler = __esmMin((() => {
7416
7487
  complete: true
7417
7488
  });
7418
7489
  } catch (err) {
7419
- logger$87.error("Error handling log request", {
7490
+ logger$88.error("Error handling log request", {
7420
7491
  executionId: msg.executionId,
7421
7492
  error: toErrorMessage(err)
7422
7493
  });
@@ -7471,13 +7542,13 @@ async function loadEventLogRange(args) {
7471
7542
  }
7472
7543
  } catch (err) {
7473
7544
  if (hotRows.length === 0) {
7474
- logger$86.error("cold-store fetchRange failed with no hot fallback; propagating", {
7545
+ logger$87.error("cold-store fetchRange failed with no hot fallback; propagating", {
7475
7546
  routingKey,
7476
7547
  error: toErrorMessage(err)
7477
7548
  });
7478
7549
  throw err;
7479
7550
  }
7480
- logger$86.warn("cold-store fetchRange failed; returning hot rows only", {
7551
+ logger$87.warn("cold-store fetchRange failed; returning hot rows only", {
7481
7552
  routingKey,
7482
7553
  error: toErrorMessage(err)
7483
7554
  });
@@ -7503,7 +7574,7 @@ async function loadEventLogByDeliveryId(args) {
7503
7574
  if (hotRow) return hotRow;
7504
7575
  if (!coldStore) return null;
7505
7576
  if (!routingKey) {
7506
- logger$86.warn("cold-store delivery lookup without routingKey hint — scan skipped", {
7577
+ logger$87.warn("cold-store delivery lookup without routingKey hint — scan skipped", {
7507
7578
  orgId,
7508
7579
  deliveryId
7509
7580
  });
@@ -7519,7 +7590,7 @@ async function loadEventLogByDeliveryId(args) {
7519
7590
  toTs: warmCutoff
7520
7591
  })) if (row.org_id === orgId && row.delivery_id === deliveryId) return row;
7521
7592
  } catch (err) {
7522
- logger$86.warn("cold-store fetchRange failed for delivery lookup", {
7593
+ logger$87.warn("cold-store fetchRange failed for delivery lookup", {
7523
7594
  routingKey,
7524
7595
  orgId,
7525
7596
  deliveryId,
@@ -7528,9 +7599,9 @@ async function loadEventLogByDeliveryId(args) {
7528
7599
  }
7529
7600
  return null;
7530
7601
  }
7531
- var logger$86, EVENT_LOG_WARM_TTL_DAYS;
7602
+ var logger$87, EVENT_LOG_WARM_TTL_DAYS;
7532
7603
  var init_load_event_log_range = __esmMin((() => {
7533
- logger$86 = createLogger({ prefix: "load-event-log-range" });
7604
+ logger$87 = createLogger({ prefix: "load-event-log-range" });
7534
7605
  EVENT_LOG_WARM_TTL_DAYS = 30;
7535
7606
  }));
7536
7607
  //#endregion
@@ -7593,7 +7664,7 @@ function parsePolicyColumn(raw) {
7593
7664
  const candidate = typeof raw === "string" ? safeParseJson(raw) : raw;
7594
7665
  const result = dashboardWritePolicyMapSchema.safeParse(candidate);
7595
7666
  if (!result.success) {
7596
- logger$85.warn("Invalid dashboard_write_policy column shape — treating as empty", { error: result.error.message });
7667
+ logger$86.warn("Invalid dashboard_write_policy column shape — treating as empty", { error: result.error.message });
7597
7668
  return {};
7598
7669
  }
7599
7670
  return result.data;
@@ -7735,9 +7806,9 @@ async function resetDashboardWritePolicy(db, customerId, options) {
7735
7806
  if (Object.keys(updates).length === 0) return current;
7736
7807
  return setDashboardWritePolicy(db, customerId, updates, options);
7737
7808
  }
7738
- var logger$85, CACHE_TTL_MS, cache, dashboardWritePolicyEvents$1, DashboardWritePolicyDisabledError;
7809
+ var logger$86, CACHE_TTL_MS, cache, dashboardWritePolicyEvents$1, DashboardWritePolicyDisabledError;
7739
7810
  var init_dashboard_write_policy = __esmMin((() => {
7740
- logger$85 = createLogger({ prefix: "dashboard-write-policy" });
7811
+ logger$86 = createLogger({ prefix: "dashboard-write-policy" });
7741
7812
  CACHE_TTL_MS = 3e4;
7742
7813
  cache = /* @__PURE__ */ new Map();
7743
7814
  dashboardWritePolicyEvents$1 = new EventEmitter();
@@ -7815,11 +7886,11 @@ function decodeEventLogCursor(s) {
7815
7886
  return null;
7816
7887
  }
7817
7888
  }
7818
- var logger$84, DashboardHandler$1;
7889
+ var logger$85, DashboardHandler$1;
7819
7890
  var init_handler = __esmMin((() => {
7820
7891
  init_load_event_log_range();
7821
7892
  init_dashboard_write_policy();
7822
- logger$84 = createLogger({ prefix: "dashboard-handler" });
7893
+ logger$85 = createLogger({ prefix: "dashboard-handler" });
7823
7894
  DashboardHandler$1 = class {
7824
7895
  db;
7825
7896
  logStorage;
@@ -8074,7 +8145,7 @@ var init_handler = __esmMin((() => {
8074
8145
  ...trustContext && { trustContext }
8075
8146
  });
8076
8147
  if (!validated.success) {
8077
- logger$84.error("Outgoing dashboard.run.detail response validation failed", {
8148
+ logger$85.error("Outgoing dashboard.run.detail response validation failed", {
8078
8149
  runId: msg.runId,
8079
8150
  errors: validated.error.issues
8080
8151
  });
@@ -8101,7 +8172,7 @@ var init_handler = __esmMin((() => {
8101
8172
  ...validated.data.trustContext && { trustContext: validated.data.trustContext }
8102
8173
  });
8103
8174
  } catch (err) {
8104
- logger$84.error("Error handling dashboard.run.detail", {
8175
+ logger$85.error("Error handling dashboard.run.detail", {
8105
8176
  runId: msg.runId,
8106
8177
  error: toErrorMessage(err)
8107
8178
  });
@@ -8159,7 +8230,7 @@ var init_handler = __esmMin((() => {
8159
8230
  totalLines: lines.length
8160
8231
  });
8161
8232
  if (!validated.success) {
8162
- logger$84.error("Outgoing dashboard.step.logs response validation failed", {
8233
+ logger$85.error("Outgoing dashboard.step.logs response validation failed", {
8163
8234
  runId: msg.runId,
8164
8235
  jobId: msg.jobId,
8165
8236
  stepIndex: msg.stepIndex,
@@ -8189,7 +8260,7 @@ var init_handler = __esmMin((() => {
8189
8260
  totalLines: validated.data.totalLines
8190
8261
  });
8191
8262
  } catch (err) {
8192
- logger$84.error("Error handling dashboard.step.logs", {
8263
+ logger$85.error("Error handling dashboard.step.logs", {
8193
8264
  runId: msg.runId,
8194
8265
  jobId: msg.jobId,
8195
8266
  stepIndex: msg.stepIndex,
@@ -8216,7 +8287,7 @@ var init_handler = __esmMin((() => {
8216
8287
  const ctx = this.contextOrFallback(await this.resolveOrgForRun(msg.runId));
8217
8288
  const payloadPath = `executions/${msg.runId}/webhook-payload.json`;
8218
8289
  const backend = this.logStorage.constructor.name;
8219
- logger$84.info("Dashboard payload request received", {
8290
+ logger$85.info("Dashboard payload request received", {
8220
8291
  requestId: msg.requestId,
8221
8292
  runId: msg.runId,
8222
8293
  payloadPath,
@@ -8226,7 +8297,7 @@ var init_handler = __esmMin((() => {
8226
8297
  try {
8227
8298
  const result = await this.logStorage.read(payloadPath);
8228
8299
  if (!result.data) {
8229
- logger$84.info("Dashboard payload not found", {
8300
+ logger$85.info("Dashboard payload not found", {
8230
8301
  requestId: msg.requestId,
8231
8302
  runId: msg.runId,
8232
8303
  payloadPath,
@@ -8248,7 +8319,7 @@ var init_handler = __esmMin((() => {
8248
8319
  try {
8249
8320
  payload = JSON.parse(result.data);
8250
8321
  } catch {
8251
- logger$84.error("Dashboard payload data is not valid JSON", {
8322
+ logger$85.error("Dashboard payload data is not valid JSON", {
8252
8323
  requestId: msg.requestId,
8253
8324
  runId: msg.runId,
8254
8325
  payloadPath,
@@ -8266,7 +8337,7 @@ var init_handler = __esmMin((() => {
8266
8337
  });
8267
8338
  return;
8268
8339
  }
8269
- logger$84.info("Dashboard payload served", {
8340
+ logger$85.info("Dashboard payload served", {
8270
8341
  requestId: msg.requestId,
8271
8342
  runId: msg.runId,
8272
8343
  bytes: result.data.length,
@@ -8282,7 +8353,7 @@ var init_handler = __esmMin((() => {
8282
8353
  payload
8283
8354
  });
8284
8355
  } catch (err) {
8285
- logger$84.error("Error handling dashboard.payload", {
8356
+ logger$85.error("Error handling dashboard.payload", {
8286
8357
  requestId: msg.requestId,
8287
8358
  runId: msg.runId,
8288
8359
  payloadPath,
@@ -8370,7 +8441,7 @@ var init_handler = __esmMin((() => {
8370
8441
  newRunId: result.newRunId
8371
8442
  });
8372
8443
  } catch (err) {
8373
- logger$84.error("Error handling run.rerun.request", {
8444
+ logger$85.error("Error handling run.rerun.request", {
8374
8445
  runId: msg.runId,
8375
8446
  error: toErrorMessage(err)
8376
8447
  });
@@ -8405,7 +8476,7 @@ var init_handler = __esmMin((() => {
8405
8476
  cancelledJobs: result.cancelledJobs
8406
8477
  });
8407
8478
  } catch (err) {
8408
- logger$84.error("Error handling run.cancel.request", {
8479
+ logger$85.error("Error handling run.cancel.request", {
8409
8480
  runId: msg.runId,
8410
8481
  error: toErrorMessage(err)
8411
8482
  });
@@ -8486,7 +8557,7 @@ var init_handler = __esmMin((() => {
8486
8557
  nextCursor
8487
8558
  });
8488
8559
  } catch (err) {
8489
- logger$84.error("Error handling dashboard.event-log.list", {
8560
+ logger$85.error("Error handling dashboard.event-log.list", {
8490
8561
  orgId: msg.orgId,
8491
8562
  error: toErrorMessage(err)
8492
8563
  });
@@ -8556,7 +8627,7 @@ var init_handler = __esmMin((() => {
8556
8627
  nextCursor: result.nextCursor
8557
8628
  });
8558
8629
  } catch (err) {
8559
- logger$84.error("Error handling dashboard.access-log.list", {
8630
+ logger$85.error("Error handling dashboard.access-log.list", {
8560
8631
  orgId: msg.orgId,
8561
8632
  error: toErrorMessage(err)
8562
8633
  });
@@ -8619,7 +8690,7 @@ var init_handler = __esmMin((() => {
8619
8690
  item
8620
8691
  });
8621
8692
  } catch (err) {
8622
- logger$84.error("Error handling dashboard.event-log.detail", {
8693
+ logger$85.error("Error handling dashboard.event-log.detail", {
8623
8694
  orgId: msg.orgId,
8624
8695
  deliveryId: msg.deliveryId,
8625
8696
  error: toErrorMessage(err)
@@ -8678,7 +8749,7 @@ var init_handler = __esmMin((() => {
8678
8749
  routingKey: msg.routingKey
8679
8750
  });
8680
8751
  } catch (err) {
8681
- logger$84.error("Error loading event-log row for payload stream", {
8752
+ logger$85.error("Error loading event-log row for payload stream", {
8682
8753
  orgId: msg.orgId,
8683
8754
  deliveryId: msg.deliveryId,
8684
8755
  error: toErrorMessage(err)
@@ -8711,7 +8782,7 @@ var init_handler = __esmMin((() => {
8711
8782
  const result = await this.logStorage.read(row.payload_key);
8712
8783
  decompressed = gunzipSync(Buffer.from(result.data, "binary"));
8713
8784
  } catch (err) {
8714
- logger$84.warn("Failed to read or decode event-log payload for stream", {
8785
+ logger$85.warn("Failed to read or decode event-log payload for stream", {
8715
8786
  deliveryId: msg.deliveryId,
8716
8787
  payloadKey: row.payload_key,
8717
8788
  error: toErrorMessage(err)
@@ -8813,7 +8884,7 @@ var init_handler = __esmMin((() => {
8813
8884
  nextCursor
8814
8885
  });
8815
8886
  } catch (err) {
8816
- logger$84.error("Error handling dashboard.event-dlq.list", {
8887
+ logger$85.error("Error handling dashboard.event-dlq.list", {
8817
8888
  orgId: msg.orgId,
8818
8889
  error: toErrorMessage(err)
8819
8890
  });
@@ -8854,7 +8925,7 @@ var init_handler = __esmMin((() => {
8854
8925
  total
8855
8926
  });
8856
8927
  } catch (err) {
8857
- logger$84.error("Error handling dashboard.event-dlq.count", {
8928
+ logger$85.error("Error handling dashboard.event-dlq.count", {
8858
8929
  orgId: msg.orgId,
8859
8930
  error: toErrorMessage(err)
8860
8931
  });
@@ -8915,7 +8986,7 @@ var init_handler = __esmMin((() => {
8915
8986
  try {
8916
8987
  await sql`SELECT pg_notify('kici_event_channel', ${msg.eventId})`.execute(this.eventStore.getDb());
8917
8988
  } catch (err) {
8918
- logger$84.warn("pg_notify failed after DLQ retry; scanner will catch up", {
8989
+ logger$85.warn("pg_notify failed after DLQ retry; scanner will catch up", {
8919
8990
  eventId: msg.eventId,
8920
8991
  error: toErrorMessage(err)
8921
8992
  });
@@ -8930,7 +9001,7 @@ var init_handler = __esmMin((() => {
8930
9001
  retried: true
8931
9002
  });
8932
9003
  } catch (err) {
8933
- logger$84.error("Error handling dashboard.event-dlq.retry", {
9004
+ logger$85.error("Error handling dashboard.event-dlq.retry", {
8934
9005
  orgId: msg.orgId,
8935
9006
  eventId: msg.eventId,
8936
9007
  error: toErrorMessage(err)
@@ -9001,7 +9072,7 @@ var init_handler = __esmMin((() => {
9001
9072
  discarded: true
9002
9073
  });
9003
9074
  } catch (err) {
9004
- logger$84.error("Error handling dashboard.event-dlq.discard", {
9075
+ logger$85.error("Error handling dashboard.event-dlq.discard", {
9005
9076
  orgId: msg.orgId,
9006
9077
  eventId: msg.eventId,
9007
9078
  error: toErrorMessage(err)
@@ -9035,7 +9106,7 @@ var init_handler = __esmMin((() => {
9035
9106
  newRunId: result.newRunId
9036
9107
  });
9037
9108
  } catch (err) {
9038
- logger$84.error("Error handling run.manual_schedule.request", {
9109
+ logger$85.error("Error handling run.manual_schedule.request", {
9039
9110
  registrationId: msg.registrationId,
9040
9111
  error: toErrorMessage(err)
9041
9112
  });
@@ -9080,7 +9151,7 @@ var init_handler = __esmMin((() => {
9080
9151
  if (r.run_id === runId) rows.push(r);
9081
9152
  }
9082
9153
  } catch (err) {
9083
- logger$84.warn("cold-store fetchRange failed for run-detail", {
9154
+ logger$85.warn("cold-store fetchRange failed for run-detail", {
9084
9155
  table,
9085
9156
  runId,
9086
9157
  error: toErrorMessage(err)
@@ -9417,10 +9488,10 @@ async function loadActiveGenericRoutingKeys$1(db) {
9417
9488
  has_git_config: row.git_config !== null
9418
9489
  }));
9419
9490
  }
9420
- var logger$83, GenericSourceManager;
9491
+ var logger$84, GenericSourceManager;
9421
9492
  var init_generic_sources = __esmMin((() => {
9422
9493
  init_config$4();
9423
- logger$83 = createLogger({ prefix: "generic-sources" });
9494
+ logger$84 = createLogger({ prefix: "generic-sources" });
9424
9495
  GenericSourceManager = class {
9425
9496
  constructor(db) {
9426
9497
  this.db = db;
@@ -9464,7 +9535,7 @@ var init_generic_sources = __esmMin((() => {
9464
9535
  git_config: validatedGitConfig ? JSON.stringify(validatedGitConfig) : null
9465
9536
  };
9466
9537
  const result = await this.db.insertInto("generic_webhook_sources").values(row).returningAll().executeTakeFirstOrThrow();
9467
- logger$83.info("Generic webhook source created", {
9538
+ logger$84.info("Generic webhook source created", {
9468
9539
  id: result.id,
9469
9540
  orgId: input.orgId,
9470
9541
  name: input.name,
@@ -9550,7 +9621,7 @@ var init_generic_sources = __esmMin((() => {
9550
9621
  ...updates,
9551
9622
  updated_at: sql`now()`
9552
9623
  }).where("id", "=", id).where("deleted_at", "is", null).returningAll().executeTakeFirst();
9553
- if (result) logger$83.info("Generic webhook source updated", {
9624
+ if (result) logger$84.info("Generic webhook source updated", {
9554
9625
  id,
9555
9626
  fields: Object.keys(updates)
9556
9627
  });
@@ -9561,14 +9632,14 @@ var init_generic_sources = __esmMin((() => {
9561
9632
  */
9562
9633
  async softDelete(id) {
9563
9634
  await this.db.updateTable("generic_webhook_sources").set({ deleted_at: sql`now()` }).where("id", "=", id).where("deleted_at", "is", null).execute();
9564
- logger$83.info("Generic webhook source soft-deleted", { id });
9635
+ logger$84.info("Generic webhook source soft-deleted", { id });
9565
9636
  }
9566
9637
  /**
9567
9638
  * Hard delete a source (removes the row entirely).
9568
9639
  */
9569
9640
  async hardDelete(id) {
9570
9641
  await this.db.deleteFrom("generic_webhook_sources").where("id", "=", id).execute();
9571
- logger$83.info("Generic webhook source hard-deleted", { id });
9642
+ logger$84.info("Generic webhook source hard-deleted", { id });
9572
9643
  }
9573
9644
  /**
9574
9645
  * Enable a source.
@@ -9578,7 +9649,7 @@ var init_generic_sources = __esmMin((() => {
9578
9649
  enabled: true,
9579
9650
  updated_at: sql`now()`
9580
9651
  }).where("id", "=", id).where("deleted_at", "is", null).execute();
9581
- logger$83.info("Generic webhook source enabled", { id });
9652
+ logger$84.info("Generic webhook source enabled", { id });
9582
9653
  }
9583
9654
  /**
9584
9655
  * Disable a source.
@@ -9588,7 +9659,7 @@ var init_generic_sources = __esmMin((() => {
9588
9659
  enabled: false,
9589
9660
  updated_at: sql`now()`
9590
9661
  }).where("id", "=", id).where("deleted_at", "is", null).execute();
9591
- logger$83.info("Generic webhook source disabled", { id });
9662
+ logger$84.info("Generic webhook source disabled", { id });
9592
9663
  }
9593
9664
  /**
9594
9665
  * Check if a request is a duplicate within the dedup window.
@@ -9820,9 +9891,9 @@ var init_normalizer$3 = __esmMin((() => {
9820
9891
  * kici.lock.json directly from the local filesystem. Used when the internal
9821
9892
  * provider processes webhooks for repos accessible via file:// URLs.
9822
9893
  */
9823
- var logger$82, InternalLockFileFetcher;
9894
+ var logger$83, InternalLockFileFetcher;
9824
9895
  var init_lock_file_fetcher = __esmMin((() => {
9825
- logger$82 = createLogger({ prefix: "internal-lock-file" });
9896
+ logger$83 = createLogger({ prefix: "internal-lock-file" });
9826
9897
  InternalLockFileFetcher = class {
9827
9898
  provider = "internal";
9828
9899
  /**
@@ -9850,10 +9921,10 @@ var init_lock_file_fetcher = __esmMin((() => {
9850
9921
  const content = await readFile(lockFilePath, "utf-8");
9851
9922
  const lockFile = JSON.parse(content);
9852
9923
  if (typeof lockFile.schemaVersion !== "number") {
9853
- logger$82.warn("Invalid lock file: missing or invalid schemaVersion", { lockFilePath });
9924
+ logger$83.warn("Invalid lock file: missing or invalid schemaVersion", { lockFilePath });
9854
9925
  return null;
9855
9926
  }
9856
- logger$82.info("Lock file fetched from filesystem", {
9927
+ logger$83.info("Lock file fetched from filesystem", {
9857
9928
  lockFilePath,
9858
9929
  schemaVersion: lockFile.schemaVersion,
9859
9930
  workflowCount: lockFile.workflows.length
@@ -9861,10 +9932,10 @@ var init_lock_file_fetcher = __esmMin((() => {
9861
9932
  return lockFile;
9862
9933
  } catch (err) {
9863
9934
  if (err.code === "ENOENT") {
9864
- logger$82.info("Lock file not found", { lockFilePath });
9935
+ logger$83.info("Lock file not found", { lockFilePath });
9865
9936
  return null;
9866
9937
  }
9867
- logger$82.error("Failed to read lock file", {
9938
+ logger$83.error("Failed to read lock file", {
9868
9939
  lockFilePath,
9869
9940
  error: toErrorMessage(err)
9870
9941
  });
@@ -9952,13 +10023,6 @@ var init_internal = __esmMin((() => {
9952
10023
  * Extracted to eliminate code duplication between the two entry points.
9953
10024
  * Both entry points import these helpers instead of maintaining separate copies.
9954
10025
  */
9955
- var entry_helpers_exports = /* @__PURE__ */ __exportAll({
9956
- canServeGenericProviderType: () => canServeGenericProviderType$1,
9957
- diffProviderSources: () => diffProviderSources,
9958
- extractRepoIdentifier: () => extractRepoIdentifier,
9959
- genericProviderTypeToSubtype: () => genericProviderTypeToSubtype$1,
9960
- registerInternalProviderIfConfigured: () => registerInternalProviderIfConfigured
9961
- });
9962
10026
  /**
9963
10027
  * Map a generic_webhook_sources `provider_type` (plus optional `git_config`
9964
10028
  * presence) to the canonical {@link SourceSubtype}.
@@ -9969,7 +10033,7 @@ var entry_helpers_exports = /* @__PURE__ */ __exportAll({
9969
10033
  * subtype emitted to Platform stays consistent with what the dashboard
9970
10034
  * eventually renders.
9971
10035
  */
9972
- function genericProviderTypeToSubtype$1(providerType, options) {
10036
+ function genericProviderTypeToSubtype(providerType, options) {
9973
10037
  if (options.hasGitConfig) return SourceSubtype.enum.universal_git;
9974
10038
  if (providerType === "universal-git") return SourceSubtype.enum.universal_git;
9975
10039
  if (providerType === "internal") return SourceSubtype.enum.internal;
@@ -10054,7 +10118,7 @@ function registerInternalProviderIfConfigured(registry, config) {
10054
10118
  * the same base dir).
10055
10119
  * - Any unknown provider_type returns false to fail closed.
10056
10120
  */
10057
- function canServeGenericProviderType$1(providerType, config) {
10121
+ function canServeGenericProviderType(providerType, config) {
10058
10122
  if (providerType === "generic" || providerType === "universal-git") return true;
10059
10123
  if (providerType === "internal") {
10060
10124
  const path = config.internalProviderRepoPath;
@@ -10071,6 +10135,53 @@ var init_entry_helpers = __esmMin((() => {
10071
10135
  init_internal();
10072
10136
  }));
10073
10137
  //#endregion
10138
+ //#region src/sources/build-platform-sources.ts
10139
+ var build_platform_sources_exports = /* @__PURE__ */ __exportAll({ buildPlatformProviderSources: () => buildPlatformProviderSources$1 });
10140
+ /**
10141
+ * Build the full provider-source list the orchestrator advertises to the
10142
+ * Platform: GitHub-app sources from the {@link SourceManager} plus every
10143
+ * *servable* generic-webhook source.
10144
+ *
10145
+ * Used both at boot and by the live republish closure (platform mode). It MUST
10146
+ * return the complete set every time — a live source change re-sends the whole
10147
+ * list via `platformClient.updateSources()`, which diffs against the previously
10148
+ * sent set; a partial list would make the Platform deregister the sources that
10149
+ * happened to be omitted.
10150
+ *
10151
+ * The generic-row loader is injected (rather than taking a `db`) so the merge
10152
+ * logic is unit-testable without a live database.
10153
+ */
10154
+ async function buildPlatformProviderSources$1(sourceManager, loadGenericRows, config) {
10155
+ const providerSources = [...sourceManager.getSources()];
10156
+ try {
10157
+ const genericRows = await loadGenericRows();
10158
+ const skipped = [];
10159
+ for (const gs of genericRows) if (canServeGenericProviderType(gs.provider_type, config)) providerSources.push({
10160
+ provider: "generic",
10161
+ routingKey: gs.routing_key,
10162
+ name: gs.name,
10163
+ subtype: genericProviderTypeToSubtype(gs.provider_type, { hasGitConfig: gs.has_git_config })
10164
+ });
10165
+ else skipped.push({
10166
+ routing_key: gs.routing_key,
10167
+ provider_type: gs.provider_type
10168
+ });
10169
+ if (genericRows.length > 0) logger$82.info("Added generic sources to Platform registration", {
10170
+ count: genericRows.length - skipped.length,
10171
+ skipped: skipped.length
10172
+ });
10173
+ if (skipped.length > 0) logger$82.info("Skipped non-servable generic sources for Platform registration", { skipped });
10174
+ } catch (err) {
10175
+ logger$82.warn("Failed to load generic sources for Platform registration", { error: toErrorMessage(err) });
10176
+ }
10177
+ return providerSources;
10178
+ }
10179
+ var logger$82;
10180
+ var init_build_platform_sources = __esmMin((() => {
10181
+ init_entry_helpers();
10182
+ logger$82 = createLogger({ prefix: "platform-sources" });
10183
+ }));
10184
+ //#endregion
10074
10185
  //#region src/ws/dashboard-env-handler.ts
10075
10186
  /**
10076
10187
  * Dashboard environment handler for the orchestrator.
@@ -11271,7 +11382,7 @@ var init_dashboard_registrations_handler = __esmMin((() => {
11271
11382
  "git_config"
11272
11383
  ]).where("deleted_at", "is", null).where("routing_key", "in", routingKeys).execute();
11273
11384
  for (const row of genericRows) {
11274
- const subtype = genericProviderTypeToSubtype$1(row.provider_type, { hasGitConfig: row.git_config !== null });
11385
+ const subtype = genericProviderTypeToSubtype(row.provider_type, { hasGitConfig: row.git_config !== null });
11275
11386
  result.set(row.routing_key, {
11276
11387
  routingKey: row.routing_key,
11277
11388
  name: row.name,
@@ -12610,10 +12721,10 @@ async function emitRerunEventAndCheckRun(opts) {
12610
12721
  sourceRepo: originalRun.repo_identifier,
12611
12722
  sourceRoutingKey: originalRun.routing_key ?? void 0
12612
12723
  });
12613
- if (deps.commitStatusReporter) {
12724
+ if (deps.checkRunReporter) {
12614
12725
  const [owner, repo] = originalRun.repo_identifier.split("/");
12615
12726
  const jobNames = workflow.jobs.filter(isLockStaticJob).map((j) => j.name);
12616
- deps.commitStatusReporter.setPending({
12727
+ deps.checkRunReporter.setPending({
12617
12728
  provider: originalRun.provider,
12618
12729
  owner,
12619
12730
  repo,
@@ -15038,7 +15149,7 @@ var init_peer_client = __esmMin((() => {
15038
15149
  init_peer_crypto();
15039
15150
  init_peer_credentials();
15040
15151
  logger$73 = createLogger({ prefix: "peer-client" });
15041
- SOFTWARE_VERSION$1 = "0.1.5";
15152
+ SOFTWARE_VERSION$1 = "0.1.7";
15042
15153
  PeerClient$1 = class {
15043
15154
  ws = null;
15044
15155
  _state = "disconnected";
@@ -16501,7 +16612,7 @@ var init_peer_handler = __esmMin((() => {
16501
16612
  init_peer_crypto();
16502
16613
  init_join_token();
16503
16614
  logger$72 = createLogger({ prefix: "peer-handler" });
16504
- SOFTWARE_VERSION = "0.1.5";
16615
+ SOFTWARE_VERSION = "0.1.7";
16505
16616
  RATE_LIMIT_MAX = 5;
16506
16617
  RATE_LIMIT_WINDOW_MS = 6e4;
16507
16618
  }));
@@ -17135,7 +17246,7 @@ var init_coordinator = __esmMin((() => {
17135
17246
  peerRegistry;
17136
17247
  dispatcher;
17137
17248
  executionTracker;
17138
- commitStatusReporter;
17249
+ checkRunReporter;
17139
17250
  getPeerClient;
17140
17251
  sendAndWaitAckViaHandler;
17141
17252
  sendToPeerViaHandler;
@@ -17157,7 +17268,7 @@ var init_coordinator = __esmMin((() => {
17157
17268
  this.peerRegistry = deps.peerRegistry;
17158
17269
  this.dispatcher = deps.dispatcher;
17159
17270
  this.executionTracker = deps.executionTracker;
17160
- this.commitStatusReporter = deps.commitStatusReporter;
17271
+ this.checkRunReporter = deps.checkRunReporter;
17161
17272
  this.getPeerClient = deps.getPeerClient;
17162
17273
  this.sendAndWaitAckViaHandler = deps.sendAndWaitAckViaHandler;
17163
17274
  this.sendToPeerViaHandler = deps.sendToPeerViaHandler;
@@ -17280,10 +17391,10 @@ var init_coordinator = __esmMin((() => {
17280
17391
  const repoIdentifier = (msg.repoUrl ?? "").replace(/\.git$/, "").replace(/^https?:\/\/[^/]+\//, "").replace(/^[^/]+@[^:]+:/, "") || "";
17281
17392
  const providerContext = msg.providerContext ?? {};
17282
17393
  const installationId = typeof providerContext.installationId === "number" ? providerContext.installationId : void 0;
17283
- if (this.commitStatusReporter && repoIdentifier && msg.sha) {
17394
+ if (this.checkRunReporter && repoIdentifier && msg.sha) {
17284
17395
  const [owner, repo] = repoIdentifier.split("/");
17285
17396
  if (owner && repo) try {
17286
- await this.commitStatusReporter.setPendingAwait({
17397
+ await this.checkRunReporter.setPendingAwait({
17287
17398
  provider: msg.provider ?? "",
17288
17399
  owner,
17289
17400
  repo,
@@ -23533,7 +23644,7 @@ var init_check_run_summary = __esmMin((() => {
23533
23644
  ];
23534
23645
  }));
23535
23646
  //#endregion
23536
- //#region src/reporting/commit-status.ts
23647
+ //#region src/reporting/check-run-reporter.ts
23537
23648
  /**
23538
23649
  * GitHub check run integration module.
23539
23650
  *
@@ -23548,7 +23659,7 @@ var init_check_run_summary = __esmMin((() => {
23548
23659
  * Check run IDs are tracked in-memory after creation so that subsequent
23549
23660
  * updates (job complete, workflow complete) can reference them via checks.update().
23550
23661
  *
23551
- * Enriched output (Phase 14):
23662
+ * Enriched output:
23552
23663
  * - Live step progress with checklist-style updates (debounced at 5s)
23553
23664
  * - Failed check runs include step names, error messages, exit codes, and log context
23554
23665
  * - Check run annotations link failures to step source locations in workflow files (.kici/workflows/*.ts)
@@ -23558,7 +23669,7 @@ var init_check_run_summary = __esmMin((() => {
23558
23669
  * Note: The engine-level CheckStatusPoster interface (packages/engine/src/provider/check-status-poster.ts)
23559
23670
  * provides a provider-agnostic API for posting security-related check statuses (holds, approvals,
23560
23671
  * workflow modifications). The GitHub implementation is at packages/orchestrator/src/providers/github/check-status-poster.ts.
23561
- * This CommitStatusReporter handles execution lifecycle checks (queued, in_progress, completed per job/workflow).
23672
+ * This CheckRunReporter handles execution lifecycle checks (queued, in_progress, completed per job/workflow).
23562
23673
  * Future cleanup may unify both under CheckStatusPoster, but they serve different purposes today.
23563
23674
  */
23564
23675
  /**
@@ -23580,14 +23691,14 @@ function buildJobFailureDescription(data) {
23580
23691
  if (data.error) return `Job error: ${data.error}`;
23581
23692
  return "Job failed";
23582
23693
  }
23583
- var logger$60, PROGRESS_DEBOUNCE_MS, CommitStatusReporter;
23584
- var init_commit_status = __esmMin((() => {
23694
+ var logger$60, PROGRESS_DEBOUNCE_MS, CheckRunReporter;
23695
+ var init_check_run_reporter = __esmMin((() => {
23585
23696
  init_auth();
23586
23697
  init_prometheus();
23587
23698
  init_check_run_summary();
23588
- logger$60 = createLogger({ prefix: "commit-status" });
23699
+ logger$60 = createLogger({ prefix: "check-run-reporter" });
23589
23700
  PROGRESS_DEBOUNCE_MS = 5e3;
23590
- CommitStatusReporter = class {
23701
+ CheckRunReporter = class {
23591
23702
  /**
23592
23703
  * L1 cache: composite key → check run ID.
23593
23704
  *
@@ -23842,7 +23953,7 @@ var init_commit_status = __esmMin((() => {
23842
23953
  */
23843
23954
  async recoverState() {
23844
23955
  if (!this.deps.trackingStore) return;
23845
- logger$60.info("CommitStatusReporter recovered (DB-backed state lookups enabled)");
23956
+ logger$60.info("CheckRunReporter recovered (DB-backed state lookups enabled)");
23846
23957
  }
23847
23958
  /** Track a check run key associated with a runId for later cleanup. */
23848
23959
  trackRunKey(runId, key) {
@@ -26975,10 +27086,29 @@ function createSourceRoutes(deps) {
26975
27086
  privateKey,
26976
27087
  webhookSecret
26977
27088
  });
27089
+ let webhookUrl = null;
27090
+ let webhookNote;
27091
+ if (deps.resolveSourceWebhookUrl) try {
27092
+ const resolved = await deps.resolveSourceWebhookUrl({
27093
+ routingKey: source.routing_key,
27094
+ provider,
27095
+ sourceId: source.id
27096
+ });
27097
+ webhookUrl = resolved.webhookUrl;
27098
+ webhookNote = resolved.webhookNote;
27099
+ } catch (err) {
27100
+ logger$53.warn("Failed to resolve webhook URL for added source", {
27101
+ routingKey: source.routing_key,
27102
+ error: toErrorMessage(err)
27103
+ });
27104
+ webhookNote = "resolve-failed";
27105
+ }
26978
27106
  return c.json({
26979
27107
  routingKey: source.routing_key,
26980
27108
  id: source.id,
26981
- name: source.name
27109
+ name: source.name,
27110
+ webhookUrl,
27111
+ ...webhookNote && { webhookNote }
26982
27112
  }, 201);
26983
27113
  } catch (err) {
26984
27114
  logger$53.error("Failed to add source", { error: toErrorMessage(err) });
@@ -30966,7 +31096,10 @@ function createAdminRoutes(deps) {
30966
31096
  return handleError$3(c, err);
30967
31097
  }
30968
31098
  });
30969
- if (deps.sourceStore) app.route("/api/v1/admin", createSourceRoutes({ sourceStore: deps.sourceStore }));
31099
+ if (deps.sourceStore) app.route("/api/v1/admin", createSourceRoutes({
31100
+ sourceStore: deps.sourceStore,
31101
+ resolveSourceWebhookUrl: deps.resolveSourceWebhookUrl
31102
+ }));
30970
31103
  if (deps.db && deps.pool) app.route("/api/v1/admin", createDbRoutes({
30971
31104
  db: deps.db,
30972
31105
  pool: deps.pool
@@ -31837,7 +31970,7 @@ var init_universal_git = __esmMin((() => {
31837
31970
  */
31838
31971
  function registerProviderBundleForSource(row, deps) {
31839
31972
  if (row.provider_type === "internal") {
31840
- if (!canServeGenericProviderType$1("internal", deps.config)) {
31973
+ if (!canServeGenericProviderType("internal", deps.config)) {
31841
31974
  logger$40.info("Skipping internal provider bundle registration — KICI_INTERNAL_PROVIDER_REPO_PATH not configured on this peer", {
31842
31975
  routingKey: row.routing_key,
31843
31976
  sourceName: row.name
@@ -33916,14 +34049,14 @@ var init_admin_config = __esmMin((() => {
33916
34049
  function createHealthRoutes$1(deps = {}) {
33917
34050
  return createHealthRoutes({
33918
34051
  livenessInfo: () => ({
33919
- version: "0.1.5",
33920
- buildDate: "2026-05-25T13:18:39.135Z",
33921
- buildCommit: "600c43faa",
33922
- sdkVersion: "0.1.5",
34052
+ version: "0.1.7",
34053
+ buildDate: "2026-05-26T13:18:35.789Z",
34054
+ buildCommit: "4c0abe030",
34055
+ sdkVersion: "0.1.7",
33923
34056
  sdkBundleHash: "675aafe4de03e677785ef2794d8f34951b14e2bd1e6f0ea825953d6c2abfe128",
33924
- sharedVersion: "0.1.5",
33925
- sharedBundleHash: "12d8f17547ef0a63c0d54c59d918eefb5c5ad16d44c3b4d7fce081d23fe44a7a",
33926
- engineVersion: "0.1.5",
34057
+ sharedVersion: "0.1.7",
34058
+ sharedBundleHash: "36a23a454fd75ec35f258d39f254543ec0451c6b543fe3618ce427e6e6369aae",
34059
+ engineVersion: "0.1.7",
33927
34060
  engineBundleHash: "b704538612ec796a5668765bd55e0eaeaf1bad8a2afa508f9e20ad7b9eb61d21"
33928
34061
  }),
33929
34062
  readinessCheck: deps.db ? async () => {
@@ -33958,7 +34091,7 @@ function createCapabilitiesRoutes() {
33958
34091
  const app = new Hono();
33959
34092
  app.get("/api/v1/capabilities", (c) => {
33960
34093
  const manifest = {
33961
- orchestratorVersion: "0.1.5",
34094
+ orchestratorVersion: "0.1.7",
33962
34095
  protocolVersion: PROTOCOL_VERSION,
33963
34096
  minProtocolVersion: MIN_PROTOCOL_VERSION
33964
34097
  };
@@ -34873,7 +35006,7 @@ function createApp(deps) {
34873
35006
  sourceCache: deps.sourceCache,
34874
35007
  depCache: deps.depCache,
34875
35008
  cacheStorage: deps.cacheStorage,
34876
- onJobStatus: deps.platformClient || deps.executionTracker || deps.commitStatusReporter || deps.pendingBuilds || deps.pendingInits ? (_agentId, msg) => {
35009
+ onJobStatus: deps.platformClient || deps.executionTracker || deps.checkRunReporter || deps.pendingBuilds || deps.pendingInits ? (_agentId, msg) => {
34877
35010
  if (deps.pendingBuilds && deps.pendingBuilds.has(msg.jobId)) {
34878
35011
  if (msg.state === ExecutionJobStatus.enum.success && msg.data?.buildComplete) deps.pendingBuilds.resolve(msg.jobId);
34879
35012
  else if (msg.state === ExecutionJobStatus.enum.failed || msg.state === ExecutionJobStatus.enum.cancelled) deps.pendingBuilds.reject(msg.jobId, new Error(msg.data?.error ?? `Build ${msg.state}`));
@@ -34905,13 +35038,13 @@ function createApp(deps) {
34905
35038
  },
34906
35039
  timestamp: msg.timestamp
34907
35040
  });
34908
- if (deps.commitStatusReporter && deps.executionTracker && (msg.state === ExecutionJobStatus.enum.success || msg.state === ExecutionJobStatus.enum.failed || msg.state === ExecutionJobStatus.enum.cancelled)) {
35041
+ if (deps.checkRunReporter && deps.executionTracker && (msg.state === ExecutionJobStatus.enum.success || msg.state === ExecutionJobStatus.enum.failed || msg.state === ExecutionJobStatus.enum.cancelled)) {
34909
35042
  const execContext = deps.executionTracker.getExecutionContext(msg.runId);
34910
35043
  if (execContext) {
34911
35044
  const [owner, repo] = execContext.repoIdentifier.split("/");
34912
35045
  let description;
34913
35046
  if (msg.state === ExecutionJobStatus.enum.failed && msg.data) description = buildJobFailureDescription(msg.data);
34914
- deps.commitStatusReporter.updateJobStatus({
35047
+ deps.checkRunReporter.updateJobStatus({
34915
35048
  provider: execContext.provider,
34916
35049
  owner,
34917
35050
  repo,
@@ -34962,11 +35095,11 @@ function createApp(deps) {
34962
35095
  } : msg.data;
34963
35096
  deps.executionTracker.onStepStatus(msg.runId, msg.jobId, msg.stepIndex, msg.stepName, msg.state, msg.timestamp, data, msg.logBytesStreamed);
34964
35097
  }
34965
- if (deps.commitStatusReporter && deps.executionTracker) {
35098
+ if (deps.checkRunReporter && deps.executionTracker) {
34966
35099
  const execContext = deps.executionTracker.getExecutionContext(msg.runId);
34967
35100
  if (execContext) {
34968
35101
  const [owner, repo] = execContext.repoIdentifier.split("/");
34969
- deps.commitStatusReporter.updateStepProgress({
35102
+ deps.checkRunReporter.updateStepProgress({
34970
35103
  provider: execContext.provider,
34971
35104
  owner,
34972
35105
  repo,
@@ -35260,7 +35393,7 @@ function createApp(deps) {
35260
35393
  pendingBuilds: deps.pendingBuilds,
35261
35394
  pendingInits: deps.pendingInits,
35262
35395
  pendingDynamics: deps.pendingDynamics,
35263
- commitStatusReporter: deps.commitStatusReporter,
35396
+ checkRunReporter: deps.checkRunReporter,
35264
35397
  executionTracker: deps.executionTracker,
35265
35398
  onSourceLocationsExtracted,
35266
35399
  eventRouter: deps.eventRouter,
@@ -35301,7 +35434,8 @@ function createApp(deps) {
35301
35434
  }));
35302
35435
  if (deps.adminDeps) app.route("", createAdminRoutes({
35303
35436
  ...deps.adminDeps,
35304
- accessLog: deps.accessLogWriter
35437
+ accessLog: deps.accessLogWriter,
35438
+ resolveSourceWebhookUrl: deps.resolveSourceWebhookUrl
35305
35439
  }));
35306
35440
  if (deps.genericSourceManager && deps.trustStore && deps.adminDeps) app.route("", createAdminEventRoutes({
35307
35441
  sourceManager: deps.genericSourceManager,
@@ -35358,7 +35492,7 @@ function createApp(deps) {
35358
35492
  lockFileCache: deps.lockFileCache,
35359
35493
  dispatcher: deps.dispatcher,
35360
35494
  executionTracker: deps.executionTracker,
35361
- commitStatusReporter: deps.commitStatusReporter,
35495
+ checkRunReporter: deps.checkRunReporter,
35362
35496
  sourceCache: deps.sourceCache,
35363
35497
  buildCoordinator: deps.buildCoordinator,
35364
35498
  depCache: deps.depCache,
@@ -35515,7 +35649,7 @@ var init_app = __esmMin((() => {
35515
35649
  init_blob_routes();
35516
35650
  init_agent_api_registry();
35517
35651
  init_server_options();
35518
- init_commit_status();
35652
+ init_check_run_reporter();
35519
35653
  init_agent_handler();
35520
35654
  init_observer_handler();
35521
35655
  init_test_trigger();
@@ -42726,7 +42860,7 @@ var init_stale_run_detector = __esmMin((() => {
42726
42860
  StaleRunDetector = class {
42727
42861
  db;
42728
42862
  executionTracker;
42729
- commitStatusReporter;
42863
+ checkRunReporter;
42730
42864
  scalerManager;
42731
42865
  dispatcher;
42732
42866
  registry;
@@ -42737,7 +42871,7 @@ var init_stale_run_detector = __esmMin((() => {
42737
42871
  constructor(deps) {
42738
42872
  this.db = deps.db;
42739
42873
  this.executionTracker = deps.executionTracker;
42740
- this.commitStatusReporter = deps.commitStatusReporter;
42874
+ this.checkRunReporter = deps.checkRunReporter;
42741
42875
  this.scalerManager = deps.scalerManager;
42742
42876
  this.dispatcher = deps.dispatcher;
42743
42877
  this.registry = deps.registry;
@@ -42959,11 +43093,11 @@ var init_stale_run_detector = __esmMin((() => {
42959
43093
  });
42960
43094
  markedCount++;
42961
43095
  staleRunsDetectedTotal.add(1);
42962
- if (this.commitStatusReporter) {
43096
+ if (this.checkRunReporter) {
42963
43097
  const [owner, repo] = entry.repo_identifier.split("/");
42964
43098
  const providerCtx = typeof entry.provider_context === "string" ? JSON.parse(entry.provider_context) : entry.provider_context ?? {};
42965
43099
  const installationId = typeof providerCtx.installationId === "number" ? providerCtx.installationId : void 0;
42966
- this.commitStatusReporter.updateJobStatus({
43100
+ this.checkRunReporter.updateJobStatus({
42967
43101
  provider: entry.provider,
42968
43102
  owner,
42969
43103
  repo,
@@ -43021,11 +43155,11 @@ var init_stale_run_detector = __esmMin((() => {
43021
43155
  });
43022
43156
  await this.executionTracker.cancelStepsForJob(job.run_id, job.job_id, errorMessage);
43023
43157
  affectedRunIds.add(job.run_id);
43024
- if (this.commitStatusReporter) {
43158
+ if (this.checkRunReporter) {
43025
43159
  const [owner, repo] = job.repo_identifier.split("/");
43026
43160
  const providerCtx = typeof job.provider_context === "string" ? JSON.parse(job.provider_context) : job.provider_context ?? {};
43027
43161
  const installationId = typeof providerCtx.installationId === "number" ? providerCtx.installationId : void 0;
43028
- this.commitStatusReporter.updateJobStatus({
43162
+ this.checkRunReporter.updateJobStatus({
43029
43163
  provider: job.provider,
43030
43164
  owner,
43031
43165
  repo,
@@ -44115,10 +44249,27 @@ var init_source_manager = __esmMin((() => {
44115
44249
  currentSources = [];
44116
44250
  debounceTimer = null;
44117
44251
  debounceMs;
44252
+ /**
44253
+ * Change callback. Stored in a mutable field (not read off `opts`) so a
44254
+ * mode-specific hook can rewire it after construction — the platform-mode
44255
+ * boot wires it to push the full source list to the Platform via
44256
+ * `platformClient.updateSources()`. Defaults to the (possibly no-op) value
44257
+ * passed at construction.
44258
+ */
44259
+ onSourcesChanged;
44118
44260
  constructor(opts) {
44119
44261
  this.opts = opts;
44120
44262
  this.registry = new ProviderRegistry();
44121
44263
  this.debounceMs = opts.debounceMs ?? 200;
44264
+ this.onSourcesChanged = opts.onSourcesChanged;
44265
+ }
44266
+ /**
44267
+ * Replace the change callback after construction. The SourceManager is built
44268
+ * early (before the Platform client exists); the platform-mode boot calls
44269
+ * this once the client is ready so live source changes propagate upstream.
44270
+ */
44271
+ setOnSourcesChanged(cb) {
44272
+ this.onSourcesChanged = cb;
44122
44273
  }
44123
44274
  /** Get current ProviderRegistry (rebuilt on each reload). */
44124
44275
  getRegistry() {
@@ -44193,7 +44344,7 @@ var init_source_manager = __esmMin((() => {
44193
44344
  added: diff.added.length,
44194
44345
  removed: diff.removed.length
44195
44346
  });
44196
- if (diff.added.length > 0 || diff.removed.length > 0) this.opts.onSourcesChanged(diff);
44347
+ if (diff.added.length > 0 || diff.removed.length > 0) this.onSourcesChanged(diff);
44197
44348
  }
44198
44349
  /**
44199
44350
  * Build a ProviderBundle for a source with decrypted secrets.
@@ -45842,9 +45993,19 @@ var init_generic_sources_listener = __esmMin((() => {
45842
45993
  pending = /* @__PURE__ */ new Set();
45843
45994
  debounceTimer = null;
45844
45995
  debounceMs;
45996
+ /**
45997
+ * Drain-applied-change callback. Mutable so the platform-mode boot can wire
45998
+ * it after the Platform client exists (this listener is constructed before).
45999
+ */
46000
+ onChange;
45845
46001
  constructor(opts) {
45846
46002
  this.opts = opts;
45847
46003
  this.debounceMs = opts.debounceMs ?? 200;
46004
+ this.onChange = opts.onChange;
46005
+ }
46006
+ /** Replace the drain-applied-change callback after construction. */
46007
+ setOnChange(cb) {
46008
+ this.onChange = cb;
45848
46009
  }
45849
46010
  /** Open the dedicated client and subscribe. Cold-boot bundle
45850
46011
  * registration is handled by the orchestrator-core startup loop
@@ -45890,6 +46051,7 @@ var init_generic_sources_listener = __esmMin((() => {
45890
46051
  async drain() {
45891
46052
  const keys = Array.from(this.pending);
45892
46053
  this.pending.clear();
46054
+ let appliedChange = false;
45893
46055
  for (const routingKey of keys) try {
45894
46056
  const row = await this.opts.sourceManager.getByRoutingKey(routingKey);
45895
46057
  if (!row) {
@@ -45898,6 +46060,7 @@ var init_generic_sources_listener = __esmMin((() => {
45898
46060
  routingKey,
45899
46061
  removed
45900
46062
  });
46063
+ appliedChange = true;
45901
46064
  continue;
45902
46065
  }
45903
46066
  this.opts.providerRegistry.unregister(routingKey);
@@ -45906,12 +46069,14 @@ var init_generic_sources_listener = __esmMin((() => {
45906
46069
  config: this.opts.config,
45907
46070
  secretResolver: this.opts.secretResolver
45908
46071
  });
46072
+ appliedChange = true;
45909
46073
  } catch (err) {
45910
46074
  logger$8.error("Failed to apply generic-source change", {
45911
46075
  routingKey,
45912
46076
  error: toErrorMessage(err)
45913
46077
  });
45914
46078
  }
46079
+ if (appliedChange) this.onChange?.();
45915
46080
  }
45916
46081
  };
45917
46082
  }));
@@ -47659,7 +47824,7 @@ function buildOnEventMatched(dispatcherRef, executionTracker, providerRegistryRe
47659
47824
  }
47660
47825
  };
47661
47826
  }
47662
- function initializeCluster(config, db, agentRegistry, dispatcher, executionTracker, commitStatusReporter, cacheStorage, scalerManager, registrationIndex, cronScheduler, configReloaderRef, localConfigVersionRef, stepLogBuffer, eventRetryScannerRef) {
47827
+ function initializeCluster(config, db, agentRegistry, dispatcher, executionTracker, checkRunReporter, cacheStorage, scalerManager, registrationIndex, cronScheduler, configReloaderRef, localConfigVersionRef, stepLogBuffer, eventRetryScannerRef) {
47663
47828
  const peerClients = /* @__PURE__ */ new Map();
47664
47829
  const getLocalInventory = () => ({
47665
47830
  instanceId: config.instanceId,
@@ -47763,7 +47928,7 @@ function initializeCluster(config, db, agentRegistry, dispatcher, executionTrack
47763
47928
  peerRegistry,
47764
47929
  dispatcher,
47765
47930
  executionTracker,
47766
- commitStatusReporter,
47931
+ checkRunReporter,
47767
47932
  getPeerClient: (instanceId) => peerClients.get(instanceId),
47768
47933
  sendAndWaitAckViaHandler: (targetId, msg, timeoutMs) => peerHandlerObj?.sendAndWaitAck(targetId, msg, timeoutMs) ?? Promise.resolve(false),
47769
47934
  sendToPeerViaHandler: (targetId, msg) => peerHandlerObj?.sendToPeer(targetId, msg) ?? false
@@ -47973,7 +48138,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
47973
48138
  const stepLogBuffer = new StepLogBuffer();
47974
48139
  const sourceLocationStore = new SourceLocationStore();
47975
48140
  const checkRunTrackingStore = new CheckRunTrackingStore(db);
47976
- const commitStatusReporter = new CommitStatusReporter({
48141
+ const checkRunReporter = new CheckRunReporter({
47977
48142
  providerRegistry,
47978
48143
  stepLogBuffer,
47979
48144
  trackingStore: checkRunTrackingStore,
@@ -48020,7 +48185,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
48020
48185
  });
48021
48186
  });
48022
48187
  const [owner, repo] = context.repoIdentifier.split("/");
48023
- commitStatusReporter.updateWorkflowStatus({
48188
+ checkRunReporter.updateWorkflowStatus({
48024
48189
  provider: context.provider,
48025
48190
  owner,
48026
48191
  repo,
@@ -48070,7 +48235,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
48070
48235
  orgId: trackerExtras?.orgId,
48071
48236
  onRunPruned: (runId) => {
48072
48237
  stepLogBuffer.cleanup(runId);
48073
- commitStatusReporter.cleanupRun(runId);
48238
+ checkRunReporter.cleanupRun(runId);
48074
48239
  },
48075
48240
  onWorkflowComplete: (data) => {
48076
48241
  if (!eventEmitter) return;
@@ -48176,7 +48341,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
48176
48341
  if (pgSecretStore) {
48177
48342
  providerRegistry = await sourceManager.start();
48178
48343
  providerRegistryRef.current = providerRegistry;
48179
- commitStatusReporter.updateRegistry(providerRegistry);
48344
+ checkRunReporter.updateRegistry(providerRegistry);
48180
48345
  const registeredKeys = providerRegistry.getRoutingKeys();
48181
48346
  if (registeredKeys.length > 0) logger$2.info("Provider registry built from sources", { routingKeys: registeredKeys });
48182
48347
  else logger$2.info("No sources configured yet (orchestrator can start with zero sources)");
@@ -48323,7 +48488,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
48323
48488
  ttl: config.lockfileCacheTtlMs
48324
48489
  });
48325
48490
  const configReloaderRef = { current: null };
48326
- const cluster = initializeCluster(config, db, agentRegistry, dispatcher, executionTracker, commitStatusReporter, cacheStorage, scalerManager, registrationIndex, cronScheduler, configReloaderRef, localConfigVersionRef, stepLogBuffer, eventRetryScannerRef);
48491
+ const cluster = initializeCluster(config, db, agentRegistry, dispatcher, executionTracker, checkRunReporter, cacheStorage, scalerManager, registrationIndex, cronScheduler, configReloaderRef, localConfigVersionRef, stepLogBuffer, eventRetryScannerRef);
48327
48492
  coordinatorRef.current = cluster.coordinator;
48328
48493
  if (adminDeps) adminDeps.broadcastAgentTokenRevoke = cluster.broadcastAgentTokenRevoke;
48329
48494
  let masterKeyForStore = null;
@@ -48362,7 +48527,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
48362
48527
  pendingBuilds,
48363
48528
  pendingInits,
48364
48529
  pendingDynamics,
48365
- commitStatusReporter,
48530
+ checkRunReporter,
48366
48531
  stepLogBuffer,
48367
48532
  sourceLocationStore,
48368
48533
  logStorage,
@@ -48398,6 +48563,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
48398
48563
  localConfigVersion: localConfigVersionRef.value,
48399
48564
  sourceStore,
48400
48565
  sourceManager,
48566
+ genericSourcesChangeListener,
48401
48567
  eventLogWriter,
48402
48568
  accessLogWriter,
48403
48569
  coldStore: coldStoreSingleton,
@@ -48449,7 +48615,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
48449
48615
  await sourceManager.reload();
48450
48616
  providerRegistry = sourceManager.getRegistry();
48451
48617
  providerRegistryRef.current = providerRegistry;
48452
- commitStatusReporter.updateRegistry(providerRegistry);
48618
+ checkRunReporter.updateRegistry(providerRegistry);
48453
48619
  logger$2.info("Provider registry reloaded from sources", { routingKeys: providerRegistry.getRoutingKeys() });
48454
48620
  }),
48455
48621
  onScalerReload: scalerManager ? async () => {
@@ -48550,7 +48716,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
48550
48716
  pendingBuilds,
48551
48717
  pendingInits,
48552
48718
  pendingDynamics,
48553
- commitStatusReporter,
48719
+ checkRunReporter,
48554
48720
  executionTracker,
48555
48721
  logWriter,
48556
48722
  stepLogBuffer,
@@ -48604,7 +48770,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
48604
48770
  const staleRunDetector = new StaleRunDetector({
48605
48771
  db,
48606
48772
  executionTracker,
48607
- commitStatusReporter,
48773
+ checkRunReporter,
48608
48774
  scalerManager: scalerManager ?? void 0,
48609
48775
  dispatcher,
48610
48776
  registry: agentRegistry,
@@ -48811,7 +48977,7 @@ var init_orchestrator_core = __esmMin((() => {
48811
48977
  init_scaler();
48812
48978
  init_storage();
48813
48979
  init_cache();
48814
- init_commit_status();
48980
+ init_check_run_reporter();
48815
48981
  init_check_run_tracking_store();
48816
48982
  init_scaler_state_store();
48817
48983
  init_processor();
@@ -50060,13 +50226,13 @@ var init_worker_core = __esmMin((() => {
50060
50226
  init_agent_handler();
50061
50227
  init_worker_status();
50062
50228
  init_agent_heartbeat();
50063
- ORCHESTRATOR_VERSION$1 = "0.1.5";
50064
- WORKER_BUILD_COMMIT = "600c43faa";
50065
- WORKER_SDK_VERSION = "0.1.5";
50229
+ ORCHESTRATOR_VERSION$1 = "0.1.7";
50230
+ WORKER_BUILD_COMMIT = "4c0abe030";
50231
+ WORKER_SDK_VERSION = "0.1.7";
50066
50232
  WORKER_SDK_BUNDLE_HASH = "675aafe4de03e677785ef2794d8f34951b14e2bd1e6f0ea825953d6c2abfe128";
50067
- WORKER_SHARED_VERSION = "0.1.5";
50068
- WORKER_SHARED_BUNDLE_HASH = "12d8f17547ef0a63c0d54c59d918eefb5c5ad16d44c3b4d7fce081d23fe44a7a";
50069
- WORKER_ENGINE_VERSION = "0.1.5";
50233
+ WORKER_SHARED_VERSION = "0.1.7";
50234
+ WORKER_SHARED_BUNDLE_HASH = "36a23a454fd75ec35f258d39f254543ec0451c6b543fe3618ce427e6e6369aae";
50235
+ WORKER_ENGINE_VERSION = "0.1.7";
50070
50236
  WORKER_ENGINE_BUNDLE_HASH = "b704538612ec796a5668765bd55e0eaeaf1bad8a2afa508f9e20ad7b9eb61d21";
50071
50237
  logger$1 = createLogger({ prefix: "worker" });
50072
50238
  DRAIN_TIMEOUT_MS = 3e5;
@@ -50088,13 +50254,13 @@ var init_worker_core = __esmMin((() => {
50088
50254
  * Graceful shutdown in reverse order:
50089
50255
  * Platform client -> agent WS -> heartbeat -> HTTP -> DB
50090
50256
  */
50091
- const ORCHESTRATOR_VERSION = "0.1.5";
50092
- const BUILD_COMMIT = "600c43faa";
50093
- const SDK_VERSION = "0.1.5";
50257
+ const ORCHESTRATOR_VERSION = "0.1.7";
50258
+ const BUILD_COMMIT = "4c0abe030";
50259
+ const SDK_VERSION = "0.1.7";
50094
50260
  const SDK_BUNDLE_HASH = "675aafe4de03e677785ef2794d8f34951b14e2bd1e6f0ea825953d6c2abfe128";
50095
- const SHARED_VERSION = "0.1.5";
50096
- const SHARED_BUNDLE_HASH = "12d8f17547ef0a63c0d54c59d918eefb5c5ad16d44c3b4d7fce081d23fe44a7a";
50097
- const ENGINE_VERSION = "0.1.5";
50261
+ const SHARED_VERSION = "0.1.7";
50262
+ const SHARED_BUNDLE_HASH = "36a23a454fd75ec35f258d39f254543ec0451c6b543fe3618ce427e6e6369aae";
50263
+ const ENGINE_VERSION = "0.1.7";
50098
50264
  const ENGINE_BUNDLE_HASH = "b704538612ec796a5668765bd55e0eaeaf1bad8a2afa508f9e20ad7b9eb61d21";
50099
50265
  const otelSdk = initTelemetry({
50100
50266
  serviceName: "kici-orchestrator",
@@ -50107,7 +50273,7 @@ const { LogPullHandler } = await Promise.resolve().then(() => (init_log_pull_han
50107
50273
  const { DashboardHandler } = await Promise.resolve().then(() => (init_handler(), handler_exports));
50108
50274
  const { payloadFromObject } = await Promise.resolve().then(() => (init_event_log$1(), event_log_exports));
50109
50275
  const { loadActiveGenericRoutingKeys } = await Promise.resolve().then(() => (init_generic_sources(), generic_sources_exports));
50110
- const { canServeGenericProviderType, genericProviderTypeToSubtype } = await Promise.resolve().then(() => (init_entry_helpers(), entry_helpers_exports));
50276
+ const { buildPlatformProviderSources } = await Promise.resolve().then(() => (init_build_platform_sources(), build_platform_sources_exports));
50111
50277
  const { DashboardEnvHandler } = await Promise.resolve().then(() => (init_dashboard_env_handler(), dashboard_env_handler_exports));
50112
50278
  const { DashboardRegistrationsHandler } = await Promise.resolve().then(() => (init_dashboard_registrations_handler(), dashboard_registrations_handler_exports));
50113
50279
  const { DashboardBackendsHandler } = await Promise.resolve().then(() => (init_dashboard_backends_handler(), dashboard_backends_handler_exports));
@@ -50342,28 +50508,8 @@ await guardStartup(logger, async () => {
50342
50508
  let identityLinks = [];
50343
50509
  let orgMemberPermissions = /* @__PURE__ */ new Map();
50344
50510
  const heldRunStore = new HeldRunStore(sub.db);
50345
- const providerSources = [...sub.sourceManager.getSources()];
50346
- try {
50347
- const genericRows = await loadActiveGenericRoutingKeys(sub.db);
50348
- const skipped = [];
50349
- for (const gs of genericRows) if (canServeGenericProviderType(gs.provider_type, config)) providerSources.push({
50350
- provider: "generic",
50351
- routingKey: gs.routing_key,
50352
- name: gs.name,
50353
- subtype: genericProviderTypeToSubtype(gs.provider_type, { hasGitConfig: gs.has_git_config })
50354
- });
50355
- else skipped.push({
50356
- routing_key: gs.routing_key,
50357
- provider_type: gs.provider_type
50358
- });
50359
- if (genericRows.length > 0) logger.info("Added generic sources to Platform registration", {
50360
- count: genericRows.length - skipped.length,
50361
- skipped: skipped.length
50362
- });
50363
- if (skipped.length > 0) logger.info("Skipped non-servable generic sources for Platform registration", { skipped });
50364
- } catch (err) {
50365
- logger.warn("Failed to load generic sources for Platform registration", { error: toErrorMessage(err) });
50366
- }
50511
+ const loadGenericRows = () => loadActiveGenericRoutingKeys(sub.db);
50512
+ const providerSources = await buildPlatformProviderSources(sub.sourceManager, loadGenericRows, config);
50367
50513
  let logPullSendFn = null;
50368
50514
  const logPullHandler = new LogPullHandler({
50369
50515
  logStorage: sub.logStorage,
@@ -50391,7 +50537,7 @@ await guardStartup(logger, async () => {
50391
50537
  dispatcher: sub.dispatcher,
50392
50538
  jobQueue: sub.queue,
50393
50539
  platformClient,
50394
- commitStatusReporter: sub.commitStatusReporter,
50540
+ checkRunReporter: sub.checkRunReporter,
50395
50541
  coordinator: sub.coordinator,
50396
50542
  secretResolver: sub.secretResolver,
50397
50543
  eventRouter: sub.eventRouter,
@@ -50412,7 +50558,7 @@ await guardStartup(logger, async () => {
50412
50558
  dispatcher: sub.dispatcher,
50413
50559
  jobQueue: sub.queue,
50414
50560
  platformClient,
50415
- commitStatusReporter: sub.commitStatusReporter,
50561
+ checkRunReporter: sub.checkRunReporter,
50416
50562
  coordinator: sub.coordinator,
50417
50563
  secretResolver: sub.secretResolver,
50418
50564
  eventRouter: sub.eventRouter,
@@ -50756,7 +50902,7 @@ await guardStartup(logger, async () => {
50756
50902
  onStaleCheckrunCleanup: (msg) => {
50757
50903
  for (const run of msg.runs) {
50758
50904
  const [owner, repo] = run.repoIdentifier.split("/");
50759
- sub.commitStatusReporter.cleanupStaleCheckRuns({
50905
+ sub.checkRunReporter.cleanupStaleCheckRuns({
50760
50906
  provider: run.provider,
50761
50907
  routingKey: run.routingKey,
50762
50908
  owner,
@@ -50908,7 +51054,7 @@ await guardStartup(logger, async () => {
50908
51054
  pendingBuilds: sub.pendingBuilds,
50909
51055
  pendingInits: sub.pendingInits,
50910
51056
  pendingDynamics: sub.pendingDynamics,
50911
- commitStatusReporter: sub.commitStatusReporter,
51057
+ checkRunReporter: sub.checkRunReporter,
50912
51058
  executionTracker: sub.executionTracker,
50913
51059
  coordinator: sub.coordinator,
50914
51060
  secretResolver: sub.secretResolver ?? void 0,
@@ -50948,13 +51094,18 @@ await guardStartup(logger, async () => {
50948
51094
  }
50949
51095
  }
50950
51096
  });
50951
- sub.commitStatusReporter.setOrgPublicAliasResolver(() => platformClient.getOrgPublicAlias());
51097
+ sub.checkRunReporter.setOrgPublicAliasResolver(() => platformClient.getOrgPublicAlias());
50952
51098
  logPullSendFn = (msg) => platformClient.sendRaw(msg);
50953
51099
  dashboardSendFn = (msg) => platformClient.sendRaw(msg);
50954
51100
  dashboardEnvSendFn = (msg) => platformClient.sendRaw(msg);
50955
51101
  dashboardRegSendFn = (msg) => platformClient.sendRaw(msg);
50956
51102
  dashboardBackendsSendFn = (msg) => platformClient.sendRaw(msg);
50957
51103
  dashboardGlobalWorkflowsSendFn = (msg) => platformClient.sendRaw(msg);
51104
+ const republishSources = () => {
51105
+ buildPlatformProviderSources(sub.sourceManager, loadGenericRows, config).then((sources) => platformClient.updateSources(sources)).catch((err) => logger.warn("Failed to republish sources to Platform", { error: toErrorMessage(err) }));
51106
+ };
51107
+ sub.sourceManager.setOnSourcesChanged(() => republishSources());
51108
+ sub.genericSourcesChangeListener.setOnChange(() => republishSources());
50958
51109
  const metricsReporter = new MetricsReporter({
50959
51110
  send: (msg) => platformClient.send(msg),
50960
51111
  intervalMs: 3e4,
@@ -50971,6 +51122,29 @@ await guardStartup(logger, async () => {
50971
51122
  client.connect();
50972
51123
  logger.info("Static peer client dialing", { rawUrl });
50973
51124
  }
51125
+ const resolveSourceWebhookUrl = async (params) => {
51126
+ if (params.provider !== "github") return {
51127
+ webhookUrl: null,
51128
+ webhookNote: "unsupported-provider"
51129
+ };
51130
+ try {
51131
+ const fullSources = await buildPlatformProviderSources(sub.sourceManager, loadGenericRows, config);
51132
+ const webhookUrl = await platformClient.registerSourceAndAwait(fullSources, params.routingKey);
51133
+ return webhookUrl ? { webhookUrl } : {
51134
+ webhookUrl: null,
51135
+ webhookNote: "platform-no-public-url"
51136
+ };
51137
+ } catch (err) {
51138
+ logger.warn("Failed to resolve GitHub webhook URL from Platform", {
51139
+ routingKey: params.routingKey,
51140
+ error: toErrorMessage(err)
51141
+ });
51142
+ return {
51143
+ webhookUrl: null,
51144
+ webhookNote: "platform-unavailable"
51145
+ };
51146
+ }
51147
+ };
50974
51148
  return {
50975
51149
  appDepsExtras: {
50976
51150
  platformClient,
@@ -50978,14 +51152,15 @@ await guardStartup(logger, async () => {
50978
51152
  variableStore,
50979
51153
  heldRunStore,
50980
51154
  globalWorkflowPolicy,
50981
- contributorCache
51155
+ contributorCache,
51156
+ resolveSourceWebhookUrl
50982
51157
  },
50983
51158
  configReloaderExtras: {
50984
51159
  onProviderChange: async (_newConfig, _oldConfig, s) => {
50985
51160
  await s.sourceManager.reload();
50986
51161
  const newRegistry = s.sourceManager.getRegistry();
50987
51162
  s.providerRegistry = newRegistry;
50988
- s.commitStatusReporter.updateRegistry(newRegistry);
51163
+ s.checkRunReporter.updateRegistry(newRegistry);
50989
51164
  logger.info("Provider registry reloaded from sources", { routingKeys: newRegistry.getRoutingKeys() });
50990
51165
  },
50991
51166
  onPlatformReconnect: async (newConfig) => {