@kici-dev/orchestrator 0.16.0 → 0.18.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 (592) hide show
  1. package/dist/agent/agent-version.d.ts +12 -21
  2. package/dist/agent/dispatcher.d.ts +283 -437
  3. package/dist/agent/host-roster-reaper.d.ts +8 -10
  4. package/dist/agent/host-roster.d.ts +77 -100
  5. package/dist/agent/ownership-refusal.d.ts +3 -5
  6. package/dist/agent/ownership-tracker.d.ts +42 -76
  7. package/dist/agent/registry.d.ts +121 -233
  8. package/dist/agent/token-store.d.ts +34 -77
  9. package/dist/agent-packaging/availability.d.ts +6 -9
  10. package/dist/agent-packaging/download.d.ts +6 -9
  11. package/dist/agent-packaging/install-closure.d.ts +9 -12
  12. package/dist/agent-packaging/node-binary.d.ts +6 -10
  13. package/dist/agent-packaging/node-runtime-members.d.ts +3 -5
  14. package/dist/agent-packaging/refresh.d.ts +12 -16
  15. package/dist/agent-packaging/store.d.ts +5 -6
  16. package/dist/agent-packaging/upload.d.ts +3 -4
  17. package/dist/app.d.ts +0 -3
  18. package/dist/approvals/apply-decision.d.ts +39 -45
  19. package/dist/approvals/approval-resolver.d.ts +11 -23
  20. package/dist/approvals/held-run-release-wiring.d.ts +14 -21
  21. package/dist/approvals/independent-wiring.d.ts +13 -20
  22. package/dist/approvals/resume-router.d.ts +1 -1
  23. package/dist/approvals/step-approval-bridge.d.ts +11 -21
  24. package/dist/approvals/triggerer-subject.d.ts +8 -10
  25. package/dist/artifacts/artifact-store.d.ts +55 -95
  26. package/dist/artifacts/failure-messages.d.ts +15 -20
  27. package/dist/audit/access-log.d.ts +27 -45
  28. package/dist/audit/sampling-rate-limiter.d.ts +11 -23
  29. package/dist/cache/agent-job-failed-error.d.ts +2 -3
  30. package/dist/cache/build-coordinator.d.ts +5 -28
  31. package/dist/cache/cache-upload-settle.d.ts +11 -11
  32. package/dist/cache/dep-cache.d.ts +32 -60
  33. package/dist/cache/dispatch-cache-ref-tracker.d.ts +15 -23
  34. package/dist/cache/global-eval-round-cache.d.ts +33 -41
  35. package/dist/cache/pending-builds.d.ts +2 -6
  36. package/dist/cache/pending-dynamics.d.ts +2 -7
  37. package/dist/cache/pending-global-evals.d.ts +9 -12
  38. package/dist/cache/pending-inits.d.ts +11 -22
  39. package/dist/cache/pending-precursor-db-watcher.d.ts +24 -32
  40. package/dist/cache/pending-tracker.d.ts +17 -45
  41. package/dist/cache/precursor-result.d.ts +17 -30
  42. package/dist/cache/source-cache.d.ts +36 -65
  43. package/dist/cache/user-cache.d.ts +21 -25
  44. package/dist/cancel/cancel-held-run.d.ts +13 -16
  45. package/dist/cancel/cancel-route-answer.d.ts +1 -2
  46. package/dist/cancel/cancel-run.d.ts +26 -50
  47. package/dist/cancel/dashboard-cancel-handler.d.ts +2 -2
  48. package/dist/cancel/peer-job-cancel.d.ts +11 -14
  49. package/dist/cancel/sweep-stuck-cancelling.d.ts +9 -13
  50. package/dist/cli/api-client.d.ts +33 -76
  51. package/dist/cli/commands/access-log.d.ts +4 -24
  52. package/dist/cli/commands/agent-package.d.ts +7 -15
  53. package/dist/cli/commands/agent-service/agent-env.d.ts +3 -6
  54. package/dist/cli/commands/agent-service/index.d.ts +4 -10
  55. package/dist/cli/commands/agent-service/install.d.ts +4 -11
  56. package/dist/cli/commands/agent-service/status.d.ts +4 -9
  57. package/dist/cli/commands/agent-service/upgrade.d.ts +4 -16
  58. package/dist/cli/commands/agent.d.ts +12 -25
  59. package/dist/cli/commands/api-key.d.ts +7 -7
  60. package/dist/cli/commands/attestations-list.d.ts +7 -17
  61. package/dist/cli/commands/attestations-retry.d.ts +5 -11
  62. package/dist/cli/commands/attestations-reverify.d.ts +4 -5
  63. package/dist/cli/commands/attestations.d.ts +3 -8
  64. package/dist/cli/commands/audit.d.ts +1 -5
  65. package/dist/cli/commands/backend.d.ts +2 -11
  66. package/dist/cli/commands/check-run.d.ts +7 -18
  67. package/dist/cli/commands/cluster-name.d.ts +5 -12
  68. package/dist/cli/commands/cluster-settings.d.ts +28 -53
  69. package/dist/cli/commands/cold-store.d.ts +7 -15
  70. package/dist/cli/commands/config.d.ts +9 -20
  71. package/dist/cli/commands/context.d.ts +8 -20
  72. package/dist/cli/commands/dashboard-encryption-key.d.ts +9 -14
  73. package/dist/cli/commands/db-backup.d.ts +17 -32
  74. package/dist/cli/commands/db.d.ts +3 -4
  75. package/dist/cli/commands/debug-bundle.d.ts +3 -10
  76. package/dist/cli/commands/diagnose.d.ts +3 -14
  77. package/dist/cli/commands/event-dlq.d.ts +4 -12
  78. package/dist/cli/commands/event-log.d.ts +2 -20
  79. package/dist/cli/commands/execution.d.ts +3 -9
  80. package/dist/cli/commands/firecracker/index.d.ts +3 -6
  81. package/dist/cli/commands/held-run.d.ts +23 -37
  82. package/dist/cli/commands/host.d.ts +4 -11
  83. package/dist/cli/commands/inspect-bundle.d.ts +3 -11
  84. package/dist/cli/commands/local-hook.d.ts +2 -10
  85. package/dist/cli/commands/local-trigger.d.ts +2 -2
  86. package/dist/cli/commands/orchestrator-service/drain.d.ts +3 -6
  87. package/dist/cli/commands/orchestrator-service/index.d.ts +6 -14
  88. package/dist/cli/commands/orchestrator-service/install-env.d.ts +25 -49
  89. package/dist/cli/commands/orchestrator-service/install.d.ts +2 -5
  90. package/dist/cli/commands/orchestrator-service/status.d.ts +10 -22
  91. package/dist/cli/commands/orchestrator-service/upgrade.d.ts +6 -15
  92. package/dist/cli/commands/org-settings.d.ts +5 -11
  93. package/dist/cli/commands/peer.d.ts +5 -10
  94. package/dist/cli/commands/queue.d.ts +3 -9
  95. package/dist/cli/commands/registration.d.ts +4 -8
  96. package/dist/cli/commands/remote-source.d.ts +6 -12
  97. package/dist/cli/commands/rotate.d.ts +1 -5
  98. package/dist/cli/commands/runs.d.ts +1 -30
  99. package/dist/cli/commands/scaler.d.ts +5 -12
  100. package/dist/cli/commands/secret.d.ts +1 -9
  101. package/dist/cli/commands/service-health.d.ts +5 -10
  102. package/dist/cli/commands/shared/admin-cli-access-log.d.ts +10 -19
  103. package/dist/cli/commands/shared/bare-metal-binary-check.d.ts +86 -0
  104. package/dist/cli/commands/shared/cli-action.d.ts +1 -4
  105. package/dist/cli/commands/shared/confirm.d.ts +5 -10
  106. package/dist/cli/commands/shared/db.d.ts +1 -12
  107. package/dist/cli/commands/shared/env-file-mode.d.ts +6 -9
  108. package/dist/cli/commands/shared/secret-input.d.ts +7 -21
  109. package/dist/cli/commands/shared/service-verbs.d.ts +6 -12
  110. package/dist/cli/commands/shared/unbound-context-warning.d.ts +2 -4
  111. package/dist/cli/commands/shared/upgrade-hooks.d.ts +7 -16
  112. package/dist/cli/commands/shared/upgrade-safety.d.ts +20 -31
  113. package/dist/cli/commands/shared/versioned-upgrade.d.ts +83 -161
  114. package/dist/cli/commands/signing-key.d.ts +4 -9
  115. package/dist/cli/commands/source-manifest.d.ts +11 -14
  116. package/dist/cli/commands/source.d.ts +7 -32
  117. package/dist/cli/commands/token.d.ts +4 -15
  118. package/dist/cli/commands/trust-policy.d.ts +35 -88
  119. package/dist/cli/commands/variable.d.ts +3 -5
  120. package/dist/cli/commands/workflow.d.ts +3 -24
  121. package/dist/cli/join.d.ts +3 -6
  122. package/dist/cli/kici-admin.d.ts +11 -29
  123. package/dist/cli/lazy-deps/cache.d.ts +1 -14
  124. package/dist/cli/lazy-deps/downloader.d.ts +4 -27
  125. package/dist/cli/lazy-deps/registry.d.ts +5 -25
  126. package/dist/cli/local-github-ingress-url.d.ts +5 -7
  127. package/dist/cli/loopback-callback.d.ts +6 -7
  128. package/dist/cli/open-browser.d.ts +4 -8
  129. package/dist/cli/root-option-routing.d.ts +17 -29
  130. package/dist/cli/service/backup-timer.d.ts +16 -39
  131. package/dist/cli/service/compose-path.d.ts +3 -7
  132. package/dist/cli/service/compose.d.ts +12 -30
  133. package/dist/cli/service/deploy-env.d.ts +6 -18
  134. package/dist/cli/service/entrypoint.d.ts +14 -25
  135. package/dist/cli/service/env-assignment.d.ts +6 -17
  136. package/dist/cli/service/image-digests.d.ts +6 -15
  137. package/dist/cli/service/index.d.ts +2 -18
  138. package/dist/cli/service/instance/index-file.d.ts +9 -16
  139. package/dist/cli/service/instance/manifest.d.ts +33 -59
  140. package/dist/cli/service/instance/resolve.d.ts +32 -68
  141. package/dist/cli/service/instance/types.d.ts +12 -29
  142. package/dist/cli/service/launchd.d.ts +29 -60
  143. package/dist/cli/service/platform-detect.d.ts +13 -68
  144. package/dist/cli/service/privilege.d.ts +12 -25
  145. package/dist/cli/service/shutdown-grace.d.ts +11 -20
  146. package/dist/cli/service/systemd.d.ts +7 -20
  147. package/dist/cli/service/types.d.ts +63 -114
  148. package/dist/cli/service/windows-acl.d.ts +14 -21
  149. package/dist/cli/service/windows-env-file.d.ts +10 -28
  150. package/dist/cli/service/windows.d.ts +15 -31
  151. package/dist/cli/webhook-url-notes.d.ts +4 -6
  152. package/dist/cli/wizard/agent-wizard.d.ts +3 -14
  153. package/dist/cli/wizard/orchestrator-wizard.d.ts +12 -37
  154. package/dist/cli/wizard/prompts.d.ts +6 -16
  155. package/dist/cli.js +4553 -6556
  156. package/dist/cluster/cluster-identity.d.ts +20 -32
  157. package/dist/cluster/cluster-settings-reader.d.ts +50 -77
  158. package/dist/cluster/coordinator-credential.d.ts +4 -5
  159. package/dist/cluster/coordinator.d.ts +76 -148
  160. package/dist/cluster/health-api.d.ts +2 -10
  161. package/dist/cluster/index.d.ts +1 -6
  162. package/dist/cluster/instance-heartbeat.d.ts +26 -42
  163. package/dist/cluster/join-client.d.ts +4 -7
  164. package/dist/cluster/join-handler.d.ts +3 -7
  165. package/dist/cluster/join-token.d.ts +13 -27
  166. package/dist/cluster/leader-gated-scheduler.d.ts +8 -17
  167. package/dist/cluster/orphan-recovery.d.ts +13 -35
  168. package/dist/cluster/peer-auth-coordinator.d.ts +2 -8
  169. package/dist/cluster/peer-client.d.ts +46 -76
  170. package/dist/cluster/peer-credentials.d.ts +24 -70
  171. package/dist/cluster/peer-crypto.d.ts +5 -26
  172. package/dist/cluster/peer-forget.d.ts +3 -3
  173. package/dist/cluster/peer-handler.d.ts +47 -71
  174. package/dist/cluster/peer-registry.d.ts +37 -106
  175. package/dist/cluster/plan-headroom-store.d.ts +4 -6
  176. package/dist/cluster/raft-state.d.ts +4 -13
  177. package/dist/cluster/raft.d.ts +18 -53
  178. package/dist/cluster/reconcile-identity.d.ts +8 -11
  179. package/dist/cluster/rerouted-job-guard.d.ts +7 -11
  180. package/dist/cluster/verified-issuer.d.ts +2 -3
  181. package/dist/cluster/worker-cluster-settings.d.ts +7 -10
  182. package/dist/cluster/worker-eviction.d.ts +16 -26
  183. package/dist/cold-store/load-access-log-range.d.ts +15 -31
  184. package/dist/cold-store/load-event-log-range.d.ts +13 -27
  185. package/dist/cold-store/load-secret-audit-log-range.d.ts +8 -12
  186. package/dist/cold-store/orchestrator-cold-store.d.ts +8 -28
  187. package/dist/cold-store/tables/access-log.d.ts +12 -14
  188. package/dist/cold-store/tables/event-log.d.ts +4 -8
  189. package/dist/cold-store/tables/execution-runs.d.ts +6 -11
  190. package/dist/cold-store/tables/secret-audit-log.d.ts +5 -12
  191. package/dist/concurrency/dispatch-next-queued.d.ts +13 -25
  192. package/dist/concurrency/queue-manager.d.ts +22 -54
  193. package/dist/concurrency/waiters.d.ts +15 -31
  194. package/dist/config/encryption.d.ts +0 -2
  195. package/dist/config/loader.d.ts +0 -1
  196. package/dist/config/reload.d.ts +0 -6
  197. package/dist/config/resolver.d.ts +0 -4
  198. package/dist/config/shared-store.d.ts +0 -2
  199. package/dist/config/types.d.ts +0 -3
  200. package/dist/content-requirements-cache.d.ts +0 -1
  201. package/dist/contexts/context-store.d.ts +0 -2
  202. package/dist/contexts/held-runs.d.ts +0 -2
  203. package/dist/contexts/variable-store.d.ts +0 -2
  204. package/dist/dashboard/attestation-filters.d.ts +13 -18
  205. package/dist/dashboard/handler.d.ts +143 -307
  206. package/dist/db/client.d.ts +2 -6
  207. package/dist/db/deferred-index-build.d.ts +8 -10
  208. package/dist/db/deferred-indexes.d.ts +15 -22
  209. package/dist/db/migration-provider.d.ts +2 -4
  210. package/dist/db/migration-test-harness.d.ts +26 -44
  211. package/dist/db/migrations/001_initial.d.ts +1 -4
  212. package/dist/db/migrations/002_config_versions_key_version.d.ts +5 -8
  213. package/dist/db/migrations/003_access_log.d.ts +10 -15
  214. package/dist/db/migrations/004_rename_bundle_to_source.d.ts +7 -9
  215. package/dist/db/migrations/005_cold_store_chunk_counter.d.ts +4 -10
  216. package/dist/db/migrations/006_runs_jobs_steps_archived_at.d.ts +9 -29
  217. package/dist/db/migrations/007_audit_logs_archived_at.d.ts +11 -30
  218. package/dist/db/migrations/008_event_log_archived_at.d.ts +14 -29
  219. package/dist/db/migrations/009_access_log_trigram.d.ts +4 -8
  220. package/dist/db/migrations/010_cold_store_chunks.d.ts +16 -26
  221. package/dist/db/migrations/011_drop_source_secrets_notify.d.ts +6 -14
  222. package/dist/db/migrations/012_peer_credentials_active_uniq.d.ts +9 -14
  223. package/dist/db/migrations/013_execution_log_bytes.d.ts +5 -13
  224. package/dist/db/migrations/014_kici_events_lease_retry.d.ts +14 -27
  225. package/dist/db/migrations/015_org_settings_customer_scoped.d.ts +12 -17
  226. package/dist/db/migrations/016_org_settings_allow_http_npm.d.ts +4 -6
  227. package/dist/db/migrations/019_generic_sources_change_notify.d.ts +13 -17
  228. package/dist/db/migrations/020_org_settings_dashboard_write_policy.d.ts +5 -8
  229. package/dist/db/migrations/021_check_run_tracking.d.ts +5 -17
  230. package/dist/db/migrations/022_scaler_manager_state.d.ts +10 -20
  231. package/dist/db/migrations/023_dispatch_queue_recovery_deadline.d.ts +7 -18
  232. package/dist/db/migrations/024_dispatch_queue_provisioning_error.d.ts +5 -11
  233. package/dist/db/migrations/025_init_failure.d.ts +5 -9
  234. package/dist/db/migrations/027_workflow_timeout.d.ts +5 -13
  235. package/dist/db/migrations/029_dispatch_queue_attempts.d.ts +4 -10
  236. package/dist/db/migrations/030_held_runs_env_set_null.d.ts +5 -6
  237. package/dist/db/migrations/031_dispatch_queue_ack_deadline.d.ts +6 -12
  238. package/dist/db/migrations/033_org_settings_approval.d.ts +7 -10
  239. package/dist/db/migrations/034_held_runs_generalize.d.ts +10 -18
  240. package/dist/db/migrations/035_pending_workflow_contexts.d.ts +4 -5
  241. package/dist/db/migrations/037_generic_sources_provider_type_local.d.ts +5 -6
  242. package/dist/db/migrations/038_remote_sources.d.ts +5 -7
  243. package/dist/db/migrations/045_host_properties.d.ts +5 -9
  244. package/dist/db/migrations/046_join_token_consumed_by_instance.d.ts +5 -10
  245. package/dist/db/migrations/048_host_reboot_pending.d.ts +6 -12
  246. package/dist/db/migrations/049_held_runs_payload.d.ts +3 -8
  247. package/dist/db/migrations/050_sources_slug.d.ts +4 -5
  248. package/dist/db/migrations/051_binding_host_pattern.d.ts +7 -10
  249. package/dist/db/migrations/052_host_reach_metadata.d.ts +8 -11
  250. package/dist/db/migrations/053_agent_token_single_use.d.ts +6 -10
  251. package/dist/db/migrations/054_local_working_tree.d.ts +4 -6
  252. package/dist/db/migrations/055_agent_token_mandatory_labels.d.ts +6 -11
  253. package/dist/db/migrations/056_execution_jobs_environments.d.ts +4 -11
  254. package/dist/db/migrations/064_execution_jobs_skipped_environments.d.ts +6 -9
  255. package/dist/db/migrations/065_pending_attestations.d.ts +9 -12
  256. package/dist/db/migrations/066_pending_attestations_rejected.d.ts +4 -7
  257. package/dist/db/migrations/068_request_idempotency.d.ts +7 -9
  258. package/dist/db/migrations/069_reroute_tunables.d.ts +6 -14
  259. package/dist/db/migrations/071_batch_accumulation.d.ts +8 -16
  260. package/dist/db/migrations/072_dispatch_queue_run_id_index.d.ts +3 -9
  261. package/dist/db/migrations/074_normalize_zero_concurrency_limit.d.ts +4 -7
  262. package/dist/db/migrations/076_artifacts.d.ts +7 -8
  263. package/dist/db/migrations/078_org_settings_backup_staleness.d.ts +3 -6
  264. package/dist/db/migrations/079_org_settings_scaler_spawn_timeout.d.ts +4 -8
  265. package/dist/db/migrations/080_cluster_settings.d.ts +6 -10
  266. package/dist/db/migrations/081_org_settings_queue_timeout.d.ts +7 -11
  267. package/dist/db/migrations/082_host_s3_reachable.d.ts +5 -10
  268. package/dist/db/migrations/083_org_settings_artifact_caps.d.ts +6 -8
  269. package/dist/db/migrations/084_orchestrator_signing_keys.d.ts +8 -13
  270. package/dist/db/migrations/085_cluster_settings_reroute_flap_grace_ms.d.ts +4 -5
  271. package/dist/db/migrations/086_cluster_settings_max_fanout_hosts.d.ts +3 -3
  272. package/dist/db/migrations/087_cluster_settings_event_router_rate_limit.d.ts +5 -3
  273. package/dist/db/migrations/088_cluster_settings_cache_max_tarball_bytes.d.ts +3 -3
  274. package/dist/db/migrations/089_cluster_settings_cache_ttl_days.d.ts +3 -5
  275. package/dist/db/migrations/090_cluster_settings_concurrency_wait_timeout_ms.d.ts +3 -6
  276. package/dist/db/migrations/091_cluster_settings_agent_token_ttl_ms.d.ts +3 -6
  277. package/dist/db/migrations/092_cluster_settings_version.d.ts +5 -9
  278. package/dist/db/migrations/094_dashboard_encryption_keys.d.ts +9 -14
  279. package/dist/db/migrations/095_dashboard_write_policy_tristate.d.ts +2 -6
  280. package/dist/db/migrations/099_cluster_settings_dashboard_verified_issuer.d.ts +8 -11
  281. package/dist/db/migrations/101_contexts_hold_expiry_drop_default.d.ts +9 -15
  282. package/dist/db/migrations/102_dispatch_queue_agent_id.d.ts +6 -11
  283. package/dist/db/migrations/103_cluster_settings_ownership_db_check_timeout_ms.d.ts +6 -12
  284. package/dist/db/migrations/104_check_run_terminal_sent.d.ts +8 -14
  285. package/dist/db/migrations/105_org_trust_policy.d.ts +5 -7
  286. package/dist/db/migrations/106_cluster_settings_check_run_tracking_ttl_days.d.ts +4 -12
  287. package/dist/db/migrations/107_check_run_tracking_updated_at_index.d.ts +8 -14
  288. package/dist/db/migrations/113_execution_runs_workflow_repo_index.d.ts +10 -19
  289. package/dist/db/migrations/115_global_workflows_cluster_switch.d.ts +2 -3
  290. package/dist/db/migrations/121_org_settings_allow_untrusted_dockerfile_builds.d.ts +7 -8
  291. package/dist/db/migrations/122_host_roster_scaler_managed.d.ts +9 -16
  292. package/dist/db/migrations/123_workflow_registrations_default_branch.d.ts +8 -16
  293. package/dist/db/migrations/125_org_trust_directory.d.ts +13 -21
  294. package/dist/db/migrations/126_held_runs_posted_pending_check.d.ts +10 -16
  295. package/dist/db/migrations/127_org_trust_policy_approval_expiry_seconds.d.ts +8 -16
  296. package/dist/db/migrations/128_execution_runs_global_eval_round.d.ts +6 -11
  297. package/dist/db/migrations/129_execution_runs_dispatch_routing_key.d.ts +8 -11
  298. package/dist/db/migrations/130_scaler_provision_outcomes.d.ts +13 -20
  299. package/dist/db/migrations/131_execution_jobs_git_credentials.d.ts +12 -22
  300. package/dist/db/migrations/132_execution_runs_trigger_event.d.ts +6 -16
  301. package/dist/db/migrations/133_dispatch_queue_source_tar_digest.d.ts +6 -9
  302. package/dist/db/migrations/140_dispatch_queue_canonical_labels.d.ts +22 -40
  303. package/dist/db/migrations/143_execution_jobs_precursor_result.d.ts +9 -18
  304. package/dist/db/migrations/144_execution_runs_registration_window.d.ts +12 -20
  305. package/dist/db/migrations/147_sealed_job_secrets.d.ts +5 -9
  306. package/dist/db/migrations/148_cluster_settings_sealed_secrets_retry_backoff_ms.d.ts +7 -13
  307. package/dist/db/migrations/150_execution_runs_status_epoch.d.ts +6 -11
  308. package/dist/db/migrations/152_org_settings_cache_upload_settle_timeout.d.ts +5 -8
  309. package/dist/db/migrations/157_host_roster_identity_source.d.ts +9 -13
  310. package/dist/db/migrations/159_org_id_widen_to_source_width.d.ts +5 -0
  311. package/dist/db/migrator.d.ts +17 -25
  312. package/dist/db/notify-listener.d.ts +8 -11
  313. package/dist/db/repos/dashboard-encryption-keys-repo.d.ts +9 -10
  314. package/dist/db/synthetic-job-ids.d.ts +6 -8
  315. package/dist/db/types.d.ts +531 -1058
  316. package/dist/deployment/deployment-identity.d.ts +42 -60
  317. package/dist/diagnostics/bundle-reader.d.ts +3 -15
  318. package/dist/diagnostics/bundle-writer.d.ts +5 -12
  319. package/dist/diagnostics/checks/agents.d.ts +1 -7
  320. package/dist/diagnostics/checks/backup.d.ts +7 -10
  321. package/dist/diagnostics/checks/certs.d.ts +1 -6
  322. package/dist/diagnostics/checks/config.d.ts +2 -5
  323. package/dist/diagnostics/checks/db.d.ts +1 -1
  324. package/dist/diagnostics/checks/disk.d.ts +1 -6
  325. package/dist/diagnostics/checks/firecracker-network.d.ts +3 -3
  326. package/dist/diagnostics/checks/index.d.ts +0 -6
  327. package/dist/diagnostics/checks/retention.d.ts +3 -6
  328. package/dist/diagnostics/checks/scaler.d.ts +3 -7
  329. package/dist/diagnostics/checks/ws.d.ts +1 -6
  330. package/dist/diagnostics/fleet-collector.d.ts +11 -14
  331. package/dist/diagnostics/fleet-constants.d.ts +1 -3
  332. package/dist/diagnostics/fleet-selection.d.ts +3 -7
  333. package/dist/diagnostics/fleet-topology.d.ts +2 -6
  334. package/dist/diagnostics/fleet-wiring.d.ts +6 -12
  335. package/dist/diagnostics/index.d.ts +0 -5
  336. package/dist/diagnostics/runner.d.ts +4 -8
  337. package/dist/diagnostics/types.d.ts +10 -21
  338. package/dist/drain/drain-controller.d.ts +16 -22
  339. package/dist/entry-helpers.d.ts +0 -2
  340. package/dist/events/circuit-breaker.d.ts +0 -3
  341. package/dist/events/event-router.d.ts +1 -2
  342. package/dist/events/event-store.d.ts +0 -9
  343. package/dist/events/trust-store.d.ts +0 -3
  344. package/dist/events/types.d.ts +0 -9
  345. package/dist/firecracker/host-network.d.ts +24 -30
  346. package/dist/firecracker/net-interfaces.d.ts +4 -7
  347. package/dist/helpers/rate-limiter.d.ts +0 -1
  348. package/dist/index.js +251 -486
  349. package/dist/metrics/agent-metrics-aggregator.d.ts +24 -67
  350. package/dist/metrics/metrics-reporter.d.ts +4 -13
  351. package/dist/metrics/prometheus.d.ts +47 -81
  352. package/dist/orchestrator-core.d.ts +3 -7
  353. package/dist/pipeline/content-filter.d.ts +20 -30
  354. package/dist/pipeline/cross-source-tally.d.ts +7 -8
  355. package/dist/pipeline/decorating-secret-resolver.d.ts +4 -8
  356. package/dist/pipeline/degraded-reason.d.ts +3 -4
  357. package/dist/pipeline/direct-ingress-deps.d.ts +15 -24
  358. package/dist/pipeline/dispatch-matched-workflow.d.ts +289 -525
  359. package/dist/pipeline/flatten-lock-steps.d.ts +4 -6
  360. package/dist/pipeline/global-dispatch-identity.d.ts +5 -10
  361. package/dist/pipeline/global-eval-round.d.ts +65 -151
  362. package/dist/pipeline/global-round-hold.d.ts +5 -7
  363. package/dist/pipeline/held-context-data.d.ts +5 -8
  364. package/dist/pipeline/held-round-registrations.d.ts +8 -11
  365. package/dist/pipeline/install-gate.d.ts +15 -25
  366. package/dist/pipeline/install-secrets-resolver.d.ts +24 -34
  367. package/dist/pipeline/internal-event-pipeline.d.ts +45 -62
  368. package/dist/pipeline/invoke-gate.d.ts +27 -40
  369. package/dist/pipeline/job-contexts.d.ts +19 -36
  370. package/dist/pipeline/manual-schedule.d.ts +7 -13
  371. package/dist/pipeline/needs-scheduler.d.ts +29 -46
  372. package/dist/pipeline/pending-workflow-context.d.ts +14 -28
  373. package/dist/pipeline/process-webhook.d.ts +88 -123
  374. package/dist/pipeline/processor.d.ts +209 -355
  375. package/dist/pipeline/remote-source-store.d.ts +5 -8
  376. package/dist/pipeline/request-idempotency.d.ts +10 -13
  377. package/dist/pipeline/rerun-global.d.ts +6 -7
  378. package/dist/pipeline/rerun-inputs.d.ts +23 -37
  379. package/dist/pipeline/rerun.d.ts +34 -57
  380. package/dist/pipeline/resolve-sandbox-grant.d.ts +5 -10
  381. package/dist/pipeline/resume-workflow.d.ts +28 -34
  382. package/dist/pipeline/route-or-dispatch-jobs.d.ts +19 -30
  383. package/dist/pipeline/run-event-context.d.ts +16 -21
  384. package/dist/pipeline/sandbox-allowlist-reader.d.ts +7 -11
  385. package/dist/pipeline/security-hold-check.d.ts +56 -80
  386. package/dist/pipeline/test-pipeline.d.ts +21 -46
  387. package/dist/pipeline/unbound-job-context.d.ts +6 -9
  388. package/dist/pipeline/undispatched-hold-checks.d.ts +4 -6
  389. package/dist/pipeline/wave-scheduler.d.ts +15 -22
  390. package/dist/pipeline/webhook-payload-store.d.ts +3 -10
  391. package/dist/pipeline/workflow-lock-at-sha.d.ts +14 -20
  392. package/dist/policy/dashboard-write-policy.d.ts +1 -1
  393. package/dist/provider-registry.d.ts +0 -19
  394. package/dist/providers/generic/index.d.ts +0 -2
  395. package/dist/providers/generic/normalizer.d.ts +0 -1
  396. package/dist/providers/generic/verification.d.ts +0 -8
  397. package/dist/providers/github/auth.d.ts +0 -1
  398. package/dist/providers/github/changed-files.d.ts +2 -1
  399. package/dist/providers/github/file-contents.d.ts +0 -4
  400. package/dist/providers/github/lock-file.d.ts +0 -4
  401. package/dist/providers/github/normalizer.d.ts +1 -9
  402. package/dist/providers/local/index.d.ts +1 -2
  403. package/dist/providers/local/lock-file-fetcher.d.ts +0 -4
  404. package/dist/providers/local/normalizer.d.ts +0 -10
  405. package/dist/providers/local/repo-url-builder.d.ts +0 -2
  406. package/dist/providers/universal-git/clone-token.d.ts +0 -2
  407. package/dist/providers/universal-git/lock-file.d.ts +0 -2
  408. package/dist/providers/universal-git/normalizer.d.ts +0 -2
  409. package/dist/queue/bootstrap.d.ts +3 -15
  410. package/dist/queue/cleanup.d.ts +29 -50
  411. package/dist/queue/depth-refresher.d.ts +21 -39
  412. package/dist/queue/job-queue.d.ts +112 -163
  413. package/dist/queue/retention.d.ts +23 -36
  414. package/dist/queue/scheduled-job.d.ts +17 -39
  415. package/dist/queue/terminalize-unroutable.d.ts +21 -18
  416. package/dist/queue/unroutable-probe.d.ts +15 -22
  417. package/dist/registration/extractor.d.ts +0 -6
  418. package/dist/registration/registration-index.d.ts +0 -6
  419. package/dist/registration/registration-store.d.ts +0 -9
  420. package/dist/reporting/agent-failure-category.d.ts +3 -5
  421. package/dist/reporting/check-run-reporter.d.ts +142 -316
  422. package/dist/reporting/check-run-summary.d.ts +16 -35
  423. package/dist/reporting/check-run-tracking-store.d.ts +54 -107
  424. package/dist/reporting/execution-tracker.d.ts +356 -526
  425. package/dist/reporting/fs-log-storage.d.ts +31 -33
  426. package/dist/reporting/job-check-run-completion.d.ts +14 -22
  427. package/dist/reporting/log-chunk-sink.d.ts +11 -16
  428. package/dist/reporting/log-pull-handler.d.ts +4 -13
  429. package/dist/reporting/log-retention.d.ts +3 -4
  430. package/dist/reporting/log-storage.d.ts +24 -52
  431. package/dist/reporting/log-writer.d.ts +28 -56
  432. package/dist/reporting/peer-log-normalize.d.ts +4 -8
  433. package/dist/reporting/run-aggregator.d.ts +6 -11
  434. package/dist/reporting/run-summary-fields.d.ts +5 -8
  435. package/dist/reporting/s3-log-storage.d.ts +31 -50
  436. package/dist/reporting/step-display-order.d.ts +11 -21
  437. package/dist/reporting/step-log-buffer.d.ts +7 -28
  438. package/dist/reporting/step-log-reader.d.ts +11 -19
  439. package/dist/routes/admin-access-log.d.ts +4 -6
  440. package/dist/routes/admin-auth.d.ts +19 -38
  441. package/dist/routes/admin-backends.d.ts +3 -14
  442. package/dist/routes/admin-cluster-name.d.ts +13 -21
  443. package/dist/routes/admin-cluster-settings.d.ts +6 -9
  444. package/dist/routes/admin-config.d.ts +7 -19
  445. package/dist/routes/admin-contexts.d.ts +6 -13
  446. package/dist/routes/admin-db.d.ts +5 -10
  447. package/dist/routes/admin-event-dlq.d.ts +3 -5
  448. package/dist/routes/admin-event-inspect.d.ts +3 -4
  449. package/dist/routes/admin-event-log.d.ts +3 -7
  450. package/dist/routes/admin-events.d.ts +16 -30
  451. package/dist/routes/admin-held-runs.d.ts +52 -76
  452. package/dist/routes/admin-maintenance.d.ts +3 -6
  453. package/dist/routes/admin-orchestrator-drain.d.ts +0 -2
  454. package/dist/routes/admin-org-settings.d.ts +8 -14
  455. package/dist/routes/admin-peer-forget.d.ts +0 -1
  456. package/dist/routes/admin-queue-execution.d.ts +3 -3
  457. package/dist/routes/admin-registrations.d.ts +3 -12
  458. package/dist/routes/admin-runs.d.ts +16 -29
  459. package/dist/routes/admin-scaler-orphans.d.ts +4 -4
  460. package/dist/routes/admin-scaler-reload.d.ts +5 -8
  461. package/dist/routes/admin-scheduled-jobs.d.ts +3 -4
  462. package/dist/routes/admin-sources.d.ts +20 -29
  463. package/dist/routes/admin-trust-policy.d.ts +31 -48
  464. package/dist/routes/admin.d.ts +67 -94
  465. package/dist/routes/caller-identity.d.ts +45 -0
  466. package/dist/routes/capabilities.d.ts +8 -13
  467. package/dist/routes/diagnostics.d.ts +2 -10
  468. package/dist/routes/fleet.d.ts +1 -2
  469. package/dist/routes/github-webhook.d.ts +2 -5
  470. package/dist/routes/health.d.ts +6 -19
  471. package/dist/routes/provenance-oidc.d.ts +3 -3
  472. package/dist/routes/test-direct.d.ts +46 -0
  473. package/dist/routes/uploads.d.ts +14 -19
  474. package/dist/routes/webhooks.d.ts +2 -24
  475. package/dist/scaler/agent-binary-location.d.ts +77 -0
  476. package/dist/scaler/agent-fit.d.ts +2 -2
  477. package/dist/scaler/backend-factory.d.ts +10 -18
  478. package/dist/scaler/bare-metal-backend.d.ts +28 -45
  479. package/dist/scaler/claim-store.d.ts +20 -43
  480. package/dist/scaler/config.d.ts +10 -37
  481. package/dist/scaler/container-backend.d.ts +22 -35
  482. package/dist/scaler/container-hostconfig.d.ts +10 -16
  483. package/dist/scaler/container-routing.d.ts +10 -13
  484. package/dist/scaler/disk-guard.d.ts +2 -3
  485. package/dist/scaler/event-backend.d.ts +33 -58
  486. package/dist/scaler/event-provision-reaper.d.ts +61 -84
  487. package/dist/scaler/failure-tracker.d.ts +6 -13
  488. package/dist/scaler/file-tail.d.ts +6 -19
  489. package/dist/scaler/firecracker-api.d.ts +19 -63
  490. package/dist/scaler/firecracker-backend.d.ts +142 -258
  491. package/dist/scaler/host-access.d.ts +7 -10
  492. package/dist/scaler/index.d.ts +3 -6
  493. package/dist/scaler/ip-allocator.d.ts +30 -82
  494. package/dist/scaler/label-matcher.d.ts +14 -35
  495. package/dist/scaler/log-forwarder.d.ts +6 -25
  496. package/dist/scaler/machine-ledger.d.ts +39 -86
  497. package/dist/scaler/manager.d.ts +517 -787
  498. package/dist/scaler/pending-scale-sweeper.d.ts +8 -11
  499. package/dist/scaler/reap-orphans.d.ts +8 -12
  500. package/dist/scaler/resolve-container-auth.d.ts +12 -21
  501. package/dist/scaler/scaler-events.d.ts +2 -5
  502. package/dist/scaler/scaler-state-store.d.ts +127 -189
  503. package/dist/scaler/spawn-errors.d.ts +1 -4
  504. package/dist/scaler/startup-orphan-sweep.d.ts +3 -4
  505. package/dist/scaler/startup-tools-check.d.ts +21 -0
  506. package/dist/scaler/types.d.ts +142 -255
  507. package/dist/scaler/vm-job-bindings.d.ts +5 -9
  508. package/dist/scaler/warm-pool.d.ts +46 -93
  509. package/dist/secrets/audit-logger.d.ts +0 -3
  510. package/dist/secrets/backend-health.d.ts +0 -9
  511. package/dist/secrets/backend-registry.d.ts +0 -9
  512. package/dist/secrets/cleanup.d.ts +0 -1
  513. package/dist/secrets/config.d.ts +0 -3
  514. package/dist/secrets/ephemeral-keys.d.ts +0 -3
  515. package/dist/secrets/pg-secret-store.d.ts +0 -3
  516. package/dist/secrets/rbac.d.ts +5 -7
  517. package/dist/secrets/routing-key-scope.d.ts +1 -0
  518. package/dist/secrets/secret-output-store.d.ts +0 -6
  519. package/dist/secrets/secret-resolver.d.ts +2 -6
  520. package/dist/secrets/token-manager.d.ts +1 -4
  521. package/dist/secrets/vault-secret-store.d.ts +0 -13
  522. package/dist/security/comment-handler.d.ts +0 -2
  523. package/dist/security/workflow-diff.d.ts +1 -1
  524. package/dist/server.js +49004 -53782
  525. package/dist/sources/source-manager.d.ts +0 -3
  526. package/dist/sources/source-store.d.ts +0 -9
  527. package/dist/sources/source-validator.d.ts +0 -3
  528. package/dist/stale-detector/all-terminal-runs.d.ts +8 -11
  529. package/dist/stale-detector/gate-deadline-detector.d.ts +14 -19
  530. package/dist/stale-detector/reboot-deadline-sweep.d.ts +7 -11
  531. package/dist/stale-detector/stale-dispatch-candidates.d.ts +13 -20
  532. package/dist/stale-detector/stale-run-detector.d.ts +74 -121
  533. package/dist/stale-detector/workflow-deadline-detector.d.ts +15 -43
  534. package/dist/standalone.js +9342 -13077
  535. package/dist/storage/blob-routes.d.ts +10 -19
  536. package/dist/storage/filesystem.d.ts +19 -29
  537. package/dist/storage/index.d.ts +2 -10
  538. package/dist/storage/key-discriminator.d.ts +8 -10
  539. package/dist/storage/loopback-guard.d.ts +27 -45
  540. package/dist/storage/s3.d.ts +26 -53
  541. package/dist/storage/sign-url.d.ts +7 -22
  542. package/dist/storage/types.d.ts +46 -72
  543. package/dist/webhook/event-log.d.ts +0 -2
  544. package/dist/webhook/generic-sources.d.ts +0 -21
  545. package/dist/webhook/ingest-admission.d.ts +0 -1
  546. package/dist/webhook/relay-buffer.d.ts +2 -2
  547. package/dist/webhook/verify-inbound.d.ts +0 -1
  548. package/dist/worker/in-memory-execution-tracker.d.ts +9 -31
  549. package/dist/worker/in-memory-job-queue.d.ts +32 -72
  550. package/dist/worker/peer-outbox.d.ts +5 -8
  551. package/dist/worker/reroute-dispatch.d.ts +4 -6
  552. package/dist/worker/static-agent-token-store.d.ts +6 -27
  553. package/dist/worker/worker-outbox-relay.d.ts +2 -2
  554. package/dist/worker/worker-status.d.ts +3 -20
  555. package/dist/ws/agent-api-registry.d.ts +8 -27
  556. package/dist/ws/agent-handler.d.ts +63 -110
  557. package/dist/ws/agent-heartbeat.d.ts +5 -12
  558. package/dist/ws/bringup-api.d.ts +31 -38
  559. package/dist/ws/dashboard-backends-handler.d.ts +12 -22
  560. package/dist/ws/dashboard-context-handler.d.ts +37 -80
  561. package/dist/ws/dashboard-diagnostics-handler.d.ts +8 -25
  562. package/dist/ws/dashboard-dispatch-guard.d.ts +3 -4
  563. package/dist/ws/dashboard-fleet-handler.d.ts +9 -13
  564. package/dist/ws/dashboard-fleet-write-handler.d.ts +7 -21
  565. package/dist/ws/dashboard-global-workflows-handler.d.ts +22 -44
  566. package/dist/ws/dashboard-registrations-handler.d.ts +10 -27
  567. package/dist/ws/dashboard-run-state-handler.d.ts +10 -13
  568. package/dist/ws/event-buffer.d.ts +3 -6
  569. package/dist/ws/execution-status-frame.d.ts +7 -10
  570. package/dist/ws/failure-messages.d.ts +9 -14
  571. package/dist/ws/fleet-agent-collector.d.ts +6 -12
  572. package/dist/ws/fleet-runs-on-all.d.ts +1 -6
  573. package/dist/ws/git-credential-relay.d.ts +12 -20
  574. package/dist/ws/inventory-api.d.ts +4 -5
  575. package/dist/ws/observer-registry.d.ts +14 -59
  576. package/dist/ws/ownership-gate.d.ts +1 -1
  577. package/dist/ws/platform-client.d.ts +21 -30
  578. package/dist/ws/replay-chunker.d.ts +7 -10
  579. package/dist/ws/server-options.d.ts +5 -9
  580. package/dist/ws/test-relay-handlers.d.ts +46 -63
  581. package/installer-image-digests.json +3 -3
  582. package/package.json +6 -5
  583. package/sbom.spdx.json +53 -53
  584. package/dist/__test-helpers__/fake-scaler-state-store.d.ts +0 -24
  585. package/dist/__test-helpers__/mock-db-query.d.ts +0 -129
  586. package/dist/__test-helpers__/mock-db.d.ts +0 -134
  587. package/dist/__test-helpers__/mock-ws.d.ts +0 -13
  588. package/dist/__test-helpers__/peer-mutual-auth.d.ts +0 -42
  589. package/dist/__test-helpers__/scratch-db.d.ts +0 -16
  590. package/dist/__test-helpers__/test-db.d.ts +0 -34
  591. package/dist/pipeline/dispatch-matched-workflow.test-helpers.d.ts +0 -121
  592. package/dist/scaler/container-spawn.d.ts +0 -28
