@kici-dev/orchestrator 0.1.26 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/dist/__test-helpers__/mock-db.d.ts +2 -0
  2. package/dist/agent/dispatcher.d.ts +52 -2
  3. package/dist/agent/host-roster-reaper.d.ts +1 -2
  4. package/dist/agent/host-roster.d.ts +34 -0
  5. package/dist/agent/ownership-refusal.d.ts +12 -0
  6. package/dist/agent/ownership-tracker.d.ts +64 -16
  7. package/dist/agent/token-store.d.ts +13 -0
  8. package/dist/agent-packaging/availability.d.ts +27 -0
  9. package/dist/agent-packaging/build-package.d.ts +16 -0
  10. package/dist/agent-packaging/download.d.ts +30 -0
  11. package/dist/agent-packaging/index.d.ts +9 -0
  12. package/dist/agent-packaging/install-closure.d.ts +30 -0
  13. package/dist/agent-packaging/node-binary.d.ts +26 -0
  14. package/dist/agent-packaging/refresh.d.ts +50 -0
  15. package/dist/agent-packaging/store.d.ts +15 -0
  16. package/dist/agent-packaging/upload.d.ts +24 -0
  17. package/dist/app-on-error.d.ts +29 -0
  18. package/dist/app.d.ts +69 -8
  19. package/dist/approvals/apply-decision.d.ts +1 -1
  20. package/dist/approvals/step-approval-bridge.d.ts +1 -1
  21. package/dist/artifacts/artifact-store.d.ts +233 -0
  22. package/dist/artifacts/failure-messages.d.ts +46 -0
  23. package/dist/audit/access-log.d.ts +18 -1
  24. package/dist/cache/dep-cache.d.ts +15 -0
  25. package/dist/cache/pending-inits.d.ts +4 -4
  26. package/dist/cache/user-cache.d.ts +37 -0
  27. package/dist/cancel/cancel-run.d.ts +10 -3
  28. package/dist/cancel/dashboard-cancel-handler.d.ts +19 -0
  29. package/dist/cli/api-client.d.ts +51 -5
  30. package/dist/cli/commands/agent-package.d.ts +34 -0
  31. package/dist/cli/commands/check-run.d.ts +26 -0
  32. package/dist/cli/commands/cluster-settings.d.ts +55 -0
  33. package/dist/cli/commands/context.d.ts +25 -0
  34. package/dist/cli/commands/dashboard-encryption-key.d.ts +3 -0
  35. package/dist/cli/commands/db-backup.d.ts +71 -0
  36. package/dist/cli/commands/debug-bundle.d.ts +1 -1
  37. package/dist/cli/commands/orchestrator-service/drain.d.ts +31 -0
  38. package/dist/cli/commands/orchestrator-service/index.d.ts +7 -4
  39. package/dist/cli/commands/orchestrator-service/install-env.d.ts +58 -0
  40. package/dist/cli/commands/secret.d.ts +45 -1
  41. package/dist/cli/commands/shared/admin-cli-access-log.d.ts +46 -0
  42. package/dist/cli/commands/shared/versioned-upgrade.d.ts +65 -2
  43. package/dist/cli/commands/signing-key.d.ts +3 -0
  44. package/dist/cli/commands/source.d.ts +12 -0
  45. package/dist/cli/commands/token.d.ts +9 -0
  46. package/dist/cli/commands/trust-policy.d.ts +48 -0
  47. package/dist/cli/commands/variable.d.ts +6 -6
  48. package/dist/cli/join.d.ts +1 -1
  49. package/dist/cli/service/index.d.ts +2 -2
  50. package/dist/cli/service/instance/manifest.d.ts +17 -0
  51. package/dist/cli/service/instance/resolve.d.ts +11 -0
  52. package/dist/cli/service/windows.d.ts +6 -0
  53. package/dist/cli/wizard/orchestrator-wizard.d.ts +39 -11
  54. package/dist/cli.js +10263 -3667
  55. package/dist/cluster/cluster-settings-reader.d.ts +78 -0
  56. package/dist/cluster/coordinator.d.ts +81 -9
  57. package/dist/cluster/join-client.d.ts +1 -1
  58. package/dist/cluster/leader-gated-scheduler.d.ts +50 -0
  59. package/dist/cluster/orphan-recovery.d.ts +14 -0
  60. package/dist/cluster/peer-client.d.ts +12 -2
  61. package/dist/cluster/peer-handler.d.ts +15 -4
  62. package/dist/cluster/peer-registry.d.ts +12 -0
  63. package/dist/cluster/verified-issuer-poller.d.ts +11 -0
  64. package/dist/cluster/verified-issuer.d.ts +63 -0
  65. package/dist/cold-store/tables/access-log.d.ts +1 -1
  66. package/dist/cold-store/tables/event-log.d.ts +1 -1
  67. package/dist/cold-store/tables/execution-jobs.d.ts +1 -1
  68. package/dist/cold-store/tables/execution-runs.d.ts +1 -1
  69. package/dist/cold-store/tables/execution-steps.d.ts +1 -1
  70. package/dist/cold-store/tables/secret-audit-log.d.ts +1 -1
  71. package/dist/config/loader.d.ts +1 -1
  72. package/dist/config/resolver.d.ts +2 -1
  73. package/dist/config/schema.d.ts +8 -6
  74. package/dist/config/types.d.ts +3 -2
  75. package/dist/config.d.ts +372 -46
  76. package/dist/contexts/binding-store.d.ts +36 -0
  77. package/dist/contexts/context-store.d.ts +100 -0
  78. package/dist/contexts/glob-specificity.d.ts +30 -0
  79. package/dist/{environments → contexts}/held-runs.d.ts +64 -32
  80. package/dist/{environments → contexts}/index.d.ts +1 -1
  81. package/dist/contexts/protection/aggregate.d.ts +43 -0
  82. package/dist/contexts/protection/branch-gate.d.ts +5 -0
  83. package/dist/contexts/protection/concurrency-gate.d.ts +4 -0
  84. package/dist/{environments → contexts}/protection/pipeline.d.ts +3 -3
  85. package/dist/contexts/protection/reviewer-gate.d.ts +4 -0
  86. package/dist/{environments → contexts}/protection/satisfiability.d.ts +22 -22
  87. package/dist/contexts/protection/trust-gate.d.ts +4 -0
  88. package/dist/contexts/protection/wait-timer-gate.d.ts +4 -0
  89. package/dist/contexts/variable-store.d.ts +39 -0
  90. package/dist/cron/cron-scheduler.d.ts +24 -4
  91. package/dist/cron/cron-store.d.ts +21 -7
  92. package/dist/dashboard/attestation-filters.d.ts +94 -74
  93. package/dist/dashboard/handler.d.ts +63 -3
  94. package/dist/db/migration-test-harness.d.ts +41 -0
  95. package/dist/db/migrations/067_environments_to_contexts.d.ts +36 -0
  96. package/dist/db/migrations/068_request_idempotency.d.ts +17 -0
  97. package/dist/db/migrations/069_reroute_tunables.d.ts +21 -0
  98. package/dist/db/migrations/070_execution_runs_failure_class.d.ts +4 -0
  99. package/dist/db/migrations/071_batch_accumulation.d.ts +26 -0
  100. package/dist/db/migrations/072_dispatch_queue_run_id_index.d.ts +15 -0
  101. package/dist/db/migrations/073_org_settings_ingest_concurrency.d.ts +13 -0
  102. package/dist/db/migrations/074_normalize_zero_concurrency_limit.d.ts +13 -0
  103. package/dist/db/migrations/075_ingest_overflow_buffer.d.ts +16 -0
  104. package/dist/db/migrations/076_artifacts.d.ts +19 -0
  105. package/dist/db/migrations/077_backup_runs.d.ts +13 -0
  106. package/dist/db/migrations/078_org_settings_backup_staleness.d.ts +12 -0
  107. package/dist/db/migrations/079_org_settings_scaler_spawn_timeout.d.ts +14 -0
  108. package/dist/db/migrations/080_cluster_settings.d.ts +17 -0
  109. package/dist/db/migrations/081_org_settings_queue_timeout.d.ts +19 -0
  110. package/dist/db/migrations/082_host_s3_reachable.d.ts +16 -0
  111. package/dist/db/migrations/083_org_settings_artifact_caps.d.ts +18 -0
  112. package/dist/db/migrations/084_orchestrator_signing_keys.d.ts +20 -0
  113. package/dist/db/migrations/085_cluster_settings_reroute_flap_grace_ms.d.ts +12 -0
  114. package/dist/db/migrations/086_cluster_settings_max_fanout_hosts.d.ts +12 -0
  115. package/dist/db/migrations/087_cluster_settings_event_router_rate_limit.d.ts +12 -0
  116. package/dist/db/migrations/088_cluster_settings_cache_max_tarball_bytes.d.ts +12 -0
  117. package/dist/db/migrations/089_cluster_settings_cache_ttl_days.d.ts +12 -0
  118. package/dist/db/migrations/090_cluster_settings_concurrency_wait_timeout_ms.d.ts +12 -0
  119. package/dist/db/migrations/091_cluster_settings_agent_token_ttl_ms.d.ts +12 -0
  120. package/dist/db/migrations/092_cluster_settings_version.d.ts +16 -0
  121. package/dist/db/migrations/093_org_settings_sandbox_allowlist.d.ts +4 -0
  122. package/dist/db/migrations/094_dashboard_encryption_keys.d.ts +21 -0
  123. package/dist/db/migrations/095_dashboard_write_policy_tristate.d.ts +20 -0
  124. package/dist/db/migrations/096_multi_schedule_cron_last_fired.d.ts +4 -0
  125. package/dist/db/migrations/097_execution_runs_pr_number.d.ts +4 -0
  126. package/dist/db/migrations/098_execution_runs_customer_id.d.ts +4 -0
  127. package/dist/db/migrations/099_cluster_settings_dashboard_verified_issuer.d.ts +21 -0
  128. package/dist/db/migrations/100_held_runs_hold_type_vocabulary.d.ts +31 -0
  129. package/dist/db/migrations/101_contexts_hold_expiry_drop_default.d.ts +31 -0
  130. package/dist/db/migrations/102_dispatch_queue_agent_id.d.ts +20 -0
  131. package/dist/db/migrations/103_cluster_settings_ownership_db_check_timeout_ms.d.ts +20 -0
  132. package/dist/db/migrations/104_check_run_terminal_sent.d.ts +22 -0
  133. package/dist/db/migrations/105_org_trust_policy.d.ts +19 -0
  134. package/dist/db/migrations/106_cluster_settings_check_run_tracking_ttl_days.d.ts +18 -0
  135. package/dist/db/migrations/107_check_run_tracking_updated_at_index.d.ts +23 -0
  136. package/dist/db/repos/dashboard-encryption-keys-repo.d.ts +48 -0
  137. package/dist/db/repos/signing-keys-repo.d.ts +34 -0
  138. package/dist/db/types.d.ts +499 -66
  139. package/dist/deployment/deployment-identity.d.ts +87 -2
  140. package/dist/diagnostics/checks/backup.d.ts +18 -0
  141. package/dist/diagnostics/checks/index.d.ts +2 -1
  142. package/dist/diagnostics/fleet-collector.d.ts +1 -1
  143. package/dist/drain/drain-controller.d.ts +52 -0
  144. package/dist/events/batch-accumulator.d.ts +63 -0
  145. package/dist/events/circuit-breaker.d.ts +9 -3
  146. package/dist/events/event-emitter.d.ts +31 -0
  147. package/dist/events/event-retry-scanner.d.ts +12 -2
  148. package/dist/events/event-router.d.ts +29 -0
  149. package/dist/firecracker/host-network.d.ts +2 -0
  150. package/dist/firecracker/net-interfaces.d.ts +14 -0
  151. package/dist/github-app-name-refresher/github-app-name-refresher.d.ts +19 -9
  152. package/dist/index.d.ts +2 -0
  153. package/dist/index.js +625 -22
  154. package/dist/lockfile-cache.d.ts +4 -0
  155. package/dist/lockfile-validate.d.ts +16 -9
  156. package/dist/metrics/prometheus.d.ts +114 -15
  157. package/dist/oidc/aws-kms-signer.d.ts +37 -0
  158. package/dist/oidc/command-signer.d.ts +23 -0
  159. package/dist/oidc/db-signer.d.ts +48 -0
  160. package/dist/oidc/id-token-claims.d.ts +76 -0
  161. package/dist/oidc/jwt.d.ts +18 -0
  162. package/dist/oidc/local-dev-signer.d.ts +31 -0
  163. package/dist/oidc/local-mint.d.ts +77 -0
  164. package/dist/oidc/oidc-mint-registration.d.ts +65 -0
  165. package/dist/oidc/orchestrator-mint.d.ts +97 -0
  166. package/dist/oidc/orchestrator-signer-factory.d.ts +33 -0
  167. package/dist/oidc/reconcile-signing-key.d.ts +21 -0
  168. package/dist/oidc/signer.d.ts +25 -0
  169. package/dist/oidc/signing-key-status.d.ts +23 -0
  170. package/dist/orchestrator-core.d.ts +42 -2
  171. package/dist/pipeline/decorating-secret-resolver.d.ts +5 -4
  172. package/dist/pipeline/dispatch-matched-workflow.d.ts +44 -3
  173. package/dist/pipeline/inline-eval.d.ts +2 -2
  174. package/dist/pipeline/install-secrets-resolver.d.ts +25 -14
  175. package/dist/pipeline/{job-environments.d.ts → job-contexts.d.ts} +23 -23
  176. package/dist/pipeline/manual-schedule.d.ts +28 -14
  177. package/dist/pipeline/pending-workflow-context.d.ts +1 -1
  178. package/dist/pipeline/process-webhook.d.ts +57 -2
  179. package/dist/pipeline/processor.d.ts +49 -13
  180. package/dist/pipeline/request-idempotency.d.ts +28 -0
  181. package/dist/pipeline/rerun.d.ts +20 -13
  182. package/dist/pipeline/resolve-sandbox-grant.d.ts +28 -0
  183. package/dist/pipeline/resume-workflow.d.ts +1 -1
  184. package/dist/pipeline/route-or-dispatch-jobs.d.ts +71 -0
  185. package/dist/pipeline/sandbox-allowlist-reader.d.ts +33 -0
  186. package/dist/pipeline/test-pipeline.d.ts +2 -2
  187. package/dist/policy/dashboard-write-policy.d.ts +9 -4
  188. package/dist/provenance/backfill-run.d.ts +1 -0
  189. package/dist/provenance/trust-root.d.ts +20 -0
  190. package/dist/provider-registry.d.ts +8 -0
  191. package/dist/providers/generic/normalizer.d.ts +1 -1
  192. package/dist/providers/github/auth.d.ts +1 -1
  193. package/dist/providers/github/changed-files.d.ts +14 -6
  194. package/dist/providers/github/check-status-poster.d.ts +19 -3
  195. package/dist/providers/github/contributor-resolver.d.ts +1 -1
  196. package/dist/providers/github/lock-file.d.ts +1 -1
  197. package/dist/providers/github/normalizer.d.ts +1 -1
  198. package/dist/providers/github/repo-url.d.ts +1 -1
  199. package/dist/providers/local/index.d.ts +1 -0
  200. package/dist/providers/local/local-source-config.d.ts +1 -0
  201. package/dist/providers/local/lock-file-fetcher.d.ts +1 -1
  202. package/dist/providers/local/normalizer.d.ts +1 -1
  203. package/dist/providers/local/repo-url-builder.d.ts +1 -1
  204. package/dist/providers/universal-git/changed-files.d.ts +8 -7
  205. package/dist/providers/universal-git/clone-token.d.ts +1 -1
  206. package/dist/providers/universal-git/config.d.ts +4 -4
  207. package/dist/providers/universal-git/index.d.ts +5 -1
  208. package/dist/providers/universal-git/lock-file.d.ts +6 -1
  209. package/dist/providers/universal-git/normalizer.d.ts +1 -1
  210. package/dist/providers/universal-git/repo-url.d.ts +1 -1
  211. package/dist/queue/cleanup.d.ts +69 -8
  212. package/dist/queue/job-queue.d.ts +94 -14
  213. package/dist/queue/scheduled-job.d.ts +2 -2
  214. package/dist/registration/registration-index.d.ts +1 -1
  215. package/dist/reporting/agent-failure-category.d.ts +4 -1
  216. package/dist/reporting/check-run-reporter.d.ts +34 -14
  217. package/dist/reporting/check-run-tracking-store.d.ts +70 -8
  218. package/dist/reporting/execution-tracker.d.ts +173 -17
  219. package/dist/reporting/fs-log-storage.d.ts +31 -2
  220. package/dist/reporting/job-check-run-completion.d.ts +50 -0
  221. package/dist/reporting/log-chunk-sink.d.ts +47 -0
  222. package/dist/reporting/log-retention.d.ts +16 -0
  223. package/dist/reporting/log-storage.d.ts +64 -4
  224. package/dist/reporting/log-writer.d.ts +22 -7
  225. package/dist/reporting/peer-log-normalize.d.ts +14 -0
  226. package/dist/reporting/run-aggregator.d.ts +36 -36
  227. package/dist/reporting/s3-log-storage.d.ts +102 -8
  228. package/dist/routes/admin-auth.d.ts +90 -0
  229. package/dist/routes/admin-cluster-settings.d.ts +31 -0
  230. package/dist/routes/admin-contexts.d.ts +47 -0
  231. package/dist/routes/admin-events.d.ts +3 -0
  232. package/dist/routes/admin-orchestrator-drain.d.ts +35 -0
  233. package/dist/routes/admin-registrations.d.ts +2 -2
  234. package/dist/routes/admin-runs.d.ts +9 -0
  235. package/dist/routes/admin-sources.d.ts +7 -0
  236. package/dist/routes/admin-trust-policy.d.ts +49 -0
  237. package/dist/routes/admin.d.ts +15 -1
  238. package/dist/routes/github-webhook.d.ts +9 -3
  239. package/dist/routes/provenance-oidc.d.ts +38 -0
  240. package/dist/routes/verify-attestation.d.ts +21 -0
  241. package/dist/scaler/bare-metal-backend.d.ts +9 -2
  242. package/dist/scaler/config.d.ts +25 -4
  243. package/dist/scaler/container-backend.d.ts +9 -1
  244. package/dist/scaler/firecracker-backend.d.ts +29 -2
  245. package/dist/scaler/index.d.ts +1 -1
  246. package/dist/scaler/manager.d.ts +166 -8
  247. package/dist/scaler/pending-scale-sweeper.d.ts +35 -0
  248. package/dist/scaler/types.d.ts +75 -6
  249. package/dist/secrets/backend-registry.d.ts +32 -1
  250. package/dist/secrets/context-secret-resolver.d.ts +30 -0
  251. package/dist/secrets/dashboard-encryption-key.d.ts +48 -0
  252. package/dist/secrets/ephemeral-keys.d.ts +16 -0
  253. package/dist/secrets/index.d.ts +1 -1
  254. package/dist/secrets/pg-secret-store.d.ts +13 -3
  255. package/dist/secrets/rbac.d.ts +5 -1
  256. package/dist/secrets/routing-key-scope.d.ts +6 -0
  257. package/dist/secrets/scope-routing.d.ts +126 -0
  258. package/dist/secrets/secret-resolver.d.ts +19 -32
  259. package/dist/secrets/token-manager.d.ts +5 -1
  260. package/dist/security/comment-handler.d.ts +1 -1
  261. package/dist/security/contributor-cache.d.ts +9 -1
  262. package/dist/security/trust-policy-gate.d.ts +117 -0
  263. package/dist/security/trust-policy-store.d.ts +78 -0
  264. package/dist/server.js +44012 -32721
  265. package/dist/sources/source-manager.d.ts +24 -0
  266. package/dist/stale-detector/stale-run-detector.d.ts +8 -1
  267. package/dist/standalone.js +44106 -33690
  268. package/dist/storage/blob-routes.d.ts +16 -0
  269. package/dist/storage/filesystem.d.ts +17 -0
  270. package/dist/storage/key-discriminator.d.ts +20 -0
  271. package/dist/storage/s3.d.ts +2 -0
  272. package/dist/storage/types.d.ts +16 -0
  273. package/dist/webhook/dedup.d.ts +9 -1
  274. package/dist/webhook/event-log.d.ts +13 -2
  275. package/dist/webhook/generic-sources-listener.d.ts +4 -0
  276. package/dist/webhook/ingest-admission.d.ts +140 -0
  277. package/dist/webhook/ingest-overflow-buffer.d.ts +27 -0
  278. package/dist/webhook/ingest-overflow-replayer.d.ts +49 -0
  279. package/dist/webhook/ingest-overflow-types.d.ts +73 -0
  280. package/dist/webhook/loop-lag-source.d.ts +40 -0
  281. package/dist/webhook/observed-relay-guard.d.ts +40 -0
  282. package/dist/webhook/org-ingest-cap-reader.d.ts +24 -0
  283. package/dist/webhook/register-source-bundle.d.ts +3 -0
  284. package/dist/webhook/relay-reinject.d.ts +43 -0
  285. package/dist/worker/in-memory-job-queue.d.ts +8 -3
  286. package/dist/worker-core.d.ts +10 -0
  287. package/dist/ws/agent-api-registry.d.ts +20 -0
  288. package/dist/ws/agent-handler.d.ts +63 -7
  289. package/dist/ws/bringup-api.d.ts +99 -0
  290. package/dist/ws/{dashboard-env-handler.d.ts → dashboard-context-handler.d.ts} +43 -25
  291. package/dist/ws/dashboard-run-state-handler.d.ts +31 -0
  292. package/dist/ws/failure-messages.d.ts +29 -0
  293. package/dist/ws/oidc-token-relay.d.ts +15 -0
  294. package/dist/ws/ownership-gate.d.ts +22 -0
  295. package/dist/ws/platform-client.d.ts +96 -1
  296. package/dist/ws/replay-chunker.d.ts +37 -0
  297. package/installer-image-digests.json +3 -3
  298. package/package.json +22 -21
  299. package/sbom.spdx.json +1245 -1793
  300. package/dist/cli/commands/environment.d.ts +0 -25
  301. package/dist/environments/binding-store.d.ts +0 -36
  302. package/dist/environments/environment-store.d.ts +0 -87
  303. package/dist/environments/protection/aggregate.d.ts +0 -43
  304. package/dist/environments/protection/branch-gate.d.ts +0 -5
  305. package/dist/environments/protection/concurrency-gate.d.ts +0 -7
  306. package/dist/environments/protection/reviewer-gate.d.ts +0 -7
  307. package/dist/environments/protection/trust-gate.d.ts +0 -7
  308. package/dist/environments/protection/wait-timer-gate.d.ts +0 -7
  309. package/dist/environments/variable-store.d.ts +0 -39
  310. package/dist/routes/admin-environments.d.ts +0 -47
