@kici-dev/orchestrator 0.15.0 → 0.16.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 (146) hide show
  1. package/dist/__test-helpers__/scratch-db.d.ts +16 -0
  2. package/dist/agent/registry.d.ts +1 -8
  3. package/dist/app-on-error.d.ts +1 -1
  4. package/dist/artifacts/artifact-store.d.ts +0 -2
  5. package/dist/audit/access-log.d.ts +1 -1
  6. package/dist/cache/source-cache.d.ts +1 -1
  7. package/dist/cache/user-cache.d.ts +0 -28
  8. package/dist/cli/api-client.d.ts +27 -1
  9. package/dist/cli/commands/access-log.d.ts +1 -1
  10. package/dist/cli/commands/cold-store-impl.d.ts +7 -84
  11. package/dist/cli/commands/db.d.ts +1 -0
  12. package/dist/cli/commands/orchestrator-service/status.d.ts +2 -0
  13. package/dist/cli/commands/org.d.ts +12 -0
  14. package/dist/cli/commands/scaler.d.ts +14 -0
  15. package/dist/cli/commands/secret.d.ts +1 -45
  16. package/dist/cli/commands/service-health.d.ts +21 -13
  17. package/dist/cli/commands/shared/cli-action.d.ts +17 -0
  18. package/dist/cli/commands/shared/db.d.ts +5 -5
  19. package/dist/cli/commands/shared/org-id.d.ts +5 -0
  20. package/dist/cli/commands/shared/service-verbs.d.ts +19 -0
  21. package/dist/cli/commands/shared/table.d.ts +3 -0
  22. package/dist/cli/commands/shared/unbound-context-warning.d.ts +2 -22
  23. package/dist/cli/commands/trust-policy.d.ts +7 -31
  24. package/dist/cli/kici-admin.d.ts +1 -1
  25. package/dist/cli.js +9863 -8201
  26. package/dist/cluster/coordinator.d.ts +2 -2
  27. package/dist/cluster/peer-client.d.ts +27 -1
  28. package/dist/cluster/peer-forget.d.ts +4 -9
  29. package/dist/cluster/peer-handler.d.ts +11 -1
  30. package/dist/cluster/peer-request-waiters.d.ts +26 -0
  31. package/dist/cluster/scaler-orphans-peer.d.ts +4 -9
  32. package/dist/cluster/scaler-reload-fanout.d.ts +29 -0
  33. package/dist/cluster/scaler-reload-peer.d.ts +16 -0
  34. package/dist/cluster/worker-cluster-settings.d.ts +1 -0
  35. package/dist/cold-store/load-access-log-range.d.ts +3 -3
  36. package/dist/cold-store/tables/access-log.d.ts +4 -12
  37. package/dist/cold-store/tables/event-log.d.ts +8 -19
  38. package/dist/cold-store/tables/execution-jobs.d.ts +7 -24
  39. package/dist/cold-store/tables/execution-runs.d.ts +6 -20
  40. package/dist/cold-store/tables/execution-steps.d.ts +8 -26
  41. package/dist/cold-store/tables/secret-audit-log.d.ts +4 -11
  42. package/dist/config/env-overlay.d.ts +3 -8
  43. package/dist/config/reload.d.ts +9 -2
  44. package/dist/config/schema.d.ts +2 -2
  45. package/dist/config/types.d.ts +2 -2
  46. package/dist/config.d.ts +13 -17
  47. package/dist/contexts/held-runs.d.ts +3 -6
  48. package/dist/dashboard/cursor.d.ts +12 -0
  49. package/dist/dashboard/handler.d.ts +5 -12
  50. package/dist/db/deferred-index-build.d.ts +42 -0
  51. package/dist/db/deferred-indexes.d.ts +3 -37
  52. package/dist/db/migrations/100_held_runs_hold_type_vocabulary.d.ts +3 -5
  53. package/dist/db/migrations/158_normalize_legacy_values.d.ts +4 -0
  54. package/dist/db/repos/org-ids-repo.d.ts +87 -0
  55. package/dist/db/schema-snapshot.generated.d.ts +3 -0
  56. package/dist/db/types.d.ts +5 -22
  57. package/dist/fault-injection-types.d.ts +0 -6
  58. package/dist/git/dispatch-git-auth.d.ts +6 -12
  59. package/dist/helpers/json.d.ts +3 -0
  60. package/dist/index.js +133 -136
  61. package/dist/metrics/prometheus.d.ts +0 -5
  62. package/dist/oidc/id-token-claims.d.ts +1 -1
  63. package/dist/oidc/resolve-signer.d.ts +2 -4
  64. package/dist/orchestrator-core.d.ts +10 -3
  65. package/dist/pipeline/global-eval-round.d.ts +2 -26
  66. package/dist/pipeline/install-secrets-resolver.d.ts +0 -3
  67. package/dist/pipeline/manual-schedule.d.ts +1 -7
  68. package/dist/provenance/dispatch-context.d.ts +5 -7
  69. package/dist/provenance/pending-attestations-repo.d.ts +1 -1
  70. package/dist/provenance/trust-root.d.ts +4 -5
  71. package/dist/provenance/verify-deferred-capture.d.ts +3 -3
  72. package/dist/provider-registry.d.ts +13 -40
  73. package/dist/providers/universal-git/ssh-auth.d.ts +0 -5
  74. package/dist/reporting/check-run-reporter.d.ts +8 -21
  75. package/dist/reporting/check-run-summary.d.ts +2 -2
  76. package/dist/reporting/execution-tracker.d.ts +1 -1
  77. package/dist/reporting/log-chunk-sink.d.ts +1 -1
  78. package/dist/reporting/run-summary-fields.d.ts +25 -0
  79. package/dist/reporting/s3-log-storage.d.ts +2 -2
  80. package/dist/routes/admin-access-log.d.ts +2 -9
  81. package/dist/routes/admin-backends.d.ts +2 -9
  82. package/dist/routes/admin-cluster-name.d.ts +2 -8
  83. package/dist/routes/admin-cluster-settings.d.ts +2 -8
  84. package/dist/routes/admin-config.d.ts +0 -3
  85. package/dist/routes/admin-contexts.d.ts +3 -11
  86. package/dist/routes/admin-db.d.ts +2 -9
  87. package/dist/routes/admin-env.d.ts +33 -0
  88. package/dist/routes/admin-event-dlq.d.ts +2 -9
  89. package/dist/routes/admin-event-inspect.d.ts +2 -9
  90. package/dist/routes/admin-event-log.d.ts +2 -9
  91. package/dist/routes/admin-events.d.ts +3 -13
  92. package/dist/routes/admin-held-runs.d.ts +2 -8
  93. package/dist/routes/admin-list-limit.d.ts +3 -0
  94. package/dist/routes/admin-maintenance.d.ts +2 -9
  95. package/dist/routes/admin-orchestrator-drain.d.ts +2 -9
  96. package/dist/routes/admin-org-settings.d.ts +2 -8
  97. package/dist/routes/admin-orgs.d.ts +27 -0
  98. package/dist/routes/admin-peer-forget.d.ts +2 -9
  99. package/dist/routes/admin-queue-execution.d.ts +3 -10
  100. package/dist/routes/admin-registrations.d.ts +3 -14
  101. package/dist/routes/admin-runs.d.ts +3 -14
  102. package/dist/routes/admin-scaler-orphans.d.ts +2 -9
  103. package/dist/routes/admin-scaler-reload.d.ts +41 -0
  104. package/dist/routes/admin-scheduled-jobs.d.ts +2 -9
  105. package/dist/routes/admin-signing-keys.d.ts +2 -9
  106. package/dist/routes/admin-sources.d.ts +2 -9
  107. package/dist/routes/admin-trust-policy.d.ts +2 -8
  108. package/dist/routes/admin.d.ts +15 -13
  109. package/dist/scaler/config.d.ts +12 -84
  110. package/dist/scaler/file-reload.d.ts +48 -0
  111. package/dist/scaler/manager.d.ts +47 -33
  112. package/dist/scaler/scaler-state-store.d.ts +5 -0
  113. package/dist/scaler/types.d.ts +1 -4
  114. package/dist/secrets/job-secret-gate.d.ts +2 -5
  115. package/dist/secrets/secret-resolver.d.ts +2 -4
  116. package/dist/security/trust-policy-gate.d.ts +0 -4
  117. package/dist/server.d.ts +6 -17
  118. package/dist/server.js +6693 -8005
  119. package/dist/standalone.js +5826 -6555
  120. package/dist/worker/reroute-dispatch.d.ts +1 -0
  121. package/dist/worker/reroute-spawn-control.d.ts +1 -3
  122. package/dist/worker-core.d.ts +9 -2
  123. package/dist/ws/agent-handler.d.ts +3 -3
  124. package/dist/ws/dashboard-access.d.ts +57 -0
  125. package/dist/ws/dashboard-backends-handler.d.ts +1 -6
  126. package/dist/ws/dashboard-context-handler.d.ts +10 -15
  127. package/dist/ws/dashboard-fleet-write-handler.d.ts +1 -6
  128. package/dist/ws/dashboard-global-workflows-handler.d.ts +1 -6
  129. package/dist/ws/dashboard-registrations-handler.d.ts +1 -7
  130. package/dist/ws/platform-client.d.ts +85 -330
  131. package/installer-image-digests.json +3 -3
  132. package/package.json +4 -4
  133. package/sbom.spdx.json +53 -53
  134. package/dist/cache/legacy-prefixes.d.ts +0 -19
  135. package/dist/cli/commands/agent-service/logs.d.ts +0 -14
  136. package/dist/cli/commands/agent-service/restart.d.ts +0 -12
  137. package/dist/cli/commands/agent-service/start.d.ts +0 -12
  138. package/dist/cli/commands/agent-service/stop.d.ts +0 -12
  139. package/dist/cli/commands/agent-service/uninstall.d.ts +0 -13
  140. package/dist/cli/commands/cache.d.ts +0 -51
  141. package/dist/cli/commands/orchestrator-service/logs.d.ts +0 -14
  142. package/dist/cli/commands/orchestrator-service/restart.d.ts +0 -12
  143. package/dist/cli/commands/orchestrator-service/start.d.ts +0 -12
  144. package/dist/cli/commands/orchestrator-service/stop.d.ts +0 -12
  145. package/dist/cli/commands/orchestrator-service/uninstall.d.ts +0 -13
  146. package/dist/git/inherited-secret.d.ts +0 -29
