@kici-dev/orchestrator 0.4.0 → 0.6.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.
- 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 +27 -0
- package/dist/agent/agent-version.d.ts +34 -0
- package/dist/agent/dispatcher.d.ts +151 -13
- package/dist/agent/host-roster.d.ts +37 -5
- package/dist/agent/registry.d.ts +2 -0
- package/dist/app.d.ts +56 -7
- 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 +95 -0
- package/dist/cache/index.d.ts +3 -0
- package/dist/cache/pending-global-evals.d.ts +42 -0
- package/dist/cache/pending-inits.d.ts +10 -0
- package/dist/cli/api-client.d.ts +18 -0
- package/dist/cli/commands/cluster-settings.d.ts +52 -3
- package/dist/cli/commands/diagnose.d.ts +6 -0
- package/dist/cli/commands/held-run.d.ts +58 -0
- package/dist/cli/commands/runs.d.ts +1 -0
- package/dist/cli/commands/trust-policy.d.ts +117 -12
- package/dist/cli/kici-admin.d.ts +10 -0
- package/dist/cli.js +2770 -938
- package/dist/cluster/cluster-identity.d.ts +3 -3
- package/dist/cluster/cluster-settings-reader.d.ts +59 -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 +48 -21
- package/dist/content-requirements-cache.d.ts +55 -0
- 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/109_cluster_settings_cache_knobs.d.ts +4 -0
- package/dist/db/migrations/110_cluster_settings_global_eval_knobs.d.ts +4 -0
- package/dist/db/migrations/111_cluster_settings_global_eval_wait.d.ts +4 -0
- package/dist/db/migrations/112_execution_runs_workflow_repo.d.ts +4 -0
- package/dist/db/migrations/113_execution_runs_workflow_repo_index.d.ts +30 -0
- package/dist/db/migrations/114_ingest_queue_claim.d.ts +4 -0
- package/dist/db/migrations/115_global_workflows_cluster_switch.d.ts +9 -0
- 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 +428 -12
- 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 +4 -4
- package/dist/metrics/prometheus.d.ts +170 -3
- package/dist/oidc/oidc-mint-registration.d.ts +7 -3
- package/dist/orchestrator-core.d.ts +91 -24
- package/dist/pipeline/content-filter.d.ts +71 -0
- package/dist/pipeline/direct-ingress-deps.d.ts +100 -0
- package/dist/pipeline/dispatch-matched-workflow.d.ts +521 -11
- package/dist/pipeline/global-eval-round.d.ts +307 -0
- package/dist/pipeline/internal-event-pipeline.d.ts +140 -0
- package/dist/pipeline/invoke-gate.d.ts +164 -0
- package/dist/pipeline/job-contexts.d.ts +16 -17
- package/dist/pipeline/needs-scheduler.d.ts +13 -0
- package/dist/pipeline/process-webhook.d.ts +126 -31
- package/dist/pipeline/processor.d.ts +282 -23
- 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 +15 -0
- package/dist/pipeline/security-hold-check.d.ts +217 -0
- package/dist/pipeline/test-pipeline.d.ts +12 -0
- package/dist/pipeline/undispatched-hold-checks.d.ts +23 -0
- package/dist/pipeline/webhook-payload-store.d.ts +20 -0
- package/dist/policy/dashboard-write-policy-listener.d.ts +62 -0
- package/dist/policy/dashboard-write-policy.d.ts +14 -0
- package/dist/provenance/backfill-run.d.ts +10 -1
- package/dist/provider-registry.d.ts +47 -4
- package/dist/providers/github/check-status-poster.d.ts +33 -3
- package/dist/providers/github/commit-message.d.ts +20 -0
- package/dist/providers/github/file-contents.d.ts +40 -0
- package/dist/providers/github/index.d.ts +2 -2
- package/dist/providers/github/normalizer.d.ts +3 -2
- package/dist/providers/local/normalizer.d.ts +3 -5
- package/dist/providers/universal-git/config.d.ts +2 -0
- package/dist/providers/universal-git/index.d.ts +11 -2
- package/dist/providers/universal-git/normalizer.d.ts +10 -0
- package/dist/queue/cleanup.d.ts +7 -1
- package/dist/queue/job-queue.d.ts +112 -7
- package/dist/queue/terminalize-unroutable.d.ts +13 -0
- package/dist/registration/extractor.d.ts +3 -3
- package/dist/registration/registration-index.d.ts +7 -0
- package/dist/registration/registration-run-match.d.ts +47 -0
- package/dist/registration/registration-store.d.ts +22 -0
- package/dist/reporting/check-run-reporter.d.ts +146 -2
- package/dist/reporting/check-run-summary.d.ts +25 -1
- package/dist/reporting/execution-tracker.d.ts +324 -9
- package/dist/reporting/log-chunk-sink.d.ts +8 -5
- 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-org-settings.d.ts +5 -0
- package/dist/routes/admin-trust-policy.d.ts +34 -6
- package/dist/routes/admin.d.ts +15 -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 +905 -76
- 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/global-workflow-policy.d.ts +52 -12
- 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 +56329 -42234
- 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 +37619 -23570
- package/dist/webhook/ingest-accept.d.ts +70 -0
- package/dist/webhook/ingest-overflow-buffer.d.ts +35 -4
- package/dist/webhook/ingest-overflow-replayer.d.ts +50 -6
- package/dist/worker/in-memory-job-queue.d.ts +1 -1
- package/dist/ws/agent-handler.d.ts +31 -4
- package/dist/ws/dashboard-context-handler.d.ts +28 -4
- package/dist/ws/dashboard-global-workflows-handler.d.ts +36 -9
- package/dist/ws/execution-status-frame.d.ts +32 -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 +68 -9
- package/dist/ws/test-relay-handlers.d.ts +35 -10
- package/installer-image-digests.json +3 -3
- package/package.json +24 -19
- package/sbom.spdx.json +868 -821
- package/dist/approvals/team-membership-lookup.d.ts +0 -13
- package/dist/pipeline/inline-eval.d.ts +0 -44
- 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
|
|
@@ -47,10 +47,10 @@ export declare class AgentMetricsAggregator {
|
|
|
47
47
|
private store;
|
|
48
48
|
private defaultRetentionMs;
|
|
49
49
|
/**
|
|
50
|
-
* Optional lookup: agentId → scaler backend
|
|
50
|
+
* Optional lookup: agentId → scaler backend type (e.g. `container`,
|
|
51
51
|
* `firecracker`, `bare-metal`). Returning null marks the agent as
|
|
52
52
|
* static / stateful — we then stamp the `scaler` label as `'stateful'`.
|
|
53
|
-
* Wired from ScalerManager.
|
|
53
|
+
* Wired from ScalerManager.getBackendType in production. Tests can
|
|
54
54
|
* leave it undefined; in that case the `scaler` label is omitted.
|
|
55
55
|
*/
|
|
56
56
|
private readonly getScalerForAgent?;
|
|
@@ -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.
|
|
@@ -93,6 +176,13 @@ export declare const ingestShedTotal: import("@opentelemetry/api").Counter<impor
|
|
|
93
176
|
export declare const stateReplayBreakerTripsTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
94
177
|
/** Total webhook-ingest admissions granted. */
|
|
95
178
|
export declare const ingestAdmittedTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
179
|
+
/**
|
|
180
|
+
* Webhook pipelines that threw. Labels:
|
|
181
|
+
* - phase: post_ack — the delivery was already acknowledged, so the failure
|
|
182
|
+
* could not be reported in the response and is only visible here, in the
|
|
183
|
+
* event log, and in the queue row.
|
|
184
|
+
*/
|
|
185
|
+
export declare const webhookPipelineFailuresTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
96
186
|
/** Set the current buffered-row depth (called by the buffer + replayer). */
|
|
97
187
|
export declare function setIngestOverflowBuffered(value: number): void;
|
|
98
188
|
/** Current buffered-row depth (test helper). */
|
|
@@ -121,13 +211,27 @@ export declare const webhooksProcessedTotal: import("@opentelemetry/api").Counte
|
|
|
121
211
|
/**
|
|
122
212
|
* Org trust-policy gate decisions.
|
|
123
213
|
* Labels:
|
|
124
|
-
* - arm: which policy arm decided —
|
|
125
|
-
* - action: pass | hold | reject
|
|
214
|
+
* - arm: which policy arm decided — fork_pr | none (the verdict carried no reason)
|
|
215
|
+
* - action: pass | ignore | hold | reject
|
|
126
216
|
*
|
|
127
217
|
* Incremented once per evaluated PR event, including passes, so the ratio of
|
|
128
218
|
* gated to ungated PRs is visible rather than only the gated ones.
|
|
129
219
|
*/
|
|
130
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>;
|
|
131
235
|
/**
|
|
132
236
|
* Duration of trigger matching operations (lock file evaluation).
|
|
133
237
|
* Buckets: 1ms to 5s covering fast rejects through complex evaluations.
|
|
@@ -221,7 +325,7 @@ export type ScalerSpawnFailureBound = (typeof ScalerSpawnFailureBound)[keyof typ
|
|
|
221
325
|
/**
|
|
222
326
|
* Total scaler agent spawn failures.
|
|
223
327
|
* Labels:
|
|
224
|
-
* - backend: scaler backend type (bare-metal | container | firecracker | unknown)
|
|
328
|
+
* - backend: scaler backend type (bare-metal | container | event | firecracker | unknown)
|
|
225
329
|
* - bound: true (job-bound spawn) | false (warm-pool/unbound)
|
|
226
330
|
*/
|
|
227
331
|
export declare const scalerSpawnFailuresTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
@@ -291,6 +395,58 @@ export declare const universalGitRegistrationErrorsTotal: import("@opentelemetry
|
|
|
291
395
|
* 'id_mismatch' (a username-matched link has a different provider_user_id)
|
|
292
396
|
*/
|
|
293
397
|
export declare const trustMatchRefusedNoIdTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
398
|
+
/**
|
|
399
|
+
* Candidates handed to a global eval round.
|
|
400
|
+
*
|
|
401
|
+
* Equal to `sum(kici_orch_global_eval_verdicts_total)` by construction: every
|
|
402
|
+
* candidate receives exactly one verdict, including on the fail-closed path
|
|
403
|
+
* where the round never runs. Kept as its own series because it is the natural
|
|
404
|
+
* top-line rate and the denominator the outcome breakdown divides — a
|
|
405
|
+
* divergence between the two would be a bug in the round, never a condition an
|
|
406
|
+
* operator should watch for.
|
|
407
|
+
*/
|
|
408
|
+
export declare const globalEvalCandidatesTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
409
|
+
/**
|
|
410
|
+
* Per-candidate verdicts a global eval round produced.
|
|
411
|
+
*
|
|
412
|
+
* Labels:
|
|
413
|
+
* - outcome: run (the filter admitted it) | filtered (the filter excluded it) | indeterminate (the round could not decide — a failed round, a budget breach, or a verdict that never arrived)
|
|
414
|
+
*/
|
|
415
|
+
export declare const globalEvalVerdictsTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
416
|
+
/**
|
|
417
|
+
* Wall-clock duration of one dispatched global eval round, from dispatch to
|
|
418
|
+
* settled verdicts. A cache hit records nothing — it never dispatches a round.
|
|
419
|
+
*
|
|
420
|
+
* Buckets: 1s to 10min, covering a fast round through the default 120s agent
|
|
421
|
+
* budget and the 240s orchestrator wait ceiling.
|
|
422
|
+
*
|
|
423
|
+
* Labels:
|
|
424
|
+
* - result: success (the round settled) | error (dispatch rejected, the wait ceiling fired, or the round decided nothing)
|
|
425
|
+
*/
|
|
426
|
+
export declare const globalEvalRoundDurationSeconds: import("@opentelemetry/api").Histogram<import("@opentelemetry/api").Attributes>;
|
|
427
|
+
/**
|
|
428
|
+
* Jobs a round's `DynamicJobFn` generators produced, summed over the round's
|
|
429
|
+
* candidates. Recorded once per settled round, including zero.
|
|
430
|
+
*
|
|
431
|
+
* Buckets cover the common small fan-outs through a large matrix expansion.
|
|
432
|
+
*/
|
|
433
|
+
export declare const globalEvalJobsGenerated: import("@opentelemetry/api").Histogram<import("@opentelemetry/api").Attributes>;
|
|
434
|
+
/**
|
|
435
|
+
* Global eval round cache lookups by outcome.
|
|
436
|
+
*
|
|
437
|
+
* Three outcomes, not two. An input that cannot be serialized yields no cache
|
|
438
|
+
* key at all, so it never reaches the cache and registers neither a hit nor a
|
|
439
|
+
* miss — counting only hits and misses would drop those lookups from the
|
|
440
|
+
* denominator and make the hit rate read higher than it is.
|
|
441
|
+
*
|
|
442
|
+
* Expect a hit rate near zero on a healthy cluster: the key covers the whole
|
|
443
|
+
* event, so every real push is a miss by construction. This cache is a
|
|
444
|
+
* redelivery guard, not a steady-state optimization.
|
|
445
|
+
*
|
|
446
|
+
* Labels:
|
|
447
|
+
* - result: hit | miss | unkeyable (the round input could not be serialized)
|
|
448
|
+
*/
|
|
449
|
+
export declare const globalEvalCacheLookupsTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
294
450
|
/**
|
|
295
451
|
* Internal events delivered to all matching workflows successfully (after the
|
|
296
452
|
* lease commits processed=true).
|
|
@@ -312,6 +468,17 @@ export declare const eventRetryTotal: import("@opentelemetry/api").Counter<impor
|
|
|
312
468
|
* - reason: why the event was DLQ'd (exhausted_retries)
|
|
313
469
|
*/
|
|
314
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>;
|
|
315
482
|
/**
|
|
316
483
|
* Dispatch leases that timed out before the holding node finalised them
|
|
317
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;
|
|
@@ -19,6 +19,7 @@ import { EventLogWriter } from './webhook/event-log.js';
|
|
|
19
19
|
import { AccessLogWriter } from './audit/access-log.js';
|
|
20
20
|
import { Dispatcher } from './agent/dispatcher.js';
|
|
21
21
|
import { LockFileCache } from './lockfile-cache.js';
|
|
22
|
+
import { ContentRequirementsCache } from './content-requirements-cache.js';
|
|
22
23
|
import { DedupCache } from './webhook/dedup.js';
|
|
23
24
|
import { ObserverRegistry } from './ws/observer-registry.js';
|
|
24
25
|
import { IngestAdmissionController } from './webhook/ingest-admission.js';
|
|
@@ -28,21 +29,23 @@ import { IngestOverflowBuffer } from './webhook/ingest-overflow-buffer.js';
|
|
|
28
29
|
import { IngestOverflowReplayer } from './webhook/ingest-overflow-replayer.js';
|
|
29
30
|
import { AgentMetricsAggregator } from './metrics/agent-metrics-aggregator.js';
|
|
30
31
|
import { SourceLocationStore } from './app.js';
|
|
31
|
-
import { ExecutionJobStatus, type
|
|
32
|
+
import { ExecutionJobStatus, type PeerHeartbeat, type PeerLogsCollectRequest, type PeerToPeerMessage, type InvokeResult } from '@kici-dev/engine';
|
|
32
33
|
import { ScalerManager } from './scaler/index.js';
|
|
33
34
|
import type { ScalerConfig } from './scaler/index.js';
|
|
34
35
|
import type { CacheStorage } from './storage/index.js';
|
|
35
36
|
import { type ProvenanceTrustRoot } from './provenance/trust-root.js';
|
|
36
37
|
import { type ResolvedDashboardEncryptionKey } from './secrets/dashboard-encryption-key.js';
|
|
37
|
-
import { SourceCache, BuildCoordinator, DepCache, UserCache, DispatchCacheRefTracker, PendingBuildTracker, PendingInitTracker, PendingDynamicTracker } from './cache/index.js';
|
|
38
|
+
import { SourceCache, BuildCoordinator, DepCache, UserCache, DispatchCacheRefTracker, PendingBuildTracker, PendingInitTracker, PendingDynamicTracker, PendingGlobalEvalTracker, GlobalEvalRoundCache } from './cache/index.js';
|
|
38
39
|
import { ArtifactStore } from './artifacts/artifact-store.js';
|
|
39
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';
|
|
40
43
|
import { StepLogBuffer } from './reporting/step-log-buffer.js';
|
|
41
44
|
import { type LogStorage } from './reporting/log-storage.js';
|
|
42
45
|
import { ExecutionTracker, type ExecutionTrackerDeps } from './reporting/execution-tracker.js';
|
|
43
46
|
import { LogWriter } from './reporting/log-writer.js';
|
|
44
47
|
import { type NormalizedLogChunk } from './reporting/log-chunk-sink.js';
|
|
45
|
-
import { PeerRegistry, PeerClient, createPeerHandler, RaftNode, OrphanRecovery, RunCoordinator } from './cluster/index.js';
|
|
48
|
+
import { PeerRegistry, PeerClient, createPeerHandler, RaftNode, OrphanRecovery, RunCoordinator, PlanHeadroomStore } from './cluster/index.js';
|
|
46
49
|
import { SourceStore, SourceManager } from './sources/index.js';
|
|
47
50
|
import { PgSecretStore, AuditLogger, SecretResolver } from './secrets/index.js';
|
|
48
51
|
import type { SecretStore } from '@kici-dev/engine';
|
|
@@ -50,11 +53,13 @@ import type { AdminRouteDeps } from './routes/admin.js';
|
|
|
50
53
|
import { AgentTokenStore } from './agent/token-store.js';
|
|
51
54
|
import { OwnershipTracker } from './agent/ownership-tracker.js';
|
|
52
55
|
import { EventStore } from './events/event-store.js';
|
|
53
|
-
import { EventRouter } from './events/event-router.js';
|
|
56
|
+
import { EventRouter, type EventMatchContext } from './events/event-router.js';
|
|
54
57
|
import { EventEmitter } from './events/event-emitter.js';
|
|
55
58
|
import { TrustStore } from './events/trust-store.js';
|
|
59
|
+
import type { OrchestratorFaultInjection } from './testing/fault-injection.js';
|
|
56
60
|
import { GenericSourceManager } from './webhook/generic-sources.js';
|
|
57
61
|
import { GenericSourcesChangeListener } from './webhook/generic-sources-listener.js';
|
|
62
|
+
import { DashboardWritePolicyChangeListener } from './policy/dashboard-write-policy-listener.js';
|
|
58
63
|
import { RegistrationStore } from './registration/registration-store.js';
|
|
59
64
|
import { RegistrationIndex } from './registration/registration-index.js';
|
|
60
65
|
import { CronScheduler } from './cron/cron-scheduler.js';
|
|
@@ -98,6 +103,7 @@ export interface OrchestratorSubsystems {
|
|
|
98
103
|
pendingBuilds: PendingBuildTracker | undefined;
|
|
99
104
|
pendingInits: PendingInitTracker;
|
|
100
105
|
pendingDynamics: PendingDynamicTracker;
|
|
106
|
+
pendingGlobalEvals: PendingGlobalEvalTracker;
|
|
101
107
|
checkRunReporter: CheckRunReporter;
|
|
102
108
|
stepLogBuffer: StepLogBuffer;
|
|
103
109
|
sourceLocationStore: SourceLocationStore;
|
|
@@ -119,8 +125,12 @@ export interface OrchestratorSubsystems {
|
|
|
119
125
|
tokenStore: AgentTokenStore;
|
|
120
126
|
ownershipTracker: OwnershipTracker;
|
|
121
127
|
lockFileCache: LockFileCache;
|
|
128
|
+
contentRequirementsCache: ContentRequirementsCache;
|
|
129
|
+
globalEvalCache: GlobalEvalRoundCache;
|
|
122
130
|
dedup: DedupCache;
|
|
123
131
|
eventRouter: EventRouter;
|
|
132
|
+
/** Invoke-gate dependencies (summon callback + chain-depth bound). */
|
|
133
|
+
invokeGateDeps: InvokeGateDeps;
|
|
124
134
|
/**
|
|
125
135
|
* Event store for custom internal events (system + custom). Exposed
|
|
126
136
|
* here so the dashboard handler can serve the per-org DLQ surface
|
|
@@ -129,6 +139,13 @@ export interface OrchestratorSubsystems {
|
|
|
129
139
|
eventStore: EventStore;
|
|
130
140
|
eventEmitter: EventEmitter;
|
|
131
141
|
genericSourceManager: GenericSourceManager;
|
|
142
|
+
/**
|
|
143
|
+
* Re-register a generic source's provider bundle from its database row.
|
|
144
|
+
* The webhook pipeline calls it on an exact registry miss so the read side
|
|
145
|
+
* settles against server truth rather than a stand-in bundle. Shared by the
|
|
146
|
+
* relay path (server.ts) and the direct-ingress path (app.ts).
|
|
147
|
+
*/
|
|
148
|
+
ensureProviderBundle: (routingKey: string) => Promise<boolean>;
|
|
132
149
|
trustStore: TrustStore;
|
|
133
150
|
registrationStore: RegistrationStore;
|
|
134
151
|
registrationIndex: RegistrationIndex;
|
|
@@ -142,6 +159,10 @@ export interface OrchestratorSubsystems {
|
|
|
142
159
|
getLocalInventory: () => Omit<PeerHeartbeat, 'type'>;
|
|
143
160
|
broadcastHeartbeatToAllPeers: () => void;
|
|
144
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;
|
|
145
166
|
joinHandler: JoinHandler;
|
|
146
167
|
configReloader: ConfigReloader;
|
|
147
168
|
localConfigVersion: number;
|
|
@@ -153,6 +174,12 @@ export interface OrchestratorSubsystems {
|
|
|
153
174
|
* Platform when a generic source is added/removed at runtime.
|
|
154
175
|
*/
|
|
155
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;
|
|
156
183
|
/** Inbound webhook delivery log writer (event_log table + object-storage payloads). */
|
|
157
184
|
eventLogWriter: EventLogWriter;
|
|
158
185
|
/** Access log writer (read + mutation attribution for dashboard + admin). */
|
|
@@ -193,6 +220,17 @@ export interface OrchestratorSubsystems {
|
|
|
193
220
|
ingestOverflowBuffer: IngestOverflowBuffer;
|
|
194
221
|
/** Background replayer draining the overflow buffer once capacity recovers. */
|
|
195
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;
|
|
196
234
|
}
|
|
197
235
|
/**
|
|
198
236
|
* Mode-specific hooks injected by each entry point.
|
|
@@ -262,22 +300,6 @@ export interface OrchestratorHooks {
|
|
|
262
300
|
* are skipped here — group fan-in is resolved separately by the scheduler.
|
|
263
301
|
*/
|
|
264
302
|
export declare function upstreamBaseNamesFromNeeds(needs: unknown): string[];
|
|
265
|
-
/**
|
|
266
|
-
* Partition a lock job's `runsOn` / `excludeLabels` matchers into exact label
|
|
267
|
-
* strings and regex patterns for internal-event (cron / `ctx.emit`) dispatch.
|
|
268
|
-
* Lock jobs carry `runsOn` as `LabelMatcher[]`; the coordinator routing and the
|
|
269
|
-
* direct dispatcher both need exact labels for the indexed/SQL fast path and
|
|
270
|
-
* regex patterns as a separate JS post-filter — never the raw matcher objects.
|
|
271
|
-
*/
|
|
272
|
-
export declare function internalJobRunsOnSelectors(job: {
|
|
273
|
-
runsOn?: readonly LabelMatcher[];
|
|
274
|
-
excludeLabels?: readonly LabelMatcher[];
|
|
275
|
-
}): {
|
|
276
|
-
runsOnLabels: string[];
|
|
277
|
-
runsOnPatterns: LabelMatcher[];
|
|
278
|
-
excludeLabels: string[];
|
|
279
|
-
excludePatterns: LabelMatcher[];
|
|
280
|
-
};
|
|
281
303
|
/**
|
|
282
304
|
* Parse an `execution_jobs.outputs` cell (string JSON or object) to a plain
|
|
283
305
|
* object, or null when empty / unparseable.
|
|
@@ -308,6 +330,22 @@ export declare function buildUpstreamStatusesByBase(rows: Array<{
|
|
|
308
330
|
job_name: string;
|
|
309
331
|
status?: string | null;
|
|
310
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[]>>;
|
|
311
349
|
/**
|
|
312
350
|
* Fold a `runsOnAll` upstream's host children into the `byHost` envelope
|
|
313
351
|
* `{ byHost: { '<host>': outputs }, summary: { succeededHosts, failedHosts, outputs } }`.
|
|
@@ -358,14 +396,43 @@ export declare function mergeUpstreamOutputs(db: Kysely<Database>, runId: string
|
|
|
358
396
|
mergedSecrets: Record<string, string> | undefined;
|
|
359
397
|
upstreamJobOutputs: Record<string, Record<string, unknown>> | undefined;
|
|
360
398
|
upstreamJobStatuses: Record<string, ExecutionJobStatus> | undefined;
|
|
399
|
+
upstreamInvokeResults: Record<string, InvokeResult[]> | undefined;
|
|
361
400
|
}>;
|
|
362
|
-
export declare function
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
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[]>;
|
|
366
426
|
export declare function bootstrapOrchestrator(config: AppConfig, hooks: OrchestratorHooks, options?: {
|
|
367
427
|
otelSdk?: {
|
|
368
428
|
shutdown(): Promise<void>;
|
|
369
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;
|
|
370
437
|
}): Promise<void>;
|
|
371
438
|
//# sourceMappingURL=orchestrator-core.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier-1 declarative content-requirements filter (execution-purity model, Part B).
|
|
3
|
+
*
|
|
4
|
+
* After Tier-0 trigger matching selects candidate workflows, this step fetches
|
|
5
|
+
* the source files each candidate's `requires` names — once per distinct
|
|
6
|
+
* `(repo, sha, path)` via the LRU cache — evaluates the (pure DATA) requirements
|
|
7
|
+
* with the engine matcher, and drops any candidate that FAILS or is
|
|
8
|
+
* INDETERMINATE before dispatch. No author code is executed: `requires` is a
|
|
9
|
+
* declarative query the orchestrator interprets, which is what keeps content
|
|
10
|
+
* filtering inside the orchestrator under the purity model.
|
|
11
|
+
*
|
|
12
|
+
* Fail-visible: a dropped candidate (definite negative, oversize/unparseable
|
|
13
|
+
* content, a fetch error, or no fetcher/cache available) is logged with the
|
|
14
|
+
* concrete reason. An indeterminate file NEVER passes silently.
|
|
15
|
+
*/
|
|
16
|
+
import type { FileContentsFetcher, LockContentRequirement } from '@kici-dev/engine';
|
|
17
|
+
import type { ContentRequirementsCache } from '../content-requirements-cache.js';
|
|
18
|
+
/** A workflow candidate carrying the `requires` of the trigger that matched the event. */
|
|
19
|
+
export interface ContentFilterCandidate {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly requires?: readonly LockContentRequirement[];
|
|
22
|
+
}
|
|
23
|
+
/** The event the requirements are evaluated against: source repo + ref to fetch files at. */
|
|
24
|
+
export interface ContentFilterEvent {
|
|
25
|
+
/** Provider repo identifier ("owner/repo"). */
|
|
26
|
+
readonly repo: string;
|
|
27
|
+
/** Git ref (commit SHA, or branch/tag) at which files are read. */
|
|
28
|
+
readonly sha: string;
|
|
29
|
+
}
|
|
30
|
+
export interface ContentFilterOptions {
|
|
31
|
+
/** Per-delivery file-contents fetcher; `undefined` when the provider has none. */
|
|
32
|
+
readonly fetcher: FileContentsFetcher | undefined;
|
|
33
|
+
/** Shared LRU cache; `undefined` when the deployment did not wire one. */
|
|
34
|
+
readonly cache: ContentRequirementsCache | undefined;
|
|
35
|
+
/** Delivery id for log correlation. */
|
|
36
|
+
readonly deliveryId?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* One dropped candidate.
|
|
40
|
+
*
|
|
41
|
+
* `indeterminate` separates the two reasons a drop happens, which mean opposite
|
|
42
|
+
* things to a workflow author: a definite content mismatch is the requirement
|
|
43
|
+
* doing its job, while an unreadable file, a fetch error, or a provider with no
|
|
44
|
+
* file-contents fetcher is the requirement never having been evaluated at all.
|
|
45
|
+
* Both drop the candidate — the filter is fail-visible, so an unevaluable file
|
|
46
|
+
* never passes — but a trace that renders the second as "excluded" tells an
|
|
47
|
+
* author their requirement said no when nothing ever read it.
|
|
48
|
+
*/
|
|
49
|
+
export interface DroppedCandidate {
|
|
50
|
+
readonly name: string;
|
|
51
|
+
readonly reason: string;
|
|
52
|
+
/** True when the requirement could not be evaluated, rather than evaluating to false. */
|
|
53
|
+
readonly indeterminate?: boolean;
|
|
54
|
+
}
|
|
55
|
+
export interface ContentFilterResult<C extends ContentFilterCandidate> {
|
|
56
|
+
readonly survivors: C[];
|
|
57
|
+
readonly dropped: DroppedCandidate[];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Filter candidates by their declarative content requirements.
|
|
61
|
+
*
|
|
62
|
+
* Gathers each distinct `(repo, sha, path)` once via the cache, evaluates every
|
|
63
|
+
* candidate's `requires`, and returns the survivors (pass) split from the
|
|
64
|
+
* dropped (fail / indeterminate, each logged with its reason). A candidate with
|
|
65
|
+
* no `requires` always survives without any fetch (the fast path — like an empty
|
|
66
|
+
* `paths` filter). When a candidate has `requires` but no fetcher/cache is
|
|
67
|
+
* available, it is dropped as indeterminate (fail-visible), never dispatched
|
|
68
|
+
* unfiltered.
|
|
69
|
+
*/
|
|
70
|
+
export declare function filterByContentRequirements<C extends ContentFilterCandidate>(candidates: readonly C[], event: ContentFilterEvent, opts: ContentFilterOptions): Promise<ContentFilterResult<C>>;
|
|
71
|
+
//# sourceMappingURL=content-filter.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
|