@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
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory stand-in for the `scaler_pending_claims` half of `ScalerStateStore`.
|
|
3
|
+
*
|
|
4
|
+
* It reproduces the three properties the real table enforces in SQL — a claim
|
|
5
|
+
* is consumable exactly once, a consume past `expires_at` finds nothing, and a
|
|
6
|
+
* per-agent invalidation removes every row for that agent — against an injected
|
|
7
|
+
* clock. That lets a test drive the whole register → redeem round trip without a
|
|
8
|
+
* database, so the single-use and TTL properties are executed rather than
|
|
9
|
+
* hand-fed through a stubbed answer.
|
|
10
|
+
*
|
|
11
|
+
* Only the pending-claim methods are implemented. Reaching any other
|
|
12
|
+
* `ScalerStateStore` method is a `TypeError` at the call site, not a silent
|
|
13
|
+
* no-op.
|
|
14
|
+
*/
|
|
15
|
+
import type { ScalerStateStore } from '../scaler/scaler-state-store.js';
|
|
16
|
+
/**
|
|
17
|
+
* Build an in-memory pending-claim store.
|
|
18
|
+
*
|
|
19
|
+
* @param now Clock (epoch ms) the TTL is evaluated against. Pass the same clock
|
|
20
|
+
* the `ClaimStore` under test uses, or its `expiresAt` lands in a different
|
|
21
|
+
* era than this store's `now()` and every redeem reads as expired.
|
|
22
|
+
*/
|
|
23
|
+
export declare function makeFakeScalerStateStore(now?: () => number): ScalerStateStore;
|
|
24
|
+
//# sourceMappingURL=fake-scaler-state-store.d.ts.map
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Predicate + projection evaluation for the shared `createMockDb` harness.
|
|
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
|
|
7
|
+
* 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.
|
|
10
|
+
*
|
|
11
|
+
* `createMockDb` used to return its configured rows verbatim, whatever the
|
|
12
|
+
* query asked for: a `.where(...)` or a `.select([...])` was recorded on a spy
|
|
13
|
+
* and then discarded. A test therefore observed only the rows it had itself
|
|
14
|
+
* configured, so dropping a filter or a projected column from the code under
|
|
15
|
+
* test changed nothing the test could see. This module is the evaluator that
|
|
16
|
+
* closes that: the mock now *applies* the query it was handed.
|
|
17
|
+
*
|
|
18
|
+
* Scope, stated precisely because the guarantee is partial by construction:
|
|
19
|
+
*
|
|
20
|
+
* - **Binary predicates are evaluated.** `.where(column, op, value)` for the
|
|
21
|
+
* operators in {@link MockDbOperator}. That is the overwhelming majority of
|
|
22
|
+
* the predicates this repo issues.
|
|
23
|
+
* - **Anything else is opaque and is NOT evaluated.** An expression-builder
|
|
24
|
+
* callback (`.where((eb) => …)`) and a raw `sql` fragment carry their meaning
|
|
25
|
+
* in code the mock cannot read, so they are recorded and skipped. A filter
|
|
26
|
+
* written in one of those shapes is still unpinned.
|
|
27
|
+
* - **A predicate on a column the fixture row does not declare is NOT
|
|
28
|
+
* evaluated.** The fixture, not the schema, is the source of truth here: a
|
|
29
|
+
* test row is a partial literal, and a missing key means "this test did not
|
|
30
|
+
* model that column", not "this column is NULL". Treating absence as NULL
|
|
31
|
+
* would fail nearly every fixture in the repo for saying too little, while
|
|
32
|
+
* catching nothing a fixture that *does* declare the column would not
|
|
33
|
+
* already catch. The consequence is real and worth naming: to pin a filter,
|
|
34
|
+
* a fixture row must mention the column that filter reads.
|
|
35
|
+
*
|
|
36
|
+
* Everything here is pure — no vitest, no chain state — so it is unit-tested
|
|
37
|
+
* directly in `mock-db-query.test.ts` rather than only through the mock.
|
|
38
|
+
*/
|
|
39
|
+
/** SQL comparison operators the mock evaluates. Anything else is opaque. */
|
|
40
|
+
export declare enum MockDbOperator {
|
|
41
|
+
eq = "=",
|
|
42
|
+
neq = "!=",
|
|
43
|
+
neqAnsi = "<>",
|
|
44
|
+
lt = "<",
|
|
45
|
+
lte = "<=",
|
|
46
|
+
gt = ">",
|
|
47
|
+
gte = ">=",
|
|
48
|
+
in = "in",
|
|
49
|
+
notIn = "not in",
|
|
50
|
+
is = "is",
|
|
51
|
+
isNot = "is not",
|
|
52
|
+
like = "like",
|
|
53
|
+
notLike = "not like",
|
|
54
|
+
ilike = "ilike",
|
|
55
|
+
notILike = "not ilike"
|
|
56
|
+
}
|
|
57
|
+
/** A `.where(column, op, value)` predicate the mock can evaluate. */
|
|
58
|
+
export interface BinaryPredicate {
|
|
59
|
+
kind: 'binary';
|
|
60
|
+
/** Column name with any `table.` qualifier stripped. */
|
|
61
|
+
column: string;
|
|
62
|
+
op: MockDbOperator;
|
|
63
|
+
value: unknown;
|
|
64
|
+
}
|
|
65
|
+
/** A predicate shape the mock cannot read (eb callback, raw sql, unknown op). */
|
|
66
|
+
export interface OpaquePredicate {
|
|
67
|
+
kind: 'opaque';
|
|
68
|
+
/** Why it could not be parsed — surfaced in `explainSkippedPredicates`. */
|
|
69
|
+
reason: string;
|
|
70
|
+
}
|
|
71
|
+
export type MockDbPredicate = BinaryPredicate | OpaquePredicate;
|
|
72
|
+
/** Drop a `table.` / `"table".` qualifier so a predicate keys into a flat row. */
|
|
73
|
+
export declare function unqualify(column: string): string;
|
|
74
|
+
/**
|
|
75
|
+
* Parse the arguments of one `.where(...)` call into a predicate.
|
|
76
|
+
*
|
|
77
|
+
* Only the 3-argument `(column, op, value)` form with a string column and a
|
|
78
|
+
* recognized operator is evaluable; everything else is opaque.
|
|
79
|
+
*/
|
|
80
|
+
export declare function parseWhereArgs(args: readonly unknown[]): MockDbPredicate;
|
|
81
|
+
/**
|
|
82
|
+
* Evaluate one binary predicate against a row.
|
|
83
|
+
*
|
|
84
|
+
* Returns `undefined` when the predicate cannot be decided — the row does not
|
|
85
|
+
* declare the column, or the values are not comparable. An undecided predicate
|
|
86
|
+
* does not exclude the row (see the module docblock).
|
|
87
|
+
*/
|
|
88
|
+
export declare function evaluatePredicate(row: Record<string, unknown>, predicate: BinaryPredicate): boolean | undefined;
|
|
89
|
+
/** True when the row satisfies every predicate the mock could decide. */
|
|
90
|
+
export declare function rowMatches(row: unknown, predicates: readonly MockDbPredicate[]): boolean;
|
|
91
|
+
/** Keep only the rows satisfying every decidable predicate. */
|
|
92
|
+
export declare function filterRows<T>(rows: readonly T[], predicates: readonly MockDbPredicate[]): T[];
|
|
93
|
+
/** One projected column: the row key read, and the key it is emitted under. */
|
|
94
|
+
export interface ProjectedColumn {
|
|
95
|
+
source: string;
|
|
96
|
+
alias: string;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Parse `.select(...)` arguments into a projection.
|
|
100
|
+
*
|
|
101
|
+
* Returns `undefined` when the projection cannot be modelled — an aggregate
|
|
102
|
+
* expression, an `eb` callback, a raw `sql` fragment. An unmodelled projection
|
|
103
|
+
* leaves rows untouched rather than guessing at their shape.
|
|
104
|
+
*/
|
|
105
|
+
export declare function parseSelectArgs(args: readonly unknown[]): ProjectedColumn[] | undefined;
|
|
106
|
+
/**
|
|
107
|
+
* Narrow a row to the projected columns.
|
|
108
|
+
*
|
|
109
|
+
* A projected column the fixture row does not declare is omitted rather than
|
|
110
|
+
* emitted as `undefined`, so `'key' in row` keeps meaning "the fixture modelled
|
|
111
|
+
* this" — the same convention {@link evaluatePredicate} reads.
|
|
112
|
+
*
|
|
113
|
+
* A column is read under its `source` name and, failing that, under its
|
|
114
|
+
* `alias`. Fixtures in this repo are written both ways — some model the raw
|
|
115
|
+
* table row (`storage_key`), others the row the aliased query returns
|
|
116
|
+
* (`storageKey`) — and the projection has to narrow both. Reading either name
|
|
117
|
+
* costs nothing: a column dropped from the projection disappears from the
|
|
118
|
+
* output under both conventions, which is the regression this exists to catch.
|
|
119
|
+
*/
|
|
120
|
+
export declare function projectRow<T>(row: T, columns: readonly ProjectedColumn[]): T;
|
|
121
|
+
/** Narrow every row to the projected columns. */
|
|
122
|
+
export declare function projectRows<T>(rows: readonly T[], columns: readonly ProjectedColumn[]): T[];
|
|
123
|
+
/**
|
|
124
|
+
* Describe the predicates the mock recorded but could not evaluate.
|
|
125
|
+
*
|
|
126
|
+
* Exposed so a test that cares whether its filter was actually pinned can
|
|
127
|
+
* assert the mock understood it, instead of assuming it did.
|
|
128
|
+
*/
|
|
129
|
+
export declare function explainSkippedPredicates(predicates: readonly MockDbPredicate[]): string[];
|
|
130
|
+
//# sourceMappingURL=mock-db-query.d.ts.map
|
|
@@ -15,6 +15,29 @@
|
|
|
15
15
|
*
|
|
16
16
|
* Each test can configure return values via options and access the
|
|
17
17
|
* underlying vi.fn() mocks for assertions via the `mocks` property.
|
|
18
|
+
*
|
|
19
|
+
* ## The select chain APPLIES the query (contract)
|
|
20
|
+
*
|
|
21
|
+
* A select chain does not return `selectRows` / `selectFirstRow` verbatim. It
|
|
22
|
+
* evaluates the `.where(...)` predicates and the `.select([...])` projection the
|
|
23
|
+
* code under test issued, so a test observes the query instead of restating it:
|
|
24
|
+
* dropping a filter or a projected column changes what the test sees.
|
|
25
|
+
*
|
|
26
|
+
* - **Per query, not per test.** Every `db.selectFrom(...)` builds a fresh chain
|
|
27
|
+
* with its own predicate list, so two queries in one test cannot inherit each
|
|
28
|
+
* other's filters. The `mocks.select*` spies stay shared across the whole
|
|
29
|
+
* test, so existing clause assertions are unaffected.
|
|
30
|
+
* - **Only the shapes the evaluator reads.** `.where(column, op, value)` is
|
|
31
|
+
* evaluated; an `eb` callback or a raw `sql` fragment is recorded and skipped.
|
|
32
|
+
* `.select()` is applied only when every argument is a plain column string, so
|
|
33
|
+
* an aggregate or `eb` projection leaves rows untouched.
|
|
34
|
+
* - **A predicate on a column the fixture omits does not exclude the row.** To
|
|
35
|
+
* pin a filter, the fixture row must declare the column that filter reads.
|
|
36
|
+
* - **`executeTakeFirstOrThrow` yields `{}`** when the configured row does not
|
|
37
|
+
* satisfy the query, rather than throwing as Kysely would.
|
|
38
|
+
*
|
|
39
|
+
* `mock-db-query.ts` holds the evaluator and states the same contract with its
|
|
40
|
+
* reasoning; `mock-db-query.test.ts` tests it directly.
|
|
18
41
|
*/
|
|
19
42
|
import { vi } from 'vitest';
|
|
20
43
|
export interface MockDbOptions {
|
|
@@ -72,6 +95,10 @@ export interface MockDbMocks {
|
|
|
72
95
|
insertExecute: ReturnType<typeof vi.fn>;
|
|
73
96
|
insertExecuteTakeFirstOrThrow: ReturnType<typeof vi.fn>;
|
|
74
97
|
onConflict: ReturnType<typeof vi.fn>;
|
|
98
|
+
/** The upsert's ON CONFLICT DO UPDATE SET payload — shared across both the
|
|
99
|
+
* column() and columns() shapes, so a test can assert what an existing row
|
|
100
|
+
* is actually updated with. */
|
|
101
|
+
doUpdateSet: ReturnType<typeof vi.fn>;
|
|
75
102
|
updateTable: ReturnType<typeof vi.fn>;
|
|
76
103
|
updateSet: ReturnType<typeof vi.fn>;
|
|
77
104
|
updateWhere: ReturnType<typeof vi.fn>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Comparing a self-reported agent version against a feature's minimum.
|
|
3
|
+
*
|
|
4
|
+
* An agent reports its own package version in `agent.register`
|
|
5
|
+
* (`agentRegisterSchema.version`), and the field is optional — an agent old
|
|
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
|
|
9
|
+
* routinely dispatched to a fleet that cannot run it, and the version is the
|
|
10
|
+
* only fact the orchestrator has about what the fleet understands.
|
|
11
|
+
*/
|
|
12
|
+
/** A version's release triple, with any prerelease suffix dropped. */
|
|
13
|
+
type VersionBase = [number, number, number];
|
|
14
|
+
/**
|
|
15
|
+
* Parse `MAJOR.MINOR.PATCH`, ignoring any `-prerelease` suffix, or `null` when
|
|
16
|
+
* the string is not a version at all.
|
|
17
|
+
*
|
|
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.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseVersionBase(version: string): VersionBase | null;
|
|
24
|
+
/**
|
|
25
|
+
* True when `version` is at least `minimum`, comparing release bases only.
|
|
26
|
+
*
|
|
27
|
+
* An absent or unparseable version returns `false`: the orchestrator learns
|
|
28
|
+
* nothing from it, and a feature that needs a specific agent build must not
|
|
29
|
+
* treat "we cannot tell" as "yes". Callers decide what an all-unknown fleet
|
|
30
|
+
* means for them — this function only reports what the version proves.
|
|
31
|
+
*/
|
|
32
|
+
export declare function agentVersionAtLeast(version: string | null | undefined, minimum: string): boolean;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=agent-version.d.ts.map
|
|
@@ -1,7 +1,28 @@
|
|
|
1
1
|
import type { AgentRegistry } from './registry.js';
|
|
2
2
|
import { type JobQueue, type QueuedJob, type QueuedJobInput } from '../queue/job-queue.js';
|
|
3
3
|
import type { ScaleResult, ScalerRedispatchTrigger } from '../scaler/types.js';
|
|
4
|
+
import type { ResolvedContainerSpawn } from '../scaler/types.js';
|
|
4
5
|
import type { ResourceRequest } from '@kici-dev/engine';
|
|
6
|
+
/**
|
|
7
|
+
* Why a freed agent's queue drain claimed nothing.
|
|
8
|
+
*
|
|
9
|
+
* Named rather than inlined because the value travels: it is the `reason`
|
|
10
|
+
* field of the drain-declined log line and the assertion subject of the tests
|
|
11
|
+
* that pin each exit. The five members are the five ways
|
|
12
|
+
* `Dispatcher.drainForAgent` can return without a dispatch.
|
|
13
|
+
*/
|
|
14
|
+
export declare enum AgentDrainDecline {
|
|
15
|
+
/** The agent id is not in the in-memory registry (already disconnected). */
|
|
16
|
+
NotRegistered = "agent-not-registered",
|
|
17
|
+
/** This coordinator is draining and must not claim new work. */
|
|
18
|
+
CoordinatorDraining = "coordinator-draining",
|
|
19
|
+
/** The agent is already at `maxConcurrency`. */
|
|
20
|
+
NoCapacity = "no-capacity",
|
|
21
|
+
/** The host is flagged reboot-pending, so anything dispatched would be lost. */
|
|
22
|
+
RebootPending = "reboot-pending",
|
|
23
|
+
/** Nothing in the queue matched this agent's labels or pin. */
|
|
24
|
+
NoMatchingJob = "no-matching-job"
|
|
25
|
+
}
|
|
5
26
|
/**
|
|
6
27
|
* Default per-pass cap on how many pending jobs a capacity-freed re-drive
|
|
7
28
|
* re-offers to the scaler. Bounds the burst so a single free event cannot storm
|
|
@@ -60,24 +81,24 @@ type DispatchResult = {
|
|
|
60
81
|
status: 'rejected';
|
|
61
82
|
reason: string;
|
|
62
83
|
};
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
* it uses the onDispatch callback provided at construction. The caller
|
|
72
|
-
* (app.ts or server.ts) provides an onDispatch that looks up the agent's
|
|
73
|
-
* WS from the registry and sends the job.dispatch message.
|
|
74
|
-
*/
|
|
84
|
+
export declare function containerSpawnFor(jobConfig: Record<string, unknown> | undefined): {
|
|
85
|
+
image: string;
|
|
86
|
+
authconfig?: {
|
|
87
|
+
username: string;
|
|
88
|
+
password: string;
|
|
89
|
+
serveraddress: string;
|
|
90
|
+
} | undefined;
|
|
91
|
+
} | undefined;
|
|
75
92
|
export declare class Dispatcher {
|
|
76
93
|
private readonly registry;
|
|
77
94
|
private readonly queue;
|
|
78
95
|
private readonly metrics;
|
|
79
96
|
private readonly onDispatch;
|
|
80
97
|
private readonly onNoMatchingAgent?;
|
|
98
|
+
/** See the constructor dep of the same name. */
|
|
99
|
+
private readonly canPrespawnedAgentServe?;
|
|
100
|
+
/** See the constructor dep of the same name. */
|
|
101
|
+
private readonly isPrespawnedAgent?;
|
|
81
102
|
/**
|
|
82
103
|
* Single-flight guard for `retryPendingScaleRequests`. The capacity-freed
|
|
83
104
|
* hook and the leader-gated sweep can both fire concurrently; this prevents
|
|
@@ -85,6 +106,12 @@ export declare class Dispatcher {
|
|
|
85
106
|
* the same tick.
|
|
86
107
|
*/
|
|
87
108
|
private redriveInFlight;
|
|
109
|
+
/**
|
|
110
|
+
* Single-flight guard for `redrivePendingToConnectedAgents`. The per-coord
|
|
111
|
+
* safety-net tick must not overlap itself, so a slow re-drive can't be
|
|
112
|
+
* re-entered by the next interval fire and double-scan the same pending rows.
|
|
113
|
+
*/
|
|
114
|
+
private pendingRedriveInFlight;
|
|
88
115
|
/**
|
|
89
116
|
* Tracks which jobs are dispatched to which agents.
|
|
90
117
|
* Used for marking jobs as failed on agent disconnect.
|
|
@@ -170,7 +197,34 @@ export declare class Dispatcher {
|
|
|
170
197
|
/** Optional hook called when no agent matches the job's labels.
|
|
171
198
|
* When set, receives the per-job `resources` so the scaler can apply
|
|
172
199
|
* per-scaler / per-orchestrator / per-machine caps before spawning. */
|
|
173
|
-
onNoMatchingAgent?: (labels: string[], jobId: string, runId: string, excludeLabels: string[], resources?: ResourceRequest, orgId?: string
|
|
200
|
+
onNoMatchingAgent?: (labels: string[], jobId: string, runId: string, excludeLabels: string[], resources?: ResourceRequest, orgId?: string,
|
|
201
|
+
/**
|
|
202
|
+
* The job's own container image plus registry credentials, already
|
|
203
|
+
* resolved at dispatch. Present means the backend spawns THAT image with
|
|
204
|
+
* the KiCI runtime injected instead of the pool's fixed agent image.
|
|
205
|
+
*/
|
|
206
|
+
containerSpawn?: ResolvedContainerSpawn) => Promise<ScaleResult>;
|
|
207
|
+
/**
|
|
208
|
+
* Optional scaler predicate: may this pre-spawned (warm) agent serve this
|
|
209
|
+
* job? A warm agent is generic — started before the job existed, at the
|
|
210
|
+
* pool's shape and running the pool's image, both of which are fixed when
|
|
211
|
+
* it starts. When the predicate returns false the agent is skipped and the
|
|
212
|
+
* job falls through to `onNoMatchingAgent`, which spawns one that fits.
|
|
213
|
+
* Absent (no scaler) means every agent is eligible.
|
|
214
|
+
*/
|
|
215
|
+
canPrespawnedAgentServe?: (agentId: string, job: {
|
|
216
|
+
resources?: ResourceRequest;
|
|
217
|
+
hasOwnContainerImage: boolean;
|
|
218
|
+
}) => boolean;
|
|
219
|
+
/**
|
|
220
|
+
* Whether this scaler pre-spawned the agent, i.e. whether
|
|
221
|
+
* `canPrespawnedAgentServe` can ever answer false for it. The queue drain
|
|
222
|
+
* (agent asks for work, rather than job looks for an agent) uses it to
|
|
223
|
+
* decide whether the suitability predicate is worth carrying into the
|
|
224
|
+
* claim: for every ordinary agent it is not, and the drain keeps its
|
|
225
|
+
* single-statement fast path.
|
|
226
|
+
*/
|
|
227
|
+
isPrespawnedAgent?: (agentId: string) => boolean;
|
|
174
228
|
/** Max reconnection delay from agent config (default 60s). Used to derive grace period. */
|
|
175
229
|
maxReconnectDelayMs?: number;
|
|
176
230
|
/** Callback fired when a job is permanently failed before/outside agent execution. */
|
|
@@ -259,6 +313,39 @@ export declare class Dispatcher {
|
|
|
259
313
|
* that is about to reboot. No-op when no roster store is wired.
|
|
260
314
|
*/
|
|
261
315
|
private filterRebootPending;
|
|
316
|
+
/**
|
|
317
|
+
* Drop pre-spawned (warm) agents that cannot serve this job. Sibling of
|
|
318
|
+
* {@link filterRebootPending}: both remove candidates `findAvailable` matched
|
|
319
|
+
* on labels but that are unusable for a reason labels cannot express.
|
|
320
|
+
*
|
|
321
|
+
* A warm agent's cpu, memory and container image are all set when it starts
|
|
322
|
+
* and cannot change afterwards, so a job asking for something else has to get
|
|
323
|
+
* an agent of its own. Dropping the candidate here is what sends it down the
|
|
324
|
+
* ordinary `onNoMatchingAgent` scale path. No-op when no scaler is wired.
|
|
325
|
+
*/
|
|
326
|
+
private filterUnsuitablePrespawned;
|
|
327
|
+
/**
|
|
328
|
+
* The fit question for one job: the shape it declares, and whether it brings
|
|
329
|
+
* its own container image.
|
|
330
|
+
*
|
|
331
|
+
* The shape comes from `jobConfig.resources` when the typed `resources`
|
|
332
|
+
* mirror is absent, because the mirror is optional and several dispatch paths
|
|
333
|
+
* never fill it — a job reaching {@link dispatch} straight off the webhook
|
|
334
|
+
* pipeline or off a worker's reroute handler carries its declaration in
|
|
335
|
+
* `jobConfig` alone. Reading only the mirror there reports a job that
|
|
336
|
+
* declares nothing, which admits it onto a pre-spawned agent of some other
|
|
337
|
+
* size — the exact mismatch this gate exists to refuse.
|
|
338
|
+
*/
|
|
339
|
+
private prespawnedFitFor;
|
|
340
|
+
/**
|
|
341
|
+
* The queue-drain half of {@link filterUnsuitablePrespawned}: a per-job
|
|
342
|
+
* predicate for one agent, or undefined when this agent needs no check.
|
|
343
|
+
*
|
|
344
|
+
* Undefined is the common answer — an ordinary agent is not pre-spawned, so
|
|
345
|
+
* the predicate could only ever say yes, and returning one would cost the
|
|
346
|
+
* drain its single-statement fast path for nothing.
|
|
347
|
+
*/
|
|
348
|
+
private prespawnedFitFilterFor;
|
|
262
349
|
/**
|
|
263
350
|
* Release a reboot-pending host on its real reconnect (down-then-up). Clears
|
|
264
351
|
* the persisted flag so the very next `onAgentAvailable` drain dispatches the
|
|
@@ -268,6 +355,12 @@ export declare class Dispatcher {
|
|
|
268
355
|
*/
|
|
269
356
|
releaseRebootPending(agentId: string): Promise<void>;
|
|
270
357
|
onAgentAvailable(agentId: string): Promise<void>;
|
|
358
|
+
/**
|
|
359
|
+
* Claim at most one queued job for a freed agent.
|
|
360
|
+
*
|
|
361
|
+
* Returns the reason nothing was dispatched, or null when a job was.
|
|
362
|
+
*/
|
|
363
|
+
private drainForAgent;
|
|
271
364
|
/** Record that a job began executing on its agent. */
|
|
272
365
|
markJobStarted(jobId: string): void;
|
|
273
366
|
/**
|
|
@@ -316,6 +409,51 @@ export declare class Dispatcher {
|
|
|
316
409
|
* fresh agent is spawned bound to this job.
|
|
317
410
|
*/
|
|
318
411
|
private redispatch;
|
|
412
|
+
/**
|
|
413
|
+
* Safety-net re-drive: deliver every pending job that a currently-connected,
|
|
414
|
+
* idle, matching agent could take, through the same atomic claim the drain
|
|
415
|
+
* uses (`dispatchBoundJob` → `dequeueById`).
|
|
416
|
+
*
|
|
417
|
+
* Runs per-coordinator and is NOT leader-gated: each coordinator drains the
|
|
418
|
+
* shared queue onto its OWN connected agents, and the atomic claim guarantees
|
|
419
|
+
* at most one agent (on any coordinator) wins each job, so concurrent ticks
|
|
420
|
+
* cannot double-dispatch.
|
|
421
|
+
*
|
|
422
|
+
* It closes the requeue re-drive gap. A job requeued by `handleAckExpiry` /
|
|
423
|
+
* `onJobRejected` / the leader ack sweep gets exactly one delivery attempt —
|
|
424
|
+
* `redispatch`'s single `findAvailable` + `dispatchBoundJob`. An idle matching
|
|
425
|
+
* agent whose own drain trigger (registration / completion / status) already
|
|
426
|
+
* fired before the requeue has no further trigger, so if that one attempt
|
|
427
|
+
* transiently misses the agent — the agent is momentarily at capacity while an
|
|
428
|
+
* in-flight drain holds its eagerly-claimed slot, or the agent is connected to
|
|
429
|
+
* a different coordinator than the one that ran the expiry — the requeued
|
|
430
|
+
* pending job would otherwise sit undelivered until it expired. This tick
|
|
431
|
+
* re-attempts delivery onto connected agents so the miss recovers on the next
|
|
432
|
+
* sweep.
|
|
433
|
+
*
|
|
434
|
+
* It never consults the scaler (that is `retryPendingScaleRequests`) and never
|
|
435
|
+
* spawns: it only places jobs onto agents already connected here.
|
|
436
|
+
*
|
|
437
|
+
* A failure propagates to the caller rather than being swallowed here — the
|
|
438
|
+
* per-coord interval wrapper is the single error-log site, matching the
|
|
439
|
+
* sibling recovery/ack sweeps that share its cadence. The `finally` only
|
|
440
|
+
* releases the single-flight guard.
|
|
441
|
+
*/
|
|
442
|
+
redrivePendingToConnectedAgents(maxJobs?: number): Promise<number>;
|
|
443
|
+
/**
|
|
444
|
+
* Pick a connected agent that may take a pending job, or null. A pinned
|
|
445
|
+
* host-fanout child may run ONLY on its pinned agent — and `dequeueById`
|
|
446
|
+
* ignores the pin — so a pinned job is routed to its own agent and never
|
|
447
|
+
* offered to `findAvailable`, which would mis-deliver it to any label match.
|
|
448
|
+
*
|
|
449
|
+
* Reboot-pending gate: a host whose `restart` job just completed is still
|
|
450
|
+
* connected but about to reboot, so its held post-restart job must NOT be
|
|
451
|
+
* re-driven into the about-to-die box. This is the safety-net re-drive's
|
|
452
|
+
* counterpart of the same gate in `dispatch()` / `dispatchPinned` /
|
|
453
|
+
* `drainForAgent`; without it this path re-drives the held job onto the
|
|
454
|
+
* reboot-pending host and defeats the hold.
|
|
455
|
+
*/
|
|
456
|
+
private selectConnectedTargetForPending;
|
|
319
457
|
/**
|
|
320
458
|
* Handle agent disconnect. Starts per-job recovery timers instead of
|
|
321
459
|
* immediately failing jobs, giving the agent a grace period to reconnect.
|
|
@@ -77,6 +77,13 @@ export interface UpsertHostInput {
|
|
|
77
77
|
agentId: string;
|
|
78
78
|
tokenId: string | null;
|
|
79
79
|
lifecycleClass: LifecycleClass;
|
|
80
|
+
/**
|
|
81
|
+
* True when an auto-scaler backend spawned this agent, so `runsOnAll`
|
|
82
|
+
* fan-out skips it. Derived from the scaler manager's registration lookup,
|
|
83
|
+
* never from `lifecycleClass` (which is `ephemeral` for every agent when the
|
|
84
|
+
* auth mode is `none`). Omitted ⇒ false.
|
|
85
|
+
*/
|
|
86
|
+
scalerManaged?: boolean;
|
|
80
87
|
labels: string[];
|
|
81
88
|
hostname: string | null;
|
|
82
89
|
platform: string;
|
|
@@ -176,13 +183,38 @@ export declare class HostRosterStore {
|
|
|
176
183
|
getStagedVersion(agentId: string): Promise<string | null>;
|
|
177
184
|
listAll(): Promise<HostRosterRow[]>;
|
|
178
185
|
/**
|
|
179
|
-
* Resolve
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
186
|
+
* Resolve EVERY roster host matching a label predicate (OR-of-AND include
|
|
187
|
+
* groups, minus exclude labels), tagged with its derived status. Returns
|
|
188
|
+
* declared-but-absent static hosts (status `unreachable`) so a caller can
|
|
189
|
+
* apply `onUnreachable` — the live registry alone cannot name an
|
|
190
|
+
* expected-but-absent host.
|
|
191
|
+
*
|
|
192
|
+
* This is the INVENTORY query: it includes auto-scaler-spawned hosts, whose
|
|
193
|
+
* `lifecycleClass` is what the SDK's `ctx.kici.inventory` exposes to tell
|
|
194
|
+
* them apart. `runsOnAll` fan-out uses {@link findFanoutTargets} instead.
|
|
184
195
|
*/
|
|
185
196
|
findMatching(include: readonly (readonly LabelMatcher[])[], exclude: readonly LabelMatcher[], graceMs: number): Promise<MatchedHost[]>;
|
|
197
|
+
/**
|
|
198
|
+
* Resolve the `runsOnAll` fan-out target set: {@link findMatching}, minus
|
|
199
|
+
* every auto-scaler-spawned host.
|
|
200
|
+
*
|
|
201
|
+
* Fan-out targets DECLARED fleet members. An auto-scaler agent is spawned to
|
|
202
|
+
* a pool's fixed shape, so a child pinned to one runs at that shape rather
|
|
203
|
+
* than its own — the same defect the dispatcher's warm-pool suitability gate
|
|
204
|
+
* removes, on the path a pin deliberately leaves ungated.
|
|
205
|
+
*
|
|
206
|
+
* Separate from `findMatching` on purpose: `findMatching` also backs the
|
|
207
|
+
* SDK's `inventory.query`, where a host the caller asked for must never go
|
|
208
|
+
* missing (a selector returning FEWER hosts than no selector at all).
|
|
209
|
+
*/
|
|
210
|
+
findFanoutTargets(include: readonly (readonly LabelMatcher[])[], exclude: readonly LabelMatcher[], graceMs: number): Promise<MatchedHost[]>;
|
|
211
|
+
/**
|
|
212
|
+
* Shared row loop behind {@link findMatching} and {@link findFanoutTargets}.
|
|
213
|
+
* `excludeScalerManaged` stays private to the store — each public method
|
|
214
|
+
* names its own semantics, so a call site cannot silently pick the wrong
|
|
215
|
+
* population by passing a bare boolean.
|
|
216
|
+
*/
|
|
217
|
+
private matchRows;
|
|
186
218
|
/**
|
|
187
219
|
* Map a roster row to the canonical {@link HostInventoryEntry} — the queryable
|
|
188
220
|
* shape returned by the `inventory.query`/`inventory.get` RPC and typed on the
|
package/dist/agent/registry.d.ts
CHANGED
|
@@ -137,6 +137,8 @@ export interface RosterReconciler {
|
|
|
137
137
|
agentId: string;
|
|
138
138
|
tokenId: string | null;
|
|
139
139
|
lifecycleClass: 'static' | 'ephemeral';
|
|
140
|
+
/** True when a scaler backend spawned this agent (kept out of `runsOnAll`). */
|
|
141
|
+
scalerManaged?: boolean;
|
|
140
142
|
labels: string[];
|
|
141
143
|
hostname: string | null;
|
|
142
144
|
platform: string;
|
package/dist/app.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ import type { PeerRegistry } from './cluster/peer-registry.js';
|
|
|
26
26
|
import type { JobQueue } from './queue/job-queue.js';
|
|
27
27
|
import type { DedupCache } from './webhook/dedup.js';
|
|
28
28
|
import type { LockFileCache } from './lockfile-cache.js';
|
|
29
|
+
import type { ContentRequirementsCache } from './content-requirements-cache.js';
|
|
29
30
|
import type { PlatformClient } from './ws/platform-client.js';
|
|
30
31
|
import type { ScalerManager } from './scaler/manager.js';
|
|
31
32
|
import type { ProviderRegistry } from './provider-registry.js';
|
|
@@ -37,7 +38,8 @@ import type { ArtifactStore } from './artifacts/artifact-store.js';
|
|
|
37
38
|
import type { DispatchCacheRefTracker } from './cache/index.js';
|
|
38
39
|
import type { PendingBuildTracker } from './cache/index.js';
|
|
39
40
|
import type { PendingInitTracker } from './cache/index.js';
|
|
40
|
-
import type { PendingDynamicTracker } from './cache/index.js';
|
|
41
|
+
import type { PendingDynamicTracker, PendingGlobalEvalTracker } from './cache/index.js';
|
|
42
|
+
import type { GlobalEvalRoundCache } from './cache/index.js';
|
|
41
43
|
import type { CacheStorage } from './storage/types.js';
|
|
42
44
|
import type { ProvenanceTrustRoot } from './provenance/trust-root.js';
|
|
43
45
|
import type { LocalSigner } from './oidc/local-dev-signer.js';
|
|
@@ -64,8 +66,11 @@ import type { RegistrationStore } from './registration/registration-store.js';
|
|
|
64
66
|
import type { RegistrationIndex } from './registration/registration-index.js';
|
|
65
67
|
import type { CronScheduler } from './cron/cron-scheduler.js';
|
|
66
68
|
import { type ConfigRouteDeps } from './routes/admin-config.js';
|
|
69
|
+
import type { ProcessingDeps } from './pipeline/processor.js';
|
|
70
|
+
import type { InvokeGateDeps } from './pipeline/invoke-gate.js';
|
|
67
71
|
import { WebhookIngestOutcome } from './pipeline/process-webhook.js';
|
|
68
72
|
import type { IngestOverflowBuffer } from './webhook/ingest-overflow-buffer.js';
|
|
73
|
+
import type { IngestOverflowReplayer } from './webhook/ingest-overflow-replayer.js';
|
|
69
74
|
import { type OverflowDelivery } from './webhook/ingest-overflow-types.js';
|
|
70
75
|
import type { IngestAdmissionController } from './webhook/ingest-admission.js';
|
|
71
76
|
import type { OrgIngestCapReader } from './webhook/org-ingest-cap-reader.js';
|
|
@@ -82,9 +87,8 @@ import type { GenericSourceManager } from './webhook/generic-sources.js';
|
|
|
82
87
|
import type { TrustStore } from './events/trust-store.js';
|
|
83
88
|
import type { ContextStore } from './contexts/context-store.js';
|
|
84
89
|
import type { VariableStore } from './contexts/variable-store.js';
|
|
85
|
-
import type { HeldRunStore } from './contexts/held-runs.js';
|
|
90
|
+
import type { HeldRunStore, ReleaseSignal } from './contexts/held-runs.js';
|
|
86
91
|
import type { StepApprovalBridge } from './approvals/step-approval-bridge.js';
|
|
87
|
-
import type { ContributorCache } from './security/contributor-cache.js';
|
|
88
92
|
import { AgentMetricsAggregator } from './metrics/agent-metrics-aggregator.js';
|
|
89
93
|
/**
|
|
90
94
|
* All dependencies needed to create the orchestrator Hono app.
|
|
@@ -108,6 +112,7 @@ export interface AppDependencies {
|
|
|
108
112
|
jobQueue: JobQueue;
|
|
109
113
|
dedup: DedupCache;
|
|
110
114
|
lockFileCache: LockFileCache;
|
|
115
|
+
contentRequirementsCache: ContentRequirementsCache;
|
|
111
116
|
providerRegistry: ProviderRegistry;
|
|
112
117
|
platformClient?: PlatformClient;
|
|
113
118
|
/**
|
|
@@ -126,6 +131,13 @@ export interface AppDependencies {
|
|
|
126
131
|
* for later replay; absent → capture disabled.
|
|
127
132
|
*/
|
|
128
133
|
ingestOverflowBuffer?: IngestOverflowBuffer;
|
|
134
|
+
/**
|
|
135
|
+
* Drain loop for the durable ingest queue. The accept path borrows its
|
|
136
|
+
* claim-release so a failed pipeline hands the row back for retry through the
|
|
137
|
+
* same attempt ceiling the drain uses; absent → the accept path degrades to
|
|
138
|
+
* inline ingestion.
|
|
139
|
+
*/
|
|
140
|
+
ingestOverflowReplayer?: IngestOverflowReplayer;
|
|
129
141
|
/**
|
|
130
142
|
* Fulfil deferred attestations on demand (mints in this process, which owns
|
|
131
143
|
* the Platform WS). Backs `POST /api/v1/admin/attestations/retry`. Wired only
|
|
@@ -168,6 +180,14 @@ export interface AppDependencies {
|
|
|
168
180
|
* is registered so `ctx.kici.oidc.token()` mints a `kici-local` dev token.
|
|
169
181
|
*/
|
|
170
182
|
localOidcSigner?: LocalSigner;
|
|
183
|
+
/**
|
|
184
|
+
* Test-only fault-injection policy, threaded from a test-only entrypoint via
|
|
185
|
+
* `bootstrapOrchestrator`. Undefined in production. Consumed here only for the
|
|
186
|
+
* initial-mint provenance seam (`initialMintFault`); the other seams live in
|
|
187
|
+
* the composition root / server hooks. Type-only reference — the runtime
|
|
188
|
+
* module never enters the shipped bundle.
|
|
189
|
+
*/
|
|
190
|
+
faultInjection?: import('./testing/fault-injection.js').OrchestratorFaultInjection;
|
|
171
191
|
/**
|
|
172
192
|
* Orchestrator-owned provenance signing (Phase 1 root of trust). Present when
|
|
173
193
|
* `KICI_ORCHESTRATOR_PROVENANCE_ISSUER` is configured: the orchestrator mints +
|
|
@@ -208,6 +228,8 @@ export interface AppDependencies {
|
|
|
208
228
|
pendingInits?: PendingInitTracker;
|
|
209
229
|
/** Pending dynamic tracker for DynamicJobFn evaluation coordination. */
|
|
210
230
|
pendingDynamics?: PendingDynamicTracker;
|
|
231
|
+
pendingGlobalEvals?: PendingGlobalEvalTracker;
|
|
232
|
+
globalEvalCache?: GlobalEvalRoundCache;
|
|
211
233
|
/** Commit status reporter for setting pending/success/failure/error on commits. Optional. */
|
|
212
234
|
checkRunReporter?: CheckRunReporter;
|
|
213
235
|
/** Execution tracker for DB persistence of execution state. Optional — requires database. */
|
|
@@ -244,12 +266,33 @@ export interface AppDependencies {
|
|
|
244
266
|
configRouteDeps?: ConfigRouteDeps;
|
|
245
267
|
/** Event router for internal event delivery. Optional -- if not set, event routing is inactive. */
|
|
246
268
|
eventRouter?: EventRouter;
|
|
269
|
+
/** Invoke-gate dependencies (summon callback + chain-depth bound). Optional -- if not set, invoke gates fail loudly. */
|
|
270
|
+
invokeGateDeps?: InvokeGateDeps;
|
|
271
|
+
/**
|
|
272
|
+
* Late-binding handle the internal-event dispatch adapter reads to obtain the
|
|
273
|
+
* live `ProcessingDeps` bag. `createApp` populates it, because the bag can
|
|
274
|
+
* only be assembled here while the event router that dispatches internal
|
|
275
|
+
* events is constructed earlier in the bootstrap. Left unset by callers that
|
|
276
|
+
* never route internal events (tests constructing a bare app).
|
|
277
|
+
*/
|
|
278
|
+
processingDepsRef?: {
|
|
279
|
+
current: (() => ProcessingDeps) | null;
|
|
280
|
+
};
|
|
247
281
|
/** Event store. Optional -- mounted when admin DLQ admin route should be available. */
|
|
248
282
|
eventStore?: EventStore;
|
|
249
283
|
/** Event emitter for system events (workflow/job complete). Optional -- if not set, system events are skipped. */
|
|
250
284
|
eventEmitter?: EventEmitter;
|
|
251
285
|
/** Generic webhook source manager. Optional -- if not set, generic webhooks are disabled. */
|
|
252
286
|
genericSourceManager?: GenericSourceManager;
|
|
287
|
+
/**
|
|
288
|
+
* Re-register a generic source's provider bundle from its database row,
|
|
289
|
+
* resolving to true when a per-routing-key bundle is now registered.
|
|
290
|
+
*
|
|
291
|
+
* Built in orchestrator-core so it shares the exact dependency bag the
|
|
292
|
+
* startup enumeration and the LISTEN/NOTIFY drain already register with.
|
|
293
|
+
* Optional -- wirings without one keep the previous behaviour.
|
|
294
|
+
*/
|
|
295
|
+
ensureProviderBundle?: (routingKey: string) => Promise<boolean>;
|
|
253
296
|
/** GitHub direct-ingress route deps (hybrid/independent only). Optional -- if not set, the direct GitHub ingress route is not mounted. */
|
|
254
297
|
githubSourceStore?: SourceStore;
|
|
255
298
|
githubVerifyDeps?: VerifyInboundDeps;
|
|
@@ -275,6 +318,16 @@ export interface AppDependencies {
|
|
|
275
318
|
heldRunStore?: HeldRunStore;
|
|
276
319
|
/** Step-approval bridge — opens step-scoped holds and relays their resolution back to the waiting agent. Optional. */
|
|
277
320
|
stepApprovalBridge?: StepApprovalBridge;
|
|
321
|
+
/**
|
|
322
|
+
* Re-dispatch a job whose hold was released. Supplied by both mode hooks
|
|
323
|
+
* through `appDepsExtras`; declared here so the admin held-run routes can
|
|
324
|
+
* read it type-safely rather than off an untyped spread. Optional — an app
|
|
325
|
+
* assembled without it mounts no local held-run decision surface, because a
|
|
326
|
+
* release that cannot dispatch is a row flip pretending to be a release.
|
|
327
|
+
*/
|
|
328
|
+
onJobRelease?: (signal: ReleaseSignal) => Promise<void>;
|
|
329
|
+
/** Replay the stored dispatch context of a released workflow-scoped hold. Same provenance as `onJobRelease`. */
|
|
330
|
+
onWorkflowRelease?: (signal: ReleaseSignal) => Promise<void>;
|
|
278
331
|
/** Global workflow policy for org-level permission enforcement. Optional -- if not set, global workflows are dispatched without permission checks. */
|
|
279
332
|
globalWorkflowPolicy?: GlobalWorkflowPolicy;
|
|
280
333
|
/** Inbound webhook delivery log writer. Optional -- if not set, deliveries are not persisted to event_log. */
|
|
@@ -308,10 +361,6 @@ export interface AppDependencies {
|
|
|
308
361
|
coordinator?: RunCoordinator;
|
|
309
362
|
/** Peer registry for aggregating infrastructure across cluster. Optional. */
|
|
310
363
|
peerRegistry?: PeerRegistry;
|
|
311
|
-
/** Contributor permission cache. Optional -- threaded through from server.ts
|
|
312
|
-
* so membership-related webhooks invalidate matching entries immediately
|
|
313
|
-
* (instead of waiting for the 15-minute TTL). */
|
|
314
|
-
contributorCache?: ContributorCache;
|
|
315
364
|
/**
|
|
316
365
|
* Shared aggregator for agent-pushed metrics. When omitted, app.ts
|
|
317
366
|
* constructs its own — kept optional so existing tests still work
|