@@ -1,13 +1,8 @@
1
- import { type StateReplayRun, type OrchestratorToPlatformMessage, type WebhookRelay, type WebhookRelayResult, type TrustPolicyUpdate, type StaleCheckrunCleanup, type DashboardRunDetailRequest, type DashboardRunStructuredRequest, type DashboardRunStateRequest, type DashboardRunsListRequest, type DashboardRunsFiltersRequest, type DashboardSourcesListRequest, type DashboardAdminTokensListRequest, type DashboardStepLogsRequest, type DashboardAttestationsListRequest, type DashboardAttestationsListAllRequest, type DashboardAttestationGetRequest, type DashboardAttestationRetryRequest, type DashboardArtifactsListRequest, type DashboardOrchLogsRequest, type RunRerunRequest, type ManualScheduleRequest, type RunCancelRequest, type DashboardPayloadRequest, type DashboardPlatformToOrchMessage, type TestRelayRequest, type DashboardDiagnosticsRequest, type DashboardScalerCapacityRequest, type DashboardScalerAgentsRequest, type DashboardFleetHostsRequest, type DashboardFleetHostRequest, type DashboardFleetPreviewRequest, type DashboardFleetWorkflowsForHostRequest, type JoinResponse, type DeploymentIdentity, type ConfigPaths, type OrchCapabilities, type OrchRole } from '@kici-dev/engine';
1
+ import { type StateReplayRun, type OrchestratorToPlatformMessage, type PlatformToOrchestratorMessage, type WebhookRelay, type WebhookRelayResult, type TrustPolicyUpdate, type StaleCheckrunCleanup, type DashboardAttestationRetryRequest, type RunRerunRequest, type ManualScheduleRequest, type RunCancelRequest, type DashboardPlatformToOrchMessage, type TestRelayRequest, type JoinResponse, type DeploymentIdentity, type ConfigPaths, type OrchCapabilities, type OrchRole } from '@kici-dev/engine';
2
2
  import type { PlanHeadroomStore } from '../cluster/plan-headroom-store.js';
