@kici-dev/orchestrator 0.5.0 → 0.6.1
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.
- package/dist/__test-helpers__/fake-scaler-state-store.d.ts +24 -0
- package/dist/__test-helpers__/mock-db-query.d.ts +130 -0
- package/dist/__test-helpers__/mock-db.d.ts +23 -0
- package/dist/agent/dispatcher.d.ts +81 -13
- package/dist/agent/host-roster.d.ts +37 -5
- package/dist/agent/registry.d.ts +2 -0
- package/dist/app.d.ts +33 -6
- package/dist/approvals/apply-decision.d.ts +67 -19
- package/dist/approvals/held-run-release-wiring.d.ts +45 -0
- package/dist/approvals/independent-wiring.d.ts +55 -0
- package/dist/approvals/resume-router.d.ts +9 -0
- package/dist/approvals/triggerer-subject.d.ts +37 -0
- package/dist/cache/dep-cache.d.ts +54 -10
- package/dist/cache/global-eval-round-cache.d.ts +7 -0
- package/dist/cli/api-client.d.ts +18 -0
- package/dist/cli/commands/cluster-settings.d.ts +11 -0
- package/dist/cli/commands/diagnose.d.ts +6 -0
- package/dist/cli/commands/held-run.d.ts +58 -0
- package/dist/cli/commands/trust-policy.d.ts +117 -12
- package/dist/cli/kici-admin.d.ts +10 -0
- package/dist/cli.js +2272 -1025
- package/dist/cluster/cluster-identity.d.ts +3 -3
- package/dist/cluster/cluster-settings-reader.d.ts +7 -1
- package/dist/cluster/coordinator.d.ts +44 -0
- package/dist/cluster/index.d.ts +4 -0
- package/dist/cluster/peer-handler.d.ts +19 -0
- package/dist/cluster/peer-registry.d.ts +17 -0
- package/dist/cluster/plan-headroom-store.d.ts +26 -0
- package/dist/cluster/worker-eviction.d.ts +69 -0
- package/dist/cold-store/load-event-log-range.d.ts +10 -3
- package/dist/cold-store/load-secret-audit-log-range.d.ts +4 -3
- package/dist/cold-store/tables/secret-audit-log.d.ts +4 -3
- package/dist/config.d.ts +21 -21
- package/dist/contexts/held-runs.d.ts +123 -16
- package/dist/contexts/protection/aggregate.d.ts +3 -2
- package/dist/contexts/protection/branch-gate.d.ts +15 -0
- package/dist/contexts/protection/concurrency-gate.d.ts +8 -2
- package/dist/contexts/protection/pipeline.d.ts +18 -0
- package/dist/contexts/release-queued-holds.d.ts +35 -0
- package/dist/dashboard/attestation-filters.d.ts +8 -0
- package/dist/dashboard/handler.d.ts +6 -24
- package/dist/db/migrations/116_org_plan_headroom.d.ts +4 -0
- package/dist/db/migrations/117_invoke_gate_proxy_jobs.d.ts +4 -0
- package/dist/db/migrations/118_invoke_gate_scheduling.d.ts +4 -0
- package/dist/db/migrations/119_scaler_ha_ownership.d.ts +4 -0
- package/dist/db/migrations/120_cluster_settings_scaler_reaper.d.ts +4 -0
- package/dist/db/migrations/121_org_settings_allow_untrusted_dockerfile_builds.d.ts +19 -0
- package/dist/db/migrations/122_host_roster_scaler_managed.d.ts +25 -0
- package/dist/db/migrations/123_workflow_registrations_default_branch.d.ts +24 -0
- package/dist/db/migrations/124_cluster_settings_provision_backoff.d.ts +4 -0
- package/dist/db/migrations/125_org_trust_directory.d.ts +30 -0
- package/dist/db/migrations/126_held_runs_posted_pending_check.d.ts +28 -0
- package/dist/db/migrations/127_org_trust_policy_approval_expiry_seconds.d.ts +26 -0
- package/dist/db/migrations/128_execution_runs_global_eval_round.d.ts +23 -0
- package/dist/db/migrations/129_execution_runs_dispatch_routing_key.d.ts +24 -0
- package/dist/db/migrations/130_scaler_provision_outcomes.d.ts +32 -0
- package/dist/db/types.d.ts +368 -10
- package/dist/entry-helpers.d.ts +28 -0
- package/dist/events/event-emitter.d.ts +22 -0
- package/dist/events/event-router.d.ts +87 -1
- package/dist/events/types.d.ts +2 -23
- package/dist/git/credential-broker.d.ts +94 -0
- package/dist/git/inherited-secret.d.ts +24 -0
- package/dist/git/installation-token.d.ts +38 -0
- package/dist/git/job-context.d.ts +13 -0
- package/dist/index.js +324 -84
- package/dist/metrics/agent-metrics-aggregator.d.ts +2 -2
- package/dist/metrics/prometheus.d.ts +111 -3
- package/dist/oidc/oidc-mint-registration.d.ts +7 -3
- package/dist/orchestrator-core.d.ts +79 -23
- package/dist/pipeline/direct-ingress-deps.d.ts +100 -0
- package/dist/pipeline/dispatch-matched-workflow.d.ts +302 -31
- package/dist/pipeline/global-eval-round.d.ts +14 -0
- package/dist/pipeline/internal-event-pipeline.d.ts +140 -0
- package/dist/pipeline/invoke-gate.d.ts +164 -0
- package/dist/pipeline/needs-scheduler.d.ts +13 -0
- package/dist/pipeline/process-webhook.d.ts +119 -31
- package/dist/pipeline/processor.d.ts +226 -21
- package/dist/pipeline/rerun.d.ts +21 -0
- package/dist/pipeline/resume-workflow.d.ts +40 -7
- package/dist/pipeline/route-or-dispatch-jobs.d.ts +9 -0
- package/dist/pipeline/security-hold-check.d.ts +217 -0
- package/dist/pipeline/undispatched-hold-checks.d.ts +23 -0
- package/dist/policy/dashboard-write-policy-listener.d.ts +62 -0
- package/dist/policy/dashboard-write-policy.d.ts +14 -0
- package/dist/provider-registry.d.ts +10 -2
- package/dist/providers/github/check-status-poster.d.ts +11 -0
- package/dist/providers/github/index.d.ts +0 -2
- package/dist/providers/github/normalizer.d.ts +3 -2
- package/dist/providers/local/normalizer.d.ts +3 -5
- package/dist/providers/universal-git/index.d.ts +11 -2
- package/dist/queue/job-queue.d.ts +43 -1
- package/dist/registration/extractor.d.ts +3 -3
- package/dist/registration/registration-index.d.ts +7 -0
- package/dist/registration/registration-store.d.ts +22 -0
- package/dist/reporting/check-run-reporter.d.ts +94 -1
- package/dist/reporting/check-run-summary.d.ts +25 -1
- package/dist/reporting/execution-tracker.d.ts +207 -2
- package/dist/reporting/run-aggregator.d.ts +4 -14
- package/dist/reporting/step-display-order.d.ts +43 -0
- package/dist/routes/admin-held-runs.d.ts +142 -0
- package/dist/routes/admin-trust-policy.d.ts +34 -6
- package/dist/routes/admin.d.ts +9 -0
- package/dist/scaler/backend-factory.d.ts +55 -0
- package/dist/scaler/bare-metal-backend.d.ts +43 -5
- package/dist/scaler/claim-store.d.ts +119 -0
- package/dist/scaler/config.d.ts +4 -0
- package/dist/scaler/container-backend.d.ts +18 -4
- package/dist/scaler/container-routing.d.ts +23 -0
- package/dist/scaler/container-spawn.d.ts +28 -0
- package/dist/scaler/event-backend.d.ts +124 -0
- package/dist/scaler/event-provision-reaper.d.ts +350 -0
- package/dist/scaler/failure-tracker.d.ts +1 -1
- package/dist/scaler/firecracker-backend.d.ts +33 -6
- package/dist/scaler/index.d.ts +11 -1
- package/dist/scaler/label-matcher.d.ts +4 -3
- package/dist/scaler/manager.d.ts +899 -72
- package/dist/scaler/resolve-container-auth.d.ts +45 -0
- package/dist/scaler/scaler-events.d.ts +11 -0
- package/dist/scaler/scaler-state-store.d.ts +294 -10
- package/dist/scaler/types.d.ts +131 -13
- package/dist/scaler/warm-pool.d.ts +132 -29
- package/dist/security/comment-handler.d.ts +50 -11
- package/dist/security/identity-link.d.ts +60 -0
- package/dist/security/lock-source.d.ts +11 -13
- package/dist/security/reduced-privilege-note.d.ts +59 -0
- package/dist/security/trust-directory-store.d.ts +233 -0
- package/dist/security/trust-policy-gate.d.ts +94 -59
- package/dist/security/trust-policy-store.d.ts +3 -0
- package/dist/security/trust-resolver.d.ts +14 -98
- package/dist/server.d.ts +11 -1
- package/dist/server.js +17684 -7351
- package/dist/stale-detector/gate-deadline-detector.d.ts +52 -0
- package/dist/stale-detector/stale-run-detector.d.ts +61 -3
- package/dist/standalone.js +24238 -13822
- package/dist/worker/in-memory-job-queue.d.ts +1 -1
- package/dist/ws/agent-handler.d.ts +28 -4
- package/dist/ws/dashboard-context-handler.d.ts +28 -4
- package/dist/ws/dashboard-global-workflows-handler.d.ts +6 -0
- package/dist/ws/failure-messages.d.ts +2 -0
- package/dist/ws/git-credential-relay.d.ts +39 -0
- package/dist/ws/oidc-token-relay.d.ts +6 -11
- package/dist/ws/platform-client.d.ts +54 -9
- package/installer-image-digests.json +3 -3
- package/package.json +24 -19
- package/sbom.spdx.json +864 -822
- package/dist/approvals/team-membership-lookup.d.ts +0 -13
- package/dist/providers/github/contributor-resolver.d.ts +0 -30
- package/dist/security/contributor-cache.d.ts +0 -83
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* make Mimir cardinality grow with the number of agents that have ever
|
|
10
10
|
* existed (every ephemeral firecracker microVM minted a fresh ID), which
|
|
11
11
|
* is unbounded. The caller-side dashboard filters by `scaler` instead,
|
|
12
|
-
* which has a fixed enum of values (`stateful
|
|
13
|
-
* `
|
|
12
|
+
* which has a fixed enum of values (`stateful`, plus every
|
|
13
|
+
* `ScalerBackendType`).
|
|
14
14
|
*
|
|
15
15
|
* Aggregation rules per metric kind:
|
|
16
16
|
* - counter / upDownCounter / gauge → SUM across agents in the pool
|
|
@@ -34,14 +34,97 @@ interface ScalerUsageRow {
|
|
|
34
34
|
* the on-disk ledger snapshot. Per-scaler rows omit `machinePool`.
|
|
35
35
|
*/
|
|
36
36
|
export declare function setScalerUsageBreakdown(rows: ScalerUsageRow[]): void;
|
|
37
|
+
interface WarmPoolGaugeRow {
|
|
38
|
+
/** Operator-chosen scaler name that owns the pool. */
|
|
39
|
+
scaler: string;
|
|
40
|
+
/** Normalized label set the pool keeps agents ready for. */
|
|
41
|
+
labelSet: string;
|
|
42
|
+
target: number;
|
|
43
|
+
ready: number;
|
|
44
|
+
inFlight: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Replace the current warm-pool fill state.
|
|
48
|
+
*
|
|
49
|
+
* Called by ScalerManager after each warm-pool tick and after a config reload,
|
|
50
|
+
* so the gauges follow the pool rather than the scrape.
|
|
51
|
+
*/
|
|
52
|
+
export declare function setWarmPoolGauges(rows: WarmPoolGaugeRow[]): void;
|
|
53
|
+
/**
|
|
54
|
+
* Total warm-pool spawns started.
|
|
55
|
+
* Labels:
|
|
56
|
+
* - scaler: operator-chosen scaler name that owns the pool.
|
|
57
|
+
*/
|
|
58
|
+
export declare const scalerWarmPoolSpawnsTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
59
|
+
/** Record a warm-pool spawn starting. */
|
|
60
|
+
export declare function incWarmPoolSpawns(scaler: string): void;
|
|
61
|
+
/**
|
|
62
|
+
* Total warm-pool agents destroyed as surplus to the pool's target — either
|
|
63
|
+
* past `idleTimeoutSeconds`, or immediately when a config reload lowers the
|
|
64
|
+
* target. Both paths run through the same destroy callback, so the counter
|
|
65
|
+
* covers both.
|
|
66
|
+
* Labels:
|
|
67
|
+
* - scaler: operator-chosen scaler name that owns the pool.
|
|
68
|
+
*/
|
|
69
|
+
export declare const scalerWarmPoolReapedTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
70
|
+
/** Record a warm-pool agent being destroyed. */
|
|
71
|
+
export declare function incWarmPoolReaped(scaler: string): void;
|
|
37
72
|
/** Increment the spawn-refusal counter (called by ScalerManager when a request fails the cap check). */
|
|
38
73
|
export declare function incScalerSpawnRefusals(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Why an event scaler's cluster-wide cap check failed.
|
|
76
|
+
*
|
|
77
|
+
* `reason` label for `kici_orch_scaler_cap_lock_failures_total`. The two are a
|
|
78
|
+
* different fault with a different operator response, so they must not share a
|
|
79
|
+
* series any more than either may share one with a plain capacity refusal.
|
|
80
|
+
* - `contended` — the advisory lock was still held when the wait budget
|
|
81
|
+
* expired. The database is healthy; several coordinators are scaling one hot
|
|
82
|
+
* scaler at once. Raise the scaler's cap, or the wait budget.
|
|
83
|
+
* - `unreachable` — the cap could not be evaluated at all (connection lost,
|
|
84
|
+
* statement timeout, schema error). Event autoscaling is stalled on the
|
|
85
|
+
* database and no cap arithmetic is happening anywhere.
|
|
86
|
+
*/
|
|
87
|
+
export declare const ScalerCapLockFailureReason: {
|
|
88
|
+
readonly Contended: 'contended';
|
|
89
|
+
readonly Unreachable: 'unreachable';
|
|
90
|
+
};
|
|
91
|
+
export type ScalerCapLockFailureReason = (typeof ScalerCapLockFailureReason)[keyof typeof ScalerCapLockFailureReason];
|
|
92
|
+
/**
|
|
93
|
+
* Total event-scaler cluster-wide cap checks that failed, so their spawn was
|
|
94
|
+
* refused without the cap ever being evaluated.
|
|
95
|
+
*
|
|
96
|
+
* Deliberately NOT folded into `kici_orch_scaler_spawn_refusals_total`: that
|
|
97
|
+
* series means "the cluster is full", and the operator response is to add
|
|
98
|
+
* capacity or raise a cap. This one means the cap could not be evaluated, so
|
|
99
|
+
* event spawns fail closed for a reason that has nothing to do with capacity.
|
|
100
|
+
* Labels:
|
|
101
|
+
* - reason: contended (the lock wait budget expired) | unreachable (the cap could not be evaluated at all)
|
|
102
|
+
*/
|
|
103
|
+
export declare const scalerCapLockFailuresTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
39
104
|
/**
|
|
40
105
|
* Record `count` pending jobs re-driven through the scaler by `trigger`
|
|
41
106
|
* (`hook` = capacity-freed callback, `sweep` = leader-gated backstop).
|
|
42
107
|
* Called by the dispatcher's metrics facade.
|
|
43
108
|
*/
|
|
44
109
|
export declare function incScalerRedispatch(trigger: ScalerRedispatchTrigger, count: number): void;
|
|
110
|
+
/** Record a scale-up event emitted for `scaler`. */
|
|
111
|
+
export declare function incScalerScaleUpEmitted(scaler: string): void;
|
|
112
|
+
/** Record a scale-down event emitted for `scaler` with the teardown `reason`. */
|
|
113
|
+
export declare function incScalerScaleDownEmitted(scaler: string, reason: string): void;
|
|
114
|
+
/** Record an event-scaler provision that timed out before its agent registered. */
|
|
115
|
+
export declare function incScalerExternalProvisionTimeout(scaler: string): void;
|
|
116
|
+
/** Record an adoption lookup that could not reach its spawn record. */
|
|
117
|
+
export declare function incScalerAdoptionLookupFailure(): void;
|
|
118
|
+
/** Set the current count of in-flight (provisioning + active) external agents for `scaler`. */
|
|
119
|
+
export declare function setScalerExternalProvisioningActive(scaler: string, count: number): void;
|
|
120
|
+
/**
|
|
121
|
+
* Set how many event-scaler provisions the leader has been unable to see an
|
|
122
|
+
* agent for, for at least the flap grace. Zero on every non-leader, and on a
|
|
123
|
+
* leader whose sweep is blocked.
|
|
124
|
+
*/
|
|
125
|
+
export declare function setScalerReapUnseenProvisions(count: number): void;
|
|
126
|
+
/** Set whether this coordinator's provision reaper is standing down (1) or sweeping (0). */
|
|
127
|
+
export declare function setScalerReapBlocked(blocked: boolean): void;
|
|
45
128
|
/**
|
|
46
129
|
* Merge current per-label counts with explicit `0`s for previously-seen labels
|
|
47
130
|
* whose queue has drained. Mutates `everSeen` to include the current labels.
|
|
@@ -128,13 +211,27 @@ export declare const webhooksProcessedTotal: import("@opentelemetry/api").Counte
|
|
|
128
211
|
/**
|
|
129
212
|
* Org trust-policy gate decisions.
|
|
130
213
|
* Labels:
|
|
131
|
-
* - arm: which policy arm decided —
|
|
132
|
-
* - action: pass | hold | reject
|
|
214
|
+
* - arm: which policy arm decided — fork_pr | none (the verdict carried no reason)
|
|
215
|
+
* - action: pass | ignore | hold | reject
|
|
133
216
|
*
|
|
134
217
|
* Incremented once per evaluated PR event, including passes, so the ratio of
|
|
135
218
|
* gated to ungated PRs is visible rather than only the gated ones.
|
|
136
219
|
*/
|
|
137
220
|
export declare const trustPolicyDecisionsTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
221
|
+
/**
|
|
222
|
+
* Fork pull-request events dropped by the org fork policy before any run row,
|
|
223
|
+
* check status, or job dispatch existed.
|
|
224
|
+
* Labels:
|
|
225
|
+
* - provider: the inbound delivery's provider (github, …)
|
|
226
|
+
*
|
|
227
|
+
* @conditionallyEmitted An org that does not ignore fork PRs emits no series.
|
|
228
|
+
*
|
|
229
|
+
* Distinct from `kici_orch_trust_policy_decisions_total{action="ignore"}`,
|
|
230
|
+
* which counts the verdict wherever it is reached: this counts the drop the
|
|
231
|
+
* ingest path actually performed, so a verdict that stopped being enforced
|
|
232
|
+
* shows as a divergence between the two rather than as silence.
|
|
233
|
+
*/
|
|
234
|
+
export declare const forkEventsIgnoredTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
138
235
|
/**
|
|
139
236
|
* Duration of trigger matching operations (lock file evaluation).
|
|
140
237
|
* Buckets: 1ms to 5s covering fast rejects through complex evaluations.
|
|
@@ -228,7 +325,7 @@ export type ScalerSpawnFailureBound = (typeof ScalerSpawnFailureBound)[keyof typ
|
|
|
228
325
|
/**
|
|
229
326
|
* Total scaler agent spawn failures.
|
|
230
327
|
* Labels:
|
|
231
|
-
* - backend: scaler backend type (bare-metal | container | firecracker | unknown)
|
|
328
|
+
* - backend: scaler backend type (bare-metal | container | event | firecracker | unknown)
|
|
232
329
|
* - bound: true (job-bound spawn) | false (warm-pool/unbound)
|
|
233
330
|
*/
|
|
234
331
|
export declare const scalerSpawnFailuresTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
@@ -371,6 +468,17 @@ export declare const eventRetryTotal: import("@opentelemetry/api").Counter<impor
|
|
|
371
468
|
* - reason: why the event was DLQ'd (exhausted_retries)
|
|
372
469
|
*/
|
|
373
470
|
export declare const eventDlqTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
471
|
+
/**
|
|
472
|
+
* Startup catch-up scans that threw. Emits no labels.
|
|
473
|
+
*
|
|
474
|
+
* The scan recovers the internal-event backlog a restart left behind, and it
|
|
475
|
+
* runs behind a boot latch that the composition root resolves after startup
|
|
476
|
+
* continues — so a failure cannot fail the bootstrap and is otherwise invisible
|
|
477
|
+
* until the backlog quietly ages into the DLQ. This counter is what an alert
|
|
478
|
+
* fires on; the accompanying `Deferred catch-up scan failed` log line carries
|
|
479
|
+
* the reason.
|
|
480
|
+
*/
|
|
481
|
+
export declare const eventCatchUpFailuresTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
374
482
|
/**
|
|
375
483
|
* Dispatch leases that timed out before the holding node finalised them
|
|
376
484
|
* (signals a node crash mid-dispatch). Emits no labels.
|
|
@@ -56,9 +56,13 @@ export interface OidcMintRegistrationInput {
|
|
|
56
56
|
};
|
|
57
57
|
db: Kysely<Database>;
|
|
58
58
|
orchestratorId: string;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Test-only fault-injection predicate forwarded to the relay mint handler,
|
|
61
|
+
* supplied only by the build-time test double. Only ever defers — the
|
|
62
|
+
* anti-forgery choke point is preserved. Undefined (the shipped default) means
|
|
63
|
+
* no fault injection.
|
|
64
|
+
*/
|
|
65
|
+
initialMintFault?: (audience: string) => boolean;
|
|
62
66
|
}
|
|
63
67
|
/** Decide which mint handler (if any) backs `OIDC_TOKEN_REQUEST_METHOD`. */
|
|
64
68
|
export declare function selectOidcMintRegistration(input: OidcMintRegistrationInput): OidcMintRegistration | undefined;
|
|
@@ -29,7 +29,7 @@ import { IngestOverflowBuffer } from './webhook/ingest-overflow-buffer.js';
|
|
|
29
29
|
import { IngestOverflowReplayer } from './webhook/ingest-overflow-replayer.js';
|
|
30
30
|
import { AgentMetricsAggregator } from './metrics/agent-metrics-aggregator.js';
|
|
31
31
|
import { SourceLocationStore } from './app.js';
|
|
32
|
-
import { ExecutionJobStatus, type
|
|
32
|
+
import { ExecutionJobStatus, type PeerHeartbeat, type PeerLogsCollectRequest, type PeerToPeerMessage, type InvokeResult } from '@kici-dev/engine';
|
|
33
33
|
import { ScalerManager } from './scaler/index.js';
|
|
34
34
|
import type { ScalerConfig } from './scaler/index.js';
|
|
35
35
|
import type { CacheStorage } from './storage/index.js';
|
|
@@ -38,12 +38,14 @@ import { type ResolvedDashboardEncryptionKey } from './secrets/dashboard-encrypt
|
|
|
38
38
|
import { SourceCache, BuildCoordinator, DepCache, UserCache, DispatchCacheRefTracker, PendingBuildTracker, PendingInitTracker, PendingDynamicTracker, PendingGlobalEvalTracker, GlobalEvalRoundCache } from './cache/index.js';
|
|
39
39
|
import { ArtifactStore } from './artifacts/artifact-store.js';
|
|
40
40
|
import { CheckRunReporter } from './reporting/check-run-reporter.js';
|
|
41
|
+
import type { ProcessingDeps } from './pipeline/processor.js';
|
|
42
|
+
import type { InvokeGateDeps, SummonArgs, SummonedRun } from './pipeline/invoke-gate.js';
|
|
41
43
|
import { StepLogBuffer } from './reporting/step-log-buffer.js';
|
|
42
44
|
import { type LogStorage } from './reporting/log-storage.js';
|
|
43
45
|
import { ExecutionTracker, type ExecutionTrackerDeps } from './reporting/execution-tracker.js';
|
|
44
46
|
import { LogWriter } from './reporting/log-writer.js';
|
|
45
47
|
import { type NormalizedLogChunk } from './reporting/log-chunk-sink.js';
|
|
46
|
-
import { PeerRegistry, PeerClient, createPeerHandler, RaftNode, OrphanRecovery, RunCoordinator } from './cluster/index.js';
|
|
48
|
+
import { PeerRegistry, PeerClient, createPeerHandler, RaftNode, OrphanRecovery, RunCoordinator, PlanHeadroomStore } from './cluster/index.js';
|
|
47
49
|
import { SourceStore, SourceManager } from './sources/index.js';
|
|
48
50
|
import { PgSecretStore, AuditLogger, SecretResolver } from './secrets/index.js';
|
|
49
51
|
import type { SecretStore } from '@kici-dev/engine';
|
|
@@ -51,11 +53,13 @@ import type { AdminRouteDeps } from './routes/admin.js';
|
|
|
51
53
|
import { AgentTokenStore } from './agent/token-store.js';
|
|
52
54
|
import { OwnershipTracker } from './agent/ownership-tracker.js';
|
|
53
55
|
import { EventStore } from './events/event-store.js';
|
|
54
|
-
import { EventRouter } from './events/event-router.js';
|
|
56
|
+
import { EventRouter, type EventMatchContext } from './events/event-router.js';
|
|
55
57
|
import { EventEmitter } from './events/event-emitter.js';
|
|
56
58
|
import { TrustStore } from './events/trust-store.js';
|
|
59
|
+
import type { OrchestratorFaultInjection } from './testing/fault-injection.js';
|
|
57
60
|
import { GenericSourceManager } from './webhook/generic-sources.js';
|
|
58
61
|
import { GenericSourcesChangeListener } from './webhook/generic-sources-listener.js';
|
|
62
|
+
import { DashboardWritePolicyChangeListener } from './policy/dashboard-write-policy-listener.js';
|
|
59
63
|
import { RegistrationStore } from './registration/registration-store.js';
|
|
60
64
|
import { RegistrationIndex } from './registration/registration-index.js';
|
|
61
65
|
import { CronScheduler } from './cron/cron-scheduler.js';
|
|
@@ -125,6 +129,8 @@ export interface OrchestratorSubsystems {
|
|
|
125
129
|
globalEvalCache: GlobalEvalRoundCache;
|
|
126
130
|
dedup: DedupCache;
|
|
127
131
|
eventRouter: EventRouter;
|
|
132
|
+
/** Invoke-gate dependencies (summon callback + chain-depth bound). */
|
|
133
|
+
invokeGateDeps: InvokeGateDeps;
|
|
128
134
|
/**
|
|
129
135
|
* Event store for custom internal events (system + custom). Exposed
|
|
130
136
|
* here so the dashboard handler can serve the per-org DLQ surface
|
|
@@ -153,6 +159,10 @@ export interface OrchestratorSubsystems {
|
|
|
153
159
|
getLocalInventory: () => Omit<PeerHeartbeat, 'type'>;
|
|
154
160
|
broadcastHeartbeatToAllPeers: () => void;
|
|
155
161
|
broadcastAgentTokenRevoke: (tokenId: string) => void;
|
|
162
|
+
/** Platform-owned worker-ceiling cache, read by the peer-handler admission gate. */
|
|
163
|
+
planHeadroomStore: PlanHeadroomStore;
|
|
164
|
+
/** Late-bind the coordinator's cluster.membership reporter (see ClusterInfra). */
|
|
165
|
+
setMembershipReporter: (report: () => void) => void;
|
|
156
166
|
joinHandler: JoinHandler;
|
|
157
167
|
configReloader: ConfigReloader;
|
|
158
168
|
localConfigVersion: number;
|
|
@@ -164,6 +174,12 @@ export interface OrchestratorSubsystems {
|
|
|
164
174
|
* Platform when a generic source is added/removed at runtime.
|
|
165
175
|
*/
|
|
166
176
|
genericSourcesChangeListener: GenericSourcesChangeListener;
|
|
177
|
+
/**
|
|
178
|
+
* Dashboard-write policy hot-reload listener. Keeps every coordinator's
|
|
179
|
+
* cached policy map — and the capability snapshot it advertises to the
|
|
180
|
+
* control plane — in step with a `kici-admin` write served by any peer.
|
|
181
|
+
*/
|
|
182
|
+
dashboardWritePolicyChangeListener: DashboardWritePolicyChangeListener;
|
|
167
183
|
/** Inbound webhook delivery log writer (event_log table + object-storage payloads). */
|
|
168
184
|
eventLogWriter: EventLogWriter;
|
|
169
185
|
/** Access log writer (read + mutation attribution for dashboard + admin). */
|
|
@@ -204,6 +220,17 @@ export interface OrchestratorSubsystems {
|
|
|
204
220
|
ingestOverflowBuffer: IngestOverflowBuffer;
|
|
205
221
|
/** Background replayer draining the overflow buffer once capacity recovers. */
|
|
206
222
|
ingestOverflowReplayer: IngestOverflowReplayer;
|
|
223
|
+
/**
|
|
224
|
+
* The live direct-ingress `ProcessingDeps` bag, assembled inside `createApp`.
|
|
225
|
+
*
|
|
226
|
+
* A mode hook that has to resume a held run needs the same bag the pipeline
|
|
227
|
+
* that created the hold used — otherwise the resume runs against a second,
|
|
228
|
+
* hand-assembled bag that can silently diverge from it. `createApp` runs
|
|
229
|
+
* AFTER `onSubsystemsReady`, so this throws until it has, which is why every
|
|
230
|
+
* caller must invoke it lazily (inside a release callback, never at wiring
|
|
231
|
+
* time).
|
|
232
|
+
*/
|
|
233
|
+
buildProcessingDeps: () => ProcessingDeps;
|
|
207
234
|
}
|
|
208
235
|
/**
|
|
209
236
|
* Mode-specific hooks injected by each entry point.
|
|
@@ -273,22 +300,6 @@ export interface OrchestratorHooks {
|
|
|
273
300
|
* are skipped here — group fan-in is resolved separately by the scheduler.
|
|
274
301
|
*/
|
|
275
302
|
export declare function upstreamBaseNamesFromNeeds(needs: unknown): string[];
|
|
276
|
-
/**
|
|
277
|
-
* Partition a lock job's `runsOn` / `excludeLabels` matchers into exact label
|
|
278
|
-
* strings and regex patterns for internal-event (cron / `ctx.emit`) dispatch.
|
|
279
|
-
* Lock jobs carry `runsOn` as `LabelMatcher[]`; the coordinator routing and the
|
|
280
|
-
* direct dispatcher both need exact labels for the indexed/SQL fast path and
|
|
281
|
-
* regex patterns as a separate JS post-filter — never the raw matcher objects.
|
|
282
|
-
*/
|
|
283
|
-
export declare function internalJobRunsOnSelectors(job: {
|
|
284
|
-
runsOn?: readonly LabelMatcher[];
|
|
285
|
-
excludeLabels?: readonly LabelMatcher[];
|
|
286
|
-
}): {
|
|
287
|
-
runsOnLabels: string[];
|
|
288
|
-
runsOnPatterns: LabelMatcher[];
|
|
289
|
-
excludeLabels: string[];
|
|
290
|
-
excludePatterns: LabelMatcher[];
|
|
291
|
-
};
|
|
292
303
|
/**
|
|
293
304
|
* Parse an `execution_jobs.outputs` cell (string JSON or object) to a plain
|
|
294
305
|
* object, or null when empty / unparseable.
|
|
@@ -319,6 +330,22 @@ export declare function buildUpstreamStatusesByBase(rows: Array<{
|
|
|
319
330
|
job_name: string;
|
|
320
331
|
status?: string | null;
|
|
321
332
|
}>): Record<string, ExecutionJobStatus> | undefined;
|
|
333
|
+
/**
|
|
334
|
+
* For each declared need that names an invoke gate, gather its per-run results
|
|
335
|
+
* from the gate's proxy children — `{ repo, workflow, runId, status, outputs }`,
|
|
336
|
+
* one entry per proxy. `outputs` is the proxy's non-secret mirrored outputs (the
|
|
337
|
+
* same `execution_jobs.outputs` cell `mirrorSummonedRunOntoProxy` writes); a
|
|
338
|
+
* repo's secret outputs live in `run_secret_outputs` and are never read here.
|
|
339
|
+
* Keyed by gate name; a gate that summoned zero subscribers yields an empty
|
|
340
|
+
* array (so `.result` stays an `InvokeResult[]`), while a declared need that is
|
|
341
|
+
* a regular job (no gate row) yields no key.
|
|
342
|
+
*
|
|
343
|
+
* Shared by both `ctx.needs['<gate>'].result` construction paths: the
|
|
344
|
+
* DynamicJobFn generator (via `gatherUpstreamSnapshot`) and a standard
|
|
345
|
+
* `run:`/step job (via `mergeUpstreamOutputs` → the `upstreamInvokeResults`
|
|
346
|
+
* dispatch field).
|
|
347
|
+
*/
|
|
348
|
+
export declare function gatherInvokeResults(db: Kysely<Database>, runId: string, gateNames: readonly string[]): Promise<Record<string, InvokeResult[]>>;
|
|
322
349
|
/**
|
|
323
350
|
* Fold a `runsOnAll` upstream's host children into the `byHost` envelope
|
|
324
351
|
* `{ byHost: { '<host>': outputs }, summary: { succeededHosts, failedHosts, outputs } }`.
|
|
@@ -369,14 +396,43 @@ export declare function mergeUpstreamOutputs(db: Kysely<Database>, runId: string
|
|
|
369
396
|
mergedSecrets: Record<string, string> | undefined;
|
|
370
397
|
upstreamJobOutputs: Record<string, Record<string, unknown>> | undefined;
|
|
371
398
|
upstreamJobStatuses: Record<string, ExecutionJobStatus> | undefined;
|
|
399
|
+
upstreamInvokeResults: Record<string, InvokeResult[]> | undefined;
|
|
372
400
|
}>;
|
|
373
|
-
export declare function
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
401
|
+
export declare function buildOnEventMatched(dispatcherRef: {
|
|
402
|
+
current: Dispatcher | null;
|
|
403
|
+
}, providerRegistryRef: {
|
|
404
|
+
current: ProviderRegistry;
|
|
405
|
+
}, processingDepsRef: {
|
|
406
|
+
current: (() => ProcessingDeps) | null;
|
|
407
|
+
}): (event: any, lockFile: any, matchedWorkflows: any[], context?: EventMatchContext) => Promise<void>;
|
|
408
|
+
/**
|
|
409
|
+
* Build the invoke-gate `summon` callback: match the source repo's own opt-in
|
|
410
|
+
* `kiciEvent({ name })` subscribers, dispatch each as a normal in-repo run, and
|
|
411
|
+
* return the spawned run ids so the gate can correlate a proxy job per run.
|
|
412
|
+
*
|
|
413
|
+
* This is the composition-root half of the invoke gate — it reuses the same
|
|
414
|
+
* in-process match + dispatch path the internal-event router uses
|
|
415
|
+
* (`matchKiciEventSubscribers` + `dispatchInternalEventViaPipeline`), scoped to
|
|
416
|
+
* the source repo. The gate executor (`runInvokeGate`) enforces the chain-depth
|
|
417
|
+
* bound and persists the summon↔spawn correlation.
|
|
418
|
+
*/
|
|
419
|
+
export declare function buildSummonCallback(dispatcherRef: {
|
|
420
|
+
current: Dispatcher | null;
|
|
421
|
+
}, providerRegistryRef: {
|
|
422
|
+
current: ProviderRegistry;
|
|
423
|
+
}, eventRouter: EventRouter, processingDepsRef: {
|
|
424
|
+
current: (() => ProcessingDeps) | null;
|
|
425
|
+
}): (args: SummonArgs) => Promise<SummonedRun[]>;
|
|
377
426
|
export declare function bootstrapOrchestrator(config: AppConfig, hooks: OrchestratorHooks, options?: {
|
|
378
427
|
otelSdk?: {
|
|
379
428
|
shutdown(): Promise<void>;
|
|
380
429
|
};
|
|
430
|
+
/**
|
|
431
|
+
* Test-only fault-injection policy. Undefined in production (server.ts /
|
|
432
|
+
* standalone.ts pass nothing), so every seam sees an undefined policy and
|
|
433
|
+
* runs with no fault injection. A test-only entrypoint passes a policy to
|
|
434
|
+
* drive the seams directly.
|
|
435
|
+
*/
|
|
436
|
+
faultInjection?: OrchestratorFaultInjection;
|
|
381
437
|
}): Promise<void>;
|
|
382
438
|
//# sourceMappingURL=orchestrator-core.d.ts.map
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `ProcessingDeps` bag the DIRECT-INGRESS pipeline runs on.
|
|
3
|
+
*
|
|
4
|
+
* Two pipelines assemble this bag. `server.ts` builds the one the Platform WS
|
|
5
|
+
* relay hands to `processWebhook`; this module builds the one every HTTP
|
|
6
|
+
* ingress uses — the direct GitHub route, the generic webhook routes, and the
|
|
7
|
+
* internal-event dispatch adapter. On an independent orchestrator there is no
|
|
8
|
+
* relay, so this is the ONLY bag it ever has.
|
|
9
|
+
*
|
|
10
|
+
* It lives outside `app.ts` because it is the seam an approval defect hides in.
|
|
11
|
+
* A field the composition root forgets is invisible: the pipeline reads it as
|
|
12
|
+
* `undefined`, every guard downstream is written to degrade rather than throw,
|
|
13
|
+
* and the feature is silently inert. Assembling the bag in a function with a
|
|
14
|
+
* declared return type is what lets a test assert the wiring directly instead
|
|
15
|
+
* of asserting it through a 2,000-line composition root that no test
|
|
16
|
+
* constructs.
|
|
17
|
+
*/
|
|
18
|
+
import type { ProcessingDeps } from './processor.js';
|
|
19
|
+
import { TrustDirectoryStore } from '../security/trust-directory-store.js';
|
|
20
|
+
import { TrustPolicyStore } from '../security/trust-policy-store.js';
|
|
21
|
+
import type { SourceLocationData } from '../reporting/check-run-summary.js';
|
|
22
|
+
/**
|
|
23
|
+
* Everything the bag reads that `AppDependencies` already carries.
|
|
24
|
+
*
|
|
25
|
+
* Declared structurally rather than as `AppDependencies` so this module does
|
|
26
|
+
* not import `app.ts` (which imports it) and so the fields the bag actually
|
|
27
|
+
* consumes are enumerated in one readable place. `AppDependencies` satisfies it
|
|
28
|
+
* by construction — the `createApp` call site is the compiler's check of that.
|
|
29
|
+
*/
|
|
30
|
+
export interface DirectIngressDepsSource {
|
|
31
|
+
db: ProcessingDeps['db'] & {};
|
|
32
|
+
config: {
|
|
33
|
+
mode: NonNullable<ProcessingDeps['orchestratorMode']>;
|
|
34
|
+
secretKey?: string | undefined;
|
|
35
|
+
instanceId?: string | undefined;
|
|
36
|
+
rosterGraceMs?: number | undefined;
|
|
37
|
+
maxFanoutHosts?: number | undefined;
|
|
38
|
+
globalEvalRoundTimeoutMs?: number | undefined;
|
|
39
|
+
globalEvalCandidateTimeoutMs?: number | undefined;
|
|
40
|
+
globalEvalWaitTimeoutMs?: number | undefined;
|
|
41
|
+
};
|
|
42
|
+
dedup: ProcessingDeps['dedup'];
|
|
43
|
+
providerRegistry: ProcessingDeps['providerRegistry'];
|
|
44
|
+
ensureProviderBundle?: ProcessingDeps['ensureProviderBundle'];
|
|
45
|
+
lockFileCache: ProcessingDeps['lockFileCache'];
|
|
46
|
+
contentRequirementsCache?: ProcessingDeps['contentRequirementsCache'];
|
|
47
|
+
dispatcher: ProcessingDeps['dispatcher'];
|
|
48
|
+
platformClient?: ProcessingDeps['platformClient'];
|
|
49
|
+
sourceCache?: ProcessingDeps['sourceCache'];
|
|
50
|
+
buildCoordinator?: ProcessingDeps['buildCoordinator'];
|
|
51
|
+
depCache?: ProcessingDeps['depCache'];
|
|
52
|
+
pendingBuilds?: ProcessingDeps['pendingBuilds'];
|
|
53
|
+
pendingInits?: ProcessingDeps['pendingInits'];
|
|
54
|
+
pendingDynamics?: ProcessingDeps['pendingDynamics'];
|
|
55
|
+
pendingGlobalEvals?: ProcessingDeps['pendingGlobalEvals'];
|
|
56
|
+
globalEvalCache?: ProcessingDeps['globalEvalCache'];
|
|
57
|
+
checkRunReporter?: ProcessingDeps['checkRunReporter'];
|
|
58
|
+
executionTracker?: ProcessingDeps['executionTracker'];
|
|
59
|
+
eventRouter?: ProcessingDeps['eventRouter'];
|
|
60
|
+
invokeGateDeps?: ProcessingDeps['invokeGateDeps'];
|
|
61
|
+
registrationStore?: ProcessingDeps['registrationStore'];
|
|
62
|
+
registrationIndex?: ProcessingDeps['registrationIndex'];
|
|
63
|
+
secretResolver?: ProcessingDeps['secretResolver'];
|
|
64
|
+
sandboxAllowListReader?: ProcessingDeps['sandboxAllowListReader'];
|
|
65
|
+
logStorage?: ProcessingDeps['logStorage'];
|
|
66
|
+
contextStore?: ProcessingDeps['contextStore'];
|
|
67
|
+
variableStore?: ProcessingDeps['variableStore'];
|
|
68
|
+
heldRunStore?: ProcessingDeps['heldRunStore'];
|
|
69
|
+
coordinator?: ProcessingDeps['coordinator'];
|
|
70
|
+
cronScheduler?: ProcessingDeps['cronScheduler'];
|
|
71
|
+
globalWorkflowPolicy?: ProcessingDeps['globalWorkflowPolicy'];
|
|
72
|
+
eventLogWriter?: ProcessingDeps['eventLog'];
|
|
73
|
+
accessLogWriter?: ProcessingDeps['accessLogWriter'];
|
|
74
|
+
hostRosterStore?: ProcessingDeps['hostRosterStore'];
|
|
75
|
+
clusterSettings?: ProcessingDeps['clusterSettings'];
|
|
76
|
+
}
|
|
77
|
+
/** The per-process stores this factory owns, exposed so the caller can reuse them. */
|
|
78
|
+
export interface DirectIngressStores {
|
|
79
|
+
trustDirectoryStore: TrustDirectoryStore;
|
|
80
|
+
trustPolicyStore: TrustPolicyStore;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Build the direct-ingress `ProcessingDeps` factory.
|
|
84
|
+
*
|
|
85
|
+
* The returned function assembles a fresh bag per call, so every field reads
|
|
86
|
+
* the CURRENT subsystem instance — the provider registry is swapped wholesale
|
|
87
|
+
* on a source reload, and a bag captured once would keep dispatching through
|
|
88
|
+
* the replaced one.
|
|
89
|
+
*
|
|
90
|
+
* The two stores are constructed once here rather than per call: both are
|
|
91
|
+
* stateless over the database handle, and one of them is read on every PR
|
|
92
|
+
* delivery.
|
|
93
|
+
*/
|
|
94
|
+
export declare function createDirectIngressProcessingDeps(deps: DirectIngressDepsSource, hooks: {
|
|
95
|
+
onSourceLocationsExtracted: (workflowName: string, jobName: string, locations: Array<SourceLocationData | undefined>) => void;
|
|
96
|
+
}): {
|
|
97
|
+
build: () => ProcessingDeps;
|
|
98
|
+
stores: DirectIngressStores;
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=direct-ingress-deps.d.ts.map
|