@kici-dev/orchestrator 0.17.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 (589) 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 +35 -52
  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 +25 -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 +5 -12
  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 +4568 -6571
  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 +240 -482
  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 +20 -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 +16 -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 +17 -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 +5 -12
  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/uploads.d.ts +5 -11
  473. package/dist/routes/webhooks.d.ts +2 -24
  474. package/dist/scaler/agent-binary-location.d.ts +77 -0
  475. package/dist/scaler/agent-fit.d.ts +2 -2
  476. package/dist/scaler/backend-factory.d.ts +10 -18
  477. package/dist/scaler/bare-metal-backend.d.ts +28 -45
  478. package/dist/scaler/claim-store.d.ts +20 -43
  479. package/dist/scaler/config.d.ts +10 -37
  480. package/dist/scaler/container-backend.d.ts +22 -35
  481. package/dist/scaler/container-hostconfig.d.ts +10 -16
  482. package/dist/scaler/container-routing.d.ts +10 -13
  483. package/dist/scaler/disk-guard.d.ts +2 -3
  484. package/dist/scaler/event-backend.d.ts +33 -58
  485. package/dist/scaler/event-provision-reaper.d.ts +61 -84
  486. package/dist/scaler/failure-tracker.d.ts +6 -13
  487. package/dist/scaler/file-tail.d.ts +6 -19
  488. package/dist/scaler/firecracker-api.d.ts +19 -63
  489. package/dist/scaler/firecracker-backend.d.ts +142 -258
  490. package/dist/scaler/host-access.d.ts +7 -10
  491. package/dist/scaler/index.d.ts +3 -6
  492. package/dist/scaler/ip-allocator.d.ts +30 -82
  493. package/dist/scaler/label-matcher.d.ts +14 -35
  494. package/dist/scaler/log-forwarder.d.ts +6 -25
  495. package/dist/scaler/machine-ledger.d.ts +39 -86
  496. package/dist/scaler/manager.d.ts +517 -787
  497. package/dist/scaler/pending-scale-sweeper.d.ts +8 -11
  498. package/dist/scaler/reap-orphans.d.ts +8 -12
  499. package/dist/scaler/resolve-container-auth.d.ts +12 -21
  500. package/dist/scaler/scaler-events.d.ts +2 -5
  501. package/dist/scaler/scaler-state-store.d.ts +127 -189
  502. package/dist/scaler/spawn-errors.d.ts +1 -4
  503. package/dist/scaler/startup-orphan-sweep.d.ts +3 -4
  504. package/dist/scaler/startup-tools-check.d.ts +21 -0
  505. package/dist/scaler/types.d.ts +142 -255
  506. package/dist/scaler/vm-job-bindings.d.ts +5 -9
  507. package/dist/scaler/warm-pool.d.ts +46 -93
  508. package/dist/secrets/audit-logger.d.ts +0 -3
  509. package/dist/secrets/backend-health.d.ts +0 -9
  510. package/dist/secrets/backend-registry.d.ts +0 -9
  511. package/dist/secrets/cleanup.d.ts +0 -1
  512. package/dist/secrets/config.d.ts +0 -3
  513. package/dist/secrets/ephemeral-keys.d.ts +0 -3
  514. package/dist/secrets/pg-secret-store.d.ts +0 -3
  515. package/dist/secrets/rbac.d.ts +0 -6
  516. package/dist/secrets/secret-output-store.d.ts +0 -6
  517. package/dist/secrets/secret-resolver.d.ts +2 -6
  518. package/dist/secrets/token-manager.d.ts +0 -4
  519. package/dist/secrets/vault-secret-store.d.ts +0 -13
  520. package/dist/security/comment-handler.d.ts +0 -2
  521. package/dist/security/workflow-diff.d.ts +1 -1
  522. package/dist/server.js +7500 -12629
  523. package/dist/sources/source-manager.d.ts +0 -3
  524. package/dist/sources/source-store.d.ts +0 -9
  525. package/dist/sources/source-validator.d.ts +0 -3
  526. package/dist/stale-detector/all-terminal-runs.d.ts +8 -11
  527. package/dist/stale-detector/gate-deadline-detector.d.ts +14 -19
  528. package/dist/stale-detector/reboot-deadline-sweep.d.ts +7 -11
  529. package/dist/stale-detector/stale-dispatch-candidates.d.ts +13 -20
  530. package/dist/stale-detector/stale-run-detector.d.ts +74 -121
  531. package/dist/stale-detector/workflow-deadline-detector.d.ts +15 -43
  532. package/dist/standalone.js +7141 -11957
  533. package/dist/storage/blob-routes.d.ts +10 -19
  534. package/dist/storage/filesystem.d.ts +19 -29
  535. package/dist/storage/index.d.ts +2 -10
  536. package/dist/storage/key-discriminator.d.ts +8 -10
  537. package/dist/storage/loopback-guard.d.ts +27 -45
  538. package/dist/storage/s3.d.ts +25 -52
  539. package/dist/storage/sign-url.d.ts +7 -22
  540. package/dist/storage/types.d.ts +44 -70
  541. package/dist/webhook/event-log.d.ts +0 -2
  542. package/dist/webhook/generic-sources.d.ts +0 -21
  543. package/dist/webhook/ingest-admission.d.ts +0 -1
  544. package/dist/webhook/relay-buffer.d.ts +2 -2
  545. package/dist/webhook/verify-inbound.d.ts +0 -1
  546. package/dist/worker/in-memory-execution-tracker.d.ts +9 -31
  547. package/dist/worker/in-memory-job-queue.d.ts +32 -72
  548. package/dist/worker/peer-outbox.d.ts +5 -8
  549. package/dist/worker/reroute-dispatch.d.ts +4 -6
  550. package/dist/worker/static-agent-token-store.d.ts +6 -27
  551. package/dist/worker/worker-outbox-relay.d.ts +2 -2
  552. package/dist/worker/worker-status.d.ts +3 -20
  553. package/dist/ws/agent-api-registry.d.ts +8 -27
  554. package/dist/ws/agent-handler.d.ts +63 -110
  555. package/dist/ws/agent-heartbeat.d.ts +5 -12
  556. package/dist/ws/bringup-api.d.ts +31 -38
  557. package/dist/ws/dashboard-backends-handler.d.ts +12 -22
  558. package/dist/ws/dashboard-context-handler.d.ts +37 -80
  559. package/dist/ws/dashboard-diagnostics-handler.d.ts +8 -25
  560. package/dist/ws/dashboard-dispatch-guard.d.ts +3 -4
  561. package/dist/ws/dashboard-fleet-handler.d.ts +9 -13
  562. package/dist/ws/dashboard-fleet-write-handler.d.ts +7 -21
  563. package/dist/ws/dashboard-global-workflows-handler.d.ts +22 -44
  564. package/dist/ws/dashboard-registrations-handler.d.ts +10 -27
  565. package/dist/ws/dashboard-run-state-handler.d.ts +10 -13
  566. package/dist/ws/event-buffer.d.ts +3 -6
  567. package/dist/ws/execution-status-frame.d.ts +7 -10
  568. package/dist/ws/failure-messages.d.ts +9 -14
  569. package/dist/ws/fleet-agent-collector.d.ts +6 -12
  570. package/dist/ws/fleet-runs-on-all.d.ts +1 -6
  571. package/dist/ws/git-credential-relay.d.ts +12 -20
  572. package/dist/ws/inventory-api.d.ts +4 -5
  573. package/dist/ws/observer-registry.d.ts +14 -59
  574. package/dist/ws/ownership-gate.d.ts +1 -1
  575. package/dist/ws/platform-client.d.ts +21 -30
  576. package/dist/ws/replay-chunker.d.ts +7 -10
  577. package/dist/ws/server-options.d.ts +5 -9
  578. package/dist/ws/test-relay-handlers.d.ts +36 -60
  579. package/installer-image-digests.json +3 -3
  580. package/package.json +6 -5
  581. package/sbom.spdx.json +53 -53
  582. package/dist/__test-helpers__/fake-scaler-state-store.d.ts +0 -24
  583. package/dist/__test-helpers__/mock-db-query.d.ts +0 -129
  584. package/dist/__test-helpers__/mock-db.d.ts +0 -134
  585. package/dist/__test-helpers__/mock-ws.d.ts +0 -13
  586. package/dist/__test-helpers__/peer-mutual-auth.d.ts +0 -42
  587. package/dist/__test-helpers__/scratch-db.d.ts +0 -16
  588. package/dist/__test-helpers__/test-db.d.ts +0 -34
  589. package/dist/pipeline/dispatch-matched-workflow.test-helpers.d.ts +0 -121
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
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;
@@ -68,7 +61,6 @@ var S3CacheStorage = class {
68
61
  endpoint: options.uploadEndpoint
69
62
  }) : this.presignClient;
