@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
|
@@ -8,10 +8,13 @@
|
|
|
8
8
|
*
|
|
9
9
|
* 1. Parses every qualified ref and groups by environment name.
|
|
10
10
|
* 2. Fires the per-environment protection-rule pipeline once per unique env
|
|
11
|
-
* (branch / trust / concurrency / reviewer / wait-timer).
|
|
12
|
-
* result
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* (branch / trust / concurrency / reviewer / wait-timer). A `reject`
|
|
12
|
+
* result fails the whole workflow dispatch with a clear reason; a
|
|
13
|
+
* `hold` / `wait` / `queue` result returns a structured `hold` decision
|
|
14
|
+
* so the caller can pause the workflow dispatch as a workflow-scoped held
|
|
15
|
+
* run and resume it when the gate clears. On the resume path the caller
|
|
16
|
+
* sets `skipProtectionGate` so the gate (already satisfied) is bypassed
|
|
17
|
+
* and secrets are resolved directly.
|
|
15
18
|
* 3. Resolves secrets per environment via `secretResolver.resolveForJob`
|
|
16
19
|
* (which writes its own audit log lines).
|
|
17
20
|
* 4. Validates each registry URL scheme: HTTPS always allowed; `http://`
|
|
@@ -26,7 +29,7 @@
|
|
|
26
29
|
* Pure helper: no imports of the dispatch giant. Tested in isolation in
|
|
27
30
|
* `install-secrets-resolver.test.ts`.
|
|
28
31
|
*/
|
|
29
|
-
import type { LockRegistry } from '@kici-dev/engine';
|
|
32
|
+
import type { ApproverClause, LockRegistry } from '@kici-dev/engine';
|
|
30
33
|
import type { TrustResolution } from '../security/trust-resolver.js';
|
|
31
34
|
import type { SecretResolver } from '../secrets/secret-resolver.js';
|
|
32
35
|
import type { EnvironmentStore } from '../environments/environment-store.js';
|
|
@@ -47,6 +50,18 @@ export interface ResolveInstallSecretsArgs {
|
|
|
47
50
|
environmentStore: EnvironmentStore | undefined;
|
|
48
51
|
secretResolver: SecretResolver | undefined;
|
|
49
52
|
protectionContext: JobDispatchContext;
|
|
53
|
+
/**
|
|
54
|
+
* Resume path: skip the protection-rule gate (already satisfied) and resolve
|
|
55
|
+
* secrets directly. The untrusted-contributor strip still runs first.
|
|
56
|
+
*/
|
|
57
|
+
skipProtectionGate?: boolean;
|
|
58
|
+
}
|
|
59
|
+
/** Normalized requirement carried on a `hold` decision. */
|
|
60
|
+
export interface InstallHoldRequirement {
|
|
61
|
+
clauses: ApproverClause[];
|
|
62
|
+
/** ISO timestamp after which the hold expires. */
|
|
63
|
+
expiresAt: string;
|
|
64
|
+
reason: string;
|
|
50
65
|
}
|
|
51
66
|
export type ResolveInstallSecretsResult = {
|
|
52
67
|
decision: 'pass';
|
|
@@ -56,6 +71,18 @@ export type ResolveInstallSecretsResult = {
|
|
|
56
71
|
} | {
|
|
57
72
|
decision: 'reject';
|
|
58
73
|
reason: string;
|
|
74
|
+
} | {
|
|
75
|
+
decision: 'hold';
|
|
76
|
+
/** The gate action that paused the dispatch. */
|
|
77
|
+
action: 'hold' | 'wait' | 'queue';
|
|
78
|
+
/** The environment whose install gate held. */
|
|
79
|
+
envName: string;
|
|
80
|
+
/** Resolved environment id (for the held row). */
|
|
81
|
+
environmentId: string;
|
|
82
|
+
/** Discriminates the release trigger: 'reviewer' | 'wait_timer' | 'concurrency' | 'security'. */
|
|
83
|
+
holdType: string;
|
|
84
|
+
queueType: 'environment' | 'security';
|
|
85
|
+
requirement: InstallHoldRequirement;
|
|
59
86
|
};
|
|
60
87
|
/** Parse `<environment>:<secret-name>`. Returns null on malformed input. */
|
|
61
88
|
export declare function parseQualifiedSecretRef(ref: string): {
|
|
@@ -19,25 +19,28 @@
|
|
|
19
19
|
*/
|
|
20
20
|
import type { Kysely } from 'kysely';
|
|
21
21
|
import type { Database } from '../db/types.js';
|
|
22
|
-
import type {
|
|
22
|
+
import type { MaterializedJob } from '@kici-dev/engine';
|
|
23
23
|
/** Result of evaluating downstream jobs after an upstream completes. */
|
|
24
24
|
export interface SchedulerResult {
|
|
25
25
|
jobName: string;
|
|
26
26
|
action: 'dispatch' | 'skip';
|
|
27
27
|
reason?: string;
|
|
28
28
|
}
|
|
29
|
-
/** Minimal lock job shape needed by insertEdgesForRun. */
|
|
30
|
-
interface LockJobLike {
|
|
31
|
-
readonly name: string;
|
|
32
|
-
readonly needs: readonly (string | NeedsEntry | NeedsGroupEntry)[];
|
|
33
|
-
readonly dependsOnGroups?: readonly string[];
|
|
34
|
-
}
|
|
35
29
|
/**
|
|
36
30
|
* Insert dependency edges at run start for static-to-static needs.
|
|
31
|
+
*
|
|
32
|
+
* Operates on materialized jobs (matrix-expanded children) and an expansion map
|
|
33
|
+
* (base job name -> the expanded child names). An upstream reference to a base
|
|
34
|
+
* name `test` that fanned into `test (a)` / `test (b)` produces one edge per
|
|
35
|
+
* child, so a downstream `needs: ['test']` waits for ALL children to terminate.
|
|
36
|
+
* Each materialized child likewise inherits the full upstream edge set under its
|
|
37
|
+
* own expanded name.
|
|
38
|
+
*
|
|
37
39
|
* NeedsGroupEntry items are skipped (resolved later via resolveGroupEdges).
|
|
38
|
-
* Root jobs (no needs, no dependsOnGroups) are marked needs_satisfied=true
|
|
40
|
+
* Root jobs (no needs, no dependsOnGroups) are marked needs_satisfied=true,
|
|
41
|
+
* keyed by expanded name.
|
|
39
42
|
*/
|
|
40
|
-
export declare function insertEdgesForRun(db: Kysely<Database>, runId: string,
|
|
43
|
+
export declare function insertEdgesForRun(db: Kysely<Database>, runId: string, jobs: readonly MaterializedJob[], expansionMap: ReadonlyMap<string, readonly string[]>): Promise<void>;
|
|
41
44
|
/**
|
|
42
45
|
* Resolve dynamic group edges after eval completion.
|
|
43
46
|
*
|
|
@@ -81,5 +84,4 @@ export declare function checkSchedulerInvariant(db: Kysely<Database>, runId: str
|
|
|
81
84
|
* due to failure propagation. Only follows edges where if_failed='skip'.
|
|
82
85
|
*/
|
|
83
86
|
export declare function getFailurePropagationTargets(db: Kysely<Database>, runId: string, failedJobName: string): Promise<string[]>;
|
|
84
|
-
export {};
|
|
85
87
|
//# sourceMappingURL=needs-scheduler.d.ts.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pending workflow dispatch context store — the workflow-level analogue of the
|
|
3
|
+
* `pending_job_contexts` store. Persists the serializable inputs of a
|
|
4
|
+
* `WorkflowDispatchContext` so a workflow whose install gate held can be
|
|
5
|
+
* resumed (reviewer approve, wait-timer expiry, concurrency slot free) by
|
|
6
|
+
* rebuilding the dispatch context and re-running `dispatchMatchedWorkflow`.
|
|
7
|
+
*
|
|
8
|
+
* Only the serializable inputs are stored — the live `deps` (ProcessingDeps)
|
|
9
|
+
* and `bundle` (ProviderBundle) are NOT persisted; they are rebuilt from the
|
|
10
|
+
* live orchestrator on resume.
|
|
11
|
+
*
|
|
12
|
+
* Writes to both an in-memory Map (fast read on the same process) and the DB
|
|
13
|
+
* (crash recovery + cross-orchestrator read), mirroring the pending-job store.
|
|
14
|
+
*/
|
|
15
|
+
import type { Kysely } from 'kysely';
|
|
16
|
+
import type { Database } from '../db/types.js';
|
|
17
|
+
import type { WorkflowDispatchContext } from './dispatch-matched-workflow.js';
|
|
18
|
+
/**
|
|
19
|
+
* The serializable subset of a `WorkflowDispatchContext` — everything except
|
|
20
|
+
* the live `deps` and `bundle`, which are rebuilt on resume. Every field here
|
|
21
|
+
* is JSON-safe (the event, payload, and lock file already ride the WS protocol
|
|
22
|
+
* as JSON).
|
|
23
|
+
*/
|
|
24
|
+
export type SerializableWorkflowDispatchInputs = Omit<WorkflowDispatchContext, 'deps' | 'bundle'>;
|
|
25
|
+
/** Extract the serializable inputs from a live dispatch context. */
|
|
26
|
+
export declare function toSerializableInputs(ctx: WorkflowDispatchContext): SerializableWorkflowDispatchInputs;
|
|
27
|
+
/** Persist the pending workflow context to the in-memory Map and the DB. */
|
|
28
|
+
export declare function storePendingWorkflowContext(db: Kysely<Database> | undefined, inputs: SerializableWorkflowDispatchInputs): Promise<void>;
|
|
29
|
+
/** Load the pending workflow context by run id (memory first, then DB). */
|
|
30
|
+
export declare function loadPendingWorkflowContext(db: Kysely<Database> | undefined, runId: string): Promise<SerializableWorkflowDispatchInputs | null>;
|
|
31
|
+
/** Delete the pending workflow context from the in-memory Map and the DB. */
|
|
32
|
+
export declare function deletePendingWorkflowContext(db: Kysely<Database> | undefined, runId: string): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Restore the in-memory Map from the DB on startup, skipping rows whose run has
|
|
35
|
+
* already reached a terminal state. Mirrors `restorePendingJobContexts`.
|
|
36
|
+
* Returns the number of restored contexts.
|
|
37
|
+
*/
|
|
38
|
+
export declare function restorePendingWorkflowContexts(db: Kysely<Database>): Promise<number>;
|
|
39
|
+
/**
|
|
40
|
+
* Clear all entries from the in-memory pending workflow contexts Map.
|
|
41
|
+
* @internal Exported for testing only.
|
|
42
|
+
*/
|
|
43
|
+
export declare function clearPendingWorkflowContextsMap(): void;
|
|
44
|
+
//# sourceMappingURL=pending-workflow-context.d.ts.map
|
|
@@ -30,9 +30,11 @@ import type { CheckRunReporter } from '../reporting/check-run-reporter.js';
|
|
|
30
30
|
import type { ExecutionTracker } from '../reporting/execution-tracker.js';
|
|
31
31
|
import type { AgentRegistry } from '../agent/registry.js';
|
|
32
32
|
import type { RunCoordinator } from '../cluster/coordinator.js';
|
|
33
|
+
import type { TeamMembershipLookup } from '../approvals/team-membership-lookup.js';
|
|
33
34
|
import type { LogStorage } from '../reporting/log-storage.js';
|
|
34
35
|
import type { SecretResolver } from '../secrets/secret-resolver.js';
|
|
35
36
|
import type { ContributorCache } from '../security/contributor-cache.js';
|
|
37
|
+
import type { AccessLogWriter } from '../audit/access-log.js';
|
|
36
38
|
import type { LockFile as FullLockFile, LockWorkflow, SimulatedEvent, WebhookNormalizer } from '@kici-dev/engine';
|
|
37
39
|
import { LockFileParseError } from '@kici-dev/engine';
|
|
38
40
|
import type { EventRouter } from '../events/event-router.js';
|
|
@@ -110,7 +112,7 @@ export declare function isRootJob(lockJob: LockJob): boolean;
|
|
|
110
112
|
* Why this exists
|
|
111
113
|
* ----------------
|
|
112
114
|
* The webhook pipeline binds `lockFileFetcher` to the inbound webhook's
|
|
113
|
-
* provider bundle. When
|
|
115
|
+
* provider bundle. When a local-sourced webhook (e.g., the staging
|
|
114
116
|
* stg-ha-smoke failover-dispatch test) arrives for a repo whose lock file
|
|
115
117
|
* is only accessible via a different provider (e.g., github), the inbound
|
|
116
118
|
* fetcher returns null and trigger matching silently drops the webhook.
|
|
@@ -141,7 +143,7 @@ export declare function isRootJob(lockJob: LockJob): boolean;
|
|
|
141
143
|
* -----------
|
|
142
144
|
* Each fallback fetcher is invoked with the REGISTRATION'S
|
|
143
145
|
* `providerContext`, NOT the inbound normalizer's credentials. This is
|
|
144
|
-
* load-bearing: the
|
|
146
|
+
* load-bearing: the LocalWebhookNormalizer returns `{}` as
|
|
145
147
|
* credentials, which would never satisfy a github fetcher that requires
|
|
146
148
|
* `installationId`. The registration carries the correct credentials
|
|
147
149
|
* because it was created via the owning provider's source.
|
|
@@ -176,8 +178,10 @@ export declare function resolveLockFileWithFallback(args: {
|
|
|
176
178
|
* Resolve the customer/org ID for a routing key.
|
|
177
179
|
*
|
|
178
180
|
* Checks the `sources` table first (GitHub App sources), then
|
|
179
|
-
* `generic_webhook_sources` (generic webhook sources)
|
|
180
|
-
*
|
|
181
|
+
* `generic_webhook_sources` (generic webhook sources), then `remote_sources`
|
|
182
|
+
* (the auto-provisioned anchor for Platform-relayed `kici run remote`, routing
|
|
183
|
+
* key `remote:<orgId>`). Falls back to '__default__' if none of the three
|
|
184
|
+
* tables has the routing key.
|
|
181
185
|
*/
|
|
182
186
|
export declare function resolveOrgId(db: Kysely<Database>, routingKey: string): Promise<string>;
|
|
183
187
|
/**
|
|
@@ -213,6 +217,17 @@ export declare function extractCommitMessage(event: string, payload: unknown): s
|
|
|
213
217
|
* Build a human-readable summary for a security hold check.
|
|
214
218
|
*/
|
|
215
219
|
export declare function buildSecurityHoldSummary(reason: string, tier: string, contributorUsername?: string): string;
|
|
220
|
+
/**
|
|
221
|
+
* Build the pending check-run description for a job/workflow approval hold,
|
|
222
|
+
* naming the clauses an approver must satisfy. `{team:X}` renders as
|
|
223
|
+
* "team X", `{user:Y}` as "user Y". An empty clause list (any eligible
|
|
224
|
+
* reviewer satisfies the hold) falls back to a generic message.
|
|
225
|
+
*/
|
|
226
|
+
export declare function summarizeApprovalClauses(clauses: ReadonlyArray<{
|
|
227
|
+
team: string;
|
|
228
|
+
} | {
|
|
229
|
+
user: string;
|
|
230
|
+
}>): string;
|
|
216
231
|
/**
|
|
217
232
|
* Dependencies for the processing pipeline.
|
|
218
233
|
* All injected for testability. Fully provider-agnostic.
|
|
@@ -283,6 +298,12 @@ export interface ProcessingDeps {
|
|
|
283
298
|
identityLinks?: IdentityLink[];
|
|
284
299
|
/** ci_trust permission levels per user ID from Platform push. Optional -- defaults to empty. */
|
|
285
300
|
orgMemberPermissions?: Map<string, PermissionLevel>;
|
|
301
|
+
/**
|
|
302
|
+
* Team-membership lookup pushed from the Platform (team name → member set).
|
|
303
|
+
* Consumed by the approval resolver to satisfy `{team}` approval clauses.
|
|
304
|
+
* Optional -- defaults to "no teams".
|
|
305
|
+
*/
|
|
306
|
+
teamMembershipLookup?: TeamMembershipLookup;
|
|
286
307
|
/** Global workflow policy for org-level permission enforcement. Optional -- if not set, global workflows are unrestricted. */
|
|
287
308
|
globalWorkflowPolicy?: GlobalWorkflowPolicy;
|
|
288
309
|
/** Inbound webhook delivery log writer. Optional -- if not set, deliveries are not persisted to event_log. */
|
|
@@ -296,6 +317,9 @@ export interface ProcessingDeps {
|
|
|
296
317
|
* created in server.ts and threaded through both the Platform-relay WS
|
|
297
318
|
* path and the generic webhook HTTP path. */
|
|
298
319
|
contributorCache?: ContributorCache;
|
|
320
|
+
/** Access-log writer for the orchestrator audit stream. Optional -- if not
|
|
321
|
+
* set, hold-creation audit rows (`held_run.request`) are skipped. */
|
|
322
|
+
accessLogWriter?: AccessLogWriter;
|
|
299
323
|
}
|
|
300
324
|
/**
|
|
301
325
|
* Check if any trigger in the lock file workflows uses path filters.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import type { Database, RemoteSourceRow } from '../db/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Deterministic routing key for an org's Platform-relayed remote runs. A
|
|
5
|
+
* Platform-relayed `test.trigger` carries this key; `resolveOrgId` maps it back
|
|
6
|
+
* to the canonical org id via the `remote_sources` row.
|
|
7
|
+
*/
|
|
8
|
+
export declare function remoteRoutingKeyFor(orgId: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Idempotently upsert the `remote_sources` anchor for an org. Called on every
|
|
11
|
+
* Platform (re)connect once the orchestrator learns its canonical org id from
|
|
12
|
+
* `auth.success`. The unique `(customer_id)` constraint makes this a safe
|
|
13
|
+
* self-heal — re-running updates `cluster_id` if the cluster identity changed.
|
|
14
|
+
*/
|
|
15
|
+
export declare function provisionRemoteSource(db: Kysely<Database>, params: {
|
|
16
|
+
orgId: string;
|
|
17
|
+
clusterId: string | null;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
/** Read the auto-provisioned remote-source row for an org, if it exists. */
|
|
20
|
+
export declare function getRemoteSource(db: Kysely<Database>, orgId: string): Promise<RemoteSourceRow | undefined>;
|
|
21
|
+
//# sourceMappingURL=remote-source-store.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import type { Database } from '../db/types.js';
|
|
3
|
+
import type { ProcessingDeps } from './processor.js';
|
|
4
|
+
import type { ReleaseSignal } from '../environments/held-runs.js';
|
|
5
|
+
import { type WorkflowDispatchContext } from './dispatch-matched-workflow.js';
|
|
6
|
+
import { type SerializableWorkflowDispatchInputs } from './pending-workflow-context.js';
|
|
7
|
+
/**
|
|
8
|
+
* Rebuild a live `WorkflowDispatchContext` from the persisted serializable
|
|
9
|
+
* inputs by re-attaching the orchestrator's live `deps` and reconstructing the
|
|
10
|
+
* provider `bundle` from the live registry (keyed by the stored routing key).
|
|
11
|
+
* Returns null when the provider bundle can no longer be resolved.
|
|
12
|
+
*/
|
|
13
|
+
export declare function rebuildWorkflowDispatchContext(inputs: SerializableWorkflowDispatchInputs, deps: ProcessingDeps): WorkflowDispatchContext | null;
|
|
14
|
+
/**
|
|
15
|
+
* Resume a released workflow install-gate hold. Loads the pending context,
|
|
16
|
+
* rebuilds the dispatch context, and re-dispatches with the gate skipped. On a
|
|
17
|
+
* lost pending context (or unresolvable provider bundle) the run is failed
|
|
18
|
+
* loudly rather than silently dropped.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resumeWorkflow(signal: ReleaseSignal, deps: ProcessingDeps, db: Kysely<Database> | undefined): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Cancel a rejected workflow install-gate hold: mark the run cancelled and drop
|
|
23
|
+
* the pending context.
|
|
24
|
+
*/
|
|
25
|
+
export declare function rejectWorkflow(runId: string, deps: ProcessingDeps, db: Kysely<Database> | undefined, reason: string): Promise<void>;
|
|
26
|
+
//# sourceMappingURL=resume-workflow.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local filesystem (`file://`) source provider implementations.
|
|
3
|
+
*
|
|
4
|
+
* Provides a complete provider bundle for cloning a git repository that is
|
|
5
|
+
* already present on the agent's filesystem, with no remote forge, no webhook
|
|
6
|
+
* signature verification, and no network clone. Uses file:// URLs for cloning
|
|
7
|
+
* and reads lock files directly from the filesystem.
|
|
8
|
+
*
|
|
9
|
+
* Classes:
|
|
10
|
+
* - LocalWebhookNormalizer -> WebhookNormalizer (extracts from custom headers)
|
|
11
|
+
* - LocalLockFileFetcher -> LockFileFetcher (reads from local filesystem)
|
|
12
|
+
* - LocalRepoUrlBuilder -> RepoUrlBuilder (returns file:// URLs)
|
|
13
|
+
*/
|
|
14
|
+
import type { ProviderBundle } from '../../provider-registry.js';
|
|
15
|
+
export { LocalWebhookNormalizer } from './normalizer.js';
|
|
16
|
+
export { LocalLockFileFetcher } from './lock-file-fetcher.js';
|
|
17
|
+
export { LocalRepoUrlBuilder } from './repo-url-builder.js';
|
|
18
|
+
/**
|
|
19
|
+
* Create a ProviderBundle for a local filesystem (`file://`) source.
|
|
20
|
+
*
|
|
21
|
+
* Provides normalizer, lock file fetcher, and repo URL builder.
|
|
22
|
+
* Clone token provider and changed files fetcher are null since
|
|
23
|
+
* file:// URLs need no auth and local events don't track changed files.
|
|
24
|
+
*
|
|
25
|
+
* @param opts.repoBasePath - Base directory where the repo(s) live on disk
|
|
26
|
+
* @param opts.cloneUrlBase - Optional URL base for clone operations (e.g. git://host/path)
|
|
27
|
+
* @returns Complete ProviderBundle for the local provider
|
|
28
|
+
*/
|
|
29
|
+
export declare function createLocalProviderBundle(opts: {
|
|
30
|
+
repoBasePath: string;
|
|
31
|
+
cloneUrlBase?: string;
|
|
32
|
+
}): ProviderBundle;
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for a local filesystem (`file://`) source, stored as JSONB in
|
|
3
|
+
* `generic_webhook_sources.git_config` and discriminated from universal-git
|
|
4
|
+
* config by the row's `provider_type='local'`.
|
|
5
|
+
*
|
|
6
|
+
* A local source clones a git repository that already exists on the agent's
|
|
7
|
+
* filesystem (host path for bare-metal scalers, image-bundled / rootfs /
|
|
8
|
+
* bind-mounted path for container + Firecracker scalers). The orchestrator does
|
|
9
|
+
* not verify in-agent reachability — that is the operator's responsibility.
|
|
10
|
+
*/
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
export declare const LocalSourceConfigSchema: z.ZodObject<{
|
|
13
|
+
repoBasePath: z.ZodString;
|
|
14
|
+
cloneUrlBase: z.ZodOptional<z.ZodString>;
|
|
15
|
+
}, z.core.$strict>;
|
|
16
|
+
export type LocalSourceConfig = z.infer<typeof LocalSourceConfigSchema>;
|
|
17
|
+
//# sourceMappingURL=local-source-config.d.ts.map
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Local filesystem lock file fetcher.
|
|
3
3
|
*
|
|
4
4
|
* Implements the LockFileFetcher interface from @kici-dev/engine by reading
|
|
5
|
-
* kici.lock.json directly from the local filesystem. Used when the
|
|
5
|
+
* kici.lock.json directly from the local filesystem. Used when the local
|
|
6
6
|
* provider processes webhooks for repos accessible via file:// URLs.
|
|
7
7
|
*/
|
|
8
8
|
import type { LockFileFetcher, LockFile } from '@kici-dev/engine';
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Local provider implementation of LockFileFetcher.
|
|
11
11
|
*
|
|
12
12
|
* Reads kici.lock.json from the local filesystem at the path derived from
|
|
13
13
|
* the repoIdentifier (which is expected to be a file:// URL or a local path).
|
|
14
14
|
*/
|
|
15
|
-
export declare class
|
|
15
|
+
export declare class LocalLockFileFetcher implements LockFileFetcher {
|
|
16
16
|
private readonly repoBasePath;
|
|
17
|
-
readonly provider: "
|
|
17
|
+
readonly provider: "local";
|
|
18
18
|
/**
|
|
19
|
-
* @param repoBasePath - Base directory for
|
|
19
|
+
* @param repoBasePath - Base directory for the repo(s). When repoIdentifier
|
|
20
20
|
* starts with 'file://', it is stripped and used as-is. Otherwise
|
|
21
21
|
* repoBasePath is used as the root.
|
|
22
22
|
*/
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Local filesystem source webhook normalizer.
|
|
3
3
|
*
|
|
4
|
-
* Implements the WebhookNormalizer interface from @kici-dev/engine for
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* Event type and routing key are extracted from custom headers.
|
|
4
|
+
* Implements the WebhookNormalizer interface from @kici-dev/engine for local
|
|
5
|
+
* (`file://`) sources. Drives the full webhook processing pipeline without a
|
|
6
|
+
* remote forge: signature verification is skipped (local sources use
|
|
7
|
+
* verification='none'), and event type / routing key are extracted from custom
|
|
8
|
+
* headers.
|
|
10
9
|
*/
|
|
11
10
|
import type { WebhookNormalizer, SimulatedEvent, AccessCacheInvalidation } from '@kici-dev/engine';
|
|
12
11
|
/**
|
|
13
|
-
*
|
|
12
|
+
* Local provider implementation of WebhookNormalizer.
|
|
14
13
|
*
|
|
15
|
-
* Maps
|
|
16
|
-
*
|
|
14
|
+
* Maps the synthetic webhook headers and payloads sent to a local source into
|
|
15
|
+
* KiCI's universal SimulatedEvent format. Payloads use the same GitHub-shaped
|
|
16
|
+
* structure the trigger CLI / post-receive hook build
|
|
17
17
|
* (e.g., {ref: 'refs/heads/master', repository: {full_name: 'test/repo'}}).
|
|
18
18
|
*/
|
|
19
|
-
export declare class
|
|
20
|
-
readonly provider: "
|
|
19
|
+
export declare class LocalWebhookNormalizer implements WebhookNormalizer {
|
|
20
|
+
readonly provider: "local";
|
|
21
21
|
/**
|
|
22
|
-
* Extract routing key from
|
|
22
|
+
* Extract routing key from the local-source webhook headers.
|
|
23
23
|
*
|
|
24
24
|
* Checks x-kici-routing-key first (explicit routing), then falls back
|
|
25
25
|
* to x-kici-source-id (generic source ID format).
|
|
@@ -38,42 +38,42 @@ export declare class InternalWebhookNormalizer implements WebhookNormalizer {
|
|
|
38
38
|
/**
|
|
39
39
|
* Verify signature -- always returns true.
|
|
40
40
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
41
|
+
* Local sources use verification='none' — there is no remote forge to sign
|
|
42
|
+
* the payload. The operator is responsible for only registering repos they
|
|
43
|
+
* trust (see docs/user/providers/local-file.md).
|
|
44
44
|
*/
|
|
45
45
|
verifySignature(_body: string, _headers: Record<string, string>, _secret: string): boolean;
|
|
46
46
|
/**
|
|
47
|
-
* Extract repository identifier from
|
|
47
|
+
* Extract repository identifier from a local-source webhook payload.
|
|
48
48
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
49
|
+
* Local-source events use GitHub-shaped payloads, so we extract from
|
|
50
|
+
* payload.repository.full_name if present.
|
|
51
51
|
*/
|
|
52
52
|
extractRepoIdentifier(payload: unknown): string | null;
|
|
53
53
|
/**
|
|
54
|
-
* Extract ref from
|
|
54
|
+
* Extract ref from a local-source webhook payload.
|
|
55
55
|
*
|
|
56
|
-
*
|
|
56
|
+
* Local-source events use GitHub-shaped payloads, so extraction logic
|
|
57
57
|
* mirrors GitHub's: push -> payload.after, PR -> payload.pull_request.head.sha.
|
|
58
58
|
*/
|
|
59
59
|
extractRef(eventType: string, payload: unknown): string;
|
|
60
60
|
/**
|
|
61
|
-
* Extract credentials --
|
|
61
|
+
* Extract credentials -- local sources carry no provider credentials.
|
|
62
62
|
*/
|
|
63
63
|
extractCredentials(_payload: unknown): Record<string, unknown>;
|
|
64
64
|
/**
|
|
65
|
-
* Normalize
|
|
65
|
+
* Normalize a local-source webhook event into a SimulatedEvent.
|
|
66
66
|
*
|
|
67
67
|
* Extracts branch information from payload.ref (stripping refs/heads/ prefix)
|
|
68
|
-
* and preserves the raw payload for trigger matching. Falls back to '
|
|
68
|
+
* and preserves the raw payload for trigger matching. Falls back to '__local__'
|
|
69
69
|
* when no ref is present.
|
|
70
70
|
*/
|
|
71
71
|
normalizeEvent(eventType: string, _action: string | null, payload: unknown): SimulatedEvent | null;
|
|
72
72
|
/**
|
|
73
|
-
* Map membership-related
|
|
73
|
+
* Map membership-related local-source webhook events to ContributorCache
|
|
74
74
|
* invalidations.
|
|
75
75
|
*
|
|
76
|
-
*
|
|
76
|
+
* Local-source payloads are GitHub-shaped by design, so the mapping
|
|
77
77
|
* mirrors the GitHub normalizer exactly:
|
|
78
78
|
*
|
|
79
79
|
* - `member`: repo-user
|
|
@@ -81,8 +81,8 @@ export declare class InternalWebhookNormalizer implements WebhookNormalizer {
|
|
|
81
81
|
* - `membership`: user-in-org
|
|
82
82
|
* - `team` (repo-scoped actions only): repo
|
|
83
83
|
*
|
|
84
|
-
* This lets
|
|
85
|
-
* `
|
|
84
|
+
* This lets membership-invalidation paths be exercised through
|
|
85
|
+
* `sendLocalWebhook()` without requiring a real GitHub App.
|
|
86
86
|
*/
|
|
87
87
|
getAccessCacheInvalidations(eventType: string, _action: string | null, payload: unknown): AccessCacheInvalidation[];
|
|
88
88
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Local filesystem repo URL builder.
|
|
3
3
|
*
|
|
4
4
|
* Implements the RepoUrlBuilder interface from @kici-dev/engine by returning
|
|
5
5
|
* file:// URLs for local filesystem access, or network URLs (git://, http://)
|
|
@@ -7,16 +7,16 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { RepoUrlBuilder } from '@kici-dev/engine';
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Local provider implementation of RepoUrlBuilder.
|
|
11
11
|
*
|
|
12
12
|
* Builds clone URLs for repository access. When cloneUrlBase is set (e.g. to
|
|
13
13
|
* a git:// daemon URL), uses it for clone URLs so remote agents on different
|
|
14
14
|
* machines can clone. Otherwise falls back to file:// URLs for local access.
|
|
15
15
|
*/
|
|
16
|
-
export declare class
|
|
16
|
+
export declare class LocalRepoUrlBuilder implements RepoUrlBuilder {
|
|
17
17
|
private readonly repoBasePath;
|
|
18
18
|
private readonly cloneUrlBase?;
|
|
19
|
-
readonly provider: "
|
|
19
|
+
readonly provider: "local";
|
|
20
20
|
/**
|
|
21
21
|
* @param repoBasePath - Base directory where test repos live on disk
|
|
22
22
|
* @param cloneUrlBase - Optional URL base for clone operations (e.g. git://host/path).
|
|
@@ -34,8 +34,8 @@ export declare class InternalRepoUrlBuilder implements RepoUrlBuilder {
|
|
|
34
34
|
/**
|
|
35
35
|
* Build a raw file URL -- returns empty string.
|
|
36
36
|
*
|
|
37
|
-
*
|
|
38
|
-
* The lock file is fetched via
|
|
37
|
+
* Local repos have no web UI, so raw file URLs are not applicable.
|
|
38
|
+
* The lock file is fetched via LocalLockFileFetcher (filesystem) instead.
|
|
39
39
|
*/
|
|
40
40
|
buildRawFileUrl(_repoIdentifier: string, _ref: string, _path: string): string;
|
|
41
41
|
}
|
|
@@ -395,6 +395,39 @@ export declare class ExecutionTracker {
|
|
|
395
395
|
triggerEvent?: string;
|
|
396
396
|
commitMessage?: string;
|
|
397
397
|
}): Promise<void>;
|
|
398
|
+
/**
|
|
399
|
+
* Record a run paused at the workflow install gate (a `registries:` /
|
|
400
|
+
* `installEnv:` protection rule returned hold / wait / queue). Writes an
|
|
401
|
+
* `execution_runs` row in the `held` state — alive and resumable — so the
|
|
402
|
+
* dashboard run list surfaces the paused workflow. No jobs are tracked: the
|
|
403
|
+
* workflow-scoped held_runs row + pending workflow context (written by the
|
|
404
|
+
* caller) keep the run from being counted complete. Idempotent on runId.
|
|
405
|
+
*/
|
|
406
|
+
recordRunHeld(args: {
|
|
407
|
+
runId: string;
|
|
408
|
+
workflowName: string;
|
|
409
|
+
provider: string;
|
|
410
|
+
repoIdentifier: string;
|
|
411
|
+
ref: string;
|
|
412
|
+
sha: string;
|
|
413
|
+
deliveryId: string | null;
|
|
414
|
+
providerContext: Record<string, unknown>;
|
|
415
|
+
routingKey: string;
|
|
416
|
+
environmentName?: string;
|
|
417
|
+
reason: string;
|
|
418
|
+
triggerEvent?: string;
|
|
419
|
+
commitMessage?: string;
|
|
420
|
+
}): Promise<void>;
|
|
421
|
+
/**
|
|
422
|
+
* Flip a `held` run back to `pending` so the resumed dispatch can proceed
|
|
423
|
+
* into job dispatch. Returns true when a held row was found and updated.
|
|
424
|
+
*/
|
|
425
|
+
resumeHeldRun(runId: string): Promise<boolean>;
|
|
426
|
+
/**
|
|
427
|
+
* Cancel a held run (reviewer rejected the install gate). Flips the held row
|
|
428
|
+
* to `cancelled` and fires the status-change forward so Platform projects it.
|
|
429
|
+
*/
|
|
430
|
+
cancelHeldRun(runId: string, reason: string): Promise<void>;
|
|
398
431
|
/**
|
|
399
432
|
* Mark a run as failed immediately with a reason message.
|
|
400
433
|
*
|
|
@@ -26,15 +26,14 @@ interface AdminEventRouteDeps {
|
|
|
26
26
|
rbac: RbacEnforcer;
|
|
27
27
|
/**
|
|
28
28
|
* The in-process bundle registry. The POST /generic-sources handler
|
|
29
|
-
* registers
|
|
29
|
+
* registers a local / universal-git bundle into this registry
|
|
30
30
|
* immediately after the source row lands in the DB, so the next
|
|
31
31
|
* webhook against that source resolves the right normalizer without
|
|
32
32
|
* waiting for an orchestrator restart.
|
|
33
33
|
*/
|
|
34
34
|
providerRegistry: ProviderRegistry;
|
|
35
|
-
/**
|
|
36
|
-
*
|
|
37
|
-
* `internalProviderRepoPath` / `internalProviderCloneUrl` config. */
|
|
35
|
+
/** Passed through to `registerProviderBundleForSource` (universal-git bundle
|
|
36
|
+
* build reads cluster config; local bundles read the row's own git_config). */
|
|
38
37
|
config: AppConfig;
|
|
39
38
|
/** Required for universal-git source registration — `null` is allowed;
|
|
40
39
|
* rows with `git_config` are skipped + metric-bumped in that case. */
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fleet log-collection admin routes.
|
|
3
|
+
*
|
|
4
|
+
* GET /admin/fleet-topology — enumerate the cluster (no fan-out) for
|
|
5
|
+
* `debug-bundle --fleet --list` / `--pick`.
|
|
6
|
+
* POST /admin/fleet-bundle — drive the recursive fan-out and stream the
|
|
7
|
+
* assembled nested ZIP back as an octet-stream.
|
|
8
|
+
*
|
|
9
|
+
* Both are protected by the same Bearer admin-token auth as the other admin
|
|
10
|
+
* routes (token-manager validation).
|
|
11
|
+
*/
|
|
12
|
+
import { Hono } from 'hono';
|
|
13
|
+
import type { TokenManager } from '../secrets/token-manager.js';
|
|
14
|
+
import type { FleetRoutesDeps } from '../app.js';
|
|
15
|
+
export interface FleetAdminRouteDeps {
|
|
16
|
+
fleet: FleetRoutesDeps;
|
|
17
|
+
tokenManager: TokenManager;
|
|
18
|
+
}
|
|
19
|
+
export declare function createFleetRoutes(deps: FleetAdminRouteDeps): Hono;
|
|
20
|
+
//# sourceMappingURL=fleet.d.ts.map
|