package/dist/index.js CHANGED
@@ -22,17 +22,13 @@ import { exec } from "node:child_process";
22
22
  //#endregion
23
23
  //#region src/storage/s3.ts
24
24
  /**
25
- * S3-backed cache storage.
25
+ * S3-backed cache storage; AWS SDK v3 modules load only when S3 storage is configured.
26
26
  *
27
- * Stores cached items in S3 with custom metadata headers for TTL tracking.
28
- * Uses AWS SDK v3 modular imports -- only loaded when S3 storage is configured.
29
- *
30
- * Metadata storage:
27
+ * TTL metadata headers:
31
28
  * x-amz-meta-created-at -- ISO timestamp of creation
32
29
  * x-amz-meta-last-accessed-at -- ISO timestamp of last access
33
30
  *
34
31
  * TTL is enforced lazily: expired items are deleted on access.
35
- * Pre-signed URLs are generated for getUrl() with 15-minute expiry.
36
32
  */
37
33
  const logger$5 = createLogger({ prefix: "s3-cache" });
38
34
  /** Pre-signed download URL expiry in seconds (15 minutes) */
@@ -41,17 +37,14 @@ const PRESIGNED_URL_EXPIRY_SECONDS = 900;
41
37
  const UPLOAD_URL_EXPIRY_SECONDS = 1800;