70
63
  }
71
- /** Build the full S3 object key from a cache key. */
72
64
  objectKey(key) {
73
65
  return `${this.prefix}${key}`;
74
66
  }
@@ -78,17 +70,11 @@ var S3CacheStorage = class {
78
70
  const lastAccessed = new Date(meta.lastAccessedAt).getTime();
79
71
  return Date.now() - lastAccessed > ttl;
80
72
  }
81
- /**
82
- * Read metadata from an S3 object's custom headers.
83
- * Returns null if the object doesn't exist (NoSuchKey/NotFound).
84
- */
73
+ /** Null when the object does not exist (NoSuchKey/NotFound). */
85
74
  async readMeta(key) {
86
75
  return (await this.readHead(key))?.meta ?? null;
87
76
  }
88
- /**
89
- * Read an object's TTL metadata together with the ETag of the version it
90
- * belongs to. Returns null if the object doesn't exist (NoSuchKey/NotFound).
91
- */
77
+ /** TTL metadata plus the ETag of its version; null when the object does not exist. */
92
78
  async readHead(key) {
93
79
  try {
94
80
  const head = await this.client.send(new HeadObjectCommand({
@@ -111,25 +97,16 @@ var S3CacheStorage = class {
111
97
  }
112
98
  }
113
99
  /**
114
- * Update metadata on an S3 object by copying it to itself.
115
- * This is the standard S3 pattern for updating metadata without re-uploading data.
116
- *
117
- * The copy is conditional on `etag`, the version whose metadata the caller
118
- * read. A self-copy is a whole-object write: without the condition, one that
119
- * races a `put()` of the same key can land after it and write the older body
120
- * back. Cache pointers are rewritten in place while builds publish them, so a
121
- * touch-on-read racing a publish reverted the pointer to a tarball that no
122
- * longer exists. `CopySourceIfMatch` pins the bytes copied to that version and
123
- * `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.
124
104
  *
125
- * Returns false when the object was replaced since the read (`412`), or is
126
- * being replaced right now (`409 ConditionalRequestConflict`): the newer
127
- * 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.
128
107
  *
129
- * An S3-compatible backend that does not implement conditional copies
130
- * answers `501 NotImplemented`. The copy then runs again without the
131
- * condition, and later copies skip it, as on a backend that ignores the
132
- * headers.
108
+ * A backend without conditional copies answers `501 NotImplemented`; the copy reruns
109
+ * unconditionally, and later copies skip the condition.
133
110
  */
134
111
  async updateMeta(key, meta, etag) {
135
112
  const condition = this.conditionalCopySupported ? etag : void 0;
@@ -164,15 +141,15 @@ var S3CacheStorage = class {
164
141
  }
165
142
  }));
166
143
  }
167
- /** Check if an error is a failed conditional request (PreconditionFailed, 412). */
144
+ /** A failed conditional request (PreconditionFailed, 412). */
168
145
  isPreconditionFailedError(err) {
169
146
  return this.hasErrorShape(err, "PreconditionFailed", 412);
170
147
  }
171
- /** Check if an error is a conditional write that raced another write (ConditionalRequestConflict, 409). */
148
+ /** A conditional write that raced another write (ConditionalRequestConflict, 409). */
172
149
  isConditionalConflictError(err) {
173
150
  return this.hasErrorShape(err, "ConditionalRequestConflict", 409);
174
151
  }
175
- /** Check if an error is a request the backend does not implement (NotImplemented, 501). */
152
+ /** A request the backend does not implement (NotImplemented, 501). */
176
153
  isNotImplementedError(err) {
177
154
  return this.hasErrorShape(err, "NotImplemented", 501);
178
155
  }
@@ -181,7 +158,7 @@ var S3CacheStorage = class {
181
158
  if (err.name === name) return true;
182
159
  return err.$metadata?.httpStatusCode === status;
183
160
  }
184
- /** Check if an error is a "not found" error (NoSuchKey, NotFound, 404). */
161
+ /** NoSuchKey, NotFound or 404. */
185
162
  isNotFoundError(err) {
186
163
  if (typeof err !== "object" || err === null) return false;
187
164
  const name = err.name;
@@ -359,30 +336,21 @@ var S3CacheStorage = class {
359
336
  //#endregion
360
337
  //#region src/storage/sign-url.ts
361
338
  /**
362
- * HMAC-signed URL tokens for the filesystem cache backend.
363
- *
364
- * Pre-signed S3 URLs are not available for filesystem storage, so the
365
- * filesystem backend mints HMAC-SHA256 tokens that the orchestrator's HTTP
366
- * 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:
367
341
  *
368
342
  * `${expiresUnixMs}.${hexSig}`
369
343
  *
370
- * Signature input: `${method}:${key}:${expiresUnixMs}` with HMAC-SHA256 keyed
371
- * by a per-orchestrator-process secret (random 32-byte hex at boot, persists
372
- * for the lifetime of the process). Tokens become invalid on orchestrator
373
- * restart — fine for the filesystem backend's single-host / test-sandbox use
374
- * 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.
375
346
  */
376
- /** Default URL lifetime: 1 hour (matches S3 backend's PUT-URL lifetime). */
347
+ /** Default URL lifetime: 1 hour. */
377
348
  const DEFAULT_SIGN_URL_TTL_MS = 36e5;
378
349
  function computeSig(secret, method, key, expiresMs) {
379
350
  const hmac = createHmac("sha256", secret);
380
351
  hmac.update(`${method}:${key}:${expiresMs}`);
381
352
  return hmac.digest("hex");
382
353
  }
383
- /**
384
- * Mint a signed token for the given (method, key, expiry) triple.
385
- */
386
354
  function signToken(secret, method, key, ttlMs = DEFAULT_SIGN_URL_TTL_MS) {
387
355
  const expiresMs = Date.now() + ttlMs;
388
356
  return {
@@ -393,19 +361,15 @@ function signToken(secret, method, key, ttlMs = DEFAULT_SIGN_URL_TTL_MS) {
393
361
  //#endregion
394
362
  //#region src/storage/filesystem.ts
395
363
  /**
396
- * Filesystem-backed cache storage.
397
- *
398
- * Mirrors the `CacheStorage` interface that `S3CacheStorage` provides, but
399
- * stores blobs as files under a configured base directory. Pre-signed URLs
400
- * are replaced by HMAC-signed `http://<orchUrl>/api/v1/cache/blob/...` URLs
401
- * — 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.
402
366
  *
403
- * Intended for single-host deployments and test sandboxes where standing up
404
- * 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`).
405
369
  *
406
- * Metadata is co-located as a sibling JSON file (`<key>.meta.json`) so the
407
- * data file is byte-identical to what the agent receives over HTTP. TTL is
408
- * 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.
409
373
  */
410
374
  const DEFAULT_ROUTE_PREFIX = "/api/v1/cache/blob/";
411
375
  var FilesystemCacheStorage = class {
@@ -422,9 +386,9 @@ var FilesystemCacheStorage = class {
422
386
  this.routePrefix = (options.routePrefix ?? DEFAULT_ROUTE_PREFIX).replace(/\/?$/, "/");
423
387
  }
424
388
  /**
425
- * Map a cache key to its on-disk path. Keys may contain `/`, which becomes a
426
- * directory separator. Reject keys containing `..` segments or NUL bytes to
427
- * 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.
428
392
  */
429
393
  resolvePath(key) {
430
394
  if (key.includes("\0") || key.split("/").some((seg) => seg === ".." || seg === "")) throw new Error(`Invalid cache key: ${JSON.stringify(key)}`);
@@ -534,19 +498,14 @@ var FilesystemCacheStorage = class {
534
498
  });
535
499
  }
536
500
  /**
537
- * List cache keys under a prefix.
538
- *
539
- * The prefix is a **key prefix**, not necessarily a directory — `UserCache`'s
540
- * `restoreKeys` fallback lists on `${prefix}${seg(restoreKey)}`, a partial
541
- * 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:
542
504
  *
543
505
  * - trailing `/` — a directory. Walk it directly; this is the hot path.
544
- * - no trailing `/` — a partial name. Walk the parent directory and filter by
545
- * the prefix, since the prefix itself may name a file (or nothing at all).
546
- *
547
- * Reading the prefix as a directory in the second case is what made the
548
- * `restoreKeys` fallback silently never hit here (`ENOENT` → `[]`) or throw
549
- * (`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`).
550
509
  */
551
510
  async list(subPrefix) {
552
511
  const isDirPrefix = subPrefix.endsWith("/");
@@ -587,10 +546,9 @@ var FilesystemCacheStorage = class {
587
546
  });
588
547
  }
589
548
  /**
590
- * Recursively collect data files under `dir`, returning each as a cache key
591
- * relative to `basePath` paired with its mtime. Metadata sidecars
592
- * (`*.meta.json`) and the atomic-write temp files (`*.tmp-*`) are skipped so
593
- * `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.
594
552
  */
595
553
  async walkDataFiles(dir, keyPrefix) {
596
554
  const out = [];
@@ -627,9 +585,8 @@ function isNotFoundFsError(err) {
627
585
  return code === "ENOENT" || code === "ENOTDIR";
628
586
  }
629
587
  /**
630
- * Write a file atomically: write to a temp sibling, fsync, rename. Avoids
631
- * partial reads if the orchestrator crashes mid-write. The temp suffix is
632
- * 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.
633
590
  */
634
591
  async function writeFileAtomic(path, data) {
635
592
  const tmp = `${path}.tmp-${randomBytes(6).toString("hex")}`;
@@ -644,9 +601,6 @@ async function writeFileAtomic(path, data) {
644
601
  }
645
602
  //#endregion
646
603
  //#region src/storage/index.ts
647
- /**
648
- * Create a cache storage backend from configuration.
649
- */
650
604
  function createCacheStorage(config) {
651
605
  if (config.type === "s3") return new S3CacheStorage({
652
606
  bucket: config.bucket,
@@ -669,61 +623,44 @@ function createCacheStorage(config) {
669
623
  //#endregion
670
624
  //#region src/cache/source-cache.ts
671
625
  /**
672
- * Source-tarball cache layer wrapping CacheStorage.
673
- *
674
- * Stores customer-workflow source tarballs — the `.kici/` directory minus
675
- * `node_modules/`, packed by the agent's build job via `source-packer.ts` —
676
- * under the tarball's OWN content hash, with a small pointer resolving an org's
677
- * workflow `contentHash` to that hash. Tarballs are platform-independent: raw
678
- * TypeScript source is identical across architectures. Refreshes TTL on reads
679
- * (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.
680
631
  *
681
632
  * Keys: `source/v2/{orgId}/{sourceTarDigest}.tar.gz` (immutable) and
682
- * `source/v2/{orgId}/{contentHash}.hash` (the pointer) — the shape `dep-cache.ts`
683
- * already uses, for the same reasons — content addressing and org scoping.
684
- *
685
- * **Content addressing** makes a mismatched pair unrepresentable. At
686
- * `source/{contentHash}.tar.gz` the object's key was derived from something
687
- * other than its bytes, so nothing a reader fetched could be verified against
688
- * 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:
689
635
  *
690
- * **Org scoping** makes the key a tenant's key. `contentHash` alone is a
691
- * property of a `.kici/` tree, so two repositories scaffolded from the same
692
- * `kici init` template — or a fork and its upstream — produced one object, and
693
- * whichever built first won for the life of that object. On an orchestrator
694
- * serving more than one org that is a cross-tenant read of `.kici/` contents.
695
- * The org is the tenant boundary and the segment the user cache already scopes
696
- * by; inside one org, sharing a key now means the two trees are byte-identical,
697
- * 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.
698
644
  *
699
- * Legacy `source/{contentHash}.tar.gz` objects are **not read**. Only a
700
- * `compileSchemaVersion: 5` lock can name one, and that `contentHash` covers
701
- * the workflow entry file alone rather than the tree the tarball holds — the
702
- * defect this layout closes — so serving it would serve the bug. For a v6 lock
703
- * the fallback is unreachable anyway, since the schema bump moves every hash.
704
- * Old objects are orphaned. The cache TTL is enforced lazily on access, so
705
- * 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").
706
650
  */
707
651
  const logger$4 = createLogger({ prefix: "source-cache" });
708
652
  /**
709
- * Cache key for a source tarball, addressed by the tarball's OWN content hash:
710
- * `source/v2/{orgId}/{sourceTarDigest}.tar.gz`.
711
- *
712
- * Naming the object by its own hash means every pair a reader can observe is
713
- * self-consistent, and the bytes at a given key can never change after a URL is
714
- * 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.
715
655
  */
716
656
  function sourceTarballKey(orgId, sourceTarDigest) {
717
657
  return `source/v2/${orgId}/${sourceTarDigest}.tar.gz`;
718
658
  }
719
659
  /**
720
- * Cache key for the pointer that resolves a workflow `contentHash` to the
721
- * content hash of the tarball built from it: `source/v2/{orgId}/{contentHash}.hash`.
722
- *
723
- * This is the one mutable object in the scheme. A concurrent write replaces a
724
- * pointer wholesale — there is no half-written window — so the worst a racing
725
- * pair of builders can do is leave whichever pointer landed last, and both
726
- * 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.
727
664
  */
728
665
  function sourcePointerKey(orgId, contentHash) {
729
666
  return `source/v2/${orgId}/${contentHash}.hash`;
@@ -733,16 +670,13 @@ var SourceCache = class SourceCache {
733
670
  constructor(options) {
734
671
  this.storage = options.storage;
735
672
  }
736
- /** The single place the pointer indirection is read. */
673
+ /** Resolves the pointer indirection (`getUrlAndDigest` reads it inline to touch it). */
737
674
  async resolvePointer(orgId, contentHash) {
738
675
  return (await this.storage.get(sourcePointerKey(orgId, contentHash)))?.toString("utf-8").trim() || null;
739
676
  }
740
677
  /**
741
- * Whether a source tarball for this org's `contentHash` exists.
742
- *
743
- * Both halves must be present: a pointer whose tarball has aged out is a
744
- * miss, not a hit, or the caller skips a rebuild and dispatches a URL that
745
- * 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.
746
680
  */
747
681
  async has(orgId, contentHash) {
748
682
  const digest = await this.resolvePointer(orgId, contentHash);
@@ -769,13 +703,9 @@ var SourceCache = class SourceCache {
769
703
  return data;
770
704
  }
771
705
  /**
772
- * A pre-signed download URL and the tarball's own digest.
773
- *
774
- * The pointer is resolved FIRST: it names the content hash, which is also the
775
- * tarball's key, so the url and the digest returned here are read from a
776
- * single source of truth and cannot disagree. Returns null on a miss —
777
- * including a pointer with no tarball behind it, which is unverifiable and so
778
- * 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).
779
709
  */
780
710
  async getUrlAndDigest(orgId, contentHash) {
781
711
  const pointerKey = sourcePointerKey(orgId, contentHash);
@@ -802,19 +732,15 @@ var SourceCache = class SourceCache {
802
732
  return (await this.getUrlAndDigest(orgId, contentHash))?.url ?? null;
803
733
  }
804
734
  /**
805
- * A pre-signed upload URL for direct agent-to-storage upload.
806
- *
807
- * Takes the tarball's OWN digest, not the workflow `contentHash`: the agent
808
- * 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`.
809
737
  */
810
738
  async getUploadUrl(orgId, sourceTarDigest) {
811
739
  return this.storage.getUploadUrl(sourceTarballKey(orgId, sourceTarDigest));
812
740
  }
813
741
  /**
814
- * Publish the pointer that makes an uploaded tarball discoverable by
815
- * `contentHash`. Called only after the agent confirms its upload completed —
816
- * publishing before the bytes land would let a reader follow the pointer to a
817
- * 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.
818
744
  */
819
745
  async publishPointer(orgId, contentHash, sourceTarDigest) {
820
746
  await this.storage.put(sourcePointerKey(orgId, contentHash), sourceTarDigest);
@@ -835,7 +761,6 @@ var SourceCache = class SourceCache {
835
761
  static computeDigest(data) {
836
762
  return sha256(data);
837
763
  }
838
- /** Remove a source tarball and its pointer. */
839
764
  async remove(orgId, contentHash) {
840
765
  const digest = await this.resolvePointer(orgId, contentHash);
841
766
  await this.storage.delete(sourcePointerKey(orgId, contentHash));
@@ -847,12 +772,9 @@ var SourceCache = class SourceCache {
847
772
  //#endregion
848
773
  //#region src/cache/dep-cache.ts
849
774
  /**
850
- * Dependency-specific cache layer wrapping CacheStorage.
851
- *
852
- * Stores dependency tarballs under their own content hash, with a small pointer
853
- * resolving lockfileHash + platform + arch to that hash. Shared CacheStorage
854
- * backend with SourceCache (same S3 bucket). Refreshes TTL on reads
855
- * (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).
856
778
  *
857
779
  * Keys: `deps/{platform}-{arch}/{depsHash}.tar.gz` (immutable) and
858
780
  * `deps/{platform}-{arch}/{lockfileHash}.hash` (the pointer).
@@ -864,17 +786,14 @@ const DEFAULT_MAX_TARBALL_BYTES = 524288e3;
864
786
  const DEFAULT_CACHE_TTL_DAYS = 30;
865
787
  const MS_PER_DAY = 864e5;
866
788
  /**
867
- * Cache key for a dependency tarball, addressed by the tarball's OWN content
868
- * 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`.
869
791
  *
870
- * Content-addressing is what makes a mismatched pair unrepresentable. When the
871
- * tarball lived at a lockfile-derived name, it and its companion `.hash` were
872
- * two independently-written objects under keys that any two builds sharing a
873
- * lockfile + platform + arch also share — so concurrent builders could leave the
874
- * `.tar.gz` from one and the `.hash` from the other, and the reader failed
875
- * verification durably. Naming the object by its own hash means every pair a
876
- * reader can observe is self-consistent, and the bytes at a given key can never
877
- * 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.
878
797
  */
879
798
  function depTarballKey(depsHash, platform, arch) {
880
799
  return `deps/${platform}-${arch}/${depsHash}.tar.gz`;
@@ -884,17 +803,14 @@ function depTarballKey(depsHash, platform, arch) {
884
803
  * tarball built from it: `deps/{platform}-{arch}/{lockfileHash}.hash`, or
885
804
  * `…/{lockfileHash}-{siblingsDigest}.hash` when the lock carries one.
886
805
  *
887
- * `siblingsDigest` is part of the key because the deps tarball carries in-repo
888
- * `workspace:` sibling directories WITH their built output, and editing a
889
- * sibling's source moves no package-manager lock file — so a `lockfileHash`-only
890
- * key restored the sibling's stale build over the fresh clone on every run. A
891
- * lock with no in-repo sibling carries no digest and keys exactly as before, so
892
- * 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.
893
810
  *
894
- * This is the one mutable object in the scheme. A concurrent write replaces a
895
- * pointer wholesale — there is no window in which it is half-written — so the
896
- * worst a racing pair of builders can do is leave whichever pointer landed last,
897
- * 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.
898
814
  */
899
815
  function depPointerKey(lockfileHash, platform, arch, siblingsDigest) {
900
816
  return `deps/${platform}-${arch}/${siblingsDigest ? `${lockfileHash}-${siblingsDigest}` : lockfileHash}.hash`;
@@ -911,28 +827,21 @@ var DepCache = class DepCache {
911
827
  this.clusterSettings = options.clusterSettings;
912
828
  }
913
829
  /**
914
- * Resolve the live dependency-cache entry TTL as a per-operation override
915
- * (ms) from `cluster_settings.cache_ttl_days`, falling back to the cluster
916
- * default. `undefined` when no reader is wired, so the storage backend uses
917
- * its own configured TTL. Passed to read/expiry operations so an operator's
918
- * `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.
919
833
  */
920
834
  async resolveTtlMsOverride() {
921
835
  if (!this.clusterSettings) return void 0;
922
836
  return await this.clusterSettings.getNumber("cache_ttl_days", this.cacheTtlDaysFallback) * MS_PER_DAY;
923
837
  }
924
- /**
925
- * Resolve a lockfile to the content hash of the tarball built from it, or
926
- * null when no pointer exists. The single place the indirection is read.
927
- */
838
+ /** Lockfile → tarball content hash, or null when no pointer exists. */
928
839
  async resolvePointer(lockfileHash, platform, arch, ttlMsOverride, siblingsDigest) {
929
840
  return (await this.storage.get(depPointerKey(lockfileHash, platform, arch, siblingsDigest), ttlMsOverride))?.toString("utf-8").trim() || null;
930
841
  }
931
842
  /**
932
- * Check if a dep tarball exists in cache.
933
- *
934
- * Both halves must be present: a pointer whose tarball has aged out is a miss,
935
- * 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.
936
845
  */
937
846
  async has(lockfileHash, platform, arch, siblingsDigest) {
938
847
  const ttlMsOverride = await this.resolveTtlMsOverride();
@@ -951,18 +860,13 @@ var DepCache = class DepCache {
951
860
  });
952
861
  return exists;
953
862
  }
954
- /**
955
- * Get a pre-signed download URL for the dep tarball (for agent delivery).
956
- * Refreshes TTL on hit.
957
- */
863
+ /** Pre-signed download URL for agent delivery. Refreshes TTL on hit. */
958
864
  async getUrl(lockfileHash, platform, arch, siblingsDigest) {
959
865
  return (await this.getUrlAndHash(lockfileHash, platform, arch, siblingsDigest))?.url ?? null;
960
866
  }
961
867
  /**
962
- * Get a pre-signed download URL and the tarball content hash.
963
- *
964
- * Returns null on cache miss — including an entry with no pointer, which is
965
- * 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).
966
870
  */
967
871
  async getUrlAndHash(lockfileHash, platform, arch, siblingsDigest) {
968
872
  const ttlMsOverride = await this.resolveTtlMsOverride();
@@ -996,17 +900,13 @@ var DepCache = class DepCache {
996
900
  hash
997
901
  };
998
902
  }
999
- /**
1000
- * Get a pre-signed upload URL for direct agent-to-S3 upload.
1001
- */
903
+ /** Pre-signed URL for direct agent-to-S3 upload. */
1002
904
  async getUploadUrl(depsHash, platform, arch) {
1003
905
  return this.storage.getUploadUrl(depTarballKey(depsHash, platform, arch));
1004
906
  }
1005
907
  /**
1006
- * Publish the pointer that makes an uploaded tarball discoverable by lockfile.
1007
- *
1008
- * Called only after the agent confirms its upload completed. Publishing before
1009
- * 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.
1010
910
  */
1011
911
  async publishPointer(lockfileHash, platform, arch, depsHash, siblingsDigest) {
1012
912
  await this.storage.put(depPointerKey(lockfileHash, platform, arch, siblingsDigest), depsHash);
@@ -1015,10 +915,7 @@ var DepCache = class DepCache {
1015
915
  arch
1016
916
  });
1017
917
  }
1018
- /**
1019
- * Store a dep tarball in cache.
1020
- * Throws if tarball exceeds max size (per user decision).
1021
- */
918
+ /** Throws when the tarball exceeds the max size. */
1022
919
  async store(lockfileHash, platform, arch, tarballData) {
1023
920
  const maxTarballBytes = this.clusterSettings ? await this.clusterSettings.getNumber("cache_max_tarball_bytes", this.maxTarballBytes) : this.maxTarballBytes;
1024
921
  if (tarballData.length > maxTarballBytes) throw new Error(`Dep tarball exceeds max size: ${tarballData.length} bytes > ${maxTarballBytes} bytes limit`);
@@ -1033,8 +930,8 @@ var DepCache = class DepCache {
1033
930
  });
1034
931
  }
1035
932
  /**
1036
- * Compute SHA-256 hash of a tarball buffer.
1037
- * 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.
1038
935
  */
1039
936
  static computeHash(data) {
1040
937
  return sha256(data);
@@ -1054,10 +951,9 @@ var DepCache = class DepCache {
1054
951
  /**
1055
952
  * A collision-resistant discriminator for a user-supplied object-key segment.
1056
953
  *
1057
- * Hashes the **exact** name, before any sanitization. Sanitizing is many-to-one
1058
- * — `seg()` maps both `/` and `_` to `_`, so `a/b` and `a_b` collapse to one
1059
- * segment — and a case-insensitive backend folds `build` onto `Build`. Hashing
1060
- * 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.
1061
957
  */
1062
958
  function keyDiscriminator(exact) {
1063
959
  return createHash("sha256").update(exact, "utf8").digest("hex").slice(0, 32);
@@ -1068,47 +964,40 @@ function keyDiscriminator(exact) {
1068
964
  * User-facing cache layer wrapping CacheStorage.
1069
965
  *
1070
966
  * Namespacing: `cache/<orgId>/<repoId>/<refScope>/<key>-<discriminator>.tar.gz`.
1071
- * The discriminator is a hash of the exact cache key, so two keys differing
1072
- * only by case stay two objects even on a case-insensitive store. `refScope`
1073
- * is `shared` for trusted refs (org-shared, default-branch cache)
1074
- * or `iso/<runId>` for untrusted refs (per-run isolated scope). Restores from
1075
- * an untrusted ref read the shared scope as a fallback but writes can NEVER
1076
- * land in the shared scope — the GitHub Actions cache-isolation model. Keyed
1077
- * 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.
1078
973
  *
1079
- * Saves are immutable (first save under an exact key wins) and atomic
1080
- * (upload to a `.tmp-<uuid>` key, then server-side copy to the final key and
1081
- * 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.
1082
977
  *
1083
- * Eviction: per-org byte quota plus the TTL the backing CacheStorage already
1084
- * enforces lazily on access. On a save that pushes the org over quota,
1085
- * least-recently-used entries (oldest `lastAccessedAt`, read from the storage
1086
- * backend's metadata) are evicted until under quota; each eviction is logged.
1087
- * The companion `.hash` / `.size` sidecar objects carry the integrity
1088
- * hash and size accounting outside the tarball's own (presigned, metadata-less)
1089
- * 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.
1090
983
  */
1091
984
  const logger$2 = createLogger({ prefix: "user-cache" });
1092
985
  /**
1093
- * Cluster-wide default quota: 5 GiB. Serves as the fallback when an org has no
1094
- * per-org override in `org_settings.user_cache_quota_bytes`. The cluster-wide
1095
- * 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.
1096
989
  */
1097
990
  const DEFAULT_USER_CACHE_QUOTA_BYTES = 5368709120;
1098
991
  /**
1099
- * Cluster-wide default entry TTL: 7 days. Fallback when an org has no per-org
1100
- * override in `org_settings.user_cache_ttl_ms`. The cluster-wide value is
1101
- * 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.
1102
995
  */
1103
996
  const DEFAULT_USER_CACHE_TTL_MS = 6048e5;
1104
997
  /** Tarball suffix for committed cache entries. */
1105
998
  const TAR_SUFFIX = ".tar.gz";
1106
- /**
1107
- * Stem prefix of an in-flight upload, `.tmp-<uuid>.tar.gz`: the presigned PUT
1108
- * target a save lands on before commit copies it to its final key.
1109
- */
999
+ /** Stem of an in-flight upload, `.tmp-<uuid>.tar.gz`, before commit copies it to its final key. */
1110
1000
  const TEMP_UPLOAD_STEM = ".tmp-";
1111
- /** Whether a listed object is an in-flight upload rather than a cache entry. */
1112
1001
  function isTempUpload(key) {
1113
1002
  return key.slice(key.lastIndexOf("/") + 1).startsWith(TEMP_UPLOAD_STEM);
1114
1003
  }
@@ -1116,36 +1005,28 @@ function isTempUpload(key) {
1116
1005
  const KEY_DISCRIMINATOR_TAIL = new RegExp(`^(.*)-([0-9a-f]{32})$`);
1117
1006
  /**
1118
1007
  * Whether a listed object is a committed entry, `<stem>-<discriminator>.tar.gz`.
1119
- *
1120
- * This is the filter the `restoreKeys` prefix scan applies to a listing, and it
1121
- * is what keeps two other kinds of object out of a restore: an in-flight
1122
- * `.tmp-<uuid>.tar.gz` upload, which is a partial tarball until commit copies
1123
- * it to its final key, and an object under the retired un-discriminated layout,
1124
- * 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.
1125
1011
  */
1126
1012
  function isCommittedEntry(key) {
1127
1013
  return key.endsWith(TAR_SUFFIX) && KEY_DISCRIMINATOR_TAIL.test(key.slice(0, -7));
1128
1014
  }
1129
1015
  /**
1130
- * Recover the reported cache key from a committed entry's stem.
1131
- *
1132
- * The value on this path is already the sanitized, lossy form, so this only
1133
- * needs to undo the discriminator the key format appends. A stem that itself
1134
- * ends in a discriminator-shaped tail loses it — that affects only the string
1135
- * 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.
1136
1020
  */
1137
1021
  function stripKeyDiscriminator(stem) {
1138
1022
  return KEY_DISCRIMINATOR_TAIL.exec(stem)?.[1] ?? stem;
1139
1023
  }
1140
1024
  /**
1141
1025
  * Sanitize a path segment so a key can never escape its org/repo/scope
1142
- * namespace. Beyond stripping disallowed characters, a segment consisting
1143
- * only of dots (`.`, `..`, …) is replaced wholesale: such a segment is a
1144
- * dot-segment that HTTP/S3 path canonicalization collapses (`a/./b` → `a/b`,
1145
- * `a/../b` → `b`), which both corrupts the namespace and breaks the SigV4
1146
- * signature on a pre-signed PUT/GET. Repo identifiers like `.` (the internal
1147
- * provider's repo id) hit exactly this case, so the all-dots guard keeps the
1148
- * 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.
1149
1030
  */
1150
1031
  function sanitizeSegment(s) {
1151
1032
  const cleaned = s.replace(/[^A-Za-z0-9._-]/g, "_");
@@ -1178,36 +1059,27 @@ function readPrefixes(ref) {
1178
1059
  return [`${base}/shared/`];
1179
1060
  }
1180
1061
  /**
1181
- * Object key for a committed cache entry.
1182
- *
1183
- * The trailing discriminator is a hash of the EXACT cache key, and it is what
1184
- * keeps `build` and `Build` apart on a case-insensitive namespace — the
1185
- * filesystem backend on a macOS or Windows host, where the two would
1186
- * otherwise resolve to one object and a restore could return the other key's
1187
- * tarball.
1188
- *
1189
- * It is deliberately a SUFFIX: `restoreByPrefix` matches `restoreKeys` by
1190
- * string prefix, so appending leaves those semantics untouched. The only
1191
- * 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.
1192
1068
  */
1193
1069
  function finalKey(prefix, key) {
1194
1070
  return `${prefix}${sanitizeSegment(key)}-${keyDiscriminator(key)}${TAR_SUFFIX}`;
1195
1071
  }
1196
- /**
1197
- * The object key a committed save under `key` lands on for this ref. This is
1198
- * the writer's own path: `beginSave` and `commitSave` address the entry
1199
- * through it.
1200
- */
1072
+ /** The writer's object key for `key` under this ref, used by `beginSave` and `commitSave`. */
1201
1073
  function userCacheEntryKey(ref, key) {
1202
1074
  return finalKey(writePrefix(ref), key);
1203
1075
  }
1204
1076
  var UserCache = class {
1205
1077
  storage;
1206
- /** Cluster-wide default quota (the `KICI_USER_CACHE_QUOTA_BYTES` value). */
1078
+ /** `KICI_USER_CACHE_QUOTA_BYTES`. */
1207
1079
  defaultQuotaBytes;
1208
- /** Cluster-wide default TTL (the `KICI_USER_CACHE_TTL_MS` value). */
1080
+ /** `KICI_USER_CACHE_TTL_MS`. */
1209
1081
  defaultTtlMs;
1210
- /** Optional per-org override reader; absent = always use the cluster defaults. */
1082
+ /** Absent = always use the cluster defaults. */
1211
1083
  orgLimitsReader;
1212
1084
  constructor(opts) {
1213
1085
  this.storage = opts.storage;
@@ -1216,10 +1088,9 @@ var UserCache = class {
1216
1088
  this.orgLimitsReader = opts.orgLimitsReader;
1217
1089
  }
1218
1090
  /**
1219
- * Resolve the effective quota + TTL for an org: the per-org override from
1220
- * `org_settings` when present, otherwise the cluster-wide default. A reader
1221
- * failure falls back to the defaults (logged) — the cache must never fail a
1222
- * 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.
1223
1094
  */
1224
1095
  async resolveLimits(org) {
1225
1096
  if (!this.orgLimitsReader) return {
@@ -1318,13 +1189,11 @@ var UserCache = class {
1318
1189
  return (await this.storage.get(`${key}.hash`))?.toString("utf-8") || void 0;
1319
1190
  }
1320
1191
  /**
1321
- * Evict least-recently-used entries for the org until total tarball size <= the per-org quota.
1322
- *
1323
- * An in-flight `.tmp-` upload is never a candidate. A presigned PUT carries
1324
- * no metadata, so it would rank oldest and be reclaimed first — freeing
1325
- * nothing, since it has no `.size` — and the concurrent commit would then
1326
- * fail on its copy to the final key. Retired un-discriminated entries stay
1327
- * 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.
1328
1197
  */
1329
1198
  async enforceQuota(ref) {
1330
1199
  const { quotaBytes } = await this.resolveLimits(ref.org);
@@ -1367,34 +1236,25 @@ var UserCache = class {
1367
1236
  }
1368
1237
  };
1369
1238
  /**
1370
- * `metadata` key set when a coordinator retires the self-issued credential its
1371
- * previous run left behind. An operator revoke never sets it, which is how a
1372
- * 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.
1373
1241
  */
1374
1242
  const RETIRED_BY_INSTANCE_KEY = "retiredByInstance";
1375
1243
  /** Default credential expiry: 90 days. */
1376
1244
  const DEFAULT_EXPIRY_DAYS = 90;
1377
- /**
1378
- * Database CRUD operations for peer credentials.
1379
- * Used by the coordinator to manage credentials for all cluster members.
1380
- */
1245
+ /** The coordinator's DB store of every cluster member's credential. */
1381
1246
  var PeerCredentialStore = class {
1382
1247
  db;
1383
1248
  constructor(db) {
1384
1249
  this.db = db;
1385
1250
  }
1386
1251
  /**
1387
- * Save a new peer credential, revoking any prior active credential for the
1388
- * same instanceId (the `peer_credentials_active_uniq` partial unique index
1389
- * 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).
1390
1254
  *
1391
- * Returns `{ revokedCount }` — how many previously-active credentials this
1392
- * save revoked. Because a coordinator's peer-clients share one
1393
- * identity-scoped credential, a `revokedCount > 0` here means every sibling
1394
- * peer-client of `instanceId` that was authenticating with the old
1395
- * credential is now invalidated and will be rejected on its next proof. The
1396
- * caller logs this so a revoke that cascades sibling rejections is visible in
1397
- * 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.
1398
1258
  */
1399
1259
  async save(opts) {
1400
1260
  const expiryDays = opts.expiryDays ?? DEFAULT_EXPIRY_DAYS;
@@ -1421,16 +1281,12 @@ var PeerCredentialStore = class {
1421
1281
  throw err;
1422
1282
  }
1423
1283
  }
1424
- /**
1425
- * Find a non-revoked, non-expired credential by its hash.
1426
- */
1284
+ /** Non-revoked, non-expired credential by hash. */
1427
1285
  async findByCredentialHash(hash) {
1428
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();
1429
1287
  return row ? mapRow(row) : null;
1430
1288
  }
1431
- /**
1432
- * Find a non-revoked, non-expired credential by instance ID.
1433
- */
1289
+ /** Newest non-revoked, non-expired credential for the instance. */
1434
1290
  async findByInstanceId(instanceId) {
1435
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();
1436
1292
  return row ? mapRow(row) : null;
@@ -1449,10 +1305,9 @@ var PeerCredentialStore = class {
1449
1305
  return row ? mapRow(row) : null;
1450
1306
  }
1451
1307
  /**
1452
- * Revoke `instanceId`'s unrevoked, self-issued row whose hash is
1453
- * `credentialHash`, recording who retired it. Every condition sits in the
1454
- * WHERE clause, so a row that changed meanwhile is left alone.
1455
- * 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.
1456
1311
  */
1457
1312
  async retireSelfIssued(opts) {
1458
1313
  const marker = JSON.stringify({ [RETIRED_BY_INSTANCE_KEY]: opts.retiredByInstance });
@@ -1462,39 +1317,25 @@ var PeerCredentialStore = class {
1462
1317
  }).where("instance_id", "=", opts.instanceId).where("credential_hash", "=", opts.credentialHash).where("revoked_at", "is", null).where(sql`metadata->>'issuance'`, "=", "self").executeTakeFirst();
1463
1318
  return Number(result?.numUpdatedRows ?? 0n) > 0;
1464
1319
  }
1465
- /**
1466
- * Update the last_seen_at timestamp for a credential.
1467
- * Optionally records which coordinator validated it.
1468
- */
1320
+ /** Bump last_seen_at; optionally record the validating coordinator. */
1469
1321
  async updateLastSeen(credentialHash, validatedBy) {
1470
1322
  const updates = { last_seen_at: /* @__PURE__ */ new Date() };
1471
1323
  if (validatedBy) updates.last_validated_by = validatedBy;
1472
1324
  await this.db.updateTable("peer_credentials").set(updates).where("credential_hash", "=", credentialHash).execute();
1473
1325
  }
1474
- /**
1475
- * Revoke a peer's credential by instance ID.
1476
- */
1477
1326
  async revoke(instanceId) {
1478
1327
  await this.db.updateTable("peer_credentials").set({ revoked_at: /* @__PURE__ */ new Date() }).where("instance_id", "=", instanceId).where("revoked_at", "is", null).execute();
1479
1328
  }
1480
- /**
1481
- * Revoke all active credentials.
1482
- * @returns The number of credentials revoked.
1483
- */
1329
+ /** @returns The number of credentials revoked. */
1484
1330
  async revokeAll() {
1485
1331
  const result = await this.db.updateTable("peer_credentials").set({ revoked_at: /* @__PURE__ */ new Date() }).where("revoked_at", "is", null).executeTakeFirst();
1486
1332
  return Number(result?.numUpdatedRows ?? 0);
1487
1333
  }
1488
- /**
1489
- * List all active (non-revoked, non-expired) credentials.
1490
- */
1334
+ /** Non-revoked, non-expired credentials, oldest first. */
1491
1335
  async listActive() {
1492
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);
1493
1337
  }
1494
1338
  };
1495
- /**
1496
- * Map a database row to a PeerCredential interface.
1497
- */
1498
1339
  function mapRow(row) {
1499
1340
  return {
1500
1341
  id: row.id,
@@ -1511,15 +1352,7 @@ function mapRow(row) {
1511
1352
  metadata: row.metadata ?? {}
1512
1353
  };
1513
1354
  }
1514
- /**
1515
- * Write credential data to a JSON file with restrictive permissions.
1516
- *
1517
- * Creates the parent directory (e.g., ~/.kici/) with 0700 if it doesn't exist.
1518
- * The credential file is written with 0600 permissions (owner read/write only).
1519
- *
1520
- * @param filePath - Absolute path to the credential file
1521
- * @param data - Credential data to persist
1522
- */
1355
+ /** Write the credential file 0600, creating its parent directory 0700 if missing. */
1523
1356
  async function writeCredentialFile(filePath, data) {
1524
1357
  const dir = dirname(filePath);
1525
1358
  await mkdir(dir, {
@@ -1530,12 +1363,7 @@ async function writeCredentialFile(filePath, data) {
1530
1363
  await writeFile(filePath, json, { mode: 384 });
1531
1364
  await chmod(filePath, 384);
1532
1365
  }
1533
- /**
1534
- * Read credential data from a JSON file.
1535
- *
1536
- * @param filePath - Absolute path to the credential file
1537
- * @returns Parsed credential data, or null if the file doesn't exist
1538
- */
1366
+ /** @returns The parsed credential file, or null if it does not exist. */
1539
1367
  async function readCredentialFile(filePath) {
1540
1368
  try {
1541
1369
  const content = await readFile(filePath, "utf-8");
@@ -1546,13 +1374,9 @@ async function readCredentialFile(filePath) {
1546
1374
  }
1547
1375
  }
1548
1376
  /**
1549
- * Construct a PeerCredentialStore bound to a Postgres URL, returning the
1550
- * store plus a disposer that closes the underlying pool. Lets tests
1551
- * exercise the real Kysely-backed store without importing pg/kysely.
1552
- *
1553
- * Intended for tests of the store's own CRUD methods — production
1554
- * code constructs the store with an already-allocated Kysely instance
1555
- * 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.
1556
1380
  */
1557
1381
  async function createPeerCredentialStoreFromUrl(databaseUrl, opts) {
1558
1382
  const pool = new pg.Pool({
@@ -1609,22 +1433,19 @@ createLogger({ prefix: "coordinator-credential" });
1609
1433
  /**
1610
1434
  * Per-orchestrator coordinator that owns the shared peer credential file.
1611
1435
  *
1612
- * A single orchestrator runs N peer-clients (one per cluster peer) that all
1613
- * share one identity-scoped credential file. Left uncoordinated, a reconnect
1614
- * storm makes each sibling independently token-join (each join revokes the
1615
- * prior credential, invalidating the others) and delete the shared file on any
1616
- * rejection — a credential revocation cascade. This coordinator serializes all
1617
- * file access through one in-process mutex so only one peer-client token-joins
1618
- * 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.
1619
1442
  *
1620
- * A coordinator without a join token also wires a `selfIssue` callback. When a
1621
- * decision finds no credential and no token, the callback issues the
1622
- * 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.
1623
1445
  *
1624
- * A coordinator also wires `corroborateRejection`. Any dialled endpoint can
1625
- * send a rejection, so before it deletes the file the coordinator asks its own
1626
- * cluster database: a credential the database holds as valid, or a database it
1627
- * 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.
1628
1449
  */
1629
1450
  const logger = createLogger({ prefix: "peer-auth-coordinator" });
1630
1451
  /** How long a waiting peer-client awaits an in-flight sibling token-join. */
@@ -1860,10 +1681,7 @@ var JoinTokenManager = class {
1860
1681
  constructor(deps) {
1861
1682
  this.deps = deps;
1862
1683
  }
1863
- /**
1864
- * Create a new join token.
1865
- * Returns the full token string (only available at creation time).
1866
- */
1684
+ /** Returns the full token string, available only at creation time. */
1867
1685
  async createToken(opts) {
1868
1686
  const expiryMs = opts.expiryMs ?? DEFAULT_EXPIRY_MS;
1869
1687
  const expiry = Date.now() + Math.floor(expiryMs);
@@ -1896,12 +1714,11 @@ var JoinTokenManager = class {
1896
1714
  * Peer token mode: claim the row the presented token's secret hashes to. Role and
1897
1715
  * routing come from the row (`claimByHash`), never from the token's routing part.
1898
1716
  *
1899
- * Self-healing reuse: a join token is re-consumable by the same joining peer
1900
- * (`peerInstanceId`) until its `expires_at`. A peer that lost its credential
1901
- * re-presents the still-valid join token already in its env, and the coordinator
1902
- * issues a fresh credential without an operator action. Reuse is bounded by both
1903
- * `expires_at` and the consuming instanceId, so it never widens a leaked token's
1904
- * 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.
1905
1722
  */
1906
1723
  async validateAndConsumeToken(token, consumedBy, peerInstanceId) {
1907
1724
  return this.claimByHash(tokenHashOf(parseToken(token).secretHex), consumedBy, peerInstanceId);
@@ -1982,10 +1799,8 @@ var JoinTokenManager = class {
1982
1799
  }
1983
1800
  };
1984
1801
  /**
1985
- * Build a JoinTokenManager backed by its own connection pool to the given
1986
- * orchestrator database URL. Mirrors `createPeerCredentialStoreFromUrl`;
1987
- * used by tests that need to exercise token validation/reuse against a real
1988
- * cluster DB.
1802
+ * A JoinTokenManager with its own connection pool, for tests against a real
1803
+ * cluster DB. Mirrors `createPeerCredentialStoreFromUrl`.
1989
1804
  */
1990
1805
  function createJoinTokenManagerFromUrl(databaseUrl, opts) {
1991
1806
  const pool = new pg.Pool({
@@ -2000,9 +1815,6 @@ function createJoinTokenManagerFromUrl(databaseUrl, opts) {
2000
1815
  }
2001
1816
  };
2002
1817
  }
2003
- /**
2004
- * Parse a join token string into routing info and secret hex.
2005
- */
2006
1818
  function parseToken(token) {
2007
1819
  const parts = token.split(".");
2008
1820
  if (parts.length !== 3 || parts[0] !== TOKEN_PREFIX) throw new Error(`Invalid join token format. Expected: ${TOKEN_PREFIX}.<routing>.<secret>`);
@@ -2529,32 +2341,18 @@ function createTrustPolicyStoreFromUrl(databaseUrl, opts) {
2529
2341
  }
2530
2342
  //#endregion
2531
2343
  //#region src/cli/api-client.ts
2344
+ /** kici-admin's HTTP client for the orchestrator admin API (Bearer token auth). */
2532
2345
  /**
2533
- * HTTP client wrapper for the kici-admin CLI.
2534
- *
2535
- * Communicates with the orchestrator admin API via Bearer token authentication.
2536
- * All methods are thin wrappers around fetch() that handle JSON serialization,
2537
- * error formatting, and URL construction.
2538
- */
2539
- /**
2540
- * `fetch` rejects with a bare `TypeError: fetch failed` when it cannot reach the
2541
- * host — it names neither the address dialled nor the knob that sets it. Printed
2542
- * through the CLI's `Error: ${message}` handler that becomes `Error: fetch
2543
- * failed`, which reads like a fault in the subcommand rather than a misaddressed
2544
- * client, and sends the operator debugging the wrong thing.
2545
- *
2546
- * The trap is sharpened by two details of this CLI. The base URL comes from
2547
- * `KICI_ADMIN_URL`, not the `KICI_ORCHESTRATOR_URL` an operator is likelier to
2548
- * have exported; and subcommands accepting `--database-url` fall back to direct
2549
- * DB access, so on a host with `KICI_DATABASE_URL` set they keep working while
2550
- * the HTTP-only ones fail — making it look like specific subcommands are broken.
2551
- *
2552
- * So: name the address, name the variable, and name the near-miss.
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.
2553
2352
  */
2554
2353
  /**
2555
- * Best-effort one-line detail from a rejected `fetch`. Returns '' when nothing
2556
- * useful is available, so the caller can omit the parenthetical rather than
2557
- * print an empty one.
2354
+ * Best-effort one-line detail from a rejected `fetch`; '' when none, so the
2355
+ * caller omits the parenthetical.
2558
2356
  */
2559
2357
  function firstCauseMessage(err) {
2560
2358
  if (!(err instanceof Error)) return "";
@@ -2568,21 +2366,16 @@ function firstCauseMessage(err) {
2568
2366
  return "";
2569
2367
  }
2570
2368
  /**
2571
- * True when a rejected `fetch` failed at the transport layer, as opposed to
2572
- * failing while the request was still being built.
2573
- *
2574
- * `fetch` uses a `TypeError` for both, so they are easy to conflate — but only
2575
- * a transport failure means the orchestrator was actually dialled. Measured
2576
- * 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:
2577
2372
  *
2578
2373
  * closed port → TypeError('fetch failed') cause: Error(ECONNREFUSED)
2579
2374
  * invalid header → TypeError('Headers.append: … invalid header …') cause: undefined
2580
2375
  * invalid URL → TypeError('Failed to parse URL from …') cause: Error(ERR_INVALID_URL)
2581
2376
  *
2582
- * The discriminator is therefore the message, NOT the presence of a `cause`:
2583
- * the invalid-URL case carries one. undici uses exactly `fetch failed` for a
2584
- * transport failure and a descriptive message for everything it rejects before
2585
- * 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.
2586
2379
  */
2587
2380
  function isTransportFailure(err) {
2588
2381
  return err instanceof TypeError && err.message === "fetch failed";
@@ -2620,9 +2413,6 @@ var AdminApiClient = class {
2620
2413
  this.baseUrl = baseUrl;
2621
2414
  this.token = token;
2622
2415
  }
2623
- /**
2624
- * Make an authenticated HTTP request to the admin API.
2625
- */
2626
2416
  async request(method, path, body) {
2627
2417
  const res = await fetchAdminApi(`${this.baseUrl}${path}`, {
2628
2418
  method,
@@ -2645,39 +2435,21 @@ var AdminApiClient = class {
2645
2435
  if (res.status === 204) return;
2646
2436
  return await res.json();
2647
2437
  }
2648
- /**
2649
- * Public GET request returning parsed JSON.
2650
- */
2651
2438
  async get(path) {
2652
2439
  return this.request("GET", path);
2653
2440
  }
2654
- /**
2655
- * Public POST request returning parsed JSON.
2656
- */
2657
2441
  async post(path, body) {
2658
2442
  return this.request("POST", path, body);
2659
2443
  }
2660
- /**
2661
- * Public PATCH request returning parsed JSON.
2662
- */
2663
2444
  async patch(path, body) {
2664
2445
  return this.request("PATCH", path, body);
2665
2446
  }
2666
- /**
2667
- * Public PUT request returning parsed JSON.
2668
- */
2669
2447
  async put(path, body) {
2670
2448
  return this.request("PUT", path, body);
2671
2449
  }
2672
- /**
2673
- * Public DELETE request returning parsed JSON.
2674
- */
2675
2450
  async delete(path) {
2676
2451
  return this.request("DELETE", path);
2677
2452
  }
2678
- /**
2679
- * Public GET request returning raw response text.
2680
- */
2681
2453
  async getText(path) {
2682
2454
  const res = await fetchAdminApi(`${this.baseUrl}${path}`, {
2683
2455
  method: "GET",
@@ -2841,13 +2613,9 @@ var AdminApiClient = class {
2841
2613
  return this.request("GET", `/api/v1/agent-tokens${qs}`);
2842
2614
  }
2843
2615
  /**
2844
- * Revoke an agent token.
2845
- *
2846
- * The orchestrator both flips `agent_tokens.revoked_at` AND
2847
- * synchronously closes every in-flight agent WS authenticated by
2848
- * this token. The returned `kicked` count is the number
2849
- * of WS connections that were closed on the wire — surface it to
2850
- * 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.
2851
2619
  */
2852
2620
  async revokeAgentToken(id) {
2853
2621
  return this.request("DELETE", `/api/v1/agent-tokens/${encodeURIComponent(id)}`);
@@ -2905,7 +2673,6 @@ var AdminApiClient = class {
2905
2673
  async drainStatus() {
2906
2674
  return this.request("GET", "/api/v1/admin/orchestrator/drain");
2907
2675
  }
2908
- /** Forget a departed peer on this coordinator and every connected sibling. */
2909
2676
  /**
2910
2677
  * Forget a departed peer on this coordinator and every connected sibling. A
2911
2678
  * refusal that only needs the backstop acknowledgement comes back as a body
@@ -3016,10 +2783,9 @@ var AdminApiClient = class {
3016
2783
  return this.request("POST", "/api/v1/admin/backends/sync");
3017
2784
  }
3018
2785
  /**
3019
- * List execution runs. `status` accepts either a single status or a
3020
- * comma-separated list (e.g. `success,failed`). `since` is an ISO-8601
3021
- * timestamp; only runs with `created_at` strictly later than this value
3022
- * 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.
3023
2789
  */
3024
2790
  async listRuns(opts) {
3025
2791
  const qs = toQuery({
@@ -3425,14 +3191,10 @@ function startManifestLoopback(opts) {
3425
3191
  //#endregion
3426
3192
  //#region src/cli/open-browser.ts
3427
3193
  /**
3428
- * Open a URL in the operator's default browser, best-effort. Used by the GitHub
3429
- * App manifest setup flow to launch the create / install pages. Failure is
3430
- * non-fatal — the caller always prints the URL too, so a headless host (or a
3431
- * blocked launcher) just falls back to copy-paste.
3432
- *
3433
- * `KICI_BROWSER_CMD` overrides the launcher: `none` suppresses it entirely
3434
- * (automated tests / headless capture), any other value is run with `{url}` substituted —
3435
- * 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.
3436
3198
  */
3437
3199
  function openBrowserBestEffort(url) {
3438
3200
  const override = process.env.KICI_BROWSER_CMD;
@@ -3466,15 +3228,13 @@ const WebhookUrlNote = z.enum([
3466
3228
  //#endregion
3467
3229
  //#region src/cli/webhook-url-notes.ts
3468
3230
  /**
3469
- * The text the CLI prints when the orchestrator returns no webhook URL. Shared
3470
- * by `kici-admin source add` and the manifest setup flow, so each
3471
- * `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.
3472
3233
  */
3473
3234
  const DASHBOARD_HINT = "Find the webhook URL in the dashboard under Sources.";
3474
3235
  /**
3475
- * Short reason shown in `(unavailable — <reason>)` when no webhook URL could be
3476
- * resolved. Takes a plain string too, because an orchestrator of another
3477
- * 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.
3478
3238
  */
3479
3239
  function webhookNoteReason(note) {
3480
3240
  switch (note) {
@@ -3506,16 +3266,14 @@ function webhookNoteHint(note) {
3506
3266
  //#endregion
3507
3267
  //#region src/cli/commands/source-manifest.ts
3508
3268
  /**
3509
- * `kici-admin source add github --manifest` — the one-click GitHub App setup
3510
- * flow. Drives GitHub's App Manifest flow end-to-end: builds a pre-configured
3511
- * manifest (KiCI's exact permissions/events/webhook URL), hands it to GitHub via
3512
- * an auto-submitting form, catches the returned short-lived setup code over a
3513
- * localhost loopback (or copy-paste in --no-browser mode), exchanges it for the
3514
- * App's id + private key + webhook secret, then reuses the existing source
3515
- * 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.
3516
3274
  *
3517
- * The private-key-bearing conversion happens entirely here on the orchestrator
3518
- * 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).
3519
3277
  */
3520
3278
  /** Static marketing-site page the CLI points at in headless paste-code mode. */
3521
3279
  const STATIC_CALLBACK_URL = "https://kici.dev/gh-manifest-callback";