@@ -0,0 +1,78 @@
1
+ import type { Kysely } from 'kysely';
2
+ import type { Database } from '../db/types.js';
3
+ /** Numeric columns on cluster_settings readable via {@link ClusterSettingsReader}. */
4
+ export type ClusterNumberColumn = 'max_github_payload_bytes' | 'event_log_max_payload_bytes' | 'lock_file_max_bytes' | 'webhook_dedup_ttl_ms' | 'contributor_cache_ttl_ms' | 'event_router_event_ttl_seconds' | 'event_router_max_dispatch_attempts' | 'queue_max_depth' | 'reroute_flap_grace_ms' | 'max_fanout_hosts' | 'event_router_rate_limit_per_workflow_per_minute' | 'cache_max_tarball_bytes' | 'cache_ttl_days' | 'check_run_tracking_ttl_days' | 'concurrency_wait_timeout_ms' | 'agent_token_ttl_ms' | 'ownership_db_check_timeout_ms';
5
+ /** Text columns on cluster_settings readable via {@link ClusterSettingsReader}. */
6
+ export type ClusterStringColumn = 'dashboard_verified_issuer';
7
+ /**
8
+ * A knob read that keeps "the operator never set this" separate from "we could
9
+ * not read it".
10
+ *
11
+ * `{ ok: true, value: null }` is a genuine unset — a missing row, a null
12
+ * column, or a cleared (empty) string. `{ ok: false }` means the query failed,
13
+ * so the caller decides: most knobs want their cluster default, but one whose
14
+ * default is a weaker trust tier must hold its last known value instead.
15
+ */
16
+ export type ClusterSettingRead<T> = {
17
+ ok: true;
18
+ value: T | null;
19
+ } | {
20
+ ok: false;
21
+ };
22
+ /**
23
+ * Reads the single cluster_settings row (id='default') once per short TTL
24
+ * window and serves every fleet-wide knob from that snapshot. `getNumber` and
25
+ * `getString` degrade to the caller's `fallback` (the config.ts cluster
26
+ * default) on no-db / missing row / null column / DB error, so a hot-path read
27
+ * never blocks on a sick DB. {@link ClusterSettingsReader.tryGetString} is the
28
+ * one exception: it reports a failed query as `{ ok: false }` rather than a
29
+ * default, for the caller whose default would be a weaker trust tier.
30
+ *
31
+ * There is exactly one row, so a whole-row cache is strictly simpler than a
32
+ * per-column cache: one DB hit per TTL window serves every column and every
33
+ * read-site.
34
+ */
35
+ export declare class ClusterSettingsReader {
36
+ private readonly db;
37
+ private readonly cacheTtlMs;
38
+ private cache;
39
+ constructor(db: Kysely<Database> | undefined, cacheTtlMs?: number);
40
+ /**
41
+ * The cached row plus whether it reflects a successful read.
42
+ *
43
+ * `readable` lives on the cache entry, not around the query, because the
44
+ * negative cache serves reads 2..N of a TTL window without touching the DB:
45
+ * deriving "unreadable" from the catch alone would report those reads as a
46
+ * genuine unset.
47
+ */
48
+ private loadSnapshot;
49
+ private loadRow;
50
+ /** Resolve a fleet-wide numeric knob; `fallback` is the config.ts cluster default. */
51
+ getNumber(column: ClusterNumberColumn, fallback: number): Promise<number>;
52
+ /**
53
+ * Resolve a fleet-wide text knob; `fallback` is the config.ts cluster default
54
+ * (which may itself be null). An empty stored string is treated as unset so an
55
+ * operator clearing the knob via the admin API behaves like a NULL.
56
+ */
57
+ getString(column: ClusterStringColumn, fallback: string | null): Promise<string | null>;
58
+ /**
59
+ * Resolve a fleet-wide text knob without collapsing a read failure into a
60
+ * default.
61
+ *
62
+ * There is deliberately no `fallback` parameter: the point of this variant is
63
+ * that the caller — not the reader — decides what an unreadable knob means.
64
+ * An empty stored string is unset, matching {@link getString}.
65
+ */
66
+ tryGetString(column: ClusterStringColumn): Promise<ClusterSettingRead<string>>;
67
+ /**
68
+ * The cluster_settings row version last seen in the cache (0 if never loaded).
69
+ *
70
+ * Synchronous — never awaits a DB read — so the heartbeat timer can read it
71
+ * safely and advertise it to workers. When the cache is cold or expired it
72
+ * kicks a non-blocking refresh so the advertised version self-heals within a
73
+ * cache-TTL window without depending on a `getNumber()` call, then returns
74
+ * the last-loaded value.
75
+ */
76
+ getCachedVersion(): number;
77
+ }
78
+ //# sourceMappingURL=cluster-settings-reader.d.ts.map
@@ -93,6 +93,23 @@ export interface RunCoordinatorDeps {
93
93
  ackTimeoutMs?: number;
94
94
  /** Stale peer timeout in ms. Default: 60000 (60s). */
95
95
  staleTimeoutMs?: number;
96
+ /**
97
+ * Per-job reroute spawn window (ms): the post-ACK re-dispatch backstop
98
+ * window. Resolves the job's org override from
99
+ * `org_settings.reroute_spawn_window_ms`, else the cluster default. When
100
+ * absent, {@link DEFAULT_REROUTE_SPAWN_WINDOW_MS} is used.
101
+ */
102
+ getRerouteSpawnWindowMs?: (job: JobToRoute) => Promise<number>;
103
+ /**
104
+ * Per-job reroute ACK timeout (ms) for the `sendAndWaitAck` deadline. When
105
+ * absent, falls back to `ackTimeoutMs` / {@link DEFAULT_ACK_TIMEOUT_MS}.
106
+ */
107
+ getRerouteAckTimeoutMs?: (job: JobToRoute) => Promise<number>;
108
+ /**
109
+ * Per-job maximum peer hops for a rerouted job. When absent, falls back to
110
+ * {@link DEFAULT_MAX_HOPS}.
111
+ */
112
+ getRerouteMaxHops?: (job: JobToRoute) => Promise<number>;
96
113
  }
