@kici-dev/orchestrator 0.1.22 → 0.1.23
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/agent/host-roster.d.ts +39 -3
- package/dist/agent/token-store.d.ts +29 -0
- package/dist/cli.js +373 -211
- package/dist/db/migrations/051_binding_host_pattern.d.ts +18 -0
- package/dist/db/migrations/052_host_reach_metadata.d.ts +19 -0
- package/dist/db/migrations/053_agent_token_single_use.d.ts +17 -0
- package/dist/db/types.d.ts +23 -0
- package/dist/environments/binding-store.d.ts +12 -3
- package/dist/environments/held-runs.d.ts +24 -0
- package/dist/metrics/prometheus.d.ts +2 -0
- package/dist/pipeline/dispatch-matched-workflow.d.ts +58 -3
- package/dist/pipeline/test-pipeline.d.ts +6 -0
- package/dist/reporting/log-writer.d.ts +19 -0
- package/dist/scaler/manager.d.ts +17 -0
- package/dist/secrets/secret-resolver.d.ts +19 -6
- package/dist/server.js +19853 -19099
- package/dist/standalone.js +24997 -24439
- package/dist/ws/bringup-api.d.ts +76 -0
- package/dist/ws/dashboard-fleet-handler.d.ts +11 -1
- package/dist/ws/fleet-runs-on-all.d.ts +3 -0
- package/dist/ws/platform-client.d.ts +4 -1
- package/dist/ws/test-relay-handlers.d.ts +9 -0
- package/installer-image-digests.json +3 -3
- package/package.json +4 -4
- package/sbom.spdx.json +50 -50
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* Add a per-host dimension to environment secret bindings:
|
|
4
|
+
*
|
|
5
|
+
* - `environment_bindings.host_pattern text NOT NULL DEFAULT '**'` — the host
|
|
6
|
+
* selector a binding applies to (exact / glob / regex, matched against a
|
|
7
|
+
* fan-out child's agentId / hostname / labels). `'**'` matches every host, so
|
|
8
|
+
* existing rows are backfilled to `'**'` and keep their fleet-wide behaviour.
|
|
9
|
+
* - The binding unique key widens from `(environment_id, scope_pattern)` to
|
|
10
|
+
* `(environment_id, scope_pattern, host_pattern)` so the same scope can carry
|
|
11
|
+
* distinct per-host selectors.
|
|
12
|
+
*
|
|
13
|
+
* Idempotent: re-running on a DB that already has the column / index is a no-op.
|
|
14
|
+
* Additive — staging data is preserved.
|
|
15
|
+
*/
|
|
16
|
+
export declare function up(db: Kysely<unknown>): Promise<void>;
|
|
17
|
+
export declare function down(db: Kysely<unknown>): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=051_binding_host_pattern.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* Add pre-agent reach metadata to the host roster so a declared host (no agent
|
|
4
|
+
* yet) can be reached over SSH for bootstrap bring-up:
|
|
5
|
+
*
|
|
6
|
+
* - `host_roster.address text NULL` — IP / hostname to SSH to.
|
|
7
|
+
* - `host_roster.ssh_user text NULL` — SSH login user (defaults to `root` at use site).
|
|
8
|
+
* - `host_roster.ssh_port int NULL` — SSH port (defaults to 22 at use site).
|
|
9
|
+
* - `host_roster.ssh_key_secret text NULL` — scoped-secret ref (`scope/key`)
|
|
10
|
+
* holding the bring-up private key. The orchestrator resolves it server-side;
|
|
11
|
+
* the key never lives in the roster.
|
|
12
|
+
*
|
|
13
|
+
* All nullable: a host with no reach metadata simply cannot be bootstrapped and
|
|
14
|
+
* behaves exactly as before. Idempotent (`ADD COLUMN IF NOT EXISTS`); additive,
|
|
15
|
+
* so staging data is preserved.
|
|
16
|
+
*/
|
|
17
|
+
export declare function up(db: Kysely<unknown>): Promise<void>;
|
|
18
|
+
export declare function down(db: Kysely<unknown>): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=052_host_reach_metadata.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* Add a single-use marker to agent tokens for the bootstrap (init-runner)
|
|
4
|
+
* bring-up flow:
|
|
5
|
+
*
|
|
6
|
+
* - `agent_tokens.consumed_at timestamptz NULL` — set the first time a
|
|
7
|
+
* single-use bootstrap token is consumed (at `agent.register`). A second
|
|
8
|
+
* register with the same token is rejected. NULL = never consumed (the
|
|
9
|
+
* default for every existing static / ephemeral token, which stay reusable
|
|
10
|
+
* until expiry).
|
|
11
|
+
*
|
|
12
|
+
* Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
|
|
13
|
+
* preserved.
|
|
14
|
+
*/
|
|
15
|
+
export declare function up(db: Kysely<unknown>): Promise<void>;
|
|
16
|
+
export declare function down(db: Kysely<unknown>): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=053_agent_token_single_use.d.ts.map
|
package/dist/db/types.d.ts
CHANGED
|
@@ -605,6 +605,12 @@ export interface EnvironmentBindingsTable {
|
|
|
605
605
|
environment_id: string;
|
|
606
606
|
/** Scope pattern for matching (e.g. workflow name glob, repo pattern) */
|
|
607
607
|
scope_pattern: string;
|
|
608
|
+
/**
|
|
609
|
+
* Host selector this binding applies to (exact / glob / regex over a fan-out
|
|
610
|
+
* child's agentId / hostname / labels). `'**'` (the default) matches every
|
|
611
|
+
* host.
|
|
612
|
+
*/
|
|
613
|
+
host_pattern: Generated<string>;
|
|
608
614
|
/** When this binding was created */
|
|
609
615
|
created_at: Generated<Date>;
|
|
610
616
|
}
|
|
@@ -863,6 +869,13 @@ export interface AgentTokenTable {
|
|
|
863
869
|
revoked_at: Date | null;
|
|
864
870
|
/** When this token expires (null = never, static tokens) */
|
|
865
871
|
expires_at: Date | null;
|
|
872
|
+
/**
|
|
873
|
+
* Single-use marker for bootstrap (init-runner) tokens. Set the first time
|
|
874
|
+
* the token is consumed at `agent.register`; a second register is rejected.
|
|
875
|
+
* NULL = never consumed (every static / ephemeral token stays reusable until
|
|
876
|
+
* expiry).
|
|
877
|
+
*/
|
|
878
|
+
consumed_at: ColumnType<Date | null, Date | string | null | undefined, Date | string | null>;
|
|
866
879
|
}
|
|
867
880
|
export type AgentTokenRow = Selectable<AgentTokenTable>;
|
|
868
881
|
export type NewAgentTokenRow = Insertable<AgentTokenTable>;
|
|
@@ -1639,6 +1652,16 @@ export interface HostRosterTable {
|
|
|
1639
1652
|
* reconnects (down-then-up). NULL = no reboot pending.
|
|
1640
1653
|
*/
|
|
1641
1654
|
reboot_pending_until: ColumnType<Date | null, Date | string | null, Date | string | null>;
|
|
1655
|
+
/**
|
|
1656
|
+
* Pre-agent reach metadata: how to SSH to a declared host before it has a
|
|
1657
|
+
* KiCI agent, for bootstrap bring-up. All nullable — a host with no reach
|
|
1658
|
+
* metadata cannot be bootstrapped and behaves exactly as before.
|
|
1659
|
+
*/
|
|
1660
|
+
address: ColumnType<string | null, string | null | undefined, string | null>;
|
|
1661
|
+
ssh_user: ColumnType<string | null, string | null | undefined, string | null>;
|
|
1662
|
+
ssh_port: ColumnType<number | null, number | null | undefined, number | null>;
|
|
1663
|
+
/** Scoped-secret ref (`scope/key`) holding the bring-up private key. */
|
|
1664
|
+
ssh_key_secret: ColumnType<string | null, string | null | undefined, string | null>;
|
|
1642
1665
|
created_at: Generated<Date>;
|
|
1643
1666
|
updated_at: ColumnType<Date, Date | string | undefined, Date | string>;
|
|
1644
1667
|
}
|
|
@@ -6,6 +6,14 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { Kysely } from 'kysely';
|
|
8
8
|
import type { Database, EnvironmentBinding } from '../db/types.js';
|
|
9
|
+
/**
|
|
10
|
+
* A scope→environment binding with its host selector. `hostPattern` defaults to
|
|
11
|
+
* `'**'` (all hosts) when omitted.
|
|
12
|
+
*/
|
|
13
|
+
export interface BindingInput {
|
|
14
|
+
scopePattern: string;
|
|
15
|
+
hostPattern?: string;
|
|
16
|
+
}
|
|
9
17
|
/**
|
|
10
18
|
* Data access layer for environment bindings.
|
|
11
19
|
*/
|
|
@@ -17,10 +25,11 @@ export declare class BindingStore {
|
|
|
17
25
|
/**
|
|
18
26
|
* Replace all bindings for an environment in a transaction.
|
|
19
27
|
*
|
|
20
|
-
* Deletes existing bindings and inserts the new set atomically.
|
|
21
|
-
*
|
|
28
|
+
* Deletes existing bindings and inserts the new set atomically. Each binding
|
|
29
|
+
* carries a `scopePattern` and an optional `hostPattern` (defaulting to
|
|
30
|
+
* `'**'`). Pass an empty array to clear all bindings.
|
|
22
31
|
*/
|
|
23
|
-
set(orgId: string, environmentId: string,
|
|
32
|
+
set(orgId: string, environmentId: string, bindings: BindingInput[]): Promise<void>;
|
|
24
33
|
/** Find bindings for an environment (alias for list, used by secret resolver). */
|
|
25
34
|
findBindingsForEnvironment(orgId: string, environmentId: string): Promise<EnvironmentBinding[]>;
|
|
26
35
|
}
|
|
@@ -104,8 +104,32 @@ export declare class HeldRunStore {
|
|
|
104
104
|
* the created row.
|
|
105
105
|
*/
|
|
106
106
|
createHold(orgId: string, data: CreateHoldData): Promise<HeldRun>;
|
|
107
|
+
/** INSERT one decision row using the given executor (root or transaction). */
|
|
108
|
+
private insertDecisionRow;
|
|
109
|
+
/** Flip a pending hold to 'approved' using the given executor. Undefined if not pending. */
|
|
110
|
+
private flipToApproved;
|
|
111
|
+
/** Flip a pending hold to 'rejected' using the given executor. Undefined if not pending. */
|
|
112
|
+
private flipToRejected;
|
|
113
|
+
/** Map a released held_runs row to the resume ReleaseSignal. */
|
|
114
|
+
private toReleaseSignal;
|
|
107
115
|
/** Record one approve/reject decision against a hold. */
|
|
108
116
|
recordDecision(heldRunId: string, data: RecordDecisionData): Promise<HeldRunApproval>;
|
|
117
|
+
/**
|
|
118
|
+
* Atomically record an approve decision and release the (now-satisfied) hold.
|
|
119
|
+
* The INSERT into `held_run_approvals` and the `held_runs` → approved UPDATE
|
|
120
|
+
* run in a single transaction, so a crash between them cannot strand the hold
|
|
121
|
+
* `pending` with a recorded approve. Throws if the hold is not found or no
|
|
122
|
+
* longer pending (the whole transaction rolls back).
|
|
123
|
+
*/
|
|
124
|
+
recordAndRelease(orgId: string, heldRunId: string, data: RecordDecisionData): Promise<ReleaseSignal>;
|
|
125
|
+
/**
|
|
126
|
+
* Atomically record a reject decision and reject the hold. The INSERT and the
|
|
127
|
+
* `held_runs` → rejected UPDATE run in a single transaction, so a crash
|
|
128
|
+
* between them cannot strand the hold `pending` with a recorded reject (which
|
|
129
|
+
* would poison `evaluate()` forever). Throws if the hold is not found or no
|
|
130
|
+
* longer pending (the whole transaction rolls back).
|
|
131
|
+
*/
|
|
132
|
+
recordAndReject(orgId: string, heldRunId: string, data: RecordDecisionData, reason?: string): Promise<HeldRun>;
|
|
109
133
|
/** List the recorded decisions for a hold, oldest first. */
|
|
110
134
|
listDecisions(heldRunId: string): Promise<HeldRunApproval[]>;
|
|
111
135
|
/** Get a single held run by id (org-scoped). Returns null if absent. */
|
|
@@ -8,6 +8,8 @@ export declare function setDeclaredHostsUnreachable(value: number): void;
|
|
|
8
8
|
export declare function setStaleRunsCurrent(value: number): void;
|
|
9
9
|
interface ScalerUsageRow {
|
|
10
10
|
scaler: string;
|
|
11
|
+
/** Backend type for this scaler (rollup dimension). `__global__` for the orchestrator-wide row. */
|
|
12
|
+
scalerType?: string;
|
|
11
13
|
machinePool?: string;
|
|
12
14
|
cpus: number;
|
|
13
15
|
memBytes: number;
|
|
@@ -14,10 +14,12 @@
|
|
|
14
14
|
* results through the pipeline.
|
|
15
15
|
*/
|
|
16
16
|
import { ExecutionJobStatus, InitFailureCategory, CacheRefScope } from '@kici-dev/engine';
|
|
17
|
-
import type { LabelMatcher, LockWorkflow, LockJob, HostTargetSelector, SimulatedEvent, WorkflowDecision, MaterializedJob, ResolvedHostAgent } from '@kici-dev/engine';
|
|
17
|
+
import type { LabelMatcher, LockWorkflow, LockJob, HostTargetSelector, SimulatedEvent, WorkflowDecision, MaterializedJob, ResolvedHostAgent, HostFacts } from '@kici-dev/engine';
|
|
18
18
|
import { type HostRosterStore } from '../agent/host-roster.js';
|
|
19
19
|
import type { WebhookInfo } from '../webhook/handler.js';
|
|
20
20
|
import type { ProviderBundle } from '../provider-registry.js';
|
|
21
|
+
import type { Dispatcher } from '../agent/dispatcher.js';
|
|
22
|
+
import type { QueuedJobInput } from '../queue/job-queue.js';
|
|
21
23
|
import type { TrustResolution } from '../security/trust-resolver.js';
|
|
22
24
|
import { type ProcessingDeps } from './processor.js';
|
|
23
25
|
/**
|
|
@@ -120,6 +122,12 @@ export interface WorkflowDispatchContext {
|
|
|
120
122
|
* runsOnAll ∩ target. Narrow-only. Undefined for webhook runs (no narrowing).
|
|
121
123
|
*/
|
|
122
124
|
target?: HostTargetSelector;
|
|
125
|
+
/**
|
|
126
|
+
* Resolved (coerced + defaulted + validated) workflow-dispatch inputs from
|
|
127
|
+
* `kici run --input`. Carried onto every dispatched job's request so the agent
|
|
128
|
+
* exposes them as `ctx.dispatchInputs`. Undefined for webhook runs.
|
|
129
|
+
*/
|
|
130
|
+
dispatchInputs?: Record<string, unknown>;
|
|
123
131
|
}
|
|
124
132
|
export interface DispatchMatchedWorkflowResult {
|
|
125
133
|
/** Number of jobs successfully dispatched (non-rejected). */
|
|
@@ -144,6 +152,30 @@ export interface DispatchMatchedWorkflowOptions {
|
|
|
144
152
|
*/
|
|
145
153
|
reuseRunId?: string;
|
|
146
154
|
}
|
|
155
|
+
type DispatchFn = (input: QueuedJobInput) => ReturnType<Dispatcher['dispatch']>;
|
|
156
|
+
interface DispatchSetup {
|
|
157
|
+
/** Wrapped dispatcher that injects ctx.extraJobConfig into every dispatch. */
|
|
158
|
+
dispatcher: {
|
|
159
|
+
dispatch: DispatchFn;
|
|
160
|
+
};
|
|
161
|
+
/** WebhookInfo overlaid with effective routing key + provider. */
|
|
162
|
+
info: WebhookInfo;
|
|
163
|
+
/** Composite delivery id on cross-source, otherwise info.deliveryId. */
|
|
164
|
+
effectiveDeliveryId: string;
|
|
165
|
+
workflowConcurrency: {
|
|
166
|
+
cancelInProgress?: boolean;
|
|
167
|
+
max?: number;
|
|
168
|
+
} | undefined;
|
|
169
|
+
workflowTimeoutMs: number | undefined;
|
|
170
|
+
/**
|
|
171
|
+
* Run mode for idempotent steps (`apply` | `check` | `check-fail-on-drift`),
|
|
172
|
+
* carried on `ctx.extraJobConfig` by the test-trigger / `kici run --check`
|
|
173
|
+
* path. Persisted onto the `execution_runs` row so `computeRunStatus` can
|
|
174
|
+
* fail a `check-fail-on-drift` run that detected drift. Undefined for the
|
|
175
|
+
* default apply-mode webhook path.
|
|
176
|
+
*/
|
|
177
|
+
checkMode: string | undefined;
|
|
178
|
+
}
|
|
147
179
|
interface RejectedJob {
|
|
148
180
|
jobId: string;
|
|
149
181
|
jobName: string;
|
|
@@ -157,6 +189,20 @@ interface RejectedJob {
|
|
|
157
189
|
*/
|
|
158
190
|
terminalStatus?: ExecutionJobStatus;
|
|
159
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Build the QueuedJobInput for a synthetic `__bringup__` job: the orchestrator
|
|
194
|
+
* dispatches one per declared-but-un-agented `includeUninitialized` child to an
|
|
195
|
+
* agent holding `kici:capability:ssh-transport`, which runs the agent-side
|
|
196
|
+
* `ensureInitRunner(targetAgentId)` over SSH. The init-runner then connects
|
|
197
|
+
* under `targetAgentId`, and the child's pinned-hold (already queued with that
|
|
198
|
+
* pin) drains its bootstrap steps onto it. The bring-up job clones nothing and
|
|
199
|
+
* runs no sandbox (`bringupOnly`).
|
|
200
|
+
*/
|
|
201
|
+
export declare function buildBringupJobInput(args: {
|
|
202
|
+
ctx: WorkflowDispatchContext;
|
|
203
|
+
setup: DispatchSetup;
|
|
204
|
+
targetAgentId: string;
|
|
205
|
+
}): QueuedJobInput;
|
|
160
206
|
/**
|
|
161
207
|
* Phase B orchestrator: probe caches, dispatch the build job (if needed),
|
|
162
208
|
* and surface enough state for downstream phases to skip / continue
|
|
@@ -227,8 +273,9 @@ export interface WavePlan {
|
|
|
227
273
|
* Compute the rolling-wave plan for a materialized job set.
|
|
228
274
|
*
|
|
229
275
|
* For each base job declaring `maxParallel` whose fan-out produced more than one
|
|
230
|
-
* child, children are ordered deterministically by `
|
|
231
|
-
*
|
|
276
|
+
* child, children are ordered deterministically by `fanoutIndex` (the
|
|
277
|
+
* agentId / variant-label rank assigned at materialization; falling back to
|
|
278
|
+
* `expandedName` for children with no index) and every child at index `>=
|
|
232
279
|
* maxParallel` is held (`wave_gated=true`). The first `maxParallel` dispatch
|
|
233
280
|
* immediately; held children release one-per-terminal via the wave-scheduler.
|
|
234
281
|
* Every child of a bounded-wave base — held or not — gets a `policy` entry so
|
|
@@ -241,6 +288,14 @@ export declare function materializeStaticJobsSafe(staticJobs: readonly LockJob[]
|
|
|
241
288
|
expansionMap: Map<string, readonly string[]>;
|
|
242
289
|
matrixFailures: RejectedJob[];
|
|
243
290
|
}>;
|
|
291
|
+
/**
|
|
292
|
+
* Build the per-host secret-resolution context for a materialized child. A
|
|
293
|
+
* `runsOnAll` host child carries its identity on `mat.agent` (preferred) or
|
|
294
|
+
* `mat.pinnedAgentId`/`mat.host`; a non-host child (matrix/static) has none, so
|
|
295
|
+
* resolution stays fleet-wide (`'**'`-only). Returns `undefined` when there are
|
|
296
|
+
* no host facts to scope by.
|
|
297
|
+
*/
|
|
298
|
+
export declare function hostCtxFromMat(mat: MaterializedJob): HostFacts | undefined;
|
|
244
299
|
export interface GeneratedJobConfig {
|
|
245
300
|
/**
|
|
246
301
|
* The generated lock job with its `name` and `needs` rewritten to expanded
|
|
@@ -73,6 +73,12 @@ export interface TestTriggerInput {
|
|
|
73
73
|
* context, where it post-filters each runsOnAll job's matched roster.
|
|
74
74
|
*/
|
|
75
75
|
target?: HostTargetSelector;
|
|
76
|
+
/**
|
|
77
|
+
* Raw operator-supplied `kici run --input KEY=VALUE` pairs (not coerced /
|
|
78
|
+
* defaulted). Validated + coerced + defaulted here against the matched
|
|
79
|
+
* workflow's lock dispatch descriptor before dispatch.
|
|
80
|
+
*/
|
|
81
|
+
dispatchInputs?: Record<string, string>;
|
|
76
82
|
}
|
|
77
83
|
/**
|
|
78
84
|
* Result of processing a test trigger.
|
|
@@ -21,7 +21,26 @@ export declare class LogWriter {
|
|
|
21
21
|
private readonly logStorage;
|
|
22
22
|
private readonly observerRegistry?;
|
|
23
23
|
private readonly isTestRun?;
|
|
24
|
+
/**
|
|
25
|
+
* In-flight `logStorage.append` promises, keyed by runId. `appendChunk` is
|
|
26
|
+
* called fire-and-forget from the agent WS handler (it does not await the
|
|
27
|
+
* storage write), so a run can flip to a terminal status while the final
|
|
28
|
+
* log chunk's append is still pending. `drain(runId)` lets a reader (the
|
|
29
|
+
* test-run logs cursor endpoint) wait for those pending writes before it
|
|
30
|
+
* reports the stream as fully drained — without this, the `done` flag can
|
|
31
|
+
* be returned `true` while the last user-visible log line is not yet on
|
|
32
|
+
* disk, dropping it from a blocking `kici run remote` follow.
|
|
33
|
+
*/
|
|
34
|
+
private readonly pendingAppends;
|
|
24
35
|
constructor(deps: LogWriterDeps);
|
|
36
|
+
/**
|
|
37
|
+
* Await every in-flight log append for `runId` that was registered before
|
|
38
|
+
* this call. Settles even if an append rejected (errors are already logged
|
|
39
|
+
* by `appendChunk`); the point is ordering, not error propagation. New
|
|
40
|
+
* appends started after this call are not waited on — a terminal run emits
|
|
41
|
+
* no further chunks, so the snapshot taken at call time is complete.
|
|
42
|
+
*/
|
|
43
|
+
drain(runId: string): Promise<void>;
|
|
25
44
|
/**
|
|
26
45
|
* Append log lines from an agent to storage in JSONL format.
|
|
27
46
|
*
|
package/dist/scaler/manager.d.ts
CHANGED
|
@@ -39,6 +39,23 @@ export interface ResolvedResources {
|
|
|
39
39
|
memBytes: number;
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Build the scaler-usage metric rows: one per active scaler (stamped with its
|
|
44
|
+
* backend type) plus a `__global__` rollup row. Pure so it is unit-testable
|
|
45
|
+
* without constructing a full ScalerManager.
|
|
46
|
+
*/
|
|
47
|
+
export declare function buildScalerUsageRows(perScalerUsage: ReadonlyMap<string, {
|
|
48
|
+
cpus: number;
|
|
49
|
+
memBytes: number;
|
|
50
|
+
}>, globalUsage: {
|
|
51
|
+
cpus: number;
|
|
52
|
+
memBytes: number;
|
|
53
|
+
}, scalerTypeOf: (name: string) => string | undefined): Array<{
|
|
54
|
+
scaler: string;
|
|
55
|
+
scalerType?: string;
|
|
56
|
+
cpus: number;
|
|
57
|
+
memBytes: number;
|
|
58
|
+
}>;
|
|
42
59
|
/**
|
|
43
60
|
* Status summary for metrics and health endpoints.
|
|
44
61
|
*/
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* longest-path-wins uses scope path after stripping backend prefix.
|
|
16
16
|
* audit log includes backend name.
|
|
17
17
|
*/
|
|
18
|
-
import { type EnvironmentBinding, type ScopedSecret } from '@kici-dev/engine';
|
|
18
|
+
import { type EnvironmentBinding, type HostFacts, type ScopedSecret } from '@kici-dev/engine';
|
|
19
19
|
import type { Logger } from '@kici-dev/shared';
|
|
20
20
|
import type { AuditLogger } from './audit-logger.js';
|
|
21
21
|
/**
|
|
@@ -69,13 +69,13 @@ export interface ResolvedSecretMeta {
|
|
|
69
69
|
* can flow through `ProcessingDeps.secretResolver`.
|
|
70
70
|
*/
|
|
71
71
|
export interface SecretResolverApi {
|
|
72
|
-
resolveForJob(orgId: string, environmentName: string): Promise<Record<string, string>>;
|
|
72
|
+
resolveForJob(orgId: string, environmentName: string, hostCtx?: HostFacts): Promise<Record<string, string>>;
|
|
73
73
|
resolveNamed(orgId: string, scope: string, key: string, opts?: {
|
|
74
74
|
store?: string;
|
|
75
75
|
runId?: string;
|
|
76
76
|
jobId?: string;
|
|
77
77
|
}): Promise<string | null>;
|
|
78
|
-
resolveForJobWithMeta(orgId: string, environmentName: string): Promise<Record<string, ResolvedSecretMeta>>;
|
|
78
|
+
resolveForJobWithMeta(orgId: string, environmentName: string, hostCtx?: HostFacts): Promise<Record<string, ResolvedSecretMeta>>;
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
81
|
* Resolves secrets for a job by matching environment bindings against scoped secrets
|
|
@@ -98,9 +98,13 @@ export declare class SecretResolver implements SecretResolverApi {
|
|
|
98
98
|
*
|
|
99
99
|
* @param orgId - Organization ID
|
|
100
100
|
* @param environmentName - Environment name to resolve secrets for
|
|
101
|
+
* @param hostCtx - Optional fan-out child identity for per-host resolution.
|
|
102
|
+
* When supplied, each binding is gated by its `host_pattern` and its
|
|
103
|
+
* `scope_pattern` is templated per-child; when omitted, only fleet-wide
|
|
104
|
+
* (`'**'`) non-templated bindings contribute.
|
|
101
105
|
* @returns Flat map of decrypted secret key-value pairs
|
|
102
106
|
*/
|
|
103
|
-
resolveForJob(orgId: string, environmentName: string): Promise<Record<string, string>>;
|
|
107
|
+
resolveForJob(orgId: string, environmentName: string, hostCtx?: HostFacts): Promise<Record<string, string>>;
|
|
104
108
|
/**
|
|
105
109
|
* Resolve a single named secret by (orgId, scope, key), optionally scoped to
|
|
106
110
|
* a specific backend. Bypasses environment bindings — this is a direct
|
|
@@ -126,7 +130,7 @@ export declare class SecretResolver implements SecretResolverApi {
|
|
|
126
130
|
*
|
|
127
131
|
* Returns the secret value along with which backend and scope provided it.
|
|
128
132
|
*/
|
|
129
|
-
resolveForJobWithMeta(orgId: string, environmentName: string): Promise<Record<string, ResolvedSecretMeta>>;
|
|
133
|
+
resolveForJobWithMeta(orgId: string, environmentName: string, hostCtx?: HostFacts): Promise<Record<string, ResolvedSecretMeta>>;
|
|
130
134
|
/**
|
|
131
135
|
* Collect all secrets from all backend stores, prefixing scopes.
|
|
132
136
|
* Per /: unreachable backends are tracked but not fatal here.
|
|
@@ -145,8 +149,17 @@ export declare class SecretResolver implements SecretResolverApi {
|
|
|
145
149
|
*/
|
|
146
150
|
private checkScopedFailure;
|
|
147
151
|
/**
|
|
148
|
-
* Find the winning secret for a given key
|
|
152
|
+
* Find the winning secret for a given key, mirroring the engine scope
|
|
153
|
+
* resolver's host-aware matching and `(host specificity, scope depth)`
|
|
154
|
+
* precedence so the enriched metadata reports the same secret the flat
|
|
155
|
+
* resolution selected.
|
|
149
156
|
*/
|
|
150
157
|
private findWinningSecret;
|
|
158
|
+
/**
|
|
159
|
+
* Resolve the effective scope pattern a binding contributes for a host,
|
|
160
|
+
* applying the host gate and per-child scope templating. Mirrors the engine
|
|
161
|
+
* scope resolver's `bindingScopeForHost`. Returns `null` to skip the binding.
|
|
162
|
+
*/
|
|
163
|
+
private bindingScopeForHost;
|
|
151
164
|
}
|
|
152
165
|
//# sourceMappingURL=secret-resolver.d.ts.map
|