@kici-dev/orchestrator 0.11.0 → 0.13.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 (158) hide show
  1. package/dist/__test-helpers__/mock-db-query.d.ts +4 -5
  2. package/dist/agent/agent-version.d.ts +5 -5
  3. package/dist/agent/dispatcher.d.ts +48 -0
  4. package/dist/agent/registry.d.ts +38 -9
  5. package/dist/agent-packaging/node-runtime-members.d.ts +14 -0
  6. package/dist/app.d.ts +9 -3
  7. package/dist/approvals/apply-decision.d.ts +1 -1
  8. package/dist/audit/access-log.d.ts +2 -3
  9. package/dist/cache/cache-upload-settle.d.ts +75 -0
  10. package/dist/cache/pending-inits.d.ts +9 -0
  11. package/dist/cancel/cancel-run.d.ts +22 -4
  12. package/dist/cancel/peer-job-cancel.d.ts +50 -0
  13. package/dist/cancel/sweep-stuck-cancelling.d.ts +3 -1
  14. package/dist/cli/commands/access-log.d.ts +3 -3
  15. package/dist/cli/commands/agent-service/agent-env.d.ts +20 -0
  16. package/dist/cli/commands/agent-service/status.d.ts +3 -3
  17. package/dist/cli/commands/attestations.d.ts +1 -1
  18. package/dist/cli/commands/context.d.ts +2 -2
  19. package/dist/cli/commands/event-dlq.d.ts +5 -6
  20. package/dist/cli/commands/event-log.d.ts +2 -3
  21. package/dist/cli/commands/execution.d.ts +1 -3
  22. package/dist/cli/commands/local-hook.d.ts +3 -2
  23. package/dist/cli/commands/local-trigger.d.ts +7 -0
  24. package/dist/cli/commands/orchestrator-service/status.d.ts +10 -3
  25. package/dist/cli/commands/queue.d.ts +1 -2
  26. package/dist/cli/commands/runs.d.ts +2 -3
  27. package/dist/cli/commands/service-health.d.ts +68 -0
  28. package/dist/cli/commands/shared/env-file-mode.d.ts +3 -2
  29. package/dist/cli/commands/shared/upgrade-safety.d.ts +11 -5
  30. package/dist/cli/commands/shared/versioned-upgrade.d.ts +119 -7
  31. package/dist/cli/commands/workflow.d.ts +3 -4
  32. package/dist/cli/open-browser.d.ts +1 -1
  33. package/dist/cli/service/entrypoint.d.ts +18 -0
  34. package/dist/cli/service/image-digests.d.ts +10 -0
  35. package/dist/cli/service/index.d.ts +4 -2
  36. package/dist/cli/service/instance/manifest.d.ts +39 -0
  37. package/dist/cli/service/launchd.d.ts +45 -10
  38. package/dist/cli/service/shutdown-grace.d.ts +35 -0
  39. package/dist/cli/service/types.d.ts +9 -0
  40. package/dist/cli/service/windows-acl.d.ts +40 -0
  41. package/dist/cli/service/windows-env-file.d.ts +45 -0
  42. package/dist/cli/service/windows.d.ts +13 -0
  43. package/dist/cli.js +2601 -1232
  44. package/dist/cluster/cluster-identity.d.ts +4 -4
  45. package/dist/cluster/coordinator-credential.d.ts +45 -0
  46. package/dist/cluster/coordinator.d.ts +18 -2
  47. package/dist/cluster/index.d.ts +1 -0
  48. package/dist/cluster/instance-heartbeat.d.ts +6 -1
  49. package/dist/cluster/join-token.d.ts +4 -2
  50. package/dist/cluster/leader-gated-scheduler.d.ts +7 -1
  51. package/dist/cluster/peer-auth-coordinator.d.ts +13 -0
  52. package/dist/cluster/peer-client.d.ts +4 -0
  53. package/dist/cluster/peer-credentials.d.ts +32 -1
  54. package/dist/cluster/raft-state.d.ts +6 -0
  55. package/dist/cluster/raft.d.ts +16 -2
  56. package/dist/cold-store/load-access-log-range.d.ts +3 -3
  57. package/dist/cold-store/load-event-log-range.d.ts +1 -1
  58. package/dist/cold-store/load-secret-audit-log-range.d.ts +2 -2
  59. package/dist/cold-store/orchestrator-cold-store.d.ts +9 -11
  60. package/dist/cold-store/tables/access-log.d.ts +2 -2
  61. package/dist/cold-store/tables/event-log.d.ts +4 -10
  62. package/dist/cold-store/tables/execution-jobs.d.ts +1 -1
  63. package/dist/cold-store/tables/execution-runs.d.ts +4 -4
  64. package/dist/cold-store/tables/execution-steps.d.ts +1 -1
  65. package/dist/cold-store/tables/secret-audit-log.d.ts +3 -3
  66. package/dist/config.d.ts +6 -1
  67. package/dist/contexts/held-runs.d.ts +2 -2
  68. package/dist/dashboard/attestation-filters.d.ts +1 -1
  69. package/dist/dashboard/handler.d.ts +8 -8
  70. package/dist/db/deferred-indexes.d.ts +2 -2
  71. package/dist/db/migrations/005_cold_store_chunk_counter.d.ts +2 -4
  72. package/dist/db/migrations/006_runs_jobs_steps_archived_at.d.ts +4 -4
  73. package/dist/db/migrations/007_audit_logs_archived_at.d.ts +6 -9
  74. package/dist/db/migrations/008_event_log_archived_at.d.ts +4 -6
  75. package/dist/db/migrations/010_cold_store_chunks.d.ts +2 -2
  76. package/dist/db/migrations/012_peer_credentials_active_uniq.d.ts +2 -4
  77. package/dist/db/migrations/016_org_settings_allow_http_npm.d.ts +2 -2
  78. package/dist/db/migrations/045_host_properties.d.ts +1 -1
  79. package/dist/db/migrations/046_join_token_consumed_by_instance.d.ts +1 -1
  80. package/dist/db/migrations/048_host_reboot_pending.d.ts +1 -1
  81. package/dist/db/migrations/049_held_runs_payload.d.ts +1 -1
  82. package/dist/db/migrations/050_sources_slug.d.ts +1 -1
  83. package/dist/db/migrations/051_binding_host_pattern.d.ts +1 -1
  84. package/dist/db/migrations/052_host_reach_metadata.d.ts +1 -1
  85. package/dist/db/migrations/053_agent_token_single_use.d.ts +1 -1
  86. package/dist/db/migrations/054_local_working_tree.d.ts +1 -1
  87. package/dist/db/migrations/055_agent_token_mandatory_labels.d.ts +1 -1
  88. package/dist/db/migrations/056_execution_jobs_environments.d.ts +1 -1
  89. package/dist/db/migrations/064_execution_jobs_skipped_environments.d.ts +1 -1
  90. package/dist/db/migrations/152_org_settings_cache_upload_settle_timeout.d.ts +15 -0
  91. package/dist/db/migrations/153_execution_runs_cancel_force.d.ts +16 -0
  92. package/dist/db/types.d.ts +27 -13
  93. package/dist/events/types.d.ts +1 -1
  94. package/dist/fault-injection-types.d.ts +2 -2
  95. package/dist/firecracker/host-network.d.ts +21 -3
  96. package/dist/firecracker/net-interfaces.d.ts +1 -1
  97. package/dist/helpers/run-detached.d.ts +12 -0
  98. package/dist/index.js +242 -67
  99. package/dist/oidc/db-signer.d.ts +1 -1
  100. package/dist/pipeline/changed-files.d.ts +51 -0
  101. package/dist/pipeline/cross-source-tally.d.ts +21 -0
  102. package/dist/pipeline/degraded-reason.d.ts +8 -0
  103. package/dist/pipeline/dispatch-matched-workflow.d.ts +10 -0
  104. package/dist/pipeline/global-eval-round.d.ts +5 -4
  105. package/dist/pipeline/processor.d.ts +11 -3
  106. package/dist/pipeline/rerun-inputs.d.ts +16 -7
  107. package/dist/provenance/retrier-mint.d.ts +1 -1
  108. package/dist/provenance/trust-root.d.ts +3 -3
  109. package/dist/providers/github/changed-files.d.ts +14 -4
  110. package/dist/providers/universal-git/changed-files.d.ts +6 -0
  111. package/dist/providers/universal-git/clone-token.d.ts +9 -13
  112. package/dist/providers/universal-git/config.d.ts +4 -0
  113. package/dist/providers/universal-git/index.d.ts +1 -2
  114. package/dist/providers/universal-git/normalizer.d.ts +2 -3
  115. package/dist/providers/universal-git/ssh-auth.d.ts +4 -4
  116. package/dist/queue/cleanup.d.ts +2 -2
  117. package/dist/queue/job-queue.d.ts +6 -6
  118. package/dist/queue/scheduled-job.d.ts +5 -7
  119. package/dist/registration/extractor.d.ts +1 -1
  120. package/dist/registration/registration-index.d.ts +1 -1
  121. package/dist/reporting/execution-tracker.d.ts +3 -3
  122. package/dist/routes/admin-access-log.d.ts +1 -1
  123. package/dist/routes/admin-auth.d.ts +2 -2
  124. package/dist/routes/admin-event-log.d.ts +2 -2
  125. package/dist/routes/admin-runs.d.ts +3 -3
  126. package/dist/routes/admin-scheduled-jobs.d.ts +2 -3
  127. package/dist/routes/health.d.ts +9 -0
  128. package/dist/scaler/container-backend.d.ts +3 -1
  129. package/dist/scaler/container-runtime.d.ts +9 -0
  130. package/dist/scaler/firecracker-backend.d.ts +15 -10
  131. package/dist/scaler/firecracker-extra-hosts.d.ts +20 -0
  132. package/dist/scaler/machine-ledger.d.ts +3 -4
  133. package/dist/scaler/manager.d.ts +26 -2
  134. package/dist/scaler/scaler-state-store.d.ts +1 -1
  135. package/dist/scaler/types.d.ts +4 -1
  136. package/dist/secrets/audit-logger.d.ts +2 -2
  137. package/dist/security/reduced-privilege-note.d.ts +2 -3
  138. package/dist/security/trust-policy-store.d.ts +3 -3
  139. package/dist/server.d.ts +2 -1
  140. package/dist/server.js +4955 -3206
  141. package/dist/stale-detector/stale-run-detector.d.ts +1 -1
  142. package/dist/stale-detector/workflow-deadline-detector.d.ts +7 -1
  143. package/dist/standalone.d.ts +1 -1
  144. package/dist/standalone.js +12944 -11243
  145. package/dist/storage/filesystem.d.ts +1 -1
  146. package/dist/storage/index.d.ts +1 -1
  147. package/dist/storage/s3.d.ts +36 -0
  148. package/dist/storage/sign-url.d.ts +2 -1
  149. package/dist/storage/types.d.ts +2 -2
  150. package/dist/ws/agent-handler.d.ts +58 -6
  151. package/dist/ws/agent-heartbeat.d.ts +4 -5
  152. package/dist/ws/dashboard-context-handler.d.ts +1 -1
  153. package/dist/ws/platform-client.d.ts +44 -32
  154. package/dist/ws/server-options.d.ts +1 -1
  155. package/dist/ws/test-relay-handlers.d.ts +1 -1
  156. package/installer-image-digests.json +3 -3
  157. package/package.json +5 -5
  158. package/sbom.spdx.json +53 -53