97
114
  export declare class RunCoordinator {
98
115
  private readonly instanceId;
@@ -104,9 +121,13 @@ export declare class RunCoordinator {
104
121
  private readonly sendAndWaitAckViaHandler?;
105
122
  private readonly sendToPeerViaHandler?;
106
123
  private readonly ackTimeoutMs;
124
+ private readonly getRerouteSpawnWindowMs;
125
+ private readonly getRerouteAckTimeoutMs;
126
+ private readonly getRerouteMaxHops;
107
127
  /**
108
128
  * Tracks which jobs have been rerouted to which peers, keyed by runId.
109
- * Used for cancel propagation and progress tracking.
129
+ * Used for cancel propagation, progress tracking, and the post-ACK spawn
130
+ * re-dispatch backstop.
110
131
  */
111
132
  private readonly reroutedJobs;
112
133
  /**
@@ -142,7 +163,7 @@ export declare class RunCoordinator {
142
163
  * this split, every job-level event was silently funnelled into
143
164
  * `onStepStatus` and the run stayed in `running` forever.
144
165
  */
145
- onPeerJobProgress(msg: JobProgress, reply?: (m: JobProgressAck) => void): void;
166
+ onPeerJobProgress(msg: JobProgress, fromPeerId: string, reply?: (m: JobProgressAck) => void): void;
146
167
  /**
147
168
  * Handle a scaler provisioning event forwarded by a worker peer.
148
169
  *
@@ -151,8 +172,25 @@ export declare class RunCoordinator {
151
172
  * coordinator's ExecutionTracker persists the event (provisioning log
152
173
  * line + dispatch-queue last-error column) just as it would for a
153
174
  * locally-emitted scaler event.
175
+ *
176
+ * Layer B fast path: a `scaler.failed` for a tracked rerouted job whose spawn
177
+ * window is still armed is the worker's NAK-after-accept — the peer accepted
178
+ * the reroute but its agent spawn failed asynchronously before reporting any
179
+ * progress. Re-dispatch immediately (the same routine the spawn-window timer
180
+ * runs) instead of waiting the window out. Idempotent with the Layer A timer:
181
+ * whichever fires first removes the tracking entry.
182
+ *
183
+ * Two guards make the re-dispatch safe. First, source provenance: the failure
184
+ * must come from `fromPeerId === tracked.peerId` (the authenticated connection
185
+ * identity), so a late `scaler.failed` relayed for the same jobId by a
186
+ * superseded peer after an earlier re-dispatch is ignored rather than bouncing
187
+ * the healthy replacement. Second, the armed-window check: once the first
188
+ * progress disarms the timer (`windowTimer` cleared to undefined), the job is
189
+ * executing and a stale failure must NOT cancel the running job. Persistence
190
+ * (`emitScalerEvent`) stays unconditional — it is keyed on `(runId, jobId)` and
191
+ * correct regardless of which peer relayed the event.
154
192
  */
155
- onPeerScalerEvent(msg: PeerScalerEvent): void;
193
+ onPeerScalerEvent(msg: PeerScalerEvent, fromPeerId: string): void;
156
194
  /**
157
195
  * Handle peer job completion. Updates ExecutionTracker.
158
196
  * The execution tracker's onJobStatus fires the needs-aware scheduler hook,
@@ -189,11 +227,24 @@ export declare class RunCoordinator {
189
227
  */
190
228
  getBackoffUntil(peerId: string): number;
191
229
  /**
192
- * Attempt to reroute a job to a peer with matching capacity.
193
- * Tries peers in order of available capacity (most capacity first).
194
- * Returns on first successful ACK.
230
+ * Attempt to reroute a job to a peer with matching capacity. Allocates the
231
+ * sender-side jobId (so the caller can register execution rows under the id
232
+ * the worker reports back against) and delegates to {@link attemptPeerRoute}.
195
233
  */
196
234
  private rerouteJob;
235
+ /**
236
+ * Try each peer with matching capacity (most capacity first) for a single
237
+ * job under a fixed `jobId`, returning on the first ACK. Reused by initial
238
+ * routing and by the post-ACK spawn re-dispatch backstop — the caller passes
239
+ * the accumulated `triedConnections` (this instance + any failed peers) so a
240
+ * re-dispatch never re-selects a peer that already failed and the receiving
241
+ * peer's loop-prevention stays correct.
242
+ */
243
+ private attemptPeerRoute;
244
+ /** Build the failure result when no peer has matching capacity (with debug log). */
245
+ private noCapacityResult;
246
+ /** Assemble the `job.reroute` wire message for a single routing attempt. */
247
+ private buildRerouteMessage;
197
248
  /**
198
249
  * Sort peers by available capacity for the given label sets.
199
250
  * Peers with more available capacity come first.
@@ -211,10 +262,31 @@ export declare class RunCoordinator {
211
262
  */
212
263
  private computeAvailableCapacity;
213
264
  /**
214
- * Track a rerouted job for cancel propagation, and durably tag the projected
215
- * `execution_jobs` row with the owning worker peer so run-recovery sweepers
216
- * do not force-fail the job while its worker is connected.
265
+ * Track a rerouted job for cancel propagation, arm the post-ACK spawn-window
266
+ * backstop timer, and durably tag the projected `execution_jobs` row with the
267
+ * owning worker peer so run-recovery sweepers do not force-fail the job while
268
+ * its worker is connected.
217
269
  */
218
270
  private trackReroutedJob;
271
+ /**
272
+ * Post-ACK spawn-window backstop. Fires when a rerouted job's peer accepted
273
+ * but produced no progress within the window (Layer A), or immediately when a
274
+ * worker relays a `scaler.failed` for the job (Layer B, via onPeerScalerEvent).
275
+ * Best-effort cancels the original peer (double-execution guard against a
276
+ * slow-but-healthy spawn), then re-runs routing to another peer, then a local
277
+ * fallback, and finally records the job failed rather than leaving it pending.
278
+ * Idempotent: whichever trigger fires first removes the tracking entry, so the
279
+ * other no-ops.
280
+ */
281
+ private handleRerouteSpawnTimeout;
282
+ /** Best-effort cancel a single job on a peer (double-execution guard). */
283
+ private cancelPeerJob;
284
+ /**
285
+ * Local fallback for a re-dispatch: dispatch the job on this coordinator under
286
+ * the existing jobId. Returns true when the local dispatcher accepts it.
287
+ */
288
+ private tryLocalRedispatch;
289
+ /** Mark a job failed when no backend (peer or local) can run it after re-dispatch. */
290
+ private failUnroutableJob;
219
291
  }
220
292
  //# sourceMappingURL=coordinator.d.ts.map
@@ -16,7 +16,7 @@ import { type JoinRequest, type JoinResponse } from '@kici-dev/engine';
16
16
  import type { ConfigBundle } from './join-handler.js';
17
17
  interface JoinClientOptions {
18
18
  token: string;
19
- /** Platform WebSocket URL for relay mode (e.g., wss://platform.kici.dev/ws) */
19
+ /** Platform WebSocket URL for relay mode (e.g., wss://api.kici.dev/ws) */
20
20
  platformUrl?: string;
21
21
  /** Peer HTTP URL for direct mode (e.g., https://orch-1:8080) */
22
22
  peerUrl?: string;
@@ -0,0 +1,50 @@
1
+ import { createLogger } from '@kici-dev/shared';
2
+ type SchedulerLogger = ReturnType<typeof createLogger>;
3
+ export interface LeaderGatedSchedulerOptions {
4
+ /** Human name for logs, e.g. "cron evaluation". */
5
+ name: string;
6
+ /** Interval between ticks, in ms. */
7
+ intervalMs: number;
8
+ /** The periodic body. Errors are caught and logged, never thrown out of the interval. */
9
+ tick: () => Promise<void> | void;
10
+ /**
11
+ * Optional setup run AFTER leader=true and BEFORE the interval starts (awaited), so the first
12
+ * tick can rely on it. Cron uses this for cache load + missed-schedule recovery.
13
+ */
14
+ onBecomeLeader?: () => Promise<void> | void;
15
+ /** Whether to unref the interval timer. Default true; pass false to keep the loop alive. */
16
+ unref?: boolean;
17
+ /**
18
+ * Logger for the lifecycle + tick-error lines. Pass the owning class's logger so the log
19
+ * prefix stays that of the scheduler site; defaults to a `leader-gated-scheduler` logger.
20
+ */
21
+ logger?: SchedulerLogger;
22
+ }
23
+ /**
24
+ * Raft-leader-only periodic scheduler. Encapsulates the become -> (optional async setup) ->
25
+ * start-interval / lose -> stop lifecycle that the orchestrator's leader-gated schedulers share.
26
+ * The interval runs only while this node is the leader.
27
+ */
28
+ export declare class LeaderGatedScheduler {
29
+ private readonly opts;
30
+ private timer;
31
+ private leader;
32
+ private readonly logger;
33
+ /**
34
+ * Monotonic tenure counter. Bumped on every leadership transition
35
+ * (onBecomeLeader / onLoseLeadership / stop). onBecomeLeader captures its
36
+ * tenure at entry and re-checks it after the awaited setup: if it changed
37
+ * during the async setup, leadership was revoked (or superseded by a newer
38
+ * tenure) mid-flight and this stale tenure must NOT start the interval — that
39
+ * would leak a timer running tick() while no longer leader.
40
+ */
41
+ private generation;
42
+ constructor(opts: LeaderGatedSchedulerOptions);
43
+ get isLeader(): boolean;
44
+ onBecomeLeader(): Promise<void>;
45
+ onLoseLeadership(): void;
46
+ stop(): void;
47
+ private clearTimer;
48
+ }
49
+ export {};
50
+ //# sourceMappingURL=leader-gated-scheduler.d.ts.map
@@ -17,11 +17,16 @@ import type { Database } from '../db/types.js';
17
17
  import type { RaftNode } from './raft.js';
18
18
  import type { PeerRegistry } from './peer-registry.js';
19
19
  import type { ExecutionTracker } from '../reporting/execution-tracker.js';
20
+ import type { ClusterSettingsReader } from './cluster-settings-reader.js';
20
21
  interface OrphanRecoveryDeps {
21
22
  db: Kysely<Database>;
22
23
  raft: RaftNode;
23
24
  peerRegistry: PeerRegistry;
24
25
  executionTracker: ExecutionTracker;
26
+ /** Reader for fleet-wide cluster tunables (reroute flap-grace override). */
27
+ clusterSettings: ClusterSettingsReader;
28
+ /** Cluster default for the reroute flap-grace window (config.rerouteFlapGraceMs). */
29
+ rerouteFlapGraceFallbackMs: number;
25
30
  /** Scan interval in ms. Default: 60000 (1 minute). */
26
31
  scanIntervalMs?: number;
27
32
  /** How long a run must be stale before considered orphaned. Default: 5 minutes. */
@@ -34,6 +39,8 @@ export declare class OrphanRecovery {
34
39
  private readonly raft;
35
40
  private readonly peerRegistry;
36
41
  private readonly executionTracker;
42
+ private readonly clusterSettings;
43
+ private readonly rerouteFlapGraceFallbackMs;
37
44
  private readonly scanIntervalMs;
38
45
  private readonly staleThresholdMs;
39
46
  private readonly jobStuckThresholdMs;
@@ -57,6 +64,13 @@ export declare class OrphanRecovery {
57
64
  * Attempt to recover a single potentially orphaned run.
58
65
  */
59
66
  private recoverRun;
67
+ /**
68
+ * Whether any job of the run moved within the stale window — a heartbeat, a
69
+ * start, or a completion. A crashed coordinator stops producing all three, so
70
+ * a genuinely orphaned run becomes eligible again within one window; a healthy
71
+ * long run never does.
72
+ */
73
+ private hasRecentProgress;
60
74
  /**
61
75
  * Check if a coordinator with the given routing key is still connected
62
76
  * as a peer in the cluster.
@@ -10,7 +10,7 @@
10
10
  * Authentication uses ECDH key exchange followed by join token (first connect)
11
11
  * or HMAC credential proof (reconnection).
12
12
  */
13
- import { type PeerHeartbeat, type PeerToPeerMessage, type JobReroute, type JobProgress, type JobProgressAck, type PeerJobCancel, type PeerLogChunk, type PeerCacheUploadRequest, type PeerCacheUploadResponse, type PeerConfigReload, type PeerConfigReloadResponse, type PeerLogsCollectRequest, type PeerLeaving, type PeerAgentTokenRevoke, type RaftVoteRequest, type RaftVoteResponse, type RaftAppendEntries } from '@kici-dev/engine';
13
+ import { type PeerHeartbeat, type PeerToPeerMessage, type JobReroute, type JobProgress, type JobProgressAck, type PeerJobCancel, type PeerLogChunk, type PeerCacheUploadRequest, type PeerCacheUploadResponse, type PeerConfigReload, type PeerConfigReloadResponse, type PeerClusterSettingsRequest, type PeerClusterSettingsResponse, type PeerLogsCollectRequest, type PeerLeaving, type PeerAgentTokenRevoke, type RaftVoteRequest, type RaftVoteResponse, type RaftAppendEntries } from '@kici-dev/engine';
14
14
  import type { PeerRegistry } from './peer-registry.js';
15
15
  import type { PeerAuthCoordinator } from './peer-auth-coordinator.js';
16
16
  type PeerConnectionState = 'disconnected' | 'connecting' | 'handshaking' | 'authenticating' | 'connected';
@@ -36,7 +36,7 @@ export interface PeerClientOptions {
36
36
  /** Callback when a job reroute request is received from peer. */
37
37
  onJobReroute: (msg: JobReroute) => Promise<void>;
38
38
  /** Callback when a job progress update is received from peer. */
39
- onJobProgress: (msg: JobProgress, reply: (m: JobProgressAck) => void) => void;
39
+ onJobProgress: (msg: JobProgress, fromPeerId: string, reply: (m: JobProgressAck) => void) => void;
40
40
  /**
41
41
  * Callback invoked once this client reaches the `connected` state (initial
42
42
  * connect AND every reconnect). Carries this client's peer URL.
@@ -114,6 +114,7 @@ export declare class PeerClient {
114
114
  private readonly ackWaiters;
115
115
  private readonly cacheWaiters;
116
116
  private readonly configReloadWaiters;
117
+ private readonly clusterSettingsWaiters;
117
118
  /** Correlates peer.logs.collect.request with the peer's chunked subtree response. */
118
119
  private readonly logsCollectWaiters;
119
120
  private readonly url;
@@ -183,6 +184,14 @@ export declare class PeerClient {
183
184
  * if the peer doesn't reply within the timeout.
184
185
  */
185
186
  sendConfigReloadAndWait(msg: PeerConfigReload, timeoutMs?: number): Promise<PeerConfigReloadResponse | null>;
187
+ /**
188
+ * Send a peer.clusterSettings.request to the connected leader and wait for the
189
+ * matching peer.clusterSettings.response carrying the worker-settings snapshot.
190
+ *
191
+ * @returns The response, or null if not connected or the leader doesn't reply
192
+ * within the timeout — the caller keeps its current (config-default) settings.
193
+ */
194
+ sendClusterSettingsRequestAndWait(msg: PeerClusterSettingsRequest, timeoutMs?: number): Promise<PeerClusterSettingsResponse | null>;
186
195
  /**
187
196
  * Send a peer.logs.collect.request to the connected peer and await its
188
197
  * reassembled subtree-bundle ZIP. Rejects on timeout, an error frame, or
@@ -236,6 +245,7 @@ export declare class PeerClient {
236
245
  private clearAckWaiters;
237
246
  private clearCacheWaiters;
238
247
  private clearConfigReloadWaiters;
248
+ private clearClusterSettingsWaiters;
239
249
  }
240
250
  export {};
241
251
  //# sourceMappingURL=peer-client.d.ts.map
@@ -6,7 +6,7 @@
6
6
  * proof (reconnection), registers the peer in PeerRegistry, and routes
7
7
  * messages bidirectionally. Sends periodic heartbeats to the connecting peer.
8
8
  */
9
- import { type PeerHeartbeat, type PeerToPeerMessage, type JobReroute, type JobProgress, type JobProgressAck, type PeerScalerEvent, type PeerJobCancel, type PeerLogChunk, type PeerCacheUploadRequest, type PeerCacheUploadResponse, type PeerConfigReload, type PeerConfigReloadResponse, type PeerLogsCollectRequest, type PeerLeaving, type PeerAgentTokenRevoke, type RaftVoteRequest, type RaftVoteResponse, type RaftAppendEntries } from '@kici-dev/engine';
9
+ import { type PeerHeartbeat, type PeerToPeerMessage, type JobReroute, type JobProgress, type JobProgressAck, type PeerScalerEvent, type PeerJobCancel, type PeerLogChunk, type PeerCacheUploadRequest, type PeerCacheUploadResponse, type PeerConfigReload, type PeerConfigReloadResponse, type PeerClusterSettingsRequest, type WorkerClusterSettings, type PeerLogsCollectRequest, type PeerLeaving, type PeerAgentTokenRevoke, type RaftVoteRequest, type RaftVoteResponse, type RaftAppendEntries } from '@kici-dev/engine';
10
10
  import type { PeerRegistry } from './peer-registry.js';
11
11
  import type { PeerCredentialStore } from './peer-credentials.js';
12
12
  import { type JoinTokenManager } from './join-token.js';
@@ -40,9 +40,9 @@ export interface PeerHandlerDeps {
40
40
  /** Callback when a job reroute request is received from peer. */
41
41
  onJobReroute: (msg: JobReroute) => Promise<void>;
42
42
  /** Callback when a job progress update is received from peer. */
43
- onJobProgress: (msg: JobProgress, reply: (m: JobProgressAck) => void) => void;
43
+ onJobProgress: (msg: JobProgress, fromPeerId: string, reply: (m: JobProgressAck) => void) => void;
44
44
  /** Callback when a scaler provisioning event is forwarded by a worker peer. */
45
- onPeerScalerEvent?: (msg: PeerScalerEvent) => void;
45
+ onPeerScalerEvent?: (msg: PeerScalerEvent, fromPeerId: string) => void;
46
46
  /** Callback when a job cancel request is received from peer. */
47
47
  onJobCancel: (msg: PeerJobCancel) => void;
48
48
  /** Callback when a log chunk is received from a worker peer. */
@@ -78,6 +78,17 @@ export interface PeerHandlerDeps {
78
78
  restartRequired?: string[];
79
79
  fieldsChanged?: string[];
80
80
  }>;
81
+ /**
82
+ * Callback when a peer.clusterSettings.request arrives from a DB-less worker.
83
+ * Resolves the worker-relevant settings snapshot (async DB read) and the
84
+ * current cluster_settings version; the result is sent back via
85
+ * peer.clusterSettings.response. If undefined, requests are answered with the
86
+ * config-default snapshot at version 0.
87
+ */
88
+ onPeerClusterSettingsRequest?: (msg: PeerClusterSettingsRequest) => Promise<{
89
+ version: number;
90
+ settings: WorkerClusterSettings;
91
+ }>;
81
92
  /**
82
93
  * Callback when a peer.logs.collect.request arrives from an incoming-dialed
83
94
  * peer. Builds this node's subtree bundle and streams it back through `send`
@@ -99,7 +110,7 @@ export declare function createPeerHandler(deps: PeerHandlerDeps): {
99
110
  sendConfigReloadAndWait: (targetInstanceId: string, msg: PeerConfigReload, timeoutMs?: number) => Promise<PeerConfigReloadResponse | null>;
100
111
  sendLogsCollectAndWait: (targetInstanceId: string, msg: PeerLogsCollectRequest, timeoutMs: number) => Promise<Buffer>;
101
112
  getConnectionCount: () => number;
102
- broadcastHeartbeat: (inventory: Omit<PeerHeartbeat, "type">) => void;
113
+ broadcastHeartbeat: (inventory: Omit<PeerHeartbeat, 'type'>) => void;
103
114
  broadcastAgentTokenRevoke: (msg: PeerAgentTokenRevoke) => void;
104
115
  cleanup: () => void;
105
116
  closeAllInbound: () => void;
@@ -46,6 +46,8 @@ export interface PeerInfo {
46
46
  configVersion: number;
47
47
  /** Registry version reported by this peer (0 = unknown/legacy). */
48
48
  registryVersion: number;
49
+ /** Cluster-settings version reported by this peer (0 = unknown/legacy). */
50
+ clusterSettingsVersion: number;
49
51
  /** Cluster role of the peer. */
50
52
  role: 'coordinator' | 'worker';
51
53
  hostname?: string;
@@ -65,6 +67,8 @@ export interface PeerRegistryOptions {
65
67
  onConfigVersionBehind?: (peerVersion: number) => void;
66
68
  /** Called when a peer's registryVersion is higher than the local version. */
67
69
  onRegistryVersionBehind?: (peerVersion: number) => void;
70
+ /** Called when a peer's clusterSettingsVersion is higher than the local version. */
71
+ onClusterSettingsVersionBehind?: (peerVersion: number) => void;
68
72
  /** Called when a peer transitions to disconnected state. */
69
73
  onPeerDisconnected?: (instanceId: string) => void;
70
74
  }
@@ -72,8 +76,10 @@ export declare class PeerRegistry {
72
76
  private readonly peers;
73
77
  private localConfigVersion;
74
78
  private localRegistryVersion;
79
+ private localClusterSettingsVersion;
75
80
  private readonly onConfigVersionBehind?;
76
81
  private readonly onRegistryVersionBehind?;
82
+ private readonly onClusterSettingsVersionBehind?;
77
83
  private readonly onPeerDisconnected?;
78
84
  constructor(options?: PeerRegistryOptions);
79
85
  /**
@@ -84,6 +90,12 @@ export declare class PeerRegistry {
84
90
  * Update the local registry version for comparison with peer heartbeats.
85
91
  */
86
92
  setLocalRegistryVersion(version: number): void;
93
+ /**
94
+ * Update the local cluster-settings version for comparison with peer
95
+ * heartbeats. A worker sets this after pulling a snapshot so it stops
96
+ * re-firing the version-behind hook on every subsequent heartbeat.
97
+ */
98
+ setLocalClusterSettingsVersion(version: number): void;
87
99
  /**
88
100
  * Add or update a peer entry. Sets initial connected state to true.
89
101
  * If the peer already exists and is connected, preserves capabilities
@@ -0,0 +1,11 @@
1
+ import { type VerifiedIssuerReader } from './verified-issuer.js';
2
+ export interface VerifiedIssuerPollerOptions {
3
+ reader: VerifiedIssuerReader;
4
+ /** The value already broadcast, so the first tick only fires on a real change. */
5
+ initial: string | null;
6
+ intervalMs: number;
7
+ onChange: (issuer: string | null) => void;
8
+ }
9
+ /** Start polling. Returns the stop function. */
10
+ export declare function startVerifiedIssuerPoller(opts: VerifiedIssuerPollerOptions): () => void;
11
+ //# sourceMappingURL=verified-issuer-poller.d.ts.map
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Resolves the Verified-tier issuer: the origin a browser fetches the
3
+ * orchestrator's dashboard-encryption key from directly, bypassing the hosted
4
+ * control plane, so TLS to the customer's own domain is the trust root.
5
+ *
6
+ * The tier is explicit opt-in and has NO environment-variable fallback. In
7
+ * particular `KICI_ORCHESTRATOR_PROVENANCE_ISSUER` (a build-attestation
8
+ * setting) must not enable it: configuring attestations is not consent to a
9
+ * different dashboard trust tier, and the Verified fetch is cross-origin, so
10
+ * switching a cluster into it unasked would hard-block every encrypted write
11
+ * whose browser cannot reach that origin.
12
+ *
13
+ * Every consumer resolves through this module — the capability broadcast via
14
+ * `tryResolveVerifiedIssuer`, the CLI via `resolveVerifiedIssuer` — so the two
15
+ * read the same setting and can never disagree about which tier is active.
16
+ * They differ only in what a failed read reports: unknown, or the opt-out
17
+ * default.
18
+ */
19
+ import type { OrchCapabilities } from '@kici-dev/engine';
20
+ import type { ClusterSettingsReader } from './cluster-settings-reader.js';
21
+ export type VerifiedIssuerReader = Pick<ClusterSettingsReader, 'getString' | 'tryGetString'>;
22
+ /**
23
+ * The opted-in verified issuer origin, or null when the tier is not enabled.
24
+ *
25
+ * Null is ambiguous here: an unreadable setting also lands on it, because the
26
+ * underlying `getString` swallows a DB error and takes the fallback. Anything
27
+ * that would ACT on the null — broadcasting a tier, choosing a key source —
28
+ * must use {@link tryResolveVerifiedIssuer} instead, or a transient DB failure
29
+ * silently downgrades the trust root. Only the CLI still reads through here,
30
+ * where the surrounding command already fails loudly on an unreachable DB.
31
+ */
32
+ export declare function resolveVerifiedIssuer(reader: VerifiedIssuerReader): Promise<string | null>;
33
+ /**
34
+ * The verified issuer, or `{ ok: false }` when the setting could not be read.
35
+ *
36
+ * The distinction matters only here: everywhere else a missing knob means "take
37
+ * the default", but this knob's default is the weaker Convenient tier, so
38
+ * answering "unset" for a failed read silently moves the trust root back to the
39
+ * hosted control plane. A caller that already knows the issuer holds it instead.
40
+ */
41
+ export type VerifiedIssuerRead = {
42
+ ok: true;
43
+ issuer: string | null;
44
+ } | {
45
+ ok: false;
46
+ };
47
+ /** Read the verified issuer, keeping a failed read distinct from an opt-out. */
48
+ export declare function tryResolveVerifiedIssuer(reader: VerifiedIssuerReader): Promise<VerifiedIssuerRead>;
49
+ /**
50
+ * The capability patch a `VerifiedIssuerRead` should broadcast.
51
+ *
52
+ * `broadcastCapabilities` MERGES its argument into the stored set, so an
53
+ * omitted key means "unchanged" and a present `null` means "the operator opted
54
+ * out". An unknown read must therefore produce an object with no key at all —
55
+ * not one whose value is `undefined`, which would still overwrite on spread.
56
+ *
57
+ * Extracted as a pure function because its only caller is a closure inside
58
+ * server.ts's connection handler, which has no test seam.
59
+ */
60
+ export declare function verifiedIssuerCapabilityUpdate(read: VerifiedIssuerRead): Partial<Pick<OrchCapabilities, 'dashboardVerifiedIssuer'>>;
61
+ /** The JWKS document URL for an issuer origin. */
62
+ export declare function jwksUrlFor(issuer: string): string;
63
+ //# sourceMappingURL=verified-issuer.d.ts.map
@@ -30,7 +30,7 @@ export interface AccessLogAdapterOptions {
30
30
  export declare class AccessLogAdapter implements TableAdapter<AccessLogColdStoreRow> {
31
31
  private readonly kdb;
32
32
  private readonly instanceId;
33
- readonly db: "orchestrator";
33
+ readonly db: 'orchestrator';
34
34
  readonly table = "access_log";
35
35
  readonly tenantColumn = "org_id";
36
36
  readonly partitionColumn = "created_at";
@@ -36,7 +36,7 @@ export interface EventLogAdapterOptions {
36
36
  export declare class EventLogAdapter implements TableAdapter<EventLogColdStoreRow> {
37
37
  private readonly kdb;
38
38
  private readonly instanceId;
39
- readonly db: "orchestrator";
39
+ readonly db: 'orchestrator';
40
40
  readonly table = "event_log";
41
41
  readonly tenantColumn = "routing_key";
42
42
  readonly partitionColumn = "received_at";
@@ -29,7 +29,7 @@ export interface ExecutionJobsAdapterOptions {
29
29
  export declare class ExecutionJobsAdapter implements TableAdapter<ExecutionJobRow> {
30
30
  private readonly kdb;
31
31
  private readonly instanceId;
32
- readonly db: "orchestrator";
32
+ readonly db: 'orchestrator';
33
33
  readonly table = "execution_jobs";
34
34
  readonly tenantColumn = "routing_key";
35
35
  readonly partitionColumn = "created_at";
@@ -24,7 +24,7 @@ export interface ExecutionRunsAdapterOptions {
24
24
  export declare class ExecutionRunsAdapter implements TableAdapter<ExecutionRunRow> {
25
25
  private readonly kdb;
26
26
  private readonly instanceId;
27
- readonly db: "orchestrator";
27
+ readonly db: 'orchestrator';
28
28
  readonly table = "execution_runs";
29
29
  readonly tenantColumn = "routing_key";
30
30
  readonly partitionColumn = "created_at";
@@ -31,7 +31,7 @@ export interface ExecutionStepsAdapterOptions {
31
31
  export declare class ExecutionStepsAdapter implements TableAdapter<ExecutionStepRow> {
32
32
  private readonly kdb;
33
33
  private readonly instanceId;
34
- readonly db: "orchestrator";
34
+ readonly db: 'orchestrator';
35
35
  readonly table = "execution_steps";
36
36
  readonly tenantColumn = "routing_key";
37
37
  readonly partitionColumn = "created_at";
@@ -23,7 +23,7 @@ export interface SecretAuditLogAdapterOptions {
23
23
  export declare class SecretAuditLogAdapter implements TableAdapter<SecretAuditLogRow> {
24
24
  private readonly kdb;
25
25
  private readonly instanceId;
26
- readonly db: "orchestrator";
26
+ readonly db: 'orchestrator';
27
27
  readonly table = "secret_audit_log";
28
28
  readonly tenantColumn = "routing_key";
29
29
  readonly partitionColumn = "timestamp";
@@ -14,7 +14,7 @@ import type { LocalConfig } from './types.js';
14
14
  * Shared config field paths that contain sensitive values.
15
15
  * Used by SharedConfigStore for encryption before DB storage.
16
16
  */
17
- export declare const SENSITIVE_FIELD_PATHS: readonly ["platform.token", "secrets.key", "secrets.bootstrapAdminToken", "cluster.joinToken"];
17
+ export declare const SENSITIVE_FIELD_PATHS: readonly ['platform.token', 'secrets.key', 'secrets.bootstrapAdminToken', 'cluster.joinToken'];
18
18
  /**
19
19
  * Load and validate the local orchestrator YAML configuration.
20
20
  *
@@ -9,6 +9,7 @@
9
9
  *
10
10
  * Precedence: env var > local YAML > shared DB > defaults
11
11
  */
12
+ import type { OrchestratorMode } from '@kici-dev/engine';
12
13
  import type { AppConfig, SharedConfig } from './types.js';
13
14
  /**
14
15
  * Phase 1 result: minimal config resolved from local sources only.
@@ -23,7 +24,7 @@ export interface LocalPhaseResult {
23
24
  /** Resolved server port */
24
25
  port: number;
25
26
  /** Resolved instance mode */
26
- mode: 'platform' | 'hybrid' | 'independent';
27
+ mode: OrchestratorMode;
27
28
  }
28
29
  /**
29
30
  * Phase 1: Resolve local-only config.