42
38
  var S3CacheStorage = class {
43
39
  client;
44
- /** Separate client for pre-signed URL generation (uses externalEndpoint if configured). */
40
+ /** Pre-signing client: externalEndpoint when configured. */
45
41
  presignClient;
46
- /** Separate client for the host CLI's pre-signed upload URL (uses uploadEndpoint if configured). */
42
+ /** Client for the developer upload URL: uploadEndpoint, else the presign client. */
47
43
  uploadPresignClient;
48
44
  bucket;
49
45
  prefix;
50
46
  ttlMs;
51
- /**
52
- * False once the backend answered a conditional self-copy with
53
- * `501 NotImplemented`. From then on `updateMeta` copies unconditionally.
54
- */
47
+ /** False once the backend answered a conditional self-copy with `501 NotImplemented`. */
55
48
  conditionalCopySupported = true;
56
49
  constructor(options) {
57
50
  this.bucket = options.bucket;
@@ -63,13 +56,11 @@ var S3CacheStorage = class {
63
56
  endpoint: options.externalEndpoint
64
57
  });
65
58
  else this.presignClient = this.client;
66
- if (options.uploadEndpoint) this.uploadPresignClient = createS3Client({
59
+ this.uploadPresignClient = options.uploadEndpoint ? createS3Client({
67
60
  ...options,
68
61
  endpoint: options.uploadEndpoint
69
- });
70
- else this.uploadPresignClient = this.client;
62
+ }) : this.presignClient;
71
63
  }