3
3
  import { RelayBufferRegistry, type RelayStartMeta } from '../webhook/relay-buffer.js';
4
4
  import type { AdmitResult } from '../webhook/ingest-admission.js';
5
- /**
6
- * Verification + processing outcome returned by the chunked relay path's
7
- * `onVerifyInbound` callback. Mirrors the shape exported by
8
- * `webhook/verify-inbound.ts` so wiring is a single hand-off without an
9
- * adapter layer.
10
- */
5
+ /** Outcome of the chunked relay path's `onVerifyInbound`; mirrors `webhook/verify-inbound.ts`. */
11
6
  export interface InboundVerifyOutcome {
12
7
  result: WebhookRelayResult;
13
8
  reason?: string;
@@ -24,31 +19,18 @@ export type ReplaySendResult = {
24
19
  skipped?: 'empty' | 'invalid' | 'disconnected' | 'breaker';
25
20
  };
26
21
  /**
27
- * A webhook source that this orchestrator manages.
28
- * Sent to Platform after auth.success so the Platform knows which
29
- * routing keys this orchestrator handles.
30
- *
31
- * Note: webhookSecret is no longer included. Secrets are pushed separately
32
- * via source.secrets after loading from PgSecretStore.
33
- *
34
- * Single source of truth lives in `../entry-helpers.ts`. Re-exported here
35
- * so existing imports of `ProviderSource` from `./platform-client.js` keep
36
- * working without churn.
22
+ * A webhook source this orchestrator manages, registered with the Platform after
23
+ * auth.success. Defined in `../entry-helpers.ts`; re-exported for existing importers.
37
24
  */
38
25
  export type { ProviderSource } from '../entry-helpers.js';
39
26
  import type { ProviderSource } from '../entry-helpers.js';
40
27
  /**
41
28
  * Hard ceiling on how long an admitted fire-and-forget relay pipeline may hold
42
- * its admission slot before it is force-released. A pipeline running longer than
43
- * this is treated as hung; releasing its slot (idempotently) prevents a
44
- * permanent slot leak that would otherwise shrink capacity for every future
45
- * webhook. Well above any legitimate ingest-pipeline duration.
29
+ * its admission slot. Past it the pipeline counts as hung and its slot is
30
+ * force-released, so a hang cannot permanently shrink ingest capacity.
46
31
  *
47
- * Exported because it is also the hard bound on anything a webhook waits for
48
- * inline: the global eval round caps its raised wait ceiling at this value,
49
- * since a ceiling past the point the relay force-releases the pipeline buys
50
- * latency and no verdict. Two copies of "5 minutes" with nothing coupling them
51
- * is exactly the pair that drifts.
32
+ * Exported because the global eval round caps its inline wait ceiling at this
33
+ * value: waiting past the force-release buys latency and no verdict.
52
34
  */
53
35
  export declare const ADMITTED_PIPELINE_LIFETIME_MS: number;
54
36
  /**
@@ -57,6 +39,18 @@ export declare const ADMITTED_PIPELINE_LIFETIME_MS: number;
57
39
  * keeps the connection.
58
40
  */
59
41
  export type FrameHandler<M> = (msg: M) => void | Promise<void>;
42
+ /**
43
+ * Platform → orchestrator frame types answered by exactly one dashboard / fleet
44
+ * read handler, looked up in {@link PlatformClientOptions.dashboardHandlers}.
45
+ */
46
+ export declare const DASHBOARD_FRAME_TYPES: readonly ["dashboard.run.detail", "dashboard.run.structured", "dashboard.run.state", "dashboard.runs.list", "dashboard.runs.filters", "dashboard.sources.list", "dashboard.admin-tokens.list", "dashboard.step.logs", "dashboard.attestations.list", "dashboard.attestations.list.all", "dashboard.attestation.get", "dashboard.artifacts.list", "dashboard.payload", "dashboard.orch.logs", "dashboard.diagnostics", "dashboard.scaler.capacity", "dashboard.scaler.agents", "dashboard.fleet.hosts", "dashboard.fleet.host", "dashboard.fleet.preview", "dashboard.fleet.workflows-for-host"];
47
+ export type DashboardFrameType = (typeof DASHBOARD_FRAME_TYPES)[number];
48
+ /** One optional handler per {@link DASHBOARD_FRAME_TYPES} entry, typed by its frame. */
49
+ export type DashboardFrameHandlers = {
50
+ [K in DashboardFrameType]?: FrameHandler<Extract<PlatformToOrchestratorMessage, {
51
+ type: K;
52
+ }>>;
53
+ };
60
54
  export interface PlatformClientOptions {
61
55
  /** WebSocket URL of the Platform relay. */
62
56
  url: string;
@@ -68,18 +62,11 @@ export interface PlatformClientOptions {
68
62
  providerSources?: ProviderSource[];
69
63
  /** Orchestrator cluster instance ID (sent in source.register for peer correlation). */
70
64
  instanceId?: string;
71
- /**
72
- * Human-friendly cluster name resolved on orch boot
73
- * (`cluster_meta.cluster_name`). Sent in source.register so Platform
74
- * can route per-orch dashboard requests by this identifier.
75
- */
65
+ /** `cluster_meta.cluster_name`; the Platform routes per-orch dashboard requests by it. */
76
66
  clusterName?: string;
77
67
  /**
78
- * Orchestrator DB identifier (UUID, seeded by migration 001 in
79
- * `cluster_meta` key `'cluster_id'`). Sent in source.register so
80
- * Platform can warn when two unrelated clusters in the same org
81
- * accidentally share a `clusterName`. HA siblings share the same orch
82
- * DB and therefore the same `clusterId`.
68
+ * `cluster_meta.cluster_id` (UUID). Lets the Platform warn when two unrelated
69
+ * clusters in one org share a `clusterName`; HA siblings share one DB and so one id.
83
70
  */
84
71
  clusterId?: string;
85
72
  /** Reachable address for peer-to-peer connections (from KICI_CLUSTER_ADDRESS env var). Null if not configured. */
@@ -123,18 +110,13 @@ export interface PlatformClientOptions {
123
110
  }) => void;
124
111
  /** Optional callback invoked after successful authentication and source registration. */
125
112
  onAuthenticated?: () => void | Promise<void>;
126
- /**
127
- * Returns this coordinator's currently-connected worker peers for the
128
- * `cluster.membership` snapshot. Undefined on a non-coordinator (or when
129
- * clustering is off) → no membership is reported.
130
- */
113
+ /** Connected worker peers for `cluster.membership`; undefined off-coordinator → none reported. */
131
114
  getWorkerPeers?: () => Array<{
132
115
  instanceId: string;
133
116
  }>;
134
117
  /**
135
- * Persisted cache of the Platform-pushed worker ceiling. Written on every
136
- * `plan.headroom`, read by `getWorkerCeiling`. Undefined → the coordinator
137
- * receives no ceiling and admits worker joins freely.
118
+ * Persisted Platform-pushed worker ceiling, written on every `plan.headroom`.
119
+ * Undefined → no ceiling, worker joins are admitted freely.
138
120
  */
139
121
  planHeadroomStore?: PlanHeadroomStore;
140
122
  /**
@@ -145,126 +127,47 @@ export interface PlatformClientOptions {
145
127
  */
146
128
  onPlanCeiling?: (ceiling: number, evictExcess: boolean) => void;
147
129
  /**
148
- * Optional callback invoked when the Platform surfaces the orchestrator's
149
- * canonical org id on `auth.success`. Used to auto-provision the
150
- * `remote_sources` anchor (`remote:<orgId>`) so Platform-relayed
151
- * `kici run remote` resolves the real tenant. Fires on every (re)connect;
152
- * provisioning is idempotent.
130
+ * Fires with the canonical org id from `auth.success` on every (re)connect, to
131
+ * idempotently provision the `remote:<orgId>` anchor `kici run remote` resolves.
153
132
  */
154
133
  onOrgIdentified?: (info: {
155
134
  orgId: string;
156
135
  clusterId: string | null;
157
136
  }) => void;
158
- /**
159
- * Optional callback fired with the provenance trust root (OIDC issuer) the
160
- * Platform supplies on `auth.success`. The orchestrator uses it to verify
161
- * provenance bundles at ingest. `null` means provenance is not configured.
162
- */
163
- onProvenanceIssuer?: (issuer: string | null) => void;
164
- /** Optional callback for dashboard run detail requests from Platform. */
165
- onDashboardRunDetail?: FrameHandler<DashboardRunDetailRequest>;
166
- /** Optional callback for dashboard structured run-result requests from Platform. */
167
- onDashboardRunStructured?: FrameHandler<DashboardRunStructuredRequest>;
168
- /** Optional callback for the run-state system reconciliation read from Platform. */
169
- onDashboardRunState?: FrameHandler<DashboardRunStateRequest>;
170
- /** Optional callback for dashboard runs.list (operator console) requests from Platform. */
171
- onDashboardRunsList?: FrameHandler<DashboardRunsListRequest>;
172
- /** Optional callback for dashboard runs.filters (operator console) requests from Platform. */
173
- onDashboardRunsFilters?: FrameHandler<DashboardRunsFiltersRequest>;
174
- /** Optional callback for dashboard sources.list (operator console) requests from Platform. */
175
- onDashboardSourcesList?: FrameHandler<DashboardSourcesListRequest>;
176
- /** Optional callback for dashboard admin-tokens.list (RBAC drift report) requests from Platform. */
177
- onDashboardAdminTokensList?: FrameHandler<DashboardAdminTokensListRequest>;
178
- /** Optional callback for dashboard step logs requests from Platform. */
179
- onDashboardStepLogs?: FrameHandler<DashboardStepLogsRequest>;
180
- /** Optional callback for dashboard attestations-list requests from Platform. */
181
- onDashboardAttestationsList?: FrameHandler<DashboardAttestationsListRequest>;
182
- /** Optional callback for org-wide attestations list (browser) requests from Platform. */
183
- onDashboardAttestationsListAll?: FrameHandler<DashboardAttestationsListAllRequest>;
184
- /** Optional callback for single-attestation detail requests from Platform. */
185
- onDashboardAttestationGet?: FrameHandler<DashboardAttestationGetRequest>;
186
137
  onDashboardAttestationRetry?: FrameHandler<DashboardAttestationRetryRequest>;
187
- /** Optional callback for dashboard artifacts-list requests from Platform. */
188
- onDashboardArtifactsList?: FrameHandler<DashboardArtifactsListRequest>;
189
- /** Optional callback for run re-run requests from Platform (dashboard action). */
190
138
  onRunRerun?: FrameHandler<RunRerunRequest>;
191
- /** Optional callback for manual schedule trigger requests from Platform (dashboard action). */
192
139
  onManualSchedule?: FrameHandler<ManualScheduleRequest>;
193
- /** Optional callback for run cancel requests from Platform (dashboard action). */
194
140
  onRunCancel?: FrameHandler<RunCancelRequest>;
195
- /** Optional callback for dashboard payload requests from Platform. */
196
- onDashboardPayload?: FrameHandler<DashboardPayloadRequest>;
197
- /** Optional callback for dashboard orchestration logs requests from Platform. */
198
- onDashboardOrchLogs?: FrameHandler<DashboardOrchLogsRequest>;
199
- /** Optional callback for dashboard environment/held-run messages from Platform. */
141
+ /** Handlers for the {@link DASHBOARD_FRAME_TYPES} read frames; a type with none is dropped. */
142
+ dashboardHandlers?: DashboardFrameHandlers;
143
+ /** Dashboard environment / held-run messages. */
200
144
  onDashboardEnvMessage?: FrameHandler<DashboardPlatformToOrchMessage>;
201
- /**
202
- * Optional callback for Platform-first `kici run remote` control-plane relay
203
- * requests (upload-init, trigger, status, logs, cancel). The handler performs
204
- * the action and replies over the WS keyed by `requestId`.
205
- */
145
+ /** `kici run remote` control-plane relay requests; the handler replies keyed by `requestId`. */
206
146
  onTestRelay?: FrameHandler<TestRelayRequest>;
207
- /** Optional callback for dashboard diagnostics requests from Platform. */
208
- onDashboardDiagnostics?: FrameHandler<DashboardDiagnosticsRequest>;
209
- /** Optional callback for dashboard scaler capacity requests from Platform. */
210
- onDashboardScalerCapacity?: FrameHandler<DashboardScalerCapacityRequest>;
211
- /** Optional callback for dashboard scaler agents requests from Platform. */
212
- onDashboardScalerAgents?: FrameHandler<DashboardScalerAgentsRequest>;
213
- /** Optional callback for fleet roster requests from Platform. */
214
- onFleetHosts?: FrameHandler<DashboardFleetHostsRequest>;
215
- /** Optional callback for fleet host-detail requests from Platform. */
216
- onFleetHost?: FrameHandler<DashboardFleetHostRequest>;
217
- /** Optional callback for fleet runsOnAll-preview requests from Platform. */
218
- onFleetPreview?: FrameHandler<DashboardFleetPreviewRequest>;
219
- /** Optional callback for fleet workflows-for-host requests from Platform. */
220
- onFleetWorkflowsForHost?: FrameHandler<DashboardFleetWorkflowsForHostRequest>;
221
- /** Optional callback for trust policy updates pushed from Platform. */
222
147
  onTrustPolicyUpdate?: FrameHandler<TrustPolicyUpdate>;
223
- /** Optional callback for stale check run cleanup requests from Platform. */
224
148
  onStaleCheckrunCleanup?: FrameHandler<StaleCheckrunCleanup>;
225
- /**
226
- * Optional handler for join.request frames relayed by the Platform. It answers
227
- * every such frame. Wiring it advertises the clusterJoinV2 capability.
228
- */
149
+ /** Optional handler for join.request frames relayed by the Platform. It answers every such frame. */
229
150
  onJoinRequest?: (raw: unknown) => Promise<JoinResponse>;
230
151
  /** Custom orchestrator capabilities to merge with ORCH_CAPABILITIES in auth.request. */
231
152
  orchCapabilities?: Partial<OrchCapabilities>;
232
153
  /**
233
- * Test-only fault-injection transform over the advertised capability manifest,
234
- * supplied only by the build-time test double to reproduce an older /
235
- * sourceless orchestrator that predates a given dashboard capability. Undefined
236
- * (the shipped default) means identity — the full capability set is advertised.
237
- */
238
- capabilitiesTransform?: (c: OrchCapabilities) => OrchCapabilities;
239
- /**
240
- * Verify a reassembled inbound webhook from the chunked relay path.
241
- *
242
- * Wired to `verifyInboundWebhook(deps, ...)` in production. Required when
243
- * Platform sends `webhook.relay.start`/`webhook.relay.chunk` (chunked path);
244
- * if absent, the orchestrator ACKs `rejected_misconfigured` because it
245
- * cannot perform the trust check the new design requires.
154
+ * Verify a reassembled chunked-relay webhook. Without it every chunked relay
155
+ * is ACKed `rejected_misconfigured`, since the trust check cannot run.
246
156
  */
247
157
  onVerifyInbound?: (meta: RelayStartMeta, body: Buffer) => Promise<InboundVerifyOutcome> | InboundVerifyOutcome;
248
- /**
249
- * Optional injected reassembly registry. Tests pass a registry with a short
250
- * TTL; production constructs a default one per PlatformClient.
251
- */
158
+ /** Reassembly registry override (tests use a short TTL). */
252
159
  relayBuffer?: RelayBufferRegistry;
253
160
  /**
254
- * Webhook-ingest admission hook. Called with the relay's routing key BEFORE
255
- * signature verification (so an unverified flood is throttled too — a verify
256
- * does a DB read). When it sheds, the relay acks `shed_retry_later` (429) and
257
- * no pipeline work runs. When it admits, the returned slot is held for the
258
- * fire-and-forget pipeline's lifetime and released on completion / error /
259
- * timeout. Absent → no admission gate (tests, minimal wirings).
161
+ * Webhook-ingest admission, called BEFORE signature verification so an
162
+ * unverified flood is throttled too (verify reads the DB). A shed acks
163
+ * `shed_retry_later` (429); an admitted slot is held for the pipeline's
164
+ * lifetime. Absent → no admission gate.
260
165
  */
261
166
  onAdmit?: (routingKey: string) => Promise<AdmitResult>;
262
167
  /**
263
- * Optional shed-recording seam. Invoked with the pre-verify relay meta +
264
- * assembled body + the admission controller's shed reason, before the
265
- * shed_retry_later ack. The wiring records the delivery durably — an
266
- * `event_log` breadcrumb, and the overflow-buffer row when that queue is
267
- * enabled. Best-effort — the client wraps it so a failure never blocks the ack.
168
+ * Records a shed delivery durably (an `event_log` breadcrumb, plus an
169
+ * overflow-buffer row when enabled) before the shed ack. Best-effort: a
170
+ * failure never blocks the ack.
268
171
  */
269
172
  onShedCapture?: (meta: RelayStartMeta, body: Buffer, reason: string) => Promise<void>;
270
173
  }
@@ -288,14 +191,9 @@ export declare function classifyDashboardRequestError(raw: {
288
191
  requestId: string;
289
192
  }, knownTypes: ReadonlySet<string>, orchVersion: string | undefined): DashboardRequestErrorFrame;
290
193
  /**
291
- * WebSocket client that connects the orchestrator to the Platform relay.
292
- *
293
- * Handles:
294
- * - Authentication handshake (auth.request -> auth.success/failure)
295
- * - Periodic heartbeat messages to keep the connection alive
296
- * - Auto-reconnect with exponential backoff (1s initial, 1.5x, jitter, 60s max)
297
- * - Webhook relay reception and ACK responses
298
- * - Event buffering during disconnection with flush on reconnect
194
+ * The orchestrator's WebSocket link to the Platform relay: auth handshake,
195
+ * heartbeat, jittered exponential reconnect, webhook relay + ACK, and event
196
+ * buffering while disconnected.
299
197
  */
300
198
  export declare class PlatformClient {
301
199
  private ws;
@@ -318,22 +216,8 @@ export declare class PlatformClient {
318
216
  private readonly token;
319
217
  private readonly onWebhookRelay;
320
218
  private providerSources;
321
- /**
322
- * Pending `registerSourceAndAwait()` callers, keyed by routing key. Resolved
323
- * with the Platform-computed webhook URL when the matching
324
- * `source.register.ack` arrives, or rejected on timeout / disconnect.
325
- */
219
+ /** `registerSourceAndAwait()` waiters by routing key, settled by ack, timeout or disconnect. */
326
220
  private readonly pendingSourceRegistrations;
327
- /**
328
- * Platform capabilities advertised on this connection (Platform → orchestrator
329
- * `platform.capabilities` frame). `undefined` means nothing advertised yet —
330
- * either a pre-capability Platform (which never advertises) or the frame has
331
- * not arrived. Feature-gated sends treat "undefined" as optimistic (send
332
- * anyway, backward-safe); only an advertised-but-absent flag suppresses a send.
333
- * Reset to `undefined` on every (re)connect so a stale advertisement can't
334
- * leak across connections.
335
- */
336
- private platformCapabilities;
337
221
  private readonly instanceId?;
338
222
  private readonly clusterName?;
339
223
  private readonly clusterId?;
@@ -354,34 +238,13 @@ export declare class PlatformClient {
354
238
  private readonly planHeadroomStore?;
355
239
  private readonly onPlanCeiling?;
356
240
  private readonly onOrgIdentified?;
357
- private readonly onProvenanceIssuer?;
358
- private readonly onDashboardRunDetail?;
359
- private readonly onDashboardRunStructured?;
360
- private readonly onDashboardRunState?;
361
- private readonly onDashboardRunsList?;
362
- private readonly onDashboardRunsFilters?;
363
- private readonly onDashboardSourcesList?;
364
- private readonly onDashboardAdminTokensList?;
365
- private readonly onDashboardStepLogs?;
366
- private readonly onDashboardAttestationsList?;
367
- private readonly onDashboardAttestationsListAll?;
368
- private readonly onDashboardAttestationGet?;
369
241
  private readonly onDashboardAttestationRetry?;
370
- private readonly onDashboardArtifactsList?;
371
242
  private readonly onRunRerun?;
372
243
  private readonly onManualSchedule?;
373
244
  private readonly onRunCancel?;
374
- private readonly onDashboardPayload?;
375
- private readonly onDashboardOrchLogs?;
245
+ private readonly dashboardHandlers;
376
246
  private readonly onDashboardEnvMessage?;
377
247
  private readonly onTestRelay?;
378
- private readonly onDashboardDiagnostics?;
379
- private readonly onDashboardScalerCapacity?;
380
- private readonly onDashboardScalerAgents?;
381
- private readonly onFleetHosts?;
382
- private readonly onFleetHost?;
383
- private readonly onFleetPreview?;
384
- private readonly onFleetWorkflowsForHost?;
385
248
  private readonly onTrustPolicyUpdate?;
386
249
  private readonly onStaleCheckrunCleanup?;
387
250
  private readonly onJoinRequest?;
@@ -391,34 +254,18 @@ export declare class PlatformClient {
391
254
  private readonly onShedCapture?;
392
255
  private readonly relayBuffer;
393
256
  /**
394
- * Public alias of the orchestrator's owning org as supplied by
395
- * Platform on `auth.success`. Used by the check-run emitter to build
396
- * outbound `details_url`s that hide the canonical `org_<12-char>` id.
397
- * `undefined` when the orchestrator runs against a Platform that
398
- * predates the alias plumbing, or before the first successful auth.
257
+ * Owning org's public alias from `auth.success`, used for outbound check-run
258
+ * `details_url`s so they hide the canonical `org_<12-char>` id.
399
259
  */
400
260
  private _orgPublicAlias?;
401
- /** Canonical Platform org id from `auth.success`; see {@link getOrgId}. */
402
261
  private _orgId?;
403
- /** The Platform's org-scoped GitHub webhook URL from the last `auth.success`. */
404
262
  private _githubWebhookUrl?;
405
- /**
406
- * Returns the cached public alias of the orchestrator's owning org,
407
- * or `undefined` if Platform has not supplied one yet. Read by
408
- * `check-run-reporter.ts` when building `details_url`.
409
- */
410
263
  getOrgPublicAlias(): string | undefined;
411
264
  /**
412
- * The canonical Platform organization id this orchestrator authenticated
413
- * as, from `auth.success`. `undefined` before the first successful auth, or
414
- * against a Platform that does not supply it.
415
- *
416
- * A generic source's routing key embeds the organization
417
- * (`generic:<orgId>:<id>`), and the Platform now refuses to register a key
418
- * naming a different one. So the source-create path reads this to refuse a
419
- * mismatched `--org` up front, naming the correct value, instead of letting
420
- * the operator create a source that registers, is rejected, and never
421
- * delivers.
265
+ * Canonical org id from `auth.success` (`undefined` before it). The Platform
266
+ * refuses a generic routing key (`generic:<orgId>:<id>`) naming another org,
267
+ * so source-create reads this to refuse a mismatched `--org` up front rather
268
+ * than create a source that never delivers.
422
269
  */
423
270
  getOrgId(): string | undefined;
424
271
  /**
@@ -430,133 +277,59 @@ export declare class PlatformClient {
430
277
  getGithubWebhookUrl(): string | null | undefined;
431
278
  constructor(options: PlatformClientOptions);
432
279
  /**
433
- * Merge `updates` into the stored orch capabilities and broadcast the
434
- * full set to Platform via `orch.capabilities.update`. Buffers via
435
- * `send()` when not yet authenticated. The next `auth.request` will
436
- * also carry the merged capabilities, so a reconnect-followed-by-
437
- * runtime-broadcast still ends Platform in the correct cache state.
280
+ * Merge `updates` and broadcast the full set (buffered while unauthenticated).
281
+ * The next `auth.request` carries the merged set too, so a reconnect cannot
282
+ * leave the Platform's cache stale.
438
283
  */
439
284
  broadcastCapabilities(updates: Partial<OrchCapabilities>): void;
440
- /**
441
- * Current merged orchestrator capabilities. Read-only view used by
442
- * tests and diagnostics; mutate via `broadcastCapabilities`.
443
- */
444
285
  getCapabilities(): OrchCapabilities;
445
- /** Current connection state. */
446
286
  get state(): ConnectionState;
447
- /** Number of messages currently buffered. */
448
287
  getBufferedCount(): number;
449
288
  /**
450
- * Complete a chunked webhook relay: verify, process if accepted, ACK.
451
- *
452
- * Called from the `webhook.relay.chunk` handler once `relayBuffer.chunk(...)`
453
- * returns `{ status: 'completed' }`. This sequence is intentionally single-pass
454
- * and inside `requestContext.run` so trace propagation works end-to-end.
289
+ * Verify, process if accepted, and ACK a fully reassembled chunked relay.
290
+ * Runs single-pass inside `requestContext.run` so trace propagation holds.
455
291
  */
456
292
  private completeChunkedRelay;
457
- /**
458
- * Initiate connection to the Platform relay.
459
- * Starts the connect -> authenticate -> ready lifecycle.
460
- */
461
293
  connect(): void;
462
- /**
463
- * Gracefully disconnect from Platform. Does not trigger reconnection.
464
- */
294
+ /** Graceful disconnect; does not reconnect. */
465
295
  disconnect(): void;
466
- /**
467
- * Send a message to Platform. If authenticated, sends immediately.
468
- * If not authenticated, buffers the message for later delivery.
469
- */
296
+ /** Send now when authenticated, otherwise buffer for the next connection. */
470
297
  send(message: OrchestratorToPlatformMessage): void;
471
298
  /**
472
- * Send the reconnect state replay as N paced frames.
473
- *
474
- * The payload is bounded by BOTH the wire schema's run cap and the Platform
475
- * limiter's byte budget, and paced under its refill rate, because a frame
476
- * breaching either one is rejected with a 4003 close — and since reconnecting
477
- * does not reduce the run count, an oversized frame is resent forever rather
478
- * than failing once.
299
+ * Send the reconnect state replay as paced frames, each within the wire
300
+ * schema's run cap and the Platform limiter's byte budget: a breaching frame
301
+ * gets a 4003 close and, since reconnecting does not shrink it, is resent forever.
479
302
  *
480
- * Uses `this.ws.send` directly rather than `this.send()` on purpose: `send()`
481
- * falls back to `this.eventBuffer` when the socket is not open, which for a
482
- * multi-frame replay would queue the remaining frames for the NEXT connection
483
- * instead of abandoning a replay whose connection has already gone. The
484
- * Platform's replay handler upserts per run, so abandoning is safe — the next
485
- * reconnect replays from scratch.
303
+ * Uses `this.ws.send`, not `send()`, so a dropped connection abandons the
304
+ * replay instead of buffering its tail for the next one. The Platform upserts
305
+ * per run, so the next reconnect replays from scratch.
486
306
  */
487
307
  sendStateReplay(runs: StateReplayRun[]): Promise<ReplaySendResult>;
488
- /**
489
- * Send a feature-gated message only if the Platform is known to support the
490
- * named capability — the orchestrator-side pre-flight for a self-hosted
491
- * orchestrator running ahead of the hosted Platform.
492
- *
493
- * Backward-safe: a Platform that never advertised capabilities (a
494
- * pre-capability build, or the advertisement hasn't arrived yet) is treated as
495
- * "unknown → send optimistically", exactly like the Platform's dashboard
496
- * pre-flight treats an absent `supportedDashboardRequests` as "unknown", never
497
- * "supports nothing". Only an *advertised* capability set that explicitly lacks
498
- * the flag suppresses the send — surfacing a diagnosable capability gap instead
499
- * of firing a frame the Platform would silently drop.
500
- */
501
- sendIfPlatformSupports(capability: string, message: OrchestratorToPlatformMessage): void;
502
- /**
503
- * Send a raw message directly on the WebSocket, bypassing typed validation.
504
- * Used for log pull response messages (log.response) which are
505
- * NOT in the OrchestratorToPlatformMessage union (they are in the separate log pull schema).
506
- */
308
+ /** Unbuffered, untyped send for frames outside the union (e.g. `log.response`). */
507
309
  sendRaw(data: unknown): void;
508
- /**
509
- * Register a new source at runtime (e.g., after config reload adds a new GitHub app).
510
- * Separate from the post-auth registration which sends all sources at once.
511
- */
310
+ /** Register one source at runtime (the post-auth registration sends them all). */
512
311
  sendSourceRegister(source: ProviderSource): void;
513
- /**
514
- * Deregister sources at runtime (e.g., after config reload removes a GitHub app).
515
- * Tells Platform to stop routing webhooks for these routing keys to this orchestrator.
516
- */
517
312
  sendSourceDeregister(source: {
518
313
  routingKey: string;
519
314
  }): void;
520
- /**
521
- * Diff current provider sources with new ones and send register/deregister as needed.
522
- * Convenience method for config reload that atomically updates routing.
523
- */
315
+ /** Diff against the current sources and send the register / deregister frames. */
524
316
  updateSources(newSources: ProviderSource[]): void;
525
317
  /**
526
- * Push the full source list to the Platform and resolve with the webhook URL
527
- * the Platform computed for `routingKey` (from the `source.register.ack`), or
528
- * `null` if the Platform has no public webhook base configured.
529
- *
530
- * Used by `kici-admin source add` (platform/hybrid mode) to print the URL
531
- * synchronously. Passing the **full** source list keeps this on the single
532
- * `updateSources` push path — the routing key being newly added means
533
- * `updateSources` emits a `source.register` whose ack carries the URL; the
534
- * later NOTIFY-driven republish then diffs to a no-op.
535
- *
536
- * Rejects on timeout or disconnect; the caller degrades to a "(unavailable)"
537
- * note rather than fabricating a URL.
318
+ * Push the full source list and resolve with the webhook URL the Platform's
319
+ * `source.register.ack` carries for `routingKey` (`null`: no public webhook
320
+ * base). `kici-admin source add` prints it. Taking the FULL list keeps this
321
+ * on the one `updateSources` path, so the later NOTIFY republish diffs to a
322
+ * no-op. Rejects on timeout or disconnect.
538
323
  */
539
324
  registerSourceAndAwait(fullSources: ProviderSource[], routingKey: string, timeoutMs?: number): Promise<string | null>;
540
- /**
541
- * Reject every pending `registerSourceAndAwait()` — called on disconnect so a
542
- * `source add` issued while the link drops fails fast instead of hanging.
543
- */
325
+ /** On disconnect, so a `source add` in flight fails fast instead of hanging. */
544
326
  private rejectPendingSourceRegistrations;
545
327
  getReconnectDelay(): number;
546
328
  private doConnect;
547
329
  private handleMessage;
548
- /**
549
- * Try the non-mainline frames (log-pull, cluster join.request) when the
550
- * primary `platformToOrchestratorMessageSchema` failed to parse. Falls back to
551
- * a structured warning if none matches.
552
- */
330
+ /** Recognition chain for frames the primary schema rejected. */
553
331
  private handleNonStandardMessage;
554
- /**
555
- * If `raw` looks like a dashboard request (a `dashboard.*` type with a
556
- * requestId) that failed schema validation, send a structured error response
557
- * keyed to its requestId and return true. Returns false when the message is
558
- * not a recognisable dashboard request (let the caller log a warning).
559
- */
332
+ /** Answer an invalid `dashboard.*` request carrying a requestId; false when `raw` is not one. */
560
333
  private respondToInvalidDashboardRequest;
561
334
  /**
562
335
  * Run the handler for one Platform frame. Nothing awaits a frame, so a throw
@@ -564,13 +337,9 @@ export declare class PlatformClient {
564
337
  * connection carries on; left unhandled it would stop the orchestrator.
565
338
  */
566
339
  private runFrameHandler;
567
- /**
568
- * Dispatch a parsed platform message to the appropriate per-area
569
- * handler. Each `case` either inlines a tiny dispatch (for one-line
570
- * forwards to a callback) or delegates to a private method when the
571
- * branch carries non-trivial logic.
572
- */
573
340
  private dispatchPlatformMessage;
341
+ /** Log a dashboard read frame and hand it to its registered handler. */
342
+ private dispatchDashboardFrame;
574
343
  private handleAuthSuccess;
575
344
  private handleAuthFailure;
576
345
  private handleWebhookRelayStart;
@@ -578,36 +347,22 @@ export declare class PlatformClient {
578
347
  private handleSourceRegisterAck;
579
348
  private handlePeerDiscover;
580
349
  private handlePeerUpdate;
581
- /**
582
- * Send a message directly on the WebSocket without buffering.
583
- * Used for ACK responses that must go immediately.
584
- */
350
+ /** Unbuffered send, for ACKs that must go now or not at all. */
585
351
  private sendDirect;
586
352
  private flushBuffer;
587
353
  private startHeartbeat;
588
354
  private stopHeartbeat;
589
- /** How often a coordinator re-sends its membership snapshot. */
590
355
  private static readonly CLUSTER_MEMBERSHIP_INTERVAL_MS;
591
- /**
592
- * Send the current worker-peer snapshot to the Platform.
593
- *
594
- * A snapshot, not a delta: a dropped frame self-heals on the next send. A
595
- * no-op when the client is not authenticated or has no worker-peer source.
596
- */
356
+ /** Worker-peer snapshot (not a delta, so a dropped frame self-heals on the next send). */
597
357
  sendClusterMembership(): void;
598
358
  private startClusterMembership;
599
359
  private stopClusterMembership;
600
360
  /**
601
- * Store the Platform's worker ceiling and act on an eviction directive.
602
- *
603
- * The stored value survives a Platform disconnect and a coordinator restart,
604
- * which is what makes the fail-open stance bounded rather than unlimited.
361
+ * Store the worker ceiling; it survives disconnects and restarts, which keeps
362
+ * the fail-open stance bounded.
605
363
  */
606
364
  private onPlanHeadroom;
607
- /**
608
- * The ceiling this coordinator enforces, or `null` when none was ever
609
- * received — in which case worker joins are admitted freely.
610
- */
365
+ /** Enforced ceiling; `null` (never received) admits worker joins freely. */
611
366
  getWorkerCeiling(): Promise<number | null>;
612
367
  private scheduleReconnect;
613
368
  private clearStabilityTimer;
@@ -1,7 +1,7 @@
1
1
  {
2
- "version": "0.15.0",
2
+ "version": "0.16.0",
3
3
  "images": {
4
- "kici-agent": "sha256:753e878b220babd497fbbab484748f122028014a2468e5dc48d45560dc4cf80e",
5
- "kici-orchestrator": "sha256:bd6655f1485e7401ab6c696090a1927d551e7d937d9f5b66c7cfa2a13c8f7d2d"
4
+ "kici-agent": "sha256:d685cb8756dd86e6bb5a160fb2190ae2728de7db06a2d3183a4f60c641418034",
5
+ "kici-orchestrator": "sha256:34f613d76f78b77966680ac2c7f326b949723b959d46cae32767075cd524577d"
6
6
  }
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kici-dev/orchestrator",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "description": "Customer-deployable orchestrator for the KiCI CI/CD stack. Receives webhook events (direct or via Platform relay), matches triggers against the lock file, and dispatches jobs to connected agents.",
5
5
  "keywords": [
6
6
  "ci",
@@ -90,8 +90,8 @@
90
90
  "ws": "^8.21.3",
91
91
  "yaml": "^2.9.1",
92
92
  "zod": "^4.6.5",
93
- "@kici-dev/engine": "0.15.0",
94
- "@kici-dev/shared": "0.15.0"
93
+ "@kici-dev/engine": "0.16.0",
94
+ "@kici-dev/shared": "0.16.0"
95
95
  },
96
96
  "kici": {
97
97
  "metrics": {
@@ -106,7 +106,7 @@
106
106
  "@types/dockerode": "^4.0.1",
107
107
  "@types/ws": "^8.18.1",
108
108
  "kysely-ctl": "^0.21.0",
109
- "@kici-dev/agent": "0.15.0"
109
+ "@kici-dev/agent": "0.16.0"
110
110
  },
111
111
  "scripts": {
112
112
  "build": "node ../../scripts/build-service.mjs && tsc --emitDeclarationOnly",