@@ -1,12 +1,11 @@
1
1
  /**
2
2
  * Predicate + projection evaluation for the shared `createMockDb` harness.
3
3
  *
4
- * Kept BYTE-IDENTICAL in two places —
5
- * `packages/orchestrator/src/__test-helpers__/mock-db-query.ts` and
6
- * `packages/platform/src/__test-helpers__/mock-db-query.ts`. Each package owns an
4
+ * Kept BYTE-IDENTICAL in the orchestrator and the Platform, which each carry a
5
+ * copy. Each package owns an
7
6
  * independent `createMockDb` builder and neither package may import the other, so
8
- * the evaluator is duplicated rather than shared. `mock-db-mirror.test.ts` in both
9
- * packages fails the moment the copies diverge.
7
+ * the evaluator is duplicated rather than shared. A drift test fails the moment
8
+ * the copies diverge.
10
9
  *
11
10
  * `createMockDb` used to return its configured rows verbatim, whatever the
12
11
  * query asked for: a `.where(...)` or a `.select([...])` was recorded on a spy
@@ -4,8 +4,8 @@
4
4
  * An agent reports its own package version in `agent.register`
5
5
  * (`agentRegisterSchema.version`), and the field is optional — an agent old
6
6
  * enough to omit it predates every feature this module gates on. The
7
- * orchestrator and the agent are deployed and upgraded independently
8
- * (`.claude/rules/compatibility.md`), so a feature the orchestrator ships is
7
+ * orchestrator and the agent are deployed and upgraded independently,
8
+ * so a feature the orchestrator ships is
9
9
  * routinely dispatched to a fleet that cannot run it, and the version is the
10
10
  * only fact the orchestrator has about what the fleet understands.
11
11
  */