72
- /** Build the full S3 object key from a cache key. */
73
64
  objectKey(key) {
74
65
  return `${this.prefix}${key}`;
75
66
  }
@@ -79,17 +70,11 @@ var S3CacheStorage = class {
79
70
  const lastAccessed = new Date(meta.lastAccessedAt).getTime();
80
71
  return Date.now() - lastAccessed > ttl;
81
72
  }
82
- /**
83
- * Read metadata from an S3 object's custom headers.
84
- * Returns null if the object doesn't exist (NoSuchKey/NotFound).
85
- */
73
+ /** Null when the object does not exist (NoSuchKey/NotFound). */
86
74
  async readMeta(key) {
87
75
  return (await this.readHead(key))?.meta ?? null;
88
76
  }
89
- /**
90
- * Read an object's TTL metadata together with the ETag of the version it
91
- * belongs to. Returns null if the object doesn't exist (NoSuchKey/NotFound).
92
- */
77
+ /** TTL metadata plus the ETag of its version; null when the object does not exist. */
93
78
  async readHead(key) {
94
79
  try {
95
80
  const head = await this.client.send(new HeadObjectCommand({
@@ -112,25 +97,16 @@ var S3CacheStorage = class {
112
97
  }
113
98
  }
114
99
  /**
115
- * Update metadata on an S3 object by copying it to itself.
116
- * This is the standard S3 pattern for updating metadata without re-uploading data.
117
- *
118
- * The copy is conditional on `etag`, the version whose metadata the caller
119
- * read. A self-copy is a whole-object write: without the condition, one that
120
- * races a `put()` of the same key can land after it and write the older body
121
- * back. Cache pointers are rewritten in place while builds publish them, so a
122
- * touch-on-read racing a publish reverted the pointer to a tarball that no
123
- * longer exists. `CopySourceIfMatch` pins the bytes copied to that version and
124
- * `IfMatch` refuses the write unless the key still holds it.
100
+ * Updates metadata by self-copy, conditional on `etag` (the version the caller read). A
101
+ * self-copy is a whole-object write: unconditioned, one racing a `put()` of the key can write
102
+ * the older body back, reverting a cache pointer to a deleted tarball. `CopySourceIfMatch`
103
+ * pins the copied bytes; `IfMatch` refuses the write unless the key still holds that version.
125
104
  *
126
- * Returns false when the object was replaced since the read (`412`), or is
127
- * being replaced right now (`409 ConditionalRequestConflict`): the newer
128
- * write stamps metadata of its own, so there is nothing left to refresh.
105
+ * Returns false when the object was replaced since the read (`412`) or is being replaced
106
+ * (`409 ConditionalRequestConflict`): the newer write stamps its own metadata.
129
107
  *
130
- * An S3-compatible backend that does not implement conditional copies
131
- * answers `501 NotImplemented`. The copy then runs again without the
132
- * condition, and later copies skip it, as on a backend that ignores the
133
- * headers.
108
+ * A backend without conditional copies answers `501 NotImplemented`; the copy reruns
109
+ * unconditionally, and later copies skip the condition.
134
110
  */
135
111
  async updateMeta(key, meta, etag) {
136
112
  const condition = this.conditionalCopySupported ? etag : void 0;
@@ -165,15 +141,15 @@ var S3CacheStorage = class {
165
141
  }
166
142
  }));
167
143
  }
168
- /** Check if an error is a failed conditional request (PreconditionFailed, 412). */
144
+ /** A failed conditional request (PreconditionFailed, 412). */
169
145
  isPreconditionFailedError(err) {
170
146
  return this.hasErrorShape(err, "PreconditionFailed", 412);
171
147
  }
172
- /** Check if an error is a conditional write that raced another write (ConditionalRequestConflict, 409). */
148
+ /** A conditional write that raced another write (ConditionalRequestConflict, 409). */
173
149
  isConditionalConflictError(err) {
174
150
  return this.hasErrorShape(err, "ConditionalRequestConflict", 409);
175
151
  }
176
- /** Check if an error is a request the backend does not implement (NotImplemented, 501). */
152
+ /** A request the backend does not implement (NotImplemented, 501). */
177
153
  isNotImplementedError(err) {
178
154
  return this.hasErrorShape(err, "NotImplemented", 501);
179
155
  }
@@ -182,7 +158,7 @@ var S3CacheStorage = class {
182
158
  if (err.name === name) return true;
183
159
  return err.$metadata?.httpStatusCode === status;
184
160
  }
185
- /** Check if an error is a "not found" error (NoSuchKey, NotFound, 404). */
161
+ /** NoSuchKey, NotFound or 404. */
186
162
  isNotFoundError(err) {
187
163
  if (typeof err !== "object" || err === null) return false;
188
164
  const name = err.name;
@@ -360,30 +336,21 @@ var S3CacheStorage = class {
360
336
  //#endregion
361
337
  //#region src/storage/sign-url.ts
362
338
  /**
363
- * HMAC-signed URL tokens for the filesystem cache backend.
364
- *
365
- * Pre-signed S3 URLs are not available for filesystem storage, so the
366
- * filesystem backend mints HMAC-SHA256 tokens that the orchestrator's HTTP
367
- * blob route verifies before serving / writing a file. Token shape:
339
+ * HMAC-SHA256 URL tokens for the filesystem cache backend (which has no pre-signed S3 URLs);
340
+ * the blob route verifies them before serving / writing a file. Token shape:
368
341
  *
369
342
  * `${expiresUnixMs}.${hexSig}`
370
343
  *
371
- * Signature input: `${method}:${key}:${expiresUnixMs}` with HMAC-SHA256 keyed
372
- * by a per-orchestrator-process secret (random 32-byte hex at boot, persists
373
- * for the lifetime of the process). Tokens become invalid on orchestrator
374
- * restart — fine for the filesystem backend's single-host / test-sandbox use
375
- * case.
344
+ * Signs `${method}:${key}:${expiresUnixMs}` with a per-process secret (random 32 bytes at
345
+ * boot), so tokens die on orchestrator restart — fine for single-host / test-sandbox use.
376
346
  */
377
- /** Default URL lifetime: 1 hour (matches S3 backend's PUT-URL lifetime). */
347
+ /** Default URL lifetime: 1 hour. */
378
348
  const DEFAULT_SIGN_URL_TTL_MS = 36e5;
379
349
  function computeSig(secret, method, key, expiresMs) {
380
350
  const hmac = createHmac("sha256", secret);
381
351
  hmac.update(`${method}:${key}:${expiresMs}`);
382
352
  return hmac.digest("hex");
383
353
  }
384
- /**
385
- * Mint a signed token for the given (method, key, expiry) triple.
386
- */
387
354
  function signToken(secret, method, key, ttlMs = DEFAULT_SIGN_URL_TTL_MS) {
388
355
  const expiresMs = Date.now() + ttlMs;
389
356
  return {
@@ -394,19 +361,15 @@ function signToken(secret, method, key, ttlMs = DEFAULT_SIGN_URL_TTL_MS) {
394
361
  //#endregion
395
362
  //#region src/storage/filesystem.ts
396
363
  /**
397
- * Filesystem-backed cache storage.
398
- *
399
- * Mirrors the `CacheStorage` interface that `S3CacheStorage` provides, but
400
- * stores blobs as files under a configured base directory. Pre-signed URLs
401
- * are replaced by HMAC-signed `http://<orchUrl>/api/v1/cache/blob/...` URLs
402
- * — see `sign-url.ts` for the token mechanics and `app.ts` for the route.
364
+ * Filesystem-backed `CacheStorage`, the counterpart of `S3CacheStorage`, for
365
+ * single-host deployments and test sandboxes. Production should still use S3.
403
366
  *
404
- * Intended for single-host deployments and test sandboxes where standing up
405
- * an S3-compatible service is overkill. Production should still use S3.
367
+ * Pre-signed URLs become HMAC-signed `http://<orchUrl>/api/v1/cache/blob/...`
368
+ * URLs (token mechanics: `sign-url.ts`; route: `app.ts`).
406
369
  *
407
- * Metadata is co-located as a sibling JSON file (`<key>.meta.json`) so the
408
- * data file is byte-identical to what the agent receives over HTTP. TTL is
409
- * enforced lazily on access — same model as the S3 backend.
370
+ * Metadata sits in a sibling `<key>.meta.json`, so the data file is
371
+ * byte-identical to what the agent receives over HTTP. TTL is enforced lazily
372
+ * on access, as in the S3 backend.
410
373
  */
411
374
  const DEFAULT_ROUTE_PREFIX = "/api/v1/cache/blob/";
412
375
  var FilesystemCacheStorage = class {
@@ -423,9 +386,9 @@ var FilesystemCacheStorage = class {
423
386
  this.routePrefix = (options.routePrefix ?? DEFAULT_ROUTE_PREFIX).replace(/\/?$/, "/");
424
387
  }
425
388
  /**
426
- * Map a cache key to its on-disk path. Keys may contain `/`, which becomes a
427
- * directory separator. Reject keys containing `..` segments or NUL bytes to
428
- * prevent path traversal — the same defence the route layer enforces too.
389
+ * Map a cache key to its on-disk path (`/` becomes a directory separator).
390
+ * Rejects `..` segments and NUL bytes against path traversal, as the route
391
+ * layer also does.
429
392
  */
430
393
  resolvePath(key) {
431
394
  if (key.includes("\0") || key.split("/").some((seg) => seg === ".." || seg === "")) throw new Error(`Invalid cache key: ${JSON.stringify(key)}`);
@@ -535,19 +498,14 @@ var FilesystemCacheStorage = class {
535
498
  });
536
499
  }
537
500
  /**
538
- * List cache keys under a prefix.
539
- *
540
- * The prefix is a **key prefix**, not necessarily a directory — `UserCache`'s
541
- * `restoreKeys` fallback lists on `${prefix}${seg(restoreKey)}`, a partial
542
- * object name. Two shapes, and both must work the way the S3 backend does:
501
+ * List cache keys under a **key prefix**, which need not be a directory:
502
+ * `UserCache`'s `restoreKeys` fallback lists on `${prefix}${seg(restoreKey)}`,
503
+ * a partial object name. Both shapes must behave as on S3:
543
504
  *
544
505
  * - trailing `/` — a directory. Walk it directly; this is the hot path.
545
- * - no trailing `/` — a partial name. Walk the parent directory and filter by
546
- * the prefix, since the prefix itself may name a file (or nothing at all).
547
- *
548
- * Reading the prefix as a directory in the second case is what made the
549
- * `restoreKeys` fallback silently never hit here (`ENOENT` → `[]`) or throw
550
- * (`ENOTDIR`, when a real object carried that exact name).
506
+ * - no trailing `/` — a partial name. Walk the parent and filter by the
507
+ * prefix, which may name a file or nothing at all. Reading it as a
508
+ * directory made `restoreKeys` never hit (`ENOENT`) or throw (`ENOTDIR`).
551
509
  */
552
510
  async list(subPrefix) {
553
511
  const isDirPrefix = subPrefix.endsWith("/");
@@ -588,10 +546,9 @@ var FilesystemCacheStorage = class {
588
546
  });
589
547
  }
590
548
  /**
591
- * Recursively collect data files under `dir`, returning each as a cache key
592
- * relative to `basePath` paired with its mtime. Metadata sidecars
593
- * (`*.meta.json`) and the atomic-write temp files (`*.tmp-*`) are skipped so
594
- * `list()` only surfaces real cache objects.
549
+ * Recursively collect data files under `dir` as `basePath`-relative keys with
550
+ * their mtime, skipping `*.meta.json` sidecars and `*.tmp-*` atomic-write
551
+ * temp files so `list()` surfaces only real cache objects.
595
552
  */
596
553
  async walkDataFiles(dir, keyPrefix) {
597
554
  const out = [];
@@ -628,9 +585,8 @@ function isNotFoundFsError(err) {
628
585
  return code === "ENOENT" || code === "ENOTDIR";
629
586
  }
630
587
  /**
631
- * Write a file atomically: write to a temp sibling, fsync, rename. Avoids
632
- * partial reads if the orchestrator crashes mid-write. The temp suffix is
633
- * randomised so concurrent writers don't collide on the same temp name.
588
+ * Write atomically (temp sibling, fsync, rename) so a crash mid-write leaves no
589
+ * partial file. The random temp suffix keeps concurrent writers apart.
634
590
  */
635
591
  async function writeFileAtomic(path, data) {
636
592
  const tmp = `${path}.tmp-${randomBytes(6).toString("hex")}`;
@@ -645,9 +601,6 @@ async function writeFileAtomic(path, data) {
645
601
  }
646
602
  //#endregion
647
603
  //#region src/storage/index.ts
648
- /**
649
- * Create a cache storage backend from configuration.
650
- */
651
604
  function createCacheStorage(config) {
652
605
  if (config.type === "s3") return new S3CacheStorage({
653
606
  bucket: config.bucket,
@@ -670,61 +623,44 @@ function createCacheStorage(config) {
670
623
  //#endregion
671
624
  //#region src/cache/source-cache.ts
672
625
  /**
673
- * Source-tarball cache layer wrapping CacheStorage.
674
- *
675
- * Stores customer-workflow source tarballs — the `.kici/` directory minus
676
- * `node_modules/`, packed by the agent's build job via `source-packer.ts` —
677
- * under the tarball's OWN content hash, with a small pointer resolving an org's
678
- * workflow `contentHash` to that hash. Tarballs are platform-independent: raw
679
- * TypeScript source is identical across architectures. Refreshes TTL on reads
680
- * (touch-on-read) so actively used sources stay in cache longer.
626
+ * Source-tarball cache over CacheStorage: the `.kici/` directory minus
627
+ * `node_modules/` (packed by the agent's build job via `source-packer.ts`),
628
+ * stored under the tarball's OWN content hash, with a pointer resolving an
629
+ * org's workflow `contentHash` to it. Tarballs are platform-independent (raw
630
+ * TypeScript source). Reads touch the TTL so active sources stay cached.
681
631
  *
682
632
  * Keys: `source/v2/{orgId}/{sourceTarDigest}.tar.gz` (immutable) and
683
- * `source/v2/{orgId}/{contentHash}.hash` (the pointer) — the shape `dep-cache.ts`
684
- * already uses, for the same reasons — content addressing and org scoping.
685
- *
686
- * **Content addressing** makes a mismatched pair unrepresentable. At
687
- * `source/{contentHash}.tar.gz` the object's key was derived from something
688
- * other than its bytes, so nothing a reader fetched could be verified against
689
- * anything, and the agent restored whatever the signed URL returned.
633
+ * `source/v2/{orgId}/{contentHash}.hash` (the pointer) — the `dep-cache.ts`
634
+ * shape, for the same reasons:
690
635
  *
691
- * **Org scoping** makes the key a tenant's key. `contentHash` alone is a
692
- * property of a `.kici/` tree, so two repositories scaffolded from the same
693
- * `kici init` template — or a fork and its upstream — produced one object, and
694
- * whichever built first won for the life of that object. On an orchestrator
695
- * serving more than one org that is a cross-tenant read of `.kici/` contents.
696
- * The org is the tenant boundary and the segment the user cache already scopes
697
- * by; inside one org, sharing a key now means the two trees are byte-identical,
698
- * so a monorepo or a same-org fork keeps its warm cache and pays nothing.
636
+ * - **Content addressing** makes a mismatched pair unrepresentable: a key not
637
+ * derived from the bytes lets nothing a reader fetches be verified.
638
+ * - **Org scoping** makes the key a tenant's key. `contentHash` alone is a
639
+ * property of a `.kici/` tree, so two repositories from the same `kici init`
640
+ * template, or a fork and its upstream, would share one object — a
641
+ * cross-tenant read on a multi-org orchestrator. The org is the tenant
642
+ * boundary the user cache scopes by too; within one org a shared key means
643
+ * byte-identical trees, so a monorepo or same-org fork keeps its warm cache.
699
644
  *
700
- * Legacy `source/{contentHash}.tar.gz` objects are **not read**. Only a
701
- * `compileSchemaVersion: 5` lock can name one, and that `contentHash` covers
702
- * the workflow entry file alone rather than the tree the tarball holds — the
703
- * defect this layout closes — so serving it would serve the bug. For a v6 lock
704
- * the fallback is unreachable anyway, since the schema bump moves every hash.
705
- * Old objects are orphaned. The cache TTL is enforced lazily on access, so
706
- * nothing here removes them.
645
+ * Retired `source/{contentHash}.tar.gz` objects are **not read**: only a
646
+ * `compileSchemaVersion: 5` lock names one, and its `contentHash` covers the
647
+ * entry file alone rather than the packed tree, so serving it would serve the
648
+ * bug. A v6 lock cannot reach it (the bump moves every hash). The lazy TTL never
649
+ * removes them (docs/operator/orchestrator/storage-layout.md § "Retired layouts").
707
650
  */
708
651
  const logger$4 = createLogger({ prefix: "source-cache" });
709
652
  /**
710
- * Cache key for a source tarball, addressed by the tarball's OWN content hash:
711
- * `source/v2/{orgId}/{sourceTarDigest}.tar.gz`.
712
- *
713
- * Naming the object by its own hash means every pair a reader can observe is
714
- * self-consistent, and the bytes at a given key can never change after a URL is
715
- * signed for it.
653
+ * Named by its own hash, so every pair a reader observes is self-consistent and
654
+ * the bytes at a key never change after a URL is signed for it.
716
655
  */
717
656
  function sourceTarballKey(orgId, sourceTarDigest) {
718
657
  return `source/v2/${orgId}/${sourceTarDigest}.tar.gz`;
719
658
  }
720
659
  /**
721
- * Cache key for the pointer that resolves a workflow `contentHash` to the
722
- * content hash of the tarball built from it: `source/v2/{orgId}/{contentHash}.hash`.
723
- *
724
- * This is the one mutable object in the scheme. A concurrent write replaces a
725
- * pointer wholesale — there is no half-written window — so the worst a racing
726
- * pair of builders can do is leave whichever pointer landed last, and both
727
- * tarballs stay valid and fetchable.
660
+ * The pointer from a workflow `contentHash` to its tarball's hash: the one
661
+ * mutable object. A write replaces it wholesale (no half-written window), so
662
+ * racing builders at worst leave the last-landed pointer, and both tarballs
663
+ * stay valid and fetchable.
728
664
  */
729
665
  function sourcePointerKey(orgId, contentHash) {
730
666
  return `source/v2/${orgId}/${contentHash}.hash`;
@@ -734,16 +670,13 @@ var SourceCache = class SourceCache {
734
670
  constructor(options) {
735
671
  this.storage = options.storage;
736
672
  }
737
- /** The single place the pointer indirection is read. */
673
+ /** Resolves the pointer indirection (`getUrlAndDigest` reads it inline to touch it). */
738
674
  async resolvePointer(orgId, contentHash) {
739
675
  return (await this.storage.get(sourcePointerKey(orgId, contentHash)))?.toString("utf-8").trim() || null;
740
676
  }
741
677
  /**
742
- * Whether a source tarball for this org's `contentHash` exists.
743
- *
744
- * Both halves must be present: a pointer whose tarball has aged out is a
745
- * miss, not a hit, or the caller skips a rebuild and dispatches a URL that
746
- * 404s on the agent.
678
+ * Both halves must exist: a pointer whose tarball aged out is a miss, or the
679
+ * caller skips a rebuild and dispatches a URL that 404s on the agent.
747
680
  */
748
681
  async has(orgId, contentHash) {
749
682
  const digest = await this.resolvePointer(orgId, contentHash);
@@ -770,13 +703,9 @@ var SourceCache = class SourceCache {
770
703
  return data;
771
704
  }
772
705
  /**
773
- * A pre-signed download URL and the tarball's own digest.
774
- *
775
- * The pointer is resolved FIRST: it names the content hash, which is also the
776
- * tarball's key, so the url and the digest returned here are read from a
777
- * single source of truth and cannot disagree. Returns null on a miss —
778
- * including a pointer with no tarball behind it, which is unverifiable and so
779
- * is deliberately not served.
706
+ * A pre-signed download URL and the tarball's own digest. The pointer is
707
+ * resolved FIRST and names both, so url and digest cannot disagree. Null on a
708
+ * miss, including a pointer with no tarball (unverifiable, so not served).
780
709
  */
781
710
  async getUrlAndDigest(orgId, contentHash) {
782
711
  const pointerKey = sourcePointerKey(orgId, contentHash);
@@ -803,19 +732,15 @@ var SourceCache = class SourceCache {
803
732
  return (await this.getUrlAndDigest(orgId, contentHash))?.url ?? null;
804
733
  }
805
734
  /**
806
- * A pre-signed upload URL for direct agent-to-storage upload.
807
- *
808
- * Takes the tarball's OWN digest, not the workflow `contentHash`: the agent
809
- * computes it before asking for a URL, and the object is named by it.
735
+ * A pre-signed agent-to-storage upload URL, keyed by the tarball's OWN digest
736
+ * (which the agent computes first), not the workflow `contentHash`.
810
737
  */
811
738
  async getUploadUrl(orgId, sourceTarDigest) {
812
739
  return this.storage.getUploadUrl(sourceTarballKey(orgId, sourceTarDigest));
813
740
  }
814
741
  /**
815
- * Publish the pointer that makes an uploaded tarball discoverable by
816
- * `contentHash`. Called only after the agent confirms its upload completed —
817
- * publishing before the bytes land would let a reader follow the pointer to a
818
- * missing object.
742
+ * Publish the pointer to an uploaded tarball. Called only after the agent
743
+ * confirms the upload, or a reader could follow it to a missing object.
819
744
  */
820
745
  async publishPointer(orgId, contentHash, sourceTarDigest) {
821
746
  await this.storage.put(sourcePointerKey(orgId, contentHash), sourceTarDigest);
@@ -836,7 +761,6 @@ var SourceCache = class SourceCache {
836
761
  static computeDigest(data) {
837
762
  return sha256(data);
838
763
  }
839
- /** Remove a source tarball and its pointer. */
840
764
  async remove(orgId, contentHash) {
841
765
  const digest = await this.resolvePointer(orgId, contentHash);
842
766
  await this.storage.delete(sourcePointerKey(orgId, contentHash));
@@ -848,12 +772,9 @@ var SourceCache = class SourceCache {
848
772
  //#endregion
849
773
  //#region src/cache/dep-cache.ts
850
774
  /**
851
- * Dependency-specific cache layer wrapping CacheStorage.
852
- *
853
- * Stores dependency tarballs under their own content hash, with a small pointer
854
- * resolving lockfileHash + platform + arch to that hash. Shared CacheStorage
855
- * backend with SourceCache (same S3 bucket). Refreshes TTL on reads
856
- * (touch-on-read).
775
+ * Dependency cache over CacheStorage (the same S3 bucket as SourceCache).
776
+ * Tarballs live under their own content hash, with a small pointer resolving
777
+ * lockfileHash + platform + arch to it. Reads refresh TTL (touch-on-read).
857
778
  *
858
779
  * Keys: `deps/{platform}-{arch}/{depsHash}.tar.gz` (immutable) and
859
780
  * `deps/{platform}-{arch}/{lockfileHash}.hash` (the pointer).
@@ -865,17 +786,14 @@ const DEFAULT_MAX_TARBALL_BYTES = 524288e3;
865
786
  const DEFAULT_CACHE_TTL_DAYS = 30;
866
787
  const MS_PER_DAY = 864e5;
867
788
  /**
868
- * Cache key for a dependency tarball, addressed by the tarball's OWN content
869
- * hash: `deps/{platform}-{arch}/{depsHash}.tar.gz`.
789
+ * Cache key for a dependency tarball, addressed by its OWN content hash:
790
+ * `deps/{platform}-{arch}/{depsHash}.tar.gz`.
870
791
  *
871
- * Content-addressing is what makes a mismatched pair unrepresentable. When the
872
- * tarball lived at a lockfile-derived name, it and its companion `.hash` were
873
- * two independently-written objects under keys that any two builds sharing a
874
- * lockfile + platform + arch also share — so concurrent builders could leave the
875
- * `.tar.gz` from one and the `.hash` from the other, and the reader failed
876
- * verification durably. Naming the object by its own hash means every pair a
877
- * reader can observe is self-consistent, and the bytes at a given key can never
878
- * change after a URL is signed for it.
792
+ * Content-addressing makes a mismatched pair unrepresentable. Under a
793
+ * lockfile-derived name, concurrent builders sharing lockfile + platform + arch
794
+ * could leave one's `.tar.gz` and the other's `.hash`, and the reader failed
795
+ * verification durably. Named by its own hash, every observable pair is
796
+ * self-consistent and a key's bytes never change after a URL is signed for it.
879
797
  */
880
798
  function depTarballKey(depsHash, platform, arch) {
881
799
  return `deps/${platform}-${arch}/${depsHash}.tar.gz`;
@@ -885,17 +803,14 @@ function depTarballKey(depsHash, platform, arch) {
885
803
  * tarball built from it: `deps/{platform}-{arch}/{lockfileHash}.hash`, or
886
804
  * `…/{lockfileHash}-{siblingsDigest}.hash` when the lock carries one.
887
805
  *
888
- * `siblingsDigest` is part of the key because the deps tarball carries in-repo
889
- * `workspace:` sibling directories WITH their built output, and editing a
890
- * sibling's source moves no package-manager lock file — so a `lockfileHash`-only
891
- * key restored the sibling's stale build over the fresh clone on every run. A
892
- * lock with no in-repo sibling carries no digest and keys exactly as before, so
893
- * existing pointers stay live.
806
+ * `siblingsDigest` is keyed because the tarball carries in-repo `workspace:`
807
+ * siblings WITH their built output, and editing a sibling moves no lock file —
808
+ * a `lockfileHash`-only key restored a stale sibling build over the fresh clone.
809
+ * A lock with no in-repo sibling carries no digest, so existing pointers stay live.
894
810
  *
895
- * This is the one mutable object in the scheme. A concurrent write replaces a
896
- * pointer wholesale — there is no window in which it is half-written — so the
897
- * worst a racing pair of builders can do is leave whichever pointer landed last,
898
- * and both tarballs remain valid and fetchable.
811
+ * The one mutable object in the scheme. A write replaces the pointer wholesale
812
+ * (never half-written), so racing builders at worst leave whichever landed
813
+ * last, and both tarballs stay valid and fetchable.
899
814
  */
900
815
  function depPointerKey(lockfileHash, platform, arch, siblingsDigest) {
901
816
  return `deps/${platform}-${arch}/${siblingsDigest ? `${lockfileHash}-${siblingsDigest}` : lockfileHash}.hash`;
@@ -912,28 +827,21 @@ var DepCache = class DepCache {
912
827
  this.clusterSettings = options.clusterSettings;
913
828
  }
914
829
  /**
915
- * Resolve the live dependency-cache entry TTL as a per-operation override
916
- * (ms) from `cluster_settings.cache_ttl_days`, falling back to the cluster
917
- * default. `undefined` when no reader is wired, so the storage backend uses
918
- * its own configured TTL. Passed to read/expiry operations so an operator's
919
- * `cache_ttl_days` change takes effect on the next lookup.
830
+ * Per-operation TTL override (ms) from `cluster_settings.cache_ttl_days`, so
831
+ * an operator's change takes effect on the next lookup. `undefined` when no
832
+ * reader is wired, so the backend uses its own configured TTL.
920
833
  */
921
834
  async resolveTtlMsOverride() {
922
835
  if (!this.clusterSettings) return void 0;
923
836
  return await this.clusterSettings.getNumber("cache_ttl_days", this.cacheTtlDaysFallback) * MS_PER_DAY;
924
837
  }
925
- /**
926
- * Resolve a lockfile to the content hash of the tarball built from it, or
927
- * null when no pointer exists. The single place the indirection is read.
928
- */
838
+ /** Lockfile → tarball content hash, or null when no pointer exists. */
929
839
  async resolvePointer(lockfileHash, platform, arch, ttlMsOverride, siblingsDigest) {
930
840
  return (await this.storage.get(depPointerKey(lockfileHash, platform, arch, siblingsDigest), ttlMsOverride))?.toString("utf-8").trim() || null;
931
841
  }
932
842
  /**
933
- * Check if a dep tarball exists in cache.
934
- *
935
- * Both halves must be present: a pointer whose tarball has aged out is a miss,
936
- * not a hit, or the caller skips a rebuild and dispatches a URL that 404s.
843
+ * Both halves must be present: a pointer whose tarball aged out is a miss, or
844
+ * the caller skips a rebuild and dispatches a URL that 404s.
937
845
  */
938
846
  async has(lockfileHash, platform, arch, siblingsDigest) {
939
847
  const ttlMsOverride = await this.resolveTtlMsOverride();
@@ -952,18 +860,13 @@ var DepCache = class DepCache {
952
860
  });
953
861
  return exists;
954
862
  }
955
- /**
956
- * Get a pre-signed download URL for the dep tarball (for agent delivery).
957
- * Refreshes TTL on hit.
958
- */
863
+ /** Pre-signed download URL for agent delivery. Refreshes TTL on hit. */
959
864
  async getUrl(lockfileHash, platform, arch, siblingsDigest) {
960
865
  return (await this.getUrlAndHash(lockfileHash, platform, arch, siblingsDigest))?.url ?? null;
961
866
  }
962
867
  /**
963
- * Get a pre-signed download URL and the tarball content hash.
964
- *
965
- * Returns null on cache miss — including an entry with no pointer, which is
966
- * unverifiable and so is deliberately not served.
868
+ * Pre-signed download URL plus tarball content hash; null on a miss,
869
+ * including an entry with no pointer (unverifiable, so never served).
967
870
  */
968
871
  async getUrlAndHash(lockfileHash, platform, arch, siblingsDigest) {
969
872
  const ttlMsOverride = await this.resolveTtlMsOverride();
@@ -997,17 +900,13 @@ var DepCache = class DepCache {
997
900
  hash
998
901
  };
999
902
  }
1000
- /**
1001
- * Get a pre-signed upload URL for direct agent-to-S3 upload.
1002
- */
903
+ /** Pre-signed URL for direct agent-to-S3 upload. */
1003
904
  async getUploadUrl(depsHash, platform, arch) {
1004
905
  return this.storage.getUploadUrl(depTarballKey(depsHash, platform, arch));
1005
906
  }
1006
907
  /**
1007
- * Publish the pointer that makes an uploaded tarball discoverable by lockfile.
1008
- *
1009
- * Called only after the agent confirms its upload completed. Publishing before
1010
- * the bytes land would let a reader follow the pointer to a missing object.
908
+ * Make an uploaded tarball discoverable by lockfile. Called only after the
909
+ * agent confirms its upload, or a reader could follow the pointer to nothing.
1011
910
  */
1012
911
  async publishPointer(lockfileHash, platform, arch, depsHash, siblingsDigest) {
1013
912
  await this.storage.put(depPointerKey(lockfileHash, platform, arch, siblingsDigest), depsHash);
@@ -1016,10 +915,7 @@ var DepCache = class DepCache {
1016
915
  arch
1017
916
  });
1018
917
  }
1019
- /**
1020
- * Store a dep tarball in cache.
1021
- * Throws if tarball exceeds max size (per user decision).
1022
- */
918
+ /** Throws when the tarball exceeds the max size. */
1023
919
  async store(lockfileHash, platform, arch, tarballData) {
1024
920
  const maxTarballBytes = this.clusterSettings ? await this.clusterSettings.getNumber("cache_max_tarball_bytes", this.maxTarballBytes) : this.maxTarballBytes;
1025
921
  if (tarballData.length > maxTarballBytes) throw new Error(`Dep tarball exceeds max size: ${tarballData.length} bytes > ${maxTarballBytes} bytes limit`);
@@ -1034,8 +930,8 @@ var DepCache = class DepCache {
1034
930
  });
1035
931
  }
1036
932
  /**
1037
- * Compute SHA-256 hash of a tarball buffer.
1038
- * Used by build agents to compute the hash for depsHash protocol field.
933
+ * Compute SHA-256 hash of a tarball buffer: the `depsHash` that `store()`
934
+ * keys and logs the tarball under.
1039
935
  */
1040
936
  static computeHash(data) {
1041
937
  return sha256(data);
@@ -1055,10 +951,9 @@ var DepCache = class DepCache {
1055
951
  /**
1056
952
  * A collision-resistant discriminator for a user-supplied object-key segment.
1057
953
  *
1058
- * Hashes the **exact** name, before any sanitization. Sanitizing is many-to-one
1059
- * — `seg()` maps both `/` and `_` to `_`, so `a/b` and `a_b` collapse to one
1060
- * segment — and a case-insensitive backend folds `build` onto `Build`. Hashing
1061
- * the pre-sanitization name is what keeps each of those pairs two objects.
954
+ * Hashes the **exact** pre-sanitization name: `seg()` maps both `/` and `_` to
955
+ * `_` (`a/b` and `a_b` collapse), and a case-insensitive backend folds `build`
956
+ * onto `Build`, so only the hash keeps each pair two objects.
1062
957
  */
1063
958
  function keyDiscriminator(exact) {
1064
959
  return createHash("sha256").update(exact, "utf8").digest("hex").slice(0, 32);
@@ -1069,47 +964,40 @@ function keyDiscriminator(exact) {
1069
964
  * User-facing cache layer wrapping CacheStorage.
1070
965
  *
1071
966
  * Namespacing: `cache/<orgId>/<repoId>/<refScope>/<key>-<discriminator>.tar.gz`.
1072
- * The discriminator is a hash of the exact cache key, so two keys differing
1073
- * only by case stay two objects even on a case-insensitive store. `refScope`
1074
- * is `shared` for trusted refs (org-shared, default-branch cache)
1075
- * or `iso/<runId>` for untrusted refs (per-run isolated scope). Restores from
1076
- * an untrusted ref read the shared scope as a fallback but writes can NEVER
1077
- * land in the shared scope — the GitHub Actions cache-isolation model. Keyed
1078
- * strictly per org so no tenant can read another tenant's cache.
967
+ * The discriminator is a hash of the exact cache key, so keys differing only by
968
+ * case stay two objects on a case-insensitive store. `refScope` is `shared` for
969
+ * trusted refs (org-shared, default-branch cache) or `iso/<runId>` for
970
+ * untrusted refs. An untrusted ref reads the shared scope as a fallback but can
971
+ * NEVER write it — the GitHub Actions cache-isolation model. Keyed strictly per
972
+ * org so no tenant can read another tenant's cache.
1079
973
  *
1080
- * Saves are immutable (first save under an exact key wins) and atomic
1081
- * (upload to a `.tmp-<uuid>` key, then server-side copy to the final key and
1082
- * delete the temp), so a crashed save never leaves a corrupt final entry.
974
+ * Saves are immutable (first save under an exact key wins) and atomic (upload
975
+ * to `.tmp-<uuid>`, server-side copy to the final key, delete the temp), so a
976
+ * crashed save never leaves a corrupt final entry.
1083
977
  *
1084
- * Eviction: per-org byte quota plus the TTL the backing CacheStorage already
1085
- * enforces lazily on access. On a save that pushes the org over quota,
1086
- * least-recently-used entries (oldest `lastAccessedAt`, read from the storage
1087
- * backend's metadata) are evicted until under quota; each eviction is logged.
1088
- * The companion `.hash` / `.size` sidecar objects carry the integrity
1089
- * hash and size accounting outside the tarball's own (presigned, metadata-less)
1090
- * upload.
978
+ * Eviction: per-org byte quota plus the TTL the backing CacheStorage enforces
979
+ * lazily on access. A save that pushes the org over quota evicts LRU entries
980
+ * (oldest `lastAccessedAt` from backend metadata) until under quota, logging
981
+ * each. The `.hash` / `.size` sidecars carry the integrity hash and size
982
+ * accounting outside the presigned, metadata-less tarball upload.
1091
983
  */
1092
984
  const logger$2 = createLogger({ prefix: "user-cache" });
1093
985
  /**
1094
- * Cluster-wide default quota: 5 GiB. Serves as the fallback when an org has no
1095
- * per-org override in `org_settings.user_cache_quota_bytes`. The cluster-wide
1096
- * value is itself operator-configurable via KICI_USER_CACHE_QUOTA_BYTES.
986
+ * Cluster-wide default quota: 5 GiB, used when an org has no
987
+ * `org_settings.user_cache_quota_bytes` override. Operator-configurable via
988
+ * KICI_USER_CACHE_QUOTA_BYTES.
1097
989
  */
1098
990
  const DEFAULT_USER_CACHE_QUOTA_BYTES = 5368709120;
1099
991
  /**
1100
- * Cluster-wide default entry TTL: 7 days. Fallback when an org has no per-org
1101
- * override in `org_settings.user_cache_ttl_ms`. The cluster-wide value is
1102
- * operator-configurable via KICI_USER_CACHE_TTL_MS.
992
+ * Cluster-wide default entry TTL: 7 days, used when an org has no
993
+ * `org_settings.user_cache_ttl_ms` override. Operator-configurable via
994
+ * KICI_USER_CACHE_TTL_MS.
1103
995
  */
1104
996
  const DEFAULT_USER_CACHE_TTL_MS = 6048e5;
1105
997
  /** Tarball suffix for committed cache entries. */
1106
998
  const TAR_SUFFIX = ".tar.gz";
1107
- /**
1108
- * Stem prefix of an in-flight upload, `.tmp-<uuid>.tar.gz`: the presigned PUT
1109
- * target a save lands on before commit copies it to its final key.
1110
- */
999
+ /** Stem of an in-flight upload, `.tmp-<uuid>.tar.gz`, before commit copies it to its final key. */
1111
1000
  const TEMP_UPLOAD_STEM = ".tmp-";
1112
- /** Whether a listed object is an in-flight upload rather than a cache entry. */
1113
1001
  function isTempUpload(key) {
1114
1002
  return key.slice(key.lastIndexOf("/") + 1).startsWith(TEMP_UPLOAD_STEM);
1115
1003
  }
@@ -1117,36 +1005,28 @@ function isTempUpload(key) {
1117
1005
  const KEY_DISCRIMINATOR_TAIL = new RegExp(`^(.*)-([0-9a-f]{32})$`);
1118
1006
  /**
1119
1007
  * Whether a listed object is a committed entry, `<stem>-<discriminator>.tar.gz`.
1120
- *
1121
- * This is the filter the `restoreKeys` prefix scan applies to a listing, and it
1122
- * is what keeps two other kinds of object out of a restore: an in-flight
1123
- * `.tmp-<uuid>.tar.gz` upload, which is a partial tarball until commit copies
1124
- * it to its final key, and an object under the retired un-discriminated layout,
1125
- * which nothing writes.
1008
+ * The `restoreKeys` prefix scan filters on it, which keeps out an in-flight
1009
+ * `.tmp-` upload (a partial tarball until commit) and an object under the
1010
+ * retired un-discriminated layout, which nothing writes.
1126
1011
  */
1127
1012
  function isCommittedEntry(key) {
1128
1013
  return key.endsWith(TAR_SUFFIX) && KEY_DISCRIMINATOR_TAIL.test(key.slice(0, -7));
1129
1014
  }
1130
1015
  /**
1131
- * Recover the reported cache key from a committed entry's stem.
1132
- *
1133
- * The value on this path is already the sanitized, lossy form, so this only
1134
- * needs to undo the discriminator the key format appends. A stem that itself
1135
- * ends in a discriminator-shaped tail loses it — that affects only the string
1136
- * reported back as `matchedKey`, never which object is served.
1016
+ * Recover the reported cache key from a committed entry's (already sanitized,
1017
+ * lossy) stem by undoing the appended discriminator. A stem that itself ends in
1018
+ * a discriminator-shaped tail loses it — that affects only the reported
1019
+ * `matchedKey`, never which object is served.
1137
1020
  */
1138
1021
  function stripKeyDiscriminator(stem) {
1139
1022
  return KEY_DISCRIMINATOR_TAIL.exec(stem)?.[1] ?? stem;
1140
1023
  }
1141
1024
  /**
1142
1025
  * Sanitize a path segment so a key can never escape its org/repo/scope
1143
- * namespace. Beyond stripping disallowed characters, a segment consisting
1144
- * only of dots (`.`, `..`, …) is replaced wholesale: such a segment is a
1145
- * dot-segment that HTTP/S3 path canonicalization collapses (`a/./b` → `a/b`,
1146
- * `a/../b` → `b`), which both corrupts the namespace and breaks the SigV4
1147
- * signature on a pre-signed PUT/GET. Repo identifiers like `.` (the internal
1148
- * provider's repo id) hit exactly this case, so the all-dots guard keeps the
1149
- * object key canonical and the namespace boundary intact.
1026
+ * namespace. An all-dots segment (`.`, `..`, …) is also rewritten: HTTP/S3
1027
+ * path canonicalization collapses it (`a/./b` → `a/b`, `a/../b` → `b`), which
1028
+ * corrupts the namespace and breaks the SigV4 signature on a pre-signed
1029
+ * PUT/GET. The internal provider's repo id `.` hits exactly this case.
1150
1030
  */
1151
1031
  function sanitizeSegment(s) {
1152
1032
  const cleaned = s.replace(/[^A-Za-z0-9._-]/g, "_");
@@ -1179,36 +1059,27 @@ function readPrefixes(ref) {
1179
1059
  return [`${base}/shared/`];
1180
1060
  }
1181
1061
  /**
1182
- * Object key for a committed cache entry.
1183
- *
1184
- * The trailing discriminator is a hash of the EXACT cache key, and it is what
1185
- * keeps `build` and `Build` apart on a case-insensitive namespace — the
1186
- * filesystem backend on a macOS or Windows host, where the two would
1187
- * otherwise resolve to one object and a restore could return the other key's
1188
- * tarball.
1189
- *
1190
- * It is deliberately a SUFFIX: `restoreByPrefix` matches `restoreKeys` by
1191
- * string prefix, so appending leaves those semantics untouched. The only
1192
- * parse that has to know about it is the `matchedKey` slice.
1062
+ * Object key for a committed cache entry. The trailing discriminator, a hash of
1063
+ * the EXACT cache key, keeps `build` and `Build` apart on a case-insensitive
1064
+ * namespace (the filesystem backend on macOS or Windows), where a restore could
1065
+ * otherwise return the other key's tarball. It is deliberately a SUFFIX:
1066
+ * `restoreByPrefix` matches `restoreKeys` by string prefix, so only the
1067
+ * `matchedKey` slice has to know about it.
1193
1068
  */
1194
1069
  function finalKey(prefix, key) {
1195
1070
  return `${prefix}${sanitizeSegment(key)}-${keyDiscriminator(key)}${TAR_SUFFIX}`;
1196
1071
  }
1197
- /**
1198
- * The object key a committed save under `key` lands on for this ref. This is
1199
- * the writer's own path: `beginSave` and `commitSave` address the entry
1200
- * through it.
1201
- */
1072
+ /** The writer's object key for `key` under this ref, used by `beginSave` and `commitSave`. */
1202
1073
  function userCacheEntryKey(ref, key) {
1203
1074
  return finalKey(writePrefix(ref), key);
1204
1075
  }
1205
1076
  var UserCache = class {
1206
1077
  storage;
1207
- /** Cluster-wide default quota (the `KICI_USER_CACHE_QUOTA_BYTES` value). */
1078
+ /** `KICI_USER_CACHE_QUOTA_BYTES`. */
1208
1079
  defaultQuotaBytes;
1209
- /** Cluster-wide default TTL (the `KICI_USER_CACHE_TTL_MS` value). */
1080
+ /** `KICI_USER_CACHE_TTL_MS`. */
1210
1081
  defaultTtlMs;
1211
- /** Optional per-org override reader; absent = always use the cluster defaults. */
1082
+ /** Absent = always use the cluster defaults. */
1212
1083
  orgLimitsReader;
1213
1084
  constructor(opts) {
1214
1085
  this.storage = opts.storage;
@@ -1217,10 +1088,9 @@ var UserCache = class {
1217
1088
  this.orgLimitsReader = opts.orgLimitsReader;
1218
1089
  }
1219
1090
  /**
1220
- * Resolve the effective quota + TTL for an org: the per-org override from
1221
- * `org_settings` when present, otherwise the cluster-wide default. A reader
1222
- * failure falls back to the defaults (logged) — the cache must never fail a
1223
- * restore/save because the settings lookup hiccupped.
1091
+ * Per-org override when present, else the cluster default. A reader failure
1092
+ * falls back to the defaults (logged): a settings-lookup hiccup must never
1093
+ * fail a restore/save.
1224
1094
  */
1225
1095
  async resolveLimits(org) {
1226
1096
  if (!this.orgLimitsReader) return {
@@ -1319,13 +1189,11 @@ var UserCache = class {
1319
1189
  return (await this.storage.get(`${key}.hash`))?.toString("utf-8") || void 0;
1320
1190
  }
1321
1191
  /**
1322
- * Evict least-recently-used entries for the org until total tarball size <= the per-org quota.
1323
- *
1324
- * An in-flight `.tmp-` upload is never a candidate. A presigned PUT carries
1325
- * no metadata, so it would rank oldest and be reclaimed first — freeing
1326
- * nothing, since it has no `.size` — and the concurrent commit would then
1327
- * fail on its copy to the final key. Retired un-discriminated entries stay
1328
- * in the set: they hold accounted bytes and are evictable like any other.
1192
+ * Evict the org's LRU entries until total tarball size <= the per-org quota.
1193
+ * An in-flight `.tmp-` upload is never a candidate: with no metadata it would
1194
+ * rank oldest and be reclaimed first, freeing nothing (no `.size`) and failing
1195
+ * the concurrent commit's copy. Retired un-discriminated entries stay
1196
+ * candidates: they hold accounted bytes.
1329
1197
  */
1330
1198
  async enforceQuota(ref) {
1331
1199
  const { quotaBytes } = await this.resolveLimits(ref.org);
@@ -1368,34 +1236,25 @@ var UserCache = class {
1368
1236
  }
1369
1237
  };
1370
1238
  /**
1371
- * `metadata` key set when a coordinator retires the self-issued credential its
1372
- * previous run left behind. An operator revoke never sets it, which is how a
1373
- * retirement is told apart from a revoke.
1239
+ * `metadata` key set when a coordinator retires its previous run's self-issued
1240
+ * credential. An operator revoke never sets it, which tells the two apart.
1374
1241
  */
1375
1242
  const RETIRED_BY_INSTANCE_KEY = "retiredByInstance";
1376
1243
  /** Default credential expiry: 90 days. */
1377
1244
  const DEFAULT_EXPIRY_DAYS = 90;
1378
- /**
1379
- * Database CRUD operations for peer credentials.
1380
- * Used by the coordinator to manage credentials for all cluster members.
1381
- */
1245
+ /** The coordinator's DB store of every cluster member's credential. */
1382
1246
  var PeerCredentialStore = class {
1383
1247
  db;
1384
1248
  constructor(db) {
1385
1249
  this.db = db;
1386
1250
  }
1387
1251
  /**
1388
- * Save a new peer credential, revoking any prior active credential for the
1389
- * same instanceId (the `peer_credentials_active_uniq` partial unique index
1390
- * permits exactly one active credential per instanceId).
1252
+ * Save a credential, revoking the instanceId's prior active one
1253
+ * (`peer_credentials_active_uniq` permits one active credential per instanceId).
1391
1254
  *
1392
- * Returns `{ revokedCount }` — how many previously-active credentials this
1393
- * save revoked. Because a coordinator's peer-clients share one
1394
- * identity-scoped credential, a `revokedCount > 0` here means every sibling
1395
- * peer-client of `instanceId` that was authenticating with the old
1396
- * credential is now invalidated and will be rejected on its next proof. The
1397
- * caller logs this so a revoke that cascades sibling rejections is visible in
1398
- * the orchestrator logs.
1255
+ * `revokedCount > 0` means every sibling peer-client of `instanceId` still on the
1256
+ * old shared credential is rejected on its next proof; the caller logs it so a
1257
+ * cascade of sibling rejections is visible.
1399
1258
  */
1400
1259
  async save(opts) {
1401
1260
  const expiryDays = opts.expiryDays ?? DEFAULT_EXPIRY_DAYS;
@@ -1422,16 +1281,12 @@ var PeerCredentialStore = class {
1422
1281
  throw err;
1423
1282
  }
1424
1283
  }
1425
- /**
1426
- * Find a non-revoked, non-expired credential by its hash.
1427
- */
1284
+ /** Non-revoked, non-expired credential by hash. */
1428
1285
  async findByCredentialHash(hash) {
1429
1286
  const row = await this.db.selectFrom("peer_credentials").selectAll().where("credential_hash", "=", hash).where("revoked_at", "is", null).where("expires_at", ">", /* @__PURE__ */ new Date()).executeTakeFirst();
1430
1287
  return row ? mapRow(row) : null;
1431
1288
  }
1432
- /**
1433
- * Find a non-revoked, non-expired credential by instance ID.
1434
- */
1289
+ /** Newest non-revoked, non-expired credential for the instance. */
1435
1290
  async findByInstanceId(instanceId) {
1436
1291
  const row = await this.db.selectFrom("peer_credentials").selectAll().where("instance_id", "=", instanceId).where("revoked_at", "is", null).where("expires_at", ">", /* @__PURE__ */ new Date()).orderBy("created_at", "desc").executeTakeFirst();
1437
1292
  return row ? mapRow(row) : null;
@@ -1450,10 +1305,9 @@ var PeerCredentialStore = class {
1450
1305
  return row ? mapRow(row) : null;
1451
1306
  }
1452
1307
  /**
1453
- * Revoke `instanceId`'s unrevoked, self-issued row whose hash is
1454
- * `credentialHash`, recording who retired it. Every condition sits in the
1455
- * WHERE clause, so a row that changed meanwhile is left alone.
1456
- * Returns whether a row was retired.
1308
+ * Revoke `instanceId`'s unrevoked self-issued row with `credentialHash`,
1309
+ * recording who retired it. Every condition is in the WHERE clause, so a row
1310
+ * that changed meanwhile is left alone. Returns whether a row was retired.
1457
1311
  */
1458
1312
  async retireSelfIssued(opts) {
1459
1313
  const marker = JSON.stringify({ [RETIRED_BY_INSTANCE_KEY]: opts.retiredByInstance });
@@ -1463,39 +1317,25 @@ var PeerCredentialStore = class {
1463
1317
  }).where("instance_id", "=", opts.instanceId).where("credential_hash", "=", opts.credentialHash).where("revoked_at", "is", null).where(sql`metadata->>'issuance'`, "=", "self").executeTakeFirst();
1464
1318
  return Number(result?.numUpdatedRows ?? 0n) > 0;
1465
1319
  }
1466
- /**
1467
- * Update the last_seen_at timestamp for a credential.
1468
- * Optionally records which coordinator validated it.
1469
- */
1320
+ /** Bump last_seen_at; optionally record the validating coordinator. */
1470
1321
  async updateLastSeen(credentialHash, validatedBy) {
1471
1322
  const updates = { last_seen_at: /* @__PURE__ */ new Date() };
1472
1323
  if (validatedBy) updates.last_validated_by = validatedBy;
1473
1324
  await this.db.updateTable("peer_credentials").set(updates).where("credential_hash", "=", credentialHash).execute();
1474
1325
  }
1475
- /**
1476
- * Revoke a peer's credential by instance ID.
1477
- */
1478
1326
  async revoke(instanceId) {
1479
1327
  await this.db.updateTable("peer_credentials").set({ revoked_at: /* @__PURE__ */ new Date() }).where("instance_id", "=", instanceId).where("revoked_at", "is", null).execute();
1480
1328
  }
1481
- /**
1482
- * Revoke all active credentials.
1483
- * @returns The number of credentials revoked.
1484
- */
1329
+ /** @returns The number of credentials revoked. */
1485
1330
  async revokeAll() {
1486
1331
  const result = await this.db.updateTable("peer_credentials").set({ revoked_at: /* @__PURE__ */ new Date() }).where("revoked_at", "is", null).executeTakeFirst();
1487
1332
  return Number(result?.numUpdatedRows ?? 0);
1488
1333
  }
1489
- /**
1490
- * List all active (non-revoked, non-expired) credentials.
1491
- */
1334
+ /** Non-revoked, non-expired credentials, oldest first. */
1492
1335
  async listActive() {
1493
1336
  return (await this.db.selectFrom("peer_credentials").selectAll().where("revoked_at", "is", null).where("expires_at", ">", /* @__PURE__ */ new Date()).orderBy("created_at", "asc").execute()).map(mapRow);
1494
1337
  }
1495
1338
  };
1496
- /**
1497
- * Map a database row to a PeerCredential interface.
1498
- */
1499
1339
  function mapRow(row) {
1500
1340
  return {
1501
1341
  id: row.id,
@@ -1512,15 +1352,7 @@ function mapRow(row) {
1512
1352
  metadata: row.metadata ?? {}
1513
1353
  };
1514
1354
  }
1515
- /**
1516
- * Write credential data to a JSON file with restrictive permissions.
1517
- *
1518
- * Creates the parent directory (e.g., ~/.kici/) with 0700 if it doesn't exist.
1519
- * The credential file is written with 0600 permissions (owner read/write only).
1520
- *
1521
- * @param filePath - Absolute path to the credential file
1522
- * @param data - Credential data to persist
1523
- */
1355
+ /** Write the credential file 0600, creating its parent directory 0700 if missing. */
1524
1356
  async function writeCredentialFile(filePath, data) {
1525
1357
  const dir = dirname(filePath);
1526
1358
  await mkdir(dir, {
@@ -1531,12 +1363,7 @@ async function writeCredentialFile(filePath, data) {
1531
1363
  await writeFile(filePath, json, { mode: 384 });
1532
1364
  await chmod(filePath, 384);
1533
1365
  }
1534
- /**
1535
- * Read credential data from a JSON file.
1536
- *
1537
- * @param filePath - Absolute path to the credential file
1538
- * @returns Parsed credential data, or null if the file doesn't exist
1539
- */
1366
+ /** @returns The parsed credential file, or null if it does not exist. */
1540
1367
  async function readCredentialFile(filePath) {
1541
1368
  try {
1542
1369
  const content = await readFile(filePath, "utf-8");
@@ -1547,13 +1374,9 @@ async function readCredentialFile(filePath) {
1547
1374
  }
1548
1375
  }
1549
1376
  /**
1550
- * Construct a PeerCredentialStore bound to a Postgres URL, returning the
1551
- * store plus a disposer that closes the underlying pool. Lets tests
1552
- * exercise the real Kysely-backed store without importing pg/kysely.
1553
- *
1554
- * Intended for tests of the store's own CRUD methods — production
1555
- * code constructs the store with an already-allocated Kysely instance
1556
- * shared with the orchestrator.
1377
+ * A store bound to a Postgres URL plus a pool disposer, so tests exercise the real
1378
+ * store without importing pg/kysely. Test-only: production passes the
1379
+ * orchestrator's shared Kysely instance.
1557
1380
  */
1558
1381
  async function createPeerCredentialStoreFromUrl(databaseUrl, opts) {
1559
1382
  const pool = new pg.Pool({
@@ -1610,22 +1433,19 @@ createLogger({ prefix: "coordinator-credential" });
1610
1433
  /**
1611
1434
  * Per-orchestrator coordinator that owns the shared peer credential file.
1612
1435
  *
1613
- * A single orchestrator runs N peer-clients (one per cluster peer) that all
1614
- * share one identity-scoped credential file. Left uncoordinated, a reconnect
1615
- * storm makes each sibling independently token-join (each join revokes the
1616
- * prior credential, invalidating the others) and delete the shared file on any
1617
- * rejection — a credential revocation cascade. This coordinator serializes all
1618
- * file access through one in-process mutex so only one peer-client token-joins
1619
- * per storm, and it never deletes a credential file a sibling has refreshed.
1436
+ * An orchestrator's peer-clients (one per peer) share one identity-scoped
1437
+ * credential file. Uncoordinated, a reconnect storm makes each sibling token-join
1438
+ * (each join revokes the prior credential, invalidating the others) and delete the
1439
+ * shared file on any rejection — a revocation cascade. One in-process mutex
1440
+ * serializes all file access, so one peer-client token-joins per storm, and a file
1441
+ * a sibling has refreshed is never deleted.
1620
1442
  *
1621
- * A coordinator without a join token also wires a `selfIssue` callback. When a
1622
- * decision finds no credential and no token, the callback issues the
1623
- * coordinator its own credential, once per storm, under the same mutex.
1443
+ * A coordinator without a join token wires `selfIssue`: with no credential and no
1444
+ * token, it issues its own credential, once per storm, under the same mutex.
1624
1445
  *
1625
- * A coordinator also wires `corroborateRejection`. Any dialled endpoint can
1626
- * send a rejection, so before it deletes the file the coordinator asks its own
1627
- * cluster database: a credential the database holds as valid, or a database it
1628
- * cannot read, keeps the file.
1446
+ * A coordinator also wires `corroborateRejection`. Any dialled endpoint can send a
1447
+ * rejection, so before deleting the file it asks its own cluster database: a
1448
+ * credential the database holds as valid, or an unreadable database, keeps the file.
1629
1449
  */
1630
1450
  const logger = createLogger({ prefix: "peer-auth-coordinator" });
1631
1451
  /** How long a waiting peer-client awaits an in-flight sibling token-join. */
@@ -1861,10 +1681,7 @@ var JoinTokenManager = class {
1861
1681
  constructor(deps) {
1862
1682
  this.deps = deps;
1863
1683
  }
1864
- /**
1865
- * Create a new join token.
1866
- * Returns the full token string (only available at creation time).
1867
- */
1684
+ /** Returns the full token string, available only at creation time. */
1868
1685
  async createToken(opts) {
1869
1686
  const expiryMs = opts.expiryMs ?? DEFAULT_EXPIRY_MS;
1870
1687
  const expiry = Date.now() + Math.floor(expiryMs);
@@ -1897,12 +1714,11 @@ var JoinTokenManager = class {
1897
1714
  * Peer token mode: claim the row the presented token's secret hashes to. Role and
1898
1715
  * routing come from the row (`claimByHash`), never from the token's routing part.
1899
1716
  *
1900
- * Self-healing reuse: a join token is re-consumable by the same joining peer
1901
- * (`peerInstanceId`) until its `expires_at`. A peer that lost its credential
1902
- * re-presents the still-valid join token already in its env, and the coordinator
1903
- * issues a fresh credential without an operator action. Reuse is bounded by both
1904
- * `expires_at` and the consuming instanceId, so it never widens a leaked token's
1905
- * usefulness beyond the instance that first consumed it.
1717
+ * Self-healing reuse: the same joining peer (`peerInstanceId`) can re-consume
1718
+ * the token until `expires_at`, so a peer that lost its credential re-presents
1719
+ * the token in its env and gets a fresh credential without an operator action.
1720
+ * Bounding reuse by `expires_at` and the consuming instanceId keeps a leaked
1721
+ * token useless beyond the instance that first consumed it.
1906
1722
  */
1907
1723
  async validateAndConsumeToken(token, consumedBy, peerInstanceId) {
1908
1724
  return this.claimByHash(tokenHashOf(parseToken(token).secretHex), consumedBy, peerInstanceId);
@@ -1983,10 +1799,8 @@ var JoinTokenManager = class {
1983
1799
  }
1984
1800
  };
1985
1801
  /**
1986
- * Build a JoinTokenManager backed by its own connection pool to the given
1987
- * orchestrator database URL. Mirrors `createPeerCredentialStoreFromUrl`;
1988
- * used by tests that need to exercise token validation/reuse against a real
1989
- * cluster DB.
1802
+ * A JoinTokenManager with its own connection pool, for tests against a real
1803
+ * cluster DB. Mirrors `createPeerCredentialStoreFromUrl`.
1990
1804
  */
1991
1805
  function createJoinTokenManagerFromUrl(databaseUrl, opts) {
1992
1806
  const pool = new pg.Pool({
@@ -2001,9 +1815,6 @@ function createJoinTokenManagerFromUrl(databaseUrl, opts) {
2001
1815
  }
2002
1816
  };
2003
1817
  }
2004
- /**
2005
- * Parse a join token string into routing info and secret hex.
2006
- */
2007
1818
  function parseToken(token) {
2008
1819
  const parts = token.split(".");
2009
1820
  if (parts.length !== 3 || parts[0] !== TOKEN_PREFIX) throw new Error(`Invalid join token format. Expected: ${TOKEN_PREFIX}.<routing>.<secret>`);
@@ -2530,32 +2341,18 @@ function createTrustPolicyStoreFromUrl(databaseUrl, opts) {
2530
2341
  }
2531
2342
  //#endregion
2532
2343
  //#region src/cli/api-client.ts
2344
+ /** kici-admin's HTTP client for the orchestrator admin API (Bearer token auth). */
2533
2345
  /**
2534
- * HTTP client wrapper for the kici-admin CLI.
2535
- *
2536
- * Communicates with the orchestrator admin API via Bearer token authentication.
2537
- * All methods are thin wrappers around fetch() that handle JSON serialization,
2538
- * error formatting, and URL construction.
2346
+ * A bare `TypeError: fetch failed` names neither the address nor the knob that
2347
+ * sets it, so it reads as a broken subcommand rather than a misaddressed client.
2348
+ * The base URL comes from `KICI_ADMIN_URL`, not `KICI_ORCHESTRATOR_URL`, and
2349
+ * subcommands with `--database-url` fall back to direct DB access, so with
2350
+ * `KICI_DATABASE_URL` set only the HTTP-only ones fail. The error therefore names
2351
+ * the address, the variable and the near-miss.
2539
2352
  */
2540
2353
  /**
2541
- * `fetch` rejects with a bare `TypeError: fetch failed` when it cannot reach the
2542
- * host — it names neither the address dialled nor the knob that sets it. Printed
2543
- * through the CLI's `Error: ${message}` handler that becomes `Error: fetch
2544
- * failed`, which reads like a fault in the subcommand rather than a misaddressed
2545
- * client, and sends the operator debugging the wrong thing.
2546
- *
2547
- * The trap is sharpened by two details of this CLI. The base URL comes from
2548
- * `KICI_ADMIN_URL`, not the `KICI_ORCHESTRATOR_URL` an operator is likelier to
2549
- * have exported; and subcommands accepting `--database-url` fall back to direct
2550
- * DB access, so on a host with `KICI_DATABASE_URL` set they keep working while
2551
- * the HTTP-only ones fail — making it look like specific subcommands are broken.
2552
- *
2553
- * So: name the address, name the variable, and name the near-miss.
2554
- */
2555
- /**
2556
- * Best-effort one-line detail from a rejected `fetch`. Returns '' when nothing
2557
- * useful is available, so the caller can omit the parenthetical rather than
2558
- * print an empty one.
2354
+ * Best-effort one-line detail from a rejected `fetch`; '' when none, so the
2355
+ * caller omits the parenthetical.
2559
2356
  */
2560
2357
  function firstCauseMessage(err) {
2561
2358
  if (!(err instanceof Error)) return "";
@@ -2569,21 +2366,16 @@ function firstCauseMessage(err) {
2569
2366
  return "";
2570
2367
  }
2571
2368
  /**
2572
- * True when a rejected `fetch` failed at the transport layer, as opposed to
2573
- * failing while the request was still being built.
2574
- *
2575
- * `fetch` uses a `TypeError` for both, so they are easy to conflate — but only
2576
- * a transport failure means the orchestrator was actually dialled. Measured
2577
- * against Node 24's undici:
2369
+ * True when a rejected `fetch` failed at the transport layer, not while the
2370
+ * request was being built. Both are a `TypeError`, but only a transport failure
2371
+ * means the orchestrator was dialled. Measured against Node 24's undici:
2578
2372
  *
2579
2373
  * closed port → TypeError('fetch failed') cause: Error(ECONNREFUSED)
2580
2374
  * invalid header → TypeError('Headers.append: … invalid header …') cause: undefined
2581
2375
  * invalid URL → TypeError('Failed to parse URL from …') cause: Error(ERR_INVALID_URL)
2582
2376
  *
2583
- * The discriminator is therefore the message, NOT the presence of a `cause`:
2584
- * the invalid-URL case carries one. undici uses exactly `fetch failed` for a
2585
- * transport failure and a descriptive message for everything it rejects before
2586
- * opening a connection.
2377
+ * So the discriminator is the message, NOT a `cause` (the invalid-URL case has
2378
+ * one): undici says exactly `fetch failed` only for a transport failure.
2587
2379
  */
2588
2380
  function isTransportFailure(err) {
2589
2381
  return err instanceof TypeError && err.message === "fetch failed";
@@ -2621,9 +2413,6 @@ var AdminApiClient = class {
2621
2413
  this.baseUrl = baseUrl;
2622
2414
  this.token = token;
2623
2415
  }
2624
- /**
2625
- * Make an authenticated HTTP request to the admin API.
2626
- */
2627
2416
  async request(method, path, body) {
2628
2417
  const res = await fetchAdminApi(`${this.baseUrl}${path}`, {
2629
2418
  method,
@@ -2646,39 +2435,21 @@ var AdminApiClient = class {
2646
2435
  if (res.status === 204) return;
2647
2436
  return await res.json();
2648
2437
  }
2649
- /**
2650
- * Public GET request returning parsed JSON.
2651
- */
2652
2438
  async get(path) {
2653
2439
  return this.request("GET", path);
2654
2440
  }
2655
- /**
2656
- * Public POST request returning parsed JSON.
2657
- */
2658
2441
  async post(path, body) {
2659
2442
  return this.request("POST", path, body);
2660
2443
  }
2661
- /**
2662
- * Public PATCH request returning parsed JSON.
2663
- */
2664
2444
  async patch(path, body) {
2665
2445
  return this.request("PATCH", path, body);
2666
2446
  }
2667
- /**
2668
- * Public PUT request returning parsed JSON.
2669
- */
2670
2447
  async put(path, body) {
2671
2448
  return this.request("PUT", path, body);
2672
2449
  }
2673
- /**
2674
- * Public DELETE request returning parsed JSON.
2675
- */
2676
2450
  async delete(path) {
2677
2451
  return this.request("DELETE", path);
2678
2452
  }
2679
- /**
2680
- * Public GET request returning raw response text.
2681
- */
2682
2453
  async getText(path) {
2683
2454
  const res = await fetchAdminApi(`${this.baseUrl}${path}`, {
2684
2455
  method: "GET",
@@ -2842,13 +2613,9 @@ var AdminApiClient = class {
2842
2613
  return this.request("GET", `/api/v1/agent-tokens${qs}`);
2843
2614
  }
2844
2615
  /**
2845
- * Revoke an agent token.
2846
- *
2847
- * The orchestrator both flips `agent_tokens.revoked_at` AND
2848
- * synchronously closes every in-flight agent WS authenticated by
2849
- * this token. The returned `kicked` count is the number
2850
- * of WS connections that were closed on the wire — surface it to
2851
- * the operator so they know the revocation actually propagated.
2616
+ * Revoke an agent token: the orchestrator sets `agent_tokens.revoked_at` AND
2617
+ * synchronously closes every agent WS authenticated by it. `kicked` counts
2618
+ * the closed connections; show it so the operator sees the revocation propagated.
2852
2619
  */
2853
2620
  async revokeAgentToken(id) {
2854
2621
  return this.request("DELETE", `/api/v1/agent-tokens/${encodeURIComponent(id)}`);
@@ -2906,7 +2673,6 @@ var AdminApiClient = class {
2906
2673
  async drainStatus() {
2907
2674
  return this.request("GET", "/api/v1/admin/orchestrator/drain");
2908
2675
  }
2909
- /** Forget a departed peer on this coordinator and every connected sibling. */
2910
2676
  /**
2911
2677
  * Forget a departed peer on this coordinator and every connected sibling. A
2912
2678
  * refusal that only needs the backstop acknowledgement comes back as a body
@@ -2978,9 +2744,17 @@ var AdminApiClient = class {
2978
2744
  async stopScalerOrphans(body) {
2979
2745
  return this.request("POST", "/api/v1/admin/scaler/orphans/stop", body);
2980
2746
  }
2747
+ /**
2748
+ * @deprecated No KiCI server serves `/api/v1/api-keys`; use `createToken`
2749
+ * (`kici-admin token create`). Removed in v1.0.0.
2750
+ */
2981
2751
  async createApiKey(opts) {
2982
2752
  return this.request("POST", "/api/v1/api-keys", opts);
2983
2753
  }
2754
+ /**
2755
+ * @deprecated No KiCI server serves `/api/v1/api-keys`; use `createToken`
2756
+ * with `routingKey` (`kici-admin token create --routing-key`). Removed in v1.0.0.
2757
+ */
2984
2758
  async addRoutingKeyPermission(keyId, pattern) {
2985
2759
  return this.request("POST", `/api/v1/api-keys/${encodeURIComponent(keyId)}/routing-permissions`, { pattern });
2986
2760
  }
@@ -3009,10 +2783,9 @@ var AdminApiClient = class {
3009
2783
  return this.request("POST", "/api/v1/admin/backends/sync");
3010
2784
  }
3011
2785
  /**
3012
- * List execution runs. `status` accepts either a single status or a
3013
- * comma-separated list (e.g. `success,failed`). `since` is an ISO-8601
3014
- * timestamp; only runs with `created_at` strictly later than this value
3015
- * are returned.
2786
+ * List runs. `status` takes one status or a comma-separated list (e.g.
2787
+ * `success,failed`). `since` is an ISO-8601 timestamp; only runs with
2788
+ * `created_at` strictly later are returned.
3016
2789
  */
3017
2790
  async listRuns(opts) {
3018
2791
  const qs = toQuery({
@@ -3418,14 +3191,10 @@ function startManifestLoopback(opts) {
3418
3191
  //#endregion
3419
3192
  //#region src/cli/open-browser.ts
3420
3193
  /**
3421
- * Open a URL in the operator's default browser, best-effort. Used by the GitHub
3422
- * App manifest setup flow to launch the create / install pages. Failure is
3423
- * non-fatal — the caller always prints the URL too, so a headless host (or a
3424
- * blocked launcher) just falls back to copy-paste.
3425
- *
3426
- * `KICI_BROWSER_CMD` overrides the launcher: `none` suppresses it entirely
3427
- * (automated tests / headless capture), any other value is run with `{url}` substituted —
3428
- * mirroring the `kici login` convention.
3194
+ * Best-effort: the caller always prints the URL too, so a headless host falls
3195
+ * back to copy-paste. `KICI_BROWSER_CMD` overrides the launcher as in
3196
+ * `kici login`: `none` suppresses it (tests, headless capture), any other
3197
+ * value runs with `{url}` substituted.
3429
3198
  */
3430
3199
  function openBrowserBestEffort(url) {
3431
3200
  const override = process.env.KICI_BROWSER_CMD;
@@ -3459,15 +3228,13 @@ const WebhookUrlNote = z.enum([
3459
3228
  //#endregion
3460
3229
  //#region src/cli/webhook-url-notes.ts
3461
3230
  /**
3462
- * The text the CLI prints when the orchestrator returns no webhook URL. Shared
3463
- * by `kici-admin source add` and the manifest setup flow, so each
3464
- * `WebhookUrlNote` reads the same in both.
3231
+ * Text for a missing webhook URL, shared by `kici-admin source add` and the
3232
+ * manifest setup flow.
3465
3233
  */
3466
3234
  const DASHBOARD_HINT = "Find the webhook URL in the dashboard under Sources.";
3467
3235
  /**
3468
- * Short reason shown in `(unavailable — <reason>)` when no webhook URL could be
3469
- * resolved. Takes a plain string too, because an orchestrator of another
3470
- * version can send a note this CLI does not know.
3236
+ * The reason in `(unavailable — <reason>)`. Takes a plain string: another
3237
+ * orchestrator version can send a note this CLI does not know.
3471
3238
  */
3472
3239
  function webhookNoteReason(note) {
3473
3240
  switch (note) {
@@ -3499,16 +3266,14 @@ function webhookNoteHint(note) {
3499
3266
  //#endregion
3500
3267
  //#region src/cli/commands/source-manifest.ts
3501
3268
  /**
3502
- * `kici-admin source add github --manifest` — the one-click GitHub App setup
3503
- * flow. Drives GitHub's App Manifest flow end-to-end: builds a pre-configured
3504
- * manifest (KiCI's exact permissions/events/webhook URL), hands it to GitHub via
3505
- * an auto-submitting form, catches the returned short-lived setup code over a
3506
- * localhost loopback (or copy-paste in --no-browser mode), exchanges it for the
3507
- * App's id + private key + webhook secret, then reuses the existing source
3508
- * storage + Platform-registration path.
3269
+ * `kici-admin source add github --manifest`: GitHub's App Manifest flow end to
3270
+ * end. The pre-configured manifest goes to GitHub through an auto-submitting
3271
+ * form; the short-lived setup code comes back over a localhost loopback (or is
3272
+ * pasted with --no-browser) and is exchanged for the App's id, private key and
3273
+ * webhook secret, which take the normal source storage and registration path.
3509
3274
  *
3510
- * The private-key-bearing conversion happens entirely here on the orchestrator
3511
- * host — it never transits the Platform (sovereignty invariant).
3275
+ * The private-key-bearing conversion runs only on the orchestrator host and
3276
+ * never transits the Platform (sovereignty invariant).
3512
3277
  */
3513
3278
  /** Static marketing-site page the CLI points at in headless paste-code mode. */
3514
3279
  const STATIC_CALLBACK_URL = "https://kici.dev/gh-manifest-callback";