@kici-dev/orchestrator 0.1.15 → 0.1.17
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/dispatcher.d.ts +18 -1
- package/dist/app.d.ts +25 -0
- package/dist/approvals/apply-decision.d.ts +70 -0
- package/dist/approvals/approval-resolver.d.ts +66 -0
- package/dist/approvals/step-approval-bridge.d.ts +72 -0
- package/dist/approvals/team-membership-lookup.d.ts +13 -0
- package/dist/cache/pending-inits.d.ts +5 -0
- package/dist/cache/user-cache.d.ts +1 -1
- package/dist/cli/api-client.d.ts +35 -0
- package/dist/cli/commands/firecracker/index.d.ts +11 -0
- package/dist/cli/commands/firecracker/provision.d.ts +13 -0
- package/dist/cli/commands/firecracker/teardown.d.ts +3 -0
- package/dist/cli/commands/firecracker/verify.d.ts +3 -0
- package/dist/cli/commands/local-hook.d.ts +15 -0
- package/dist/cli/commands/local-trigger.d.ts +24 -0
- package/dist/cli/commands/remote-source.d.ts +17 -0
- package/dist/cli/commands/scaler.d.ts +18 -0
- package/dist/cli/commands/shared/versioned-upgrade.d.ts +14 -0
- package/dist/cli/kici-admin.d.ts +23 -1
- package/dist/cli/service/image-digests.d.ts +21 -0
- package/dist/cli.js +4320 -490
- package/dist/cluster/peer-client.d.ts +23 -1
- package/dist/cluster/peer-handler.d.ts +9 -1
- package/dist/config.d.ts +0 -4
- package/dist/dashboard/handler.d.ts +26 -2
- package/dist/dashboard/needs-edges.d.ts +13 -0
- package/dist/db/migrations/033_org_settings_approval.d.ts +19 -0
- package/dist/db/migrations/034_held_runs_generalize.d.ts +24 -0
- package/dist/db/migrations/035_pending_workflow_contexts.d.ts +11 -0
- package/dist/db/migrations/036_attestations.d.ts +15 -0
- package/dist/db/migrations/037_generic_sources_provider_type_local.d.ts +19 -0
- package/dist/db/migrations/038_remote_sources.d.ts +14 -0
- package/dist/db/types.d.ts +135 -11
- package/dist/diagnostics/bundle-writer.d.ts +1 -17
- package/dist/diagnostics/checks/firecracker-network.d.ts +13 -0
- package/dist/diagnostics/checks/index.d.ts +2 -1
- package/dist/diagnostics/fleet-collector.d.ts +52 -0
- package/dist/diagnostics/fleet-constants.d.ts +8 -0
- package/dist/diagnostics/fleet-selection.d.ts +15 -0
- package/dist/diagnostics/fleet-topology.d.ts +47 -0
- package/dist/diagnostics/fleet-wiring.d.ts +60 -0
- package/dist/entry-helpers.d.ts +7 -29
- package/dist/environments/held-runs.d.ts +93 -1
- package/dist/firecracker/host-network.d.ts +83 -0
- package/dist/firecracker/persist.d.ts +14 -0
- package/dist/index.js +25 -6
- package/dist/metrics/prometheus.d.ts +4 -2
- package/dist/orchestrator-core.d.ts +57 -1
- package/dist/pipeline/dispatch-matched-workflow.d.ts +18 -1
- package/dist/pipeline/install-secrets-resolver.d.ts +32 -5
- package/dist/pipeline/needs-scheduler.d.ts +12 -10
- package/dist/pipeline/pending-workflow-context.d.ts +44 -0
- package/dist/pipeline/processor.d.ts +28 -4
- package/dist/pipeline/remote-source-store.d.ts +21 -0
- package/dist/pipeline/resume-workflow.d.ts +26 -0
- package/dist/providers/local/index.d.ts +33 -0
- package/dist/providers/local/local-source-config.d.ts +17 -0
- package/dist/providers/{internal → local}/lock-file-fetcher.d.ts +6 -6
- package/dist/providers/{internal → local}/normalizer.d.ts +28 -28
- package/dist/providers/{internal → local}/repo-url-builder.d.ts +6 -6
- package/dist/reporting/execution-tracker.d.ts +33 -0
- package/dist/routes/admin-events.d.ts +3 -4
- package/dist/routes/fleet.d.ts +20 -0
- package/dist/routes/uploads.d.ts +36 -26
- package/dist/scaler/config.d.ts +4 -2
- package/dist/scaler/disk-guard.d.ts +27 -0
- package/dist/scaler/firecracker-backend.d.ts +18 -0
- package/dist/scaler/manager.d.ts +6 -0
- package/dist/scaler/nftables.d.ts +4 -0
- package/dist/scaler/reap-orphans.d.ts +27 -0
- package/dist/scaler/types.d.ts +2 -0
- package/dist/server.js +26929 -23511
- package/dist/sources/build-platform-sources.d.ts +4 -2
- package/dist/stale-detector/stale-run-detector.d.ts +32 -1
- package/dist/standalone.js +16941 -15329
- package/dist/storage/filesystem.d.ts +2 -1
- package/dist/storage/s3.d.ts +2 -1
- package/dist/storage/types.d.ts +7 -0
- package/dist/webhook/generic-sources-listener.d.ts +4 -0
- package/dist/webhook/generic-sources.d.ts +37 -11
- package/dist/webhook/register-source-bundle.d.ts +14 -4
- package/dist/ws/agent-handler.d.ts +49 -0
- package/dist/ws/dashboard-dispatch-guard.d.ts +21 -0
- package/dist/ws/dashboard-env-handler.d.ts +47 -0
- package/dist/ws/fleet-agent-collector.d.ts +23 -0
- package/dist/ws/oidc-token-relay.d.ts +59 -0
- package/dist/ws/platform-client.d.ts +30 -1
- package/dist/ws/test-relay-handlers.d.ts +112 -0
- package/installer-image-digests.json +7 -0
- package/package.json +6 -5
- package/sbom.spdx.json +112 -57
- package/dist/providers/internal/index.d.ts +0 -32
- package/dist/routes/test-trigger.d.ts +0 -41
- package/dist/ws/observer-handler.d.ts +0 -42
|
@@ -55,6 +55,13 @@ export declare class Dispatcher {
|
|
|
55
55
|
private readonly agentJobs;
|
|
56
56
|
/** Reverse map: jobId -> agentId, for cancel-run lookups. */
|
|
57
57
|
private readonly jobToAgent;
|
|
58
|
+
/**
|
|
59
|
+
* jobId -> runId for currently-tracked jobs. Populated alongside
|
|
60
|
+
* `jobToAgent`/`agentJobs` at dispatch time and cleared with them, so the
|
|
61
|
+
* provenance token relay can resolve a job's runId from the dispatcher's own
|
|
62
|
+
* state (`resolveOwnedJob`) rather than trusting an agent-asserted value.
|
|
63
|
+
*/
|
|
64
|
+
private readonly jobRunIds;
|
|
58
65
|
/**
|
|
59
66
|
* Grace window for recently completed jobs.
|
|
60
67
|
* Allows late messages (log.chunk, step.status) to be accepted for a short
|
|
@@ -296,7 +303,7 @@ export declare class Dispatcher {
|
|
|
296
303
|
* reconnecting agent reporting the job in-flight means it had started,
|
|
297
304
|
* so mark it started for disconnect triage.
|
|
298
305
|
*/
|
|
299
|
-
restoreJobForAgent(agentId: string, jobId: string): void;
|
|
306
|
+
restoreJobForAgent(agentId: string, jobId: string, runId?: string): void;
|
|
300
307
|
/**
|
|
301
308
|
* Start a recovery timer for a job found in 'dispatched' state on startup.
|
|
302
309
|
* Called by server.ts/standalone.ts to create recovery timers for jobs
|
|
@@ -349,6 +356,16 @@ export declare class Dispatcher {
|
|
|
349
356
|
/** Remove expired entries from the completedJobs grace window map. */
|
|
350
357
|
private cleanupExpiredGraceEntries;
|
|
351
358
|
private trackJobForAgent;
|
|
359
|
+
/**
|
|
360
|
+
* Verify `agentId` currently owns `jobId`; if so, return the job's runId from
|
|
361
|
+
* the dispatcher's own tracking. Used by the provenance token relay so the
|
|
362
|
+
* orchestrator binds a minted token to a job the agent actually owns — the
|
|
363
|
+
* agent never asserts a runId. Returns `undefined` when the agent does not
|
|
364
|
+
* own the job (or the runId is no longer tracked).
|
|
365
|
+
*/
|
|
366
|
+
resolveOwnedJob(agentId: string, jobId: string): {
|
|
367
|
+
runId: string;
|
|
368
|
+
} | undefined;
|
|
352
369
|
/**
|
|
353
370
|
* Cancel a queued job (mark as failed in the dispatch queue).
|
|
354
371
|
* Used by the coordinator to clean up local fallback entries when a peer
|
package/dist/app.d.ts
CHANGED
|
@@ -48,6 +48,8 @@ import type { PeerToPeerMessage } from '@kici-dev/engine';
|
|
|
48
48
|
import type { AgentTokenStore } from './agent/token-store.js';
|
|
49
49
|
import type { OwnershipTracker } from './agent/ownership-tracker.js';
|
|
50
50
|
import type { ObserverRegistry } from './ws/observer-registry.js';
|
|
51
|
+
import type { FleetAgentCollector } from './ws/fleet-agent-collector.js';
|
|
52
|
+
import type { FleetTopology } from './diagnostics/fleet-topology.js';
|
|
51
53
|
import type { TokenManager } from './secrets/token-manager.js';
|
|
52
54
|
import type { SecretResolver } from './secrets/secret-resolver.js';
|
|
53
55
|
import { type AdminRouteDeps } from './routes/admin.js';
|
|
@@ -68,6 +70,7 @@ import type { TrustStore } from './events/trust-store.js';
|
|
|
68
70
|
import type { EnvironmentStore } from './environments/environment-store.js';
|
|
69
71
|
import type { VariableStore } from './environments/variable-store.js';
|
|
70
72
|
import type { HeldRunStore } from './environments/held-runs.js';
|
|
73
|
+
import type { StepApprovalBridge } from './approvals/step-approval-bridge.js';
|
|
71
74
|
import type { ContributorCache } from './security/contributor-cache.js';
|
|
72
75
|
import { AgentMetricsAggregator } from './metrics/agent-metrics-aggregator.js';
|
|
73
76
|
/**
|
|
@@ -132,6 +135,11 @@ export interface AppDependencies {
|
|
|
132
135
|
tokenStore?: AgentTokenStore;
|
|
133
136
|
/** Job ownership tracker for validating agent messages. Optional — requires database. */
|
|
134
137
|
ownershipTracker?: OwnershipTracker;
|
|
138
|
+
/**
|
|
139
|
+
* Orchestrator-scoped collector correlating fleet.logs.request with agents'
|
|
140
|
+
* chunked bundle responses. Shared with the fleet fan-out in orchestrator-core.
|
|
141
|
+
*/
|
|
142
|
+
fleetAgentCollector?: FleetAgentCollector;
|
|
135
143
|
/** Admin API route dependencies. Optional -- only mounted when secrets management is configured. */
|
|
136
144
|
adminDeps?: AdminRouteDeps;
|
|
137
145
|
/**
|
|
@@ -170,6 +178,8 @@ export interface AppDependencies {
|
|
|
170
178
|
variableStore?: VariableStore;
|
|
171
179
|
/** Held run store for persisting protection rule holds. Optional -- if not set, holds are not persisted. */
|
|
172
180
|
heldRunStore?: HeldRunStore;
|
|
181
|
+
/** Step-approval bridge — opens step-scoped holds and relays their resolution back to the waiting agent. Optional. */
|
|
182
|
+
stepApprovalBridge?: StepApprovalBridge;
|
|
173
183
|
/** Global workflow policy for org-level permission enforcement. Optional -- if not set, global workflows are dispatched without permission checks. */
|
|
174
184
|
globalWorkflowPolicy?: GlobalWorkflowPolicy;
|
|
175
185
|
/** Inbound webhook delivery log writer. Optional -- if not set, deliveries are not persisted to event_log. */
|
|
@@ -215,6 +225,21 @@ export interface AppDependencies {
|
|
|
215
225
|
* can read the same store and Mimir gets agent metrics per-org.
|
|
216
226
|
*/
|
|
217
227
|
agentMetricsAggregator?: AgentMetricsAggregator;
|
|
228
|
+
/**
|
|
229
|
+
* Fleet log-collection route backing. `getTopology` enumerates the cluster
|
|
230
|
+
* (no fan-out); `collectBundle` drives the recursive fan-out and returns the
|
|
231
|
+
* assembled ZIP. Mounted at /admin/fleet-topology + /admin/fleet-bundle.
|
|
232
|
+
*/
|
|
233
|
+
fleetRoutes?: FleetRoutesDeps;
|
|
234
|
+
}
|
|
235
|
+
/** Backing for the /admin/fleet-* routes. */
|
|
236
|
+
export interface FleetRoutesDeps {
|
|
237
|
+
getTopology: () => FleetTopology;
|
|
238
|
+
collectBundle: (opts: {
|
|
239
|
+
selectors: string[];
|
|
240
|
+
logWindowHours?: number;
|
|
241
|
+
timeoutSeconds?: number;
|
|
242
|
+
}) => Promise<Buffer>;
|
|
218
243
|
}
|
|
219
244
|
/**
|
|
220
245
|
* In-memory cache for step source locations extracted from lock files.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared approve/reject applier — the single code path behind both the
|
|
3
|
+
* dashboard WS handler and the `kici` CLI HTTP route, so the authorization +
|
|
4
|
+
* resume story is identical regardless of the surface.
|
|
5
|
+
*
|
|
6
|
+
* Flow for an approve:
|
|
7
|
+
* 1. Load the hold + its recorded decisions.
|
|
8
|
+
* 2. Build the team-membership lookup and run `canApprove` (eligibility +
|
|
9
|
+
* self-approval gate). Ineligible actors are rejected with a clear reason.
|
|
10
|
+
* 3. Record the decision in `held_run_approvals`.
|
|
11
|
+
* 4. Re-evaluate. If all clauses are satisfied, `release()` the hold and
|
|
12
|
+
* resume the element (re-dispatch for job/workflow; the agent bridge for
|
|
13
|
+
* step scope — wired by the caller via `onStepRelease`).
|
|
14
|
+
*
|
|
15
|
+
* A reject records the decision and `reject()`s the hold (failing the element).
|
|
16
|
+
*/
|
|
17
|
+
import { ApprovalDecision } from '@kici-dev/engine';
|
|
18
|
+
import type { HeldRunStore, ReleaseSignal } from '../environments/held-runs.js';
|
|
19
|
+
import { type TeamMembershipLookup } from './approval-resolver.js';
|
|
20
|
+
/** Outcome of applying a decision. */
|
|
21
|
+
export interface ApplyDecisionResult {
|
|
22
|
+
/** Whether the decision was accepted (recorded). */
|
|
23
|
+
accepted: boolean;
|
|
24
|
+
/** Human-readable status: 'released' | 'rejected' | 'pending' | 'ineligible' | 'not-found'. */
|
|
25
|
+
status: 'released' | 'rejected' | 'pending' | 'ineligible' | 'not-found';
|
|
26
|
+
/** When still pending, how many clauses remain unsatisfied. */
|
|
27
|
+
remainingClauses?: number;
|
|
28
|
+
/** When ineligible/not-found, a reason for the caller to surface. */
|
|
29
|
+
reason?: string;
|
|
30
|
+
/** The release signal, when the element was released (for the caller to resume). */
|
|
31
|
+
release?: ReleaseSignal;
|
|
32
|
+
}
|
|
33
|
+
/** Dependencies injected into `applyDecision` (testable in isolation). */
|
|
34
|
+
export interface ApplyDecisionDeps {
|
|
35
|
+
orgId: string;
|
|
36
|
+
store: HeldRunStore;
|
|
37
|
+
/** Team name → member user ids (from the Plan-1 trust-policy cache). */
|
|
38
|
+
teamMembershipLookup: TeamMembershipLookup;
|
|
39
|
+
/** Whether the run triggerer may self-approve (org_settings.allow_self_approval). */
|
|
40
|
+
allowSelfApproval: boolean;
|
|
41
|
+
/** Resolve the Keycloak sub of the user who triggered a run (for the self-approval gate). */
|
|
42
|
+
resolveTriggererSub: (runId: string) => Promise<string | undefined>;
|
|
43
|
+
/** Called when a job hold is released — re-dispatch the element. */
|
|
44
|
+
onJobRelease: (signal: ReleaseSignal) => Promise<void>;
|
|
45
|
+
/** Called when a step hold is released — notify the waiting agent (approved). */
|
|
46
|
+
onStepRelease?: (signal: ReleaseSignal) => Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Called when a workflow-scoped hold is released (install gate approved) —
|
|
49
|
+
* rebuild the dispatch context and resume the workflow from the install gate.
|
|
50
|
+
*/
|
|
51
|
+
onWorkflowRelease?: (signal: ReleaseSignal) => Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Called when a step-scoped hold is rejected — notify the waiting agent so it
|
|
54
|
+
* fails the step instead of blocking until expiry. Carries the holdId.
|
|
55
|
+
*/
|
|
56
|
+
onStepReject?: (heldRunId: string, reason?: string) => Promise<void> | void;
|
|
57
|
+
/**
|
|
58
|
+
* Called when a workflow-scoped hold is rejected (install gate rejected) —
|
|
59
|
+
* cancel the run and drop the pending workflow context. Carries the runId.
|
|
60
|
+
*/
|
|
61
|
+
onWorkflowReject?: (runId: string) => Promise<void>;
|
|
62
|
+
}
|
|
63
|
+
/** Apply a single approve/reject decision to a hold. */
|
|
64
|
+
export declare function applyDecision(deps: ApplyDecisionDeps, args: {
|
|
65
|
+
heldRunId: string;
|
|
66
|
+
actorSub: string;
|
|
67
|
+
decision: ApprovalDecision;
|
|
68
|
+
reason?: string;
|
|
69
|
+
}): Promise<ApplyDecisionResult>;
|
|
70
|
+
//# sourceMappingURL=apply-decision.d.ts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure approval-clause evaluator. No DB access, no I/O — given a requirement,
|
|
3
|
+
* a team-membership lookup, the recorded decisions, and (for eligibility) the
|
|
4
|
+
* run's triggerer + the self-approval policy, it answers:
|
|
5
|
+
*
|
|
6
|
+
* - `evaluate` — is the requirement satisfied (all clauses ANDed), and was it
|
|
7
|
+
* rejected (any single reject decision)?
|
|
8
|
+
* - `canApprove` — may a given actor cast an approve decision right now?
|
|
9
|
+
*
|
|
10
|
+
* Both the dashboard handler and the CLI HTTP route funnel through these so the
|
|
11
|
+
* authorization story is identical regardless of the surface.
|
|
12
|
+
*/
|
|
13
|
+
import type { ApprovalRequirement, ApproverClause } from '@kici-dev/engine';
|
|
14
|
+
/** A team name → set of member user ids (Keycloak subs). */
|
|
15
|
+
export type TeamMembershipLookup = (team: string) => Set<string>;
|
|
16
|
+
/** One recorded decision row (subset of `held_run_approvals`). */
|
|
17
|
+
export interface RecordedDecision {
|
|
18
|
+
approver_user_id: string;
|
|
19
|
+
decision: 'approve' | 'reject';
|
|
20
|
+
}
|
|
21
|
+
/** Per-clause satisfaction detail for attribution + dashboard progress. */
|
|
22
|
+
export interface PerClauseResult {
|
|
23
|
+
clause: ApproverClause;
|
|
24
|
+
satisfied: boolean;
|
|
25
|
+
/** The approver who satisfied this clause, if any. */
|
|
26
|
+
by?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface EvaluationResult {
|
|
29
|
+
/** All clauses satisfied (AND). For empty clauses: any single approve. */
|
|
30
|
+
satisfied: boolean;
|
|
31
|
+
/** Any reject decision present → the element is rejected. */
|
|
32
|
+
rejected: boolean;
|
|
33
|
+
perClause: PerClauseResult[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Is a single clause satisfied by any approve decision whose approver is
|
|
37
|
+
* eligible for the clause? Reject decisions never satisfy.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isClauseSatisfied(clause: ApproverClause, decisions: RecordedDecision[], lookup: TeamMembershipLookup): boolean;
|
|
40
|
+
/** Does an actor satisfy/qualify for a clause (team membership or exact user)? */
|
|
41
|
+
export declare function isActorEligibleForClause(actorSub: string, clause: ApproverClause, lookup: TeamMembershipLookup): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Evaluate a requirement against the recorded decisions.
|
|
44
|
+
*
|
|
45
|
+
* - A single reject decision sets `rejected` (the caller fails the element).
|
|
46
|
+
* - Empty clauses ⇒ satisfied by ANY single approve decision.
|
|
47
|
+
* - Non-empty clauses ⇒ satisfied iff every clause is satisfied (AND).
|
|
48
|
+
*/
|
|
49
|
+
export declare function evaluate(requirement: ApprovalRequirement, decisions: RecordedDecision[], lookup: TeamMembershipLookup): EvaluationResult;
|
|
50
|
+
export interface CanApproveContext {
|
|
51
|
+
/** The Keycloak sub of the user who triggered the run. */
|
|
52
|
+
triggererSub: string;
|
|
53
|
+
/** Whether the triggerer may self-approve their own held elements. */
|
|
54
|
+
allowSelfApproval: boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* May `actorSub` cast an approve decision on this requirement right now?
|
|
58
|
+
*
|
|
59
|
+
* - Self-approval gate: when `allowSelfApproval` is false and the actor is the
|
|
60
|
+
* run's triggerer, they may never approve.
|
|
61
|
+
* - Eligibility: the actor must qualify for at least one still-UNSATISFIED
|
|
62
|
+
* clause. (Approving a clause that is already satisfied adds nothing.) For an
|
|
63
|
+
* empty-clause requirement, any non-triggerer-blocked actor qualifies.
|
|
64
|
+
*/
|
|
65
|
+
export declare function canApprove(actorSub: string, requirement: ApprovalRequirement, decisions: RecordedDecision[], lookup: TeamMembershipLookup, ctx: CanApproveContext): boolean;
|
|
66
|
+
//# sourceMappingURL=approval-resolver.d.ts.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { HeldRunStore } from '../environments/held-runs.js';
|
|
2
|
+
import type { AccessLogWriter } from '../audit/access-log.js';
|
|
3
|
+
/** Outcome relayed back to the waiting agent. */
|
|
4
|
+
export type StepApprovalOutcome = 'approved' | 'rejected' | 'expired';
|
|
5
|
+
/** Arguments to open a step-scoped approval hold. */
|
|
6
|
+
export interface StepApprovalRequest {
|
|
7
|
+
agentId: string;
|
|
8
|
+
runId: string;
|
|
9
|
+
jobId: string;
|
|
10
|
+
stepIndex: number;
|
|
11
|
+
stepName: string;
|
|
12
|
+
clauses: Array<{
|
|
13
|
+
team: string;
|
|
14
|
+
} | {
|
|
15
|
+
user: string;
|
|
16
|
+
}>;
|
|
17
|
+
reason: string;
|
|
18
|
+
/** Per-gate timeout (seconds); falls back to the org default. */
|
|
19
|
+
timeoutSeconds?: number;
|
|
20
|
+
}
|
|
21
|
+
/** Dependencies injected into the bridge. */
|
|
22
|
+
export interface StepApprovalBridgeDeps {
|
|
23
|
+
store: HeldRunStore;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the orchestrator's tenant org id (same value the dashboard handler
|
|
26
|
+
* uses to read held_runs). A function because the org is resolved post-auth
|
|
27
|
+
* for sourceless orchestrators.
|
|
28
|
+
*/
|
|
29
|
+
resolveOrgId: () => string;
|
|
30
|
+
/** Resolve the authoritative approval expiry (seconds) for an org. */
|
|
31
|
+
resolveExpirySeconds: (orgId: string) => Promise<number>;
|
|
32
|
+
/**
|
|
33
|
+
* Access-log writer for the orchestrator audit stream. Optional -- if not
|
|
34
|
+
* set, the step-hold creation audit row (`held_run.request`) is skipped.
|
|
35
|
+
*/
|
|
36
|
+
accessLogWriter?: AccessLogWriter;
|
|
37
|
+
/** Routing key recorded on the audit row. Optional. */
|
|
38
|
+
routingKey?: string | null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Owns the step-scoped held_runs rows and the map from holdId → the waiting
|
|
42
|
+
* agent's resolver. The only place that opens a step hold and the only place
|
|
43
|
+
* that settles a step-scoped wait.
|
|
44
|
+
*/
|
|
45
|
+
export declare class StepApprovalBridge {
|
|
46
|
+
private readonly deps;
|
|
47
|
+
private readonly pending;
|
|
48
|
+
constructor(deps: StepApprovalBridgeDeps);
|
|
49
|
+
/**
|
|
50
|
+
* Create a step-scoped hold and return a promise that settles when the hold
|
|
51
|
+
* is approved / rejected / expired (via {@link resolve}).
|
|
52
|
+
*/
|
|
53
|
+
request(req: StepApprovalRequest): Promise<{
|
|
54
|
+
outcome: StepApprovalOutcome;
|
|
55
|
+
reason?: string;
|
|
56
|
+
}>;
|
|
57
|
+
/**
|
|
58
|
+
* Settle a step-scoped wait. Called by the approve/reject applier
|
|
59
|
+
* (`onStepRelease`) and by the stale detector (`expired`). A no-op when no
|
|
60
|
+
* agent is waiting on the hold (e.g. the agent already disconnected).
|
|
61
|
+
*/
|
|
62
|
+
resolve(holdId: string, outcome: StepApprovalOutcome, reason?: string): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Reject every pending wait for a disconnected agent. The held_runs rows are
|
|
65
|
+
* left as-is (the stale detector will expire them) — only the in-memory
|
|
66
|
+
* resolver is dropped so the handler's relayed `ws.send` is skipped.
|
|
67
|
+
*/
|
|
68
|
+
failAgent(agentId: string): void;
|
|
69
|
+
/** Number of in-flight step-approval waits (test/diagnostics). */
|
|
70
|
+
size(): number;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=step-approval-bridge.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only lookup over the team memberships pushed from the Platform via
|
|
3
|
+
* `trust_policy.update`. The orchestrator has no identity store, so this is the
|
|
4
|
+
* only source of "who is in team X" — the approval resolver uses it to satisfy
|
|
5
|
+
* `{team}` approver clauses.
|
|
6
|
+
*/
|
|
7
|
+
export interface TeamMembershipLookup {
|
|
8
|
+
/** Returns the set of member user ids for a team name (empty if unknown). */
|
|
9
|
+
getTeamMembers(name: string): Set<string>;
|
|
10
|
+
}
|
|
11
|
+
/** A lookup backed by no teams — the default before any push arrives. */
|
|
12
|
+
export declare const EMPTY_TEAM_MEMBERSHIP_LOOKUP: TeamMembershipLookup;
|
|
13
|
+
//# sourceMappingURL=team-membership-lookup.d.ts.map
|
|
@@ -12,6 +12,11 @@ export interface InitResult {
|
|
|
12
12
|
environmentName?: string;
|
|
13
13
|
env?: Record<string, string>;
|
|
14
14
|
concurrencyGroup?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Resolved matrix combinations when the target job's matrix is a dynamic
|
|
17
|
+
* function. The dispatch path re-materializes these into N execution jobs.
|
|
18
|
+
*/
|
|
19
|
+
matrixValues?: Array<Record<string, string | undefined>>;
|
|
15
20
|
}
|
|
16
21
|
export declare class PendingInitTracker extends PendingTracker<InitResult> {
|
|
17
22
|
constructor();
|
|
@@ -110,7 +110,7 @@ export declare class UserCache {
|
|
|
110
110
|
tempKey?: string;
|
|
111
111
|
}): Promise<void>;
|
|
112
112
|
private readHash;
|
|
113
|
-
/** Evict
|
|
113
|
+
/** Evict least-recently-used entries for the org until total tarball size <= the per-org quota. */
|
|
114
114
|
private enforceQuota;
|
|
115
115
|
}
|
|
116
116
|
//# sourceMappingURL=user-cache.d.ts.map
|
package/dist/cli/api-client.d.ts
CHANGED
|
@@ -5,6 +5,19 @@
|
|
|
5
5
|
* All methods are thin wrappers around fetch() that handle JSON serialization,
|
|
6
6
|
* error formatting, and URL construction.
|
|
7
7
|
*/
|
|
8
|
+
/** A node in the fleet topology returned by GET /admin/fleet-topology. */
|
|
9
|
+
export interface FleetTopologyNodeResponse {
|
|
10
|
+
kind: 'orchestrator' | 'agent';
|
|
11
|
+
id: string;
|
|
12
|
+
role?: 'coordinator' | 'worker';
|
|
13
|
+
hostname?: string;
|
|
14
|
+
labels: Record<string, string>;
|
|
15
|
+
parentId: string | null;
|
|
16
|
+
}
|
|
17
|
+
/** Response shape for GET /admin/fleet-topology. */
|
|
18
|
+
export interface FleetTopologyResponse {
|
|
19
|
+
nodes: FleetTopologyNodeResponse[];
|
|
20
|
+
}
|
|
8
21
|
/**
|
|
9
22
|
* Universal-git configuration shape carried in `git_config` on
|
|
10
23
|
* generic_webhook_sources. Matches `UniversalGitConfigSchema` in
|
|
@@ -12,6 +25,14 @@
|
|
|
12
25
|
* avoid a cross-package import in the CLI wire type.
|
|
13
26
|
*/
|
|
14
27
|
export type GenericSourceGitConfigPayload = Record<string, unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* Wire shape for a local filesystem source's config (`{ repoBasePath, cloneUrlBase? }`).
|
|
30
|
+
* Matches `LocalSourceConfigSchema` in `providers/local/local-source-config.ts`.
|
|
31
|
+
*/
|
|
32
|
+
export interface GenericSourceLocalConfigPayload {
|
|
33
|
+
repoBasePath: string;
|
|
34
|
+
cloneUrlBase?: string;
|
|
35
|
+
}
|
|
15
36
|
/**
|
|
16
37
|
* Response shape for generic webhook sources from the admin API.
|
|
17
38
|
*/
|
|
@@ -71,6 +92,17 @@ export declare class AdminApiClient {
|
|
|
71
92
|
* Public GET request returning raw response text.
|
|
72
93
|
*/
|
|
73
94
|
getText(path: string): Promise<string>;
|
|
95
|
+
/** Enumerate the cluster topology for `debug-bundle --fleet --list` / `--pick`. */
|
|
96
|
+
getFleetTopology(): Promise<FleetTopologyResponse>;
|
|
97
|
+
/**
|
|
98
|
+
* Drive the fleet fan-out and write the assembled ZIP to `outPath`. The
|
|
99
|
+
* response is an octet-stream, so it is read as bytes rather than parsed JSON.
|
|
100
|
+
*/
|
|
101
|
+
downloadFleetBundle(body: {
|
|
102
|
+
selectors: string[];
|
|
103
|
+
logWindowHours?: number;
|
|
104
|
+
timeoutSeconds?: number;
|
|
105
|
+
}, outPath: string): Promise<void>;
|
|
74
106
|
listScopes(orgId: string): Promise<{
|
|
75
107
|
scopes: string[];
|
|
76
108
|
}>;
|
|
@@ -110,6 +142,7 @@ export declare class AdminApiClient {
|
|
|
110
142
|
rateLimitRpm?: number;
|
|
111
143
|
providerType?: string;
|
|
112
144
|
gitConfig?: GenericSourceGitConfigPayload;
|
|
145
|
+
localConfig?: GenericSourceLocalConfigPayload;
|
|
113
146
|
}): Promise<{
|
|
114
147
|
source: GenericSourceResponse;
|
|
115
148
|
}>;
|
|
@@ -135,6 +168,8 @@ export declare class AdminApiClient {
|
|
|
135
168
|
providerType?: string;
|
|
136
169
|
/** `null` clears the config; omit to leave unchanged. */
|
|
137
170
|
gitConfig?: GenericSourceGitConfigPayload | null;
|
|
171
|
+
/** `null` clears the config; omit to leave unchanged. */
|
|
172
|
+
localConfig?: GenericSourceLocalConfigPayload | null;
|
|
138
173
|
}): Promise<{
|
|
139
174
|
source: GenericSourceResponse;
|
|
140
175
|
}>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `kici-admin firecracker` command group.
|
|
3
|
+
*
|
|
4
|
+
* Local host-networking ops for the orchestrator's Firecracker scaler:
|
|
5
|
+
* provision/verify/teardown the per-coordinator bridge + nft table, with
|
|
6
|
+
* --persist for reboot survival. These run directly on the host (privileged
|
|
7
|
+
* `ip`/`nft`/`systemctl`) and do NOT use the admin HTTP client.
|
|
8
|
+
*/
|
|
9
|
+
import type { Command } from 'commander';
|
|
10
|
+
export declare function registerFirecrackerCommands(program: Command): void;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { type FirecrackerBridgeConfig } from '../../../firecracker/host-network.js';
|
|
3
|
+
export interface ProvisionOptions {
|
|
4
|
+
bridge: string;
|
|
5
|
+
cidr?: string;
|
|
6
|
+
table?: string;
|
|
7
|
+
hostIface?: string;
|
|
8
|
+
persist?: boolean;
|
|
9
|
+
sudo?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function optionsToConfig(opts: ProvisionOptions): FirecrackerBridgeConfig;
|
|
12
|
+
export declare function registerProvision(group: Command): void;
|
|
13
|
+
//# sourceMappingURL=provision.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render the post-receive hook script. For each pushed ref the hook calls
|
|
3
|
+
* `kici-admin source trigger-local <id> --ref <ref> --sha <new> --base-url <url>`,
|
|
4
|
+
* so a push to any branch dispatches a run for that ref.
|
|
5
|
+
*/
|
|
6
|
+
export declare function renderPostReceiveHook(opts: {
|
|
7
|
+
sourceId: string;
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
}): string;
|
|
10
|
+
/**
|
|
11
|
+
* Write the rendered hook into the repo's `.git/hooks/post-receive` and make it
|
|
12
|
+
* executable. Throws when the path is not a git repo (no `.git/hooks` dir).
|
|
13
|
+
*/
|
|
14
|
+
export declare function installPostReceiveHook(repoPath: string, script: string): string;
|
|
15
|
+
//# sourceMappingURL=local-hook.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface LocalTriggerInput {
|
|
2
|
+
orgId: string;
|
|
3
|
+
sourceId: string;
|
|
4
|
+
repoFullName: string;
|
|
5
|
+
event: 'push' | 'pull_request';
|
|
6
|
+
ref: string;
|
|
7
|
+
sha: string;
|
|
8
|
+
defaultBranch: string;
|
|
9
|
+
}
|
|
10
|
+
export interface LocalTriggerRequest {
|
|
11
|
+
path: string;
|
|
12
|
+
headers: Record<string, string>;
|
|
13
|
+
body: string;
|
|
14
|
+
}
|
|
15
|
+
/** Build the GitHub-shaped webhook request the local provider normalizer expects. */
|
|
16
|
+
export declare function buildLocalTriggerRequest(input: LocalTriggerInput): LocalTriggerRequest;
|
|
17
|
+
/** Read HEAD ref + sha from a local git repo (used when the operator omits --ref/--sha). */
|
|
18
|
+
export declare function readRepoHead(repoPath: string): {
|
|
19
|
+
ref: string;
|
|
20
|
+
sha: string;
|
|
21
|
+
};
|
|
22
|
+
/** POST the trigger request to the orchestrator base URL. Returns the HTTP status. */
|
|
23
|
+
export declare function sendLocalTrigger(baseUrl: string, req: LocalTriggerRequest): Promise<number>;
|
|
24
|
+
//# sourceMappingURL=local-trigger.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote-source inspection command for kici-admin.
|
|
3
|
+
*
|
|
4
|
+
* Subcommand namespace: `kici-admin remote-source show`.
|
|
5
|
+
*
|
|
6
|
+
* The remote-source anchor (`remote_sources` table) maps the deterministic
|
|
7
|
+
* routing key `remote:<orgId>` to the orchestrator's canonical org id so a
|
|
8
|
+
* Platform-relayed `kici run remote` resolves the real tenant. It is
|
|
9
|
+
* auto-provisioned on Platform auth; this command lets an operator inspect or
|
|
10
|
+
* confirm the row when debugging org-anchor issues on a hidden orchestrator.
|
|
11
|
+
*
|
|
12
|
+
* Reads the orchestrator DB directly (on-host operator inspection), so it stays
|
|
13
|
+
* usable even when Platform is unreachable.
|
|
14
|
+
*/
|
|
15
|
+
import type { Command } from 'commander';
|
|
16
|
+
export declare function registerRemoteSourceCommands(program: Command): void;
|
|
17
|
+
//# sourceMappingURL=remote-source.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standalone scaler maintenance commands for kici-admin.
|
|
3
|
+
*
|
|
4
|
+
* scaler reap-orphans Free leaked Firecracker/container resources WITHOUT a
|
|
5
|
+
* running orchestrator (recovery for a wedged node whose
|
|
6
|
+
* data disk is full).
|
|
7
|
+
*
|
|
8
|
+
* This command loads the orchestrator's LOCAL config (no HTTP admin API, no DB)
|
|
9
|
+
* and runs the liveness-driven reaper. It is the sanctioned operator path for
|
|
10
|
+
* the ENOSPC bootstrap deadlock: when the data disk is 100% full the
|
|
11
|
+
* orchestrator crash-loops before its in-process orphan sweep can run, so a
|
|
12
|
+
* tool that frees disk WITHOUT the orchestrator is required.
|
|
13
|
+
*/
|
|
14
|
+
import type { Command } from 'commander';
|
|
15
|
+
/** Probe the local orchestrator /health endpoint. Healthy => it reaps itself. */
|
|
16
|
+
export declare function isOrchestratorHealthy(port: number, basePath: string): Promise<boolean>;
|
|
17
|
+
export declare function registerScalerCommands(program: Command): void;
|
|
18
|
+
//# sourceMappingURL=scaler.d.ts.map
|
|
@@ -85,6 +85,20 @@ export declare function getInstallBase(platform: ServicePlatform, name: string):
|
|
|
85
85
|
* 5. Update symlink (Unix) or service registration (Windows)
|
|
86
86
|
* 6. Start service
|
|
87
87
|
*/
|
|
88
|
+
/**
|
|
89
|
+
* Resolve the target version for an npm-source upgrade (no --from/--url).
|
|
90
|
+
*
|
|
91
|
+
* The npm-source flow assumes the operator already ran
|
|
92
|
+
* `npm install -g @kici-dev/<pkg>@<version>`, which overwrites the global
|
|
93
|
+
* package in place. The running `kici-admin` binary is therefore the new
|
|
94
|
+
* version, and `running` is its self-reported version. We default the target
|
|
95
|
+
* to it, or validate an explicitly-passed --version matches — a mismatch means
|
|
96
|
+
* the npm install did not actually update the global binary.
|
|
97
|
+
*/
|
|
98
|
+
export declare function resolveNpmSourceVersion(opts: {
|
|
99
|
+
requested: string | undefined;
|
|
100
|
+
running: string;
|
|
101
|
+
}): string;
|
|
88
102
|
export declare function performVersionedUpgrade(component: UpgradeComponent, opts: VersionedUpgradeOptions): Promise<void>;
|
|
89
103
|
export {};
|
|
90
104
|
//# sourceMappingURL=versioned-upgrade.d.ts.map
|
package/dist/cli/kici-admin.d.ts
CHANGED
|
@@ -9,5 +9,27 @@
|
|
|
9
9
|
* --url / -u Orchestrator URL (env: KICI_ADMIN_URL, default: http://localhost:8080)
|
|
10
10
|
* --token / -t Admin API token (env: KICI_ADMIN_TOKEN, required)
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
import { Command } from 'commander';
|
|
13
|
+
/**
|
|
14
|
+
* Build the kici-admin Commander program with every command group registered.
|
|
15
|
+
* Exported so the surface registry can walk the real command tree without
|
|
16
|
+
* parsing argv (no action runs during a tree walk, so `getClient` is
|
|
17
|
+
* constructed but never invoked).
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildProgram(): Command;
|
|
20
|
+
/** Build the program and parse argv — the bin-shim entry point. */
|
|
21
|
+
export declare function runCli(argv?: string[]): void;
|
|
22
|
+
/**
|
|
23
|
+
* Canonicalize a path through any symlinks, falling back to a plain `resolve`
|
|
24
|
+
* when the target does not exist on disk. The entry-point guard compares the
|
|
25
|
+
* invoked script path against this module's own path; both sides must be fully
|
|
26
|
+
* canonicalized or a symlinked invocation path silently fails the match. The
|
|
27
|
+
* canonical example is the light-package launcher running
|
|
28
|
+
* `node /tmp/.../kici-admin.cjs` on macOS, where `/tmp` is a symlink to
|
|
29
|
+
* `/private/tmp`: `process.argv[1]` keeps the `/tmp` form while the bundle's
|
|
30
|
+
* `import.meta.url` resolves to the real `/private/tmp` path, so an
|
|
31
|
+
* un-canonicalized comparison is always false and the CLI exits 0 without
|
|
32
|
+
* running any command.
|
|
33
|
+
*/
|
|
34
|
+
export declare function canonicalize(p: string): string;
|
|
13
35
|
//# sourceMappingURL=kici-admin.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the customer installer's image reference from the digest record
|
|
3
|
+
* shipped with this package (installer-image-digests.json at the package root).
|
|
4
|
+
*
|
|
5
|
+
* Emits a manifest-list-digest-pinned ref so a `docker`/`podman pull` verifies
|
|
6
|
+
* the image hash — a registry that serves substituted bits fails the pull. When
|
|
7
|
+
* the record is missing (a dev tree that never ran a release) or lacks the
|
|
8
|
+
* image, falls back to the moving `:latest` tag and warns.
|
|
9
|
+
*
|
|
10
|
+
* The record resolves relative to this module's directory and works for both
|
|
11
|
+
* layouts: the source tree (`src/cli/service/` → the JSON is three dirs up at
|
|
12
|
+
* the package root) and the single-file bundle (`dist/cli.js` → one dir up).
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Resolve `quay.io/kici-dev/<name>:<version>@sha256:<digest>` for an installer
|
|
16
|
+
* image. Falls back to `:latest` (with a warning) when no recorded digest exists.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveImageRef(name: string, opts?: {
|
|
19
|
+
filePath?: string;
|
|
20
|
+
}): string;
|
|
21
|
+
//# sourceMappingURL=image-digests.d.ts.map
|