@@ -16,9 +16,9 @@ type VersionBase = [number, number, number];
16
16
  * the string is not a version at all.
17
17
  *
18
18
  * The prerelease suffix is dropped rather than ordered because the suffixes in
19
- * play are build counters from the dev registry (`0.5.0-9159`), not semver
20
- * release candidates. Strict semver orders those BELOW `0.5.0`, which would
21
- * read every staging agent as too old for a feature it in fact carries.
19
+ * play are build counters (`0.5.0-9159`), not semver release candidates. Strict
20
+ * semver orders those BELOW `0.5.0`, which would read every agent on a
21
+ * prerelease build as too old for a feature it in fact carries.
22
22
  */
23
23
  export declare function parseVersionBase(version: string): VersionBase | null;
24
24
  /**
@@ -258,6 +258,17 @@ export declare class Dispatcher {
258
258
  */
259
259
  hasPeerCoordinators?: () => boolean | Promise<boolean>;
260
260
  });
261
+ /** Runs with the ids of the jobs each disconnect triage failed; see {@link setDisconnectCleanup}. */
262
+ private disconnectCleanup?;
263
+ /**
264
+ * Install what runs with the ids of the jobs a disconnect triage failed. The
265
+ * agent WebSocket handler installs the release of their in-memory waiters
266
+ * (pending builds, inits, dynamic evaluations, global eval rounds). It runs
267
+ * inside {@link onAgentDisconnect}, so a path that drops an agent without
268
+ * waiting for its socket (heartbeat timeout, ack timeout, token revocation)
269
+ * reaches it too.
270
+ */
271
+ setDisconnectCleanup(cleanup: (failedJobIds: string[]) => void): void;
261
272
  /**
262
273
  * Dispatch a job to a matching agent, or queue it if none available.
263
274
  *
@@ -444,6 +455,32 @@ export declare class Dispatcher {
444
455
  private failRefusedDispatch;
445
456
  /** Free the slot and tracking a claim took on its agent; a claim for no agent took none. */
446
457
  private releaseClaimAccounting;
458
+ /**
459
+ * Release the slot and tracking `jobId` holds on `agentId`, if the job is
460
+ * still tracked there. Returns false when another path (a refusal, a
461
+ * put-back, a disconnect) already took it.
462
+ */
463
+ private releaseTrackedClaim;
464
+ /**
465
+ * Hand a job this coordinator just claimed from the queue to `agentId`,
466
+ * whose slot the claim took. A query that fails before the job is sent
467
+ * returns the claim ({@link returnUndeliveredClaim}) and rethrows, so the
468
+ * agent is not left holding a slot for a job it never received.
469
+ *
470
+ * @returns whether the job was sent.
471
+ */
472
+ private sendClaimedJob;
473
+ /**
474
+ * Put back a job a queue claim took but did not send: a query failed between
475
+ * the claim and the send. The agent's slot (and the job's tracking, once
476
+ * taken) is released so the agent takes work again, and the row returns to
477
+ * pending without spending a dispatch attempt, since no agent saw it. The
478
+ * next drain or the pending re-drive offers it again. A job a refusal or a
479
+ * disconnect already took is left to that path. If the put-back fails too,
480
+ * the row stays dispatched with no ack deadline and the stale-dispatch scan
481
+ * reaps it.
482
+ */
483
+ private returnUndeliveredClaim;
447
484
  /** Record that a job began executing on its agent. */
448
485
  markJobStarted(jobId: string): void;
449
486
  /**
@@ -482,6 +519,15 @@ export declare class Dispatcher {
482
519
  * triage finds nothing to double-handle.
483
520
  */
484
521
  private handleAckExpiry;
522
+ /**
523
+ * Drop an agent that did not acknowledge a dispatch. Its other in-flight jobs
524
+ * (a multi-slot agent may run more than the one that timed out) go through
525
+ * {@link onAgentDisconnect}, which reads the registration before its first
526
+ * await to tell a scaler-managed agent from a static one, so the triage
527
+ * starts first. The unregister right after removes the agent from routing at
528
+ * once, so a redispatch cannot re-select it while the triage awaits.
529
+ */
530
+ private dropUnacknowledgingAgent;
485
531
  /**
486
532
  * Handle an explicit dispatch rejection (`job.reject`) from an agent.
487
533
  * Undoes the dispatch accounting and requeues the job for another agent.
@@ -608,6 +654,8 @@ export declare class Dispatcher {
608
654
  * Used by the cancel-run API. Returns null if the job is not tracked (e.g. already completed).
609
655
  */
610
656
  getAgentIdForJob(jobId: string): string | null;
657
+ /** The jobs of `runId` this dispatcher currently tracks to an agent. */
658
+ getTrackedJobIdsForRun(runId: string): string[];
611
659
  /**
612
660
  * Start periodic cleanup of expired grace window entries.
613
661
  * Should be called during server startup.
@@ -117,7 +117,7 @@ export interface AgentEntry {
117
117
  * The `agent_tokens.id` row used to authenticate this connection, or
118
118
  * `null` when auth mode is `none`. Indexed by `tokenIdIndex` so a
119
119
  * synchronous revocation kick can enumerate every WS authenticated by
120
- * a given token. in the pentest catalog.
120
+ * a given token.
121
121
  */
122
122
  tokenId: string | null;
123
123
  hostname: string | null;
@@ -240,10 +240,9 @@ export declare class AgentRegistry {
240
240
  *
241
241
  * Idempotent: re-scheduling the same tokenId is a no-op as long as
242
242
  * a timer is still queued — a token's `expires_at` doesn't shift
243
- * across reconnects of the same agent. Closes the sister gap
244
- * to the revocation finding (`agent-token-revocation-stale-ws`,
245
- * fixed in `993bc3d9d`) where natural TTL expiration had no
246
- * propagation path to in-flight WS connections.
243
+ * across reconnects of the same agent. Revocation kicks a token's
244
+ * in-flight WS connections at once; these timers do the same when
245
+ * the token reaches its natural TTL.
247
246
  */
248
247
  private readonly tokenExpiryTimers;
249
248
  /**
@@ -264,6 +263,37 @@ export declare class AgentRegistry {
264
263
  * registry behaves exactly as before.
265
264
  */
266
265
  constructor(deps?: AgentRegistryDeps);
266
+ /**
267
+ * Triages the in-flight jobs of an agent this registry drops on its own (a
268
+ * revoked or expired token): fails or requeues a scaler-managed agent's
269
+ * jobs, starts recovery for a static agent's. Installed by the dispatcher,
270
+ * which is built after the registry.
271
+ */
272
+ private disconnectTriage?;
273
+ /** Install the job triage {@link disconnectByTokenId} runs for each agent it drops. */
274
+ setDisconnectTriage(triage: (agentId: string) => Promise<unknown>): void;
275
+ /**
276
+ * Sockets whose `agent.register` is in flight (awaiting the scaler lookup),
277
+ * per agent id, with the id of the agent token each authenticated with
278
+ * (`null` without token auth). Kept here rather than in the WebSocket
279
+ * handler because the coordinator builds one handler per connection: a
280
+ * socket's close, and the check a registration makes against another agent
281
+ * token, must see a registration in flight on another connection.
282
+ */
283
+ private readonly registeringSockets;
284
+ /** Record that `ws`, authenticated with `tokenId`, has started registering `agentId`. */
285
+ beginRegistering(agentId: string, ws: WsLike, tokenId: string | null): void;
286
+ /** Record that `ws` has finished registering `agentId`, however it ended. */
287
+ endRegistering(agentId: string, ws: WsLike): void;
288
+ /** Whether a socket other than `ws` is registering `agentId` right now. */
289
+ isRegisteringElsewhere(agentId: string, ws: WsLike): boolean;
290
+ /**
291
+ * Whether another connection holds `agentId` under an agent token other than
292
+ * `tokenId`: the live registration, or a registration in flight on another
293
+ * socket. A registration without token auth (`null`) holds no token identity
294
+ * and conflicts with nothing.
295
+ */
296
+ isAgentIdHeldByOtherToken(agentId: string, tokenId: string, ws: WsLike): boolean;
267
297
  /**
268
298
  * Register an agent. If the agentId already exists, updates the existing
269
299
  * entry (agent reconnection scenario).
@@ -317,10 +347,9 @@ export declare class AgentRegistry {
317
347
  * Caller is the agent WS handler at register-time, when the token's
318
348
  * `agent_tokens.expires_at` column is non-null. Static tokens have
319
349
  * `expires_at = null` and are skipped at the call site (they have
320
- * no TTL by design). Closes the sister gap to the revocation
321
- * finding (`agent-token-revocation-stale-ws`, fixed in `993bc3d9d`)
322
- * where natural TTL expiration had no propagation path to
323
- * in-flight WS connections.
350
+ * no TTL by design). Revocation kicks a token's in-flight WS
351
+ * connections at once; this timer does the same at the token's
352
+ * natural TTL.
324
353
  */
325
354
  scheduleExpiryKick(tokenId: string, expiresAt: Date): void;
326
355
  /**
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The members of an official Node.js Linux or macOS archive that a KiCI payload
3
+ * vendors, relative to the archive's `node-v<version>-<os>-<arch>/` directory:
4
+ * the `node` binary, the `npm` and `npx` launchers, and the bundled npm package.
5
+ * With them in place, the agent's `resolveNpm()` finds
6
+ * `<nodeDir>/../lib/node_modules/npm/bin/npm-cli.js` beside the vendored `node`,
7
+ * so the builder role needs no npm on the host.
8
+ *
9
+ * This module has no imports so that repository tooling can read the list:
10
+ * `scripts/lib/node-dist.mjs` (the standalone package builder) keeps its own
11
+ * copy, and its test pins the two lists equal.
12
+ */
13
+ export declare const NODE_RUNTIME_MEMBERS: readonly ['bin/node', 'bin/npm', 'bin/npx', 'lib/node_modules/npm'];
14
+ //# sourceMappingURL=node-runtime-members.d.ts.map
package/dist/app.d.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  * - Request ID and logging middleware
11
11
  * - 25MB body size limit
12
12
  *
13
- * Pattern follows packages/platform/src/app.ts: returns { app, wss }.
13
+ * Same pattern as the Platform's app: returns { app, wss }.
14
14
  */
15
15
  import type { Kysely } from 'kysely';
16
16
  import type pg from 'pg';
@@ -41,6 +41,7 @@ import type { PendingInitTracker } from './cache/index.js';
41
41
  import type { PendingDynamicTracker, PendingGlobalEvalTracker } from './cache/index.js';
42
42
  import type { GlobalEvalRoundCache } from './cache/index.js';
43
43
  import type { CacheStorage } from './storage/types.js';
44
+ import type { CacheUploadSettle } from './cache/cache-upload-settle.js';
44
45
  import type { ProvenanceTrustRoot } from './provenance/trust-root.js';
45
46
  import type { LocalSigner } from './oidc/local-dev-signer.js';
46
47
  import type { CheckRunReporter } from './reporting/check-run-reporter.js';
@@ -178,6 +179,11 @@ export interface AppDependencies {
178
179
  dispatchCacheRefs?: DispatchCacheRefTracker;
179
180
  /** Cache storage backend (S3) for metadata operations on upload completion. */
180
181
  cacheStorage?: CacheStorage;
182
+ /**
183
+ * In-flight build-cache publishes plus the per-org settle bound. Constructed
184
+ * once by orchestrator-core: the agent-WS factory below runs per connection.
185
+ */
186
+ cacheUploadSettle?: CacheUploadSettle;
181
187
  /** Provenance trust root used to verify build-provenance bundles at ingest. */
182
188
  provenanceTrustRoot?: ProvenanceTrustRoot;
183
189
  /**
@@ -197,7 +203,7 @@ export interface AppDependencies {
197
203
  */
198
204
  faultInjection?: import('./fault-injection-types.js').OrchestratorFaultInjection;
199
205
  /**
200
- * Orchestrator-owned provenance signing (Phase 1 root of trust). Present when
206
+ * Orchestrator-owned provenance signing (the root of trust). Present when
201
207
  * `KICI_ORCHESTRATOR_PROVENANCE_ISSUER` is configured: the orchestrator mints +
202
208
  * signs identity tokens locally with its own ES256 key, and serves its own
203
209
  * OIDC discovery + JWKS + native verify endpoint. `resolveOrchestratorSigner`
@@ -342,7 +348,7 @@ export interface AppDependencies {
342
348
  globalWorkflowPolicy?: GlobalWorkflowPolicy;
343
349
  /** Inbound webhook delivery log writer. Optional -- if not set, deliveries are not persisted to event_log. */
344
350
  eventLogWriter?: EventLogWriter;
345
- /** Cold-store handle (Phase E). Optional -- when present, admin event-log routes can serve archived rows. */
351
+ /** Cold-store handle. Optional -- when present, admin event-log routes can serve archived rows. */
346
352
  coldStore?: ColdStore | null;
347
353
  /** Read + mutation attribution log writer. Optional -- if not set, access_log rows are not written. */
348
354
  accessLogWriter?: AccessLogWriter;
@@ -50,7 +50,7 @@ export interface ApplyDecisionResult {
50
50
  export interface ApplyDecisionDeps {
51
51
  orgId: string;
52
52
  store: HeldRunStore;
53
- /** Team name → member user ids (from the Plan-1 trust-policy cache). */
53
+ /** Team name → member user ids (from the trust-policy cache). */
54
54
  teamMembershipLookup: TeamMembershipLookup;
55
55
  /** Whether the run triggerer may self-approve (org_settings.allow_self_approval). */
56
56
  allowSelfApproval: boolean;
@@ -88,11 +88,10 @@ export declare class AccessLogWriter {
88
88
  recordInTransaction(executor: Kysely<Database> | Transaction<Database>, entry: AccessLogRecord): Promise<void>;
89
89
  private insert;
90
90
  /**
91
- * Phase D: delegates to `loadAccessLogRange` so cold-store rows are
91
+ * Delegates to `loadAccessLogRange` so cold-store rows are
92
92
  * merged transparently when pagination crosses the warm cutoff. The
93
93
  * caller-visible `{items, nextCursor}` shape is preserved. NO
94
- * --include-archived flag — access_log is "paginated/transparent"
95
- * per design §7 row 11.
94
+ * --include-archived flag — access_log is "paginated/transparent".
96
95
  */
97
96
  query(filter: AccessLogQueryFilter): Promise<AccessLogQueryResult>;
98
97
  /**
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Holding a build job's success until the cache publish its agent reported
3
+ * just before it has finished.
4
+ *
5
+ * A build agent sends `cache.upload.complete` and then, moments later, the
6
+ * build's terminal `job.status success`. The agent WebSocket handler runs
7
+ * frames concurrently, so without this record the success can release the
8
+ * jobs that wait on the build while the pointer naming the uploaded tarball is
9
+ * still being written — and they dispatch without the cache URL.
10
+ *
11
+ * The upload frame registers here before its first `await`. Frames enter the
12
+ * handler in wire order, so the registration is in place by the time the
13
+ * success frame is handled. The success then waits, bounded by the org's
14
+ * `cache_upload_settle_timeout_ms` (cluster default
15
+ * `KICI_CACHE_UPLOAD_SETTLE_TIMEOUT_MS`).
16
+ */
17
+ import type { Kysely } from 'kysely';
18
+ import type { Database } from '../db/types.js';
19
+ /** How a build success's wait for its cache publish ended. */
20
+ export declare enum CacheUploadSettleOutcome {
21
+ /** No publish was in flight for the job. */
22
+ None = "none",
23
+ /** The effective timeout is 0: the wait is turned off. */
24
+ Disabled = "disabled",
25
+ /** Every in-flight publish finished, successfully or not. */
26
+ Settled = "settled",
27
+ /** The bound passed first. The publish may still finish afterwards. */
28
+ TimedOut = "timed-out"
29
+ }
30
+ /**
31
+ * The cache publishes in flight, per job. A full build registers two (the
32
+ * dependency tarball and the source tarball); a publish always settles —
33
+ * success or failure — so a waiter never sees a rejection.
34
+ */
35
+ export declare class InFlightCacheUploads {
36
+ private readonly inFlight;
37
+ /** Register one publish for `jobId`; the returned function settles it (idempotent). */
38
+ begin(jobId: string): () => void;
39
+ has(jobId: string): boolean;
40
+ /** Number of jobs with a publish in flight. */
41
+ get size(): number;
42
+ /**
43
+ * Wait for every publish registered for `jobId` at call time, bounded by
44
+ * `timeoutMs`. A timeout leaves the records in place: they clear when their
45
+ * publishes settle.
46
+ */
47
+ waitFor(jobId: string, timeoutMs: number): Promise<CacheUploadSettleOutcome>;
48
+ }
49
+ /** What the agent WebSocket handler needs to hold a build's success. */
50
+ export interface CacheUploadSettle {
51
+ uploads: InFlightCacheUploads;
52
+ /** The effective bound for the job's org (org override, else cluster default). */
53
+ timeoutMsFor: (orgId: string | undefined) => Promise<number>;
54
+ }
55
+ export interface CacheUploadSettleResult {
56
+ outcome: CacheUploadSettleOutcome;
57
+ timeoutMs?: number;
58
+ waitedMs?: number;
59
+ }
60
+ /**
61
+ * Wait for a job's in-flight cache publishes. Reads the setting only when a
62
+ * publish is in flight, so an ordinary job's success costs no query.
63
+ */
64
+ export declare function awaitCacheUploadSettle(settle: CacheUploadSettle | undefined, job: {
65
+ jobId: string;
66
+ orgId: string | undefined;
67
+ }): Promise<CacheUploadSettleResult>;
68
+ /**
69
+ * Resolve the settle bound for an org: `org_settings.cache_upload_settle_timeout_ms`
70
+ * when set (0 included), otherwise `fallbackMs`. A missing DB, org, row or
71
+ * value, or a failed query, falls back — the caller is a frame handler that
72
+ * must not reject.
73
+ */
74
+ export declare function createCacheUploadSettleTimeoutReader(db: Kysely<Database> | undefined, fallbackMs: number): (orgId: string | undefined) => Promise<number>;
75
+ //# sourceMappingURL=cache-upload-settle.d.ts.map
@@ -28,6 +28,15 @@ export interface InitResult {
28
28
  * explicit `false` suppresses.
29
29
  */
30
30
  filterPassed?: boolean;
31
+ /**
32
+ * Verdict on the workflow's deferred `paths`, reported only when the init job
33
+ * was asked to decide them. `false` means the agent's clone diff matched none
34
+ * of them and the job must not be dispatched.
35
+ *
36
+ * Optional on purpose: an agent that predates deferred paths never sends it,
37
+ * so absence means "no verdict" and dispatch proceeds.
38
+ */
39
+ pathsPassed?: boolean;
31
40
  }
32
41
  export declare class PendingInitTracker extends PendingTracker<InitResult> {
33
42
  constructor();
@@ -33,11 +33,12 @@ export interface CancelRunDeps {
33
33
  */
34
34
  instanceId?: string;
35
35
  /**
36
- * Forward `job.cancel` to the coordinator holding the agent's socket.
37
- * Returns whether the send left this process. Undefined ⇒ no peer transport,
38
- * so a job owned by a sibling is unreachable rather than orphaned.
36
+ * Forward `job.cancel` to the coordinator holding the agent's socket, with
37
+ * `force` when the cancel is forced. Returns whether the send left this
38
+ * process. Undefined ⇒ no peer transport, so a job owned by a sibling is
39
+ * unreachable rather than orphaned.
39
40
  */
40
- cancelJobOnPeer?: (peerId: string, runId: string, jobId: string, reason: string) => boolean;
41
+ cancelJobOnPeer?: (peerId: string, runId: string, jobId: string, reason: string, force?: boolean) => boolean;
41
42
  /** How stale a `cluster_instances` heartbeat may be and still read as live. */
42
43
  ownershipGraceMs?: number;
43
44
  /**
@@ -112,4 +113,21 @@ export declare class HeldRunCancelRefusedError extends Error {
112
113
  * returns a structured already-terminal result).
113
114
  */
114
115
  export declare function cancelRunWithReason(deps: CancelRunDeps, runId: string, reason: string, options?: CancelRunOptions): Promise<CancelRunResult>;
116
+ /**
117
+ * Send `job.cancel` down this coordinator's own socket for the agent.
118
+ *
119
+ * Only an OPEN socket can receive it. A socket mid-close is still in the
120
+ * registry until its close handler unregisters it, and sending to it throws, so
121
+ * a non-OPEN socket leaves the job un-notified and the orphan sweep takes it.
122
+ * The send is wrapped so one bad socket cannot abort the whole cancellation and
123
+ * strand the run in `cancelling`.
124
+ */
125
+ export declare function sendLocalCancel(args: {
126
+ registry: Pick<AgentRegistry, 'get'>;
127
+ runId: string;
128
+ jobId: string;
129
+ agentId: string | null;
130
+ reason: string;
131
+ force: boolean;
132
+ }): boolean;
115
133
  //# sourceMappingURL=cancel-run.d.ts.map
@@ -0,0 +1,50 @@
1
+ /**
2
+ * The receiving end of `peer.job.cancel`.
3
+ *
4
+ * A sibling forwards a cancel to the coordinator its agent is connected to,
5
+ * which it reads from the host roster. That coordinator's dispatcher tracks the
6
+ * job only when it dispatched or re-adopted it: an agent that reconnected here
7
+ * from a sibling, or one not yet back after this process restarted, is known
8
+ * only to `dispatch_queue.agent_id`. So the agent is resolved from the
9
+ * dispatcher first and from the dispatch record second, and a cancel that
10
+ * cannot be delivered is logged with the reason.
11
+ */
12
+ import type { Kysely } from 'kysely';
13
+ import { z } from 'zod';
14
+ import type { PeerJobCancel } from '@kici-dev/engine';
15
+ import type { Database } from '../db/types.js';
16
+ import type { AgentRegistry } from '../agent/registry.js';
17
+ import type { Dispatcher } from '../agent/dispatcher.js';
18
+ export declare const PeerCancelOutcome: z.ZodEnum<{
19
+ "agent-not-connected": "agent-not-connected";
20
+ delivered: "delivered";
21
+ "lookup-failed": "lookup-failed";
22
+ "not-tracked": "not-tracked";
23
+ }>;
24
+ export type PeerCancelOutcome = z.infer<typeof PeerCancelOutcome>;
25
+ /** A live dispatch row: the job and the agent it was handed to. */
26
+ export interface DispatchedAgent {
27
+ jobId: string;
28
+ agentId: string | null;
29
+ }
30
+ export interface PeerCancelDelivery extends DispatchedAgent {
31
+ outcome: PeerCancelOutcome;
32
+ }
33
+ export interface PeerJobCancelDeps {
34
+ dispatcher: Pick<Dispatcher, 'getAgentIdForJob' | 'getTrackedJobIdsForRun'>;
35
+ registry: Pick<AgentRegistry, 'get'>;
36
+ /** The durable dispatch record. Absent on a worker, which has no database. */
37
+ lookupDispatched?: (runId: string, jobId: string | undefined) => Promise<DispatchedAgent[]>;
38
+ logger: {
39
+ info(message: string, meta?: object): unknown;
40
+ warn(message: string, meta?: object): unknown;
41
+ };
42
+ }
43
+ /** Read the live dispatch rows of a run, or of one job of it. */
44
+ export declare function readDispatchedAgents(db: Kysely<Database>, runId: string, jobId: string | undefined): Promise<DispatchedAgent[]>;
45
+ /**
46
+ * Deliver a `peer.job.cancel` to the agents connected here. Resolves; never
47
+ * rejects: every failure is an outcome and a warn line.
48
+ */
49
+ export declare function deliverPeerJobCancel(deps: PeerJobCancelDeps, msg: PeerJobCancel): Promise<PeerCancelDelivery[]>;
50
+ //# sourceMappingURL=peer-job-cancel.d.ts.map
@@ -3,7 +3,9 @@ import type { Database } from '../db/types.js';
3
3
  export interface SweepStuckCancellingDeps {
4
4
  db: Kysely<Database>;
5
5
  /** The canonical cancel path, bound to this orchestrator's deps. */
6
- cancelRun: (runId: string, reason: string) => Promise<unknown>;
6
+ cancelRun: (runId: string, reason: string, options: {
7
+ force: boolean;
8
+ }) => Promise<unknown>;
7
9
  /**
8
10
  * How long a run may sit in `cancelling` before it is re-driven. Twice the
9
11
  * recovery grace period: long enough that a graceful agent teardown finishes
@@ -2,9 +2,9 @@
2
2
  * Access log commands for kici-admin.
3
3
  *
4
4
  * Operator-facing read access to the orchestrator's access_log table
5
- * (read + mutation attribution with ActorPrincipal). Dogfood replacement
6
- * for raw psql when an operator asks "who read this run's payload last
7
- * Tuesday" or "show me everything a platform_operator actor did".
5
+ * (read + mutation attribution with ActorPrincipal). Use it instead of raw
6
+ * psql when an operator asks "who read this run's payload last Tuesday" or
7
+ * "show me everything a platform_operator actor did".
8
8
  *
9
9
  * access-log list List access-log rows with filters (cursor-paginated)
10
10
  * access-log show Show a single entry by id
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The env file `kici-admin agent install` writes for a new agent. Each field
3
+ * lands in the variable the agent's config loader reads; that loader refuses
4
+ * any KICI_* variable it does not know, so a misspelt key here stops the agent
5
+ * at startup. `agent-env.test.ts` loads the rendered file through the agent's
6
+ * own loader to hold the two together.
7
+ */
8
+ export interface AgentEnvFields {
9
+ /** First line of the file, a `#` comment naming what wrote it. */
10
+ header: string;
11
+ orchestratorUrl?: string;
12
+ token?: string;
13
+ /** Routing labels, written comma-separated. */
14
+ labels?: string[];
15
+ /** The agent's HTTP port; omitted, the agent uses its default. */
16
+ port?: number;
17
+ }
18
+ /** Render the env file, one `KEY=value` line per field that was given. */
19
+ export declare function renderAgentEnvFile(fields: AgentEnvFields): string;
20
+ //# sourceMappingURL=agent-env.d.ts.map
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * `kici-admin agent status` command.
3
3
  *
4
- * Shows OS-level service status (state, PID, uptime) and queries
5
- * the running agent's health API for agent-specific info (labels,
6
- * orchestrator connection, current job).
4
+ * Shows OS-level service status (state, PID, uptime) and queries the
5
+ * running agent's `/health` endpoint for its ID, orchestrator connection,
6
+ * active job count, version, build fingerprint and uptime.
7
7
  *
8
8
  * Target resolution goes through resolveInstanceTarget — the same priority chain
9
9
  * every lifecycle command uses (--instance-dir > --name > CWD manifest >
@@ -6,7 +6,7 @@
6
6
  * unverifiable rows; `--all` re-evaluates
7
7
  * every row. Direct DB + object storage.
8
8
  *
9
- * Classified `kici-admin` (orchestrator DB plane) per .claude/rules/platform-admin.md.
9
+ * Belongs to `kici-admin`: it works on the orchestrator's database.
10
10
  */
11
11
  import type { Command } from 'commander';
12
12
  import type { AdminApiClient } from '../api-client.js';
@@ -18,8 +18,8 @@
18
18
  *
19
19
  * Direct-DB mode: activated when `--database-url` is passed (or
20
20
  * KICI_DATABASE_URL / DATABASE_URL is set). Opens its own pool and runs the
21
- * SQL directly via *Direct helpers in @kici-dev/shared. Used by E2E
22
- * `globalSetup` helpers that need to seed envs before the orchestrator is up.
21
+ * SQL directly via *Direct helpers in @kici-dev/shared, so a setup script can
22
+ * seed contexts before the orchestrator is up.
23
23
  */
24
24
  import type { Command } from 'commander';
25
25
  import type { AdminApiClient } from '../api-client.js';
@@ -6,12 +6,11 @@
6
6
  * event-dlq retry <id> — clear DLQ flag, schedule for retry, pg_notify
7
7
  * event-dlq discard <id> — permanently delete a DLQ event
8
8
  *
9
- * Operator dogfooding path for at-least-once event delivery. Customers
10
- * should generally never see anything in
11
- * the DLQ — when something lands here it usually means a workflow handler is
12
- * consistently failing and should be fixed at its root cause. This CLI is the
13
- * triage surface: inspect last_error, retry once a fix is deployed, or discard
14
- * if the event is no longer relevant.
9
+ * Operator triage path for at-least-once event delivery. Customers should
10
+ * generally never see anything in the DLQ — when something lands here it
11
+ * usually means a workflow handler is consistently failing and should be fixed
12
+ * at its root cause. This CLI is the triage surface: inspect last_error, retry
13
+ * once a fix is deployed, or discard if the event is no longer relevant.
15
14
  */
16
15
  import type { Command } from 'commander';
17
16
  import type { AdminApiClient } from '../api-client.js';
@@ -2,9 +2,8 @@
2
2
  * Inbound webhook delivery log commands for kici-admin.
3
3
  *
4
4
  * Operator-facing read access to the orchestrator's event_log table via the
5
- * admin HTTP API. Dogfood replacement for raw psql / log-grep when an
6
- * operator asks "did delivery <id> arrive, and what did its payload look
7
- * like".
5
+ * admin HTTP API. Use it instead of raw psql / log-grep when an operator
6
+ * asks "did delivery <id> arrive, and what did its payload look like".
8
7
  *
9
8
  * event-log list List inbound deliveries with filters
10
9
  * event-log show Show a single delivery (optionally with payload)
@@ -7,9 +7,7 @@
7
7
  * READ-ONLY — mutations (purge-stale) live in `maintenance.ts` instead.
8
8
  * Dual-mode: HTTP (via AdminApiClient) or `--database-url` (direct DB).
9
9
  *
10
- * supersedes the original `cache list|show` framing: the real tables
11
- * the E2E call sites touch are execution_runs / execution_jobs, not
12
- * dedup_cache.
10
+ * The rows come from execution_runs / execution_jobs, not dedup_cache.
13
11
  */
14
12
  import type { Command } from 'commander';
15
13
  import type { AdminApiClient } from '../api-client.js';
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Render the post-receive hook script. For each pushed ref the hook calls
3
- * `kici-admin source trigger-local <id> --ref <ref> --sha <new> --base-url <url>`,
4
- * so a push to any branch dispatches a run for that ref.
3
+ * `kici-admin source trigger-local <id> --ref <ref> --before <old> --sha <new> --base-url <url>`,
4
+ * so a push to any branch dispatches a run for that ref, and its changed files
5
+ * are the commits the push added (`<old>..<new>`).
5
6
  */
6
7
  export declare function renderPostReceiveHook(opts: {
7
8
  sourceId: string;
@@ -5,6 +5,11 @@ export interface LocalTriggerInput {
5
5
  event: 'push' | 'pull_request';
6
6
  ref: string;
7
7
  sha: string;
8
+ /**
9
+ * The commit before the push. With it the changed files are `before..sha`;
10
+ * without it the push has no range and path filters match conservatively.
11
+ */
12
+ before?: string;
8
13
  defaultBranch: string;
9
14
  }
10
15
  export interface LocalTriggerRequest {
@@ -19,6 +24,8 @@ export declare function readRepoHead(repoPath: string): {
19
24
  ref: string;
20
25
  sha: string;
21
26
  };
27
+ /** The parent of `sha` in a local repo, or undefined for a root commit or an unreadable repo. */
28
+ export declare function readParentSha(repoPath: string, sha: string): string | undefined;
22
29
  /** POST the trigger request to the orchestrator base URL. Returns the HTTP status. */
23
30
  export declare function sendLocalTrigger(baseUrl: string, req: LocalTriggerRequest): Promise<number>;
24
31
  //# sourceMappingURL=local-trigger.d.ts.map