@kici-dev/orchestrator 0.1.26 → 0.1.27
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/app.d.ts +13 -4
- package/dist/approvals/apply-decision.d.ts +1 -1
- package/dist/approvals/step-approval-bridge.d.ts +1 -1
- package/dist/cache/pending-inits.d.ts +4 -4
- package/dist/cli/api-client.d.ts +29 -4
- package/dist/cli/commands/context.d.ts +25 -0
- package/dist/cli/commands/debug-bundle.d.ts +1 -1
- package/dist/cli/commands/variable.d.ts +6 -6
- package/dist/cli/service/windows.d.ts +6 -0
- package/dist/cli.js +526 -340
- package/dist/config.d.ts +16 -0
- package/dist/contexts/binding-store.d.ts +36 -0
- package/dist/contexts/context-store.d.ts +87 -0
- package/dist/{environments → contexts}/held-runs.d.ts +15 -15
- package/dist/{environments → contexts}/index.d.ts +1 -1
- package/dist/contexts/protection/aggregate.d.ts +43 -0
- package/dist/contexts/protection/branch-gate.d.ts +5 -0
- package/dist/contexts/protection/concurrency-gate.d.ts +7 -0
- package/dist/{environments → contexts}/protection/pipeline.d.ts +3 -3
- package/dist/contexts/protection/reviewer-gate.d.ts +7 -0
- package/dist/{environments → contexts}/protection/satisfiability.d.ts +21 -21
- package/dist/contexts/protection/trust-gate.d.ts +7 -0
- package/dist/contexts/protection/wait-timer-gate.d.ts +7 -0
- package/dist/contexts/variable-store.d.ts +39 -0
- package/dist/dashboard/attestation-filters.d.ts +10 -8
- package/dist/dashboard/handler.d.ts +28 -2
- package/dist/db/migrations/067_environments_to_contexts.d.ts +36 -0
- package/dist/db/migrations/068_request_idempotency.d.ts +17 -0
- package/dist/db/types.d.ts +78 -59
- package/dist/github-app-name-refresher/github-app-name-refresher.d.ts +1 -1
- package/dist/index.js +21 -6
- package/dist/metrics/prometheus.d.ts +2 -0
- package/dist/oidc/id-token-claims.d.ts +63 -0
- package/dist/oidc/jwt.d.ts +15 -0
- package/dist/oidc/local-dev-signer.d.ts +31 -0
- package/dist/oidc/local-mint.d.ts +77 -0
- package/dist/oidc/oidc-mint-registration.d.ts +49 -0
- package/dist/pipeline/decorating-secret-resolver.d.ts +4 -4
- package/dist/pipeline/dispatch-matched-workflow.d.ts +3 -3
- package/dist/pipeline/inline-eval.d.ts +2 -2
- package/dist/pipeline/install-secrets-resolver.d.ts +13 -13
- package/dist/pipeline/{job-environments.d.ts → job-contexts.d.ts} +23 -23
- package/dist/pipeline/manual-schedule.d.ts +8 -1
- package/dist/pipeline/processor.d.ts +6 -6
- package/dist/pipeline/request-idempotency.d.ts +28 -0
- package/dist/pipeline/rerun.d.ts +8 -0
- package/dist/pipeline/resume-workflow.d.ts +1 -1
- package/dist/pipeline/test-pipeline.d.ts +2 -2
- package/dist/provenance/trust-root.d.ts +7 -0
- package/dist/provider-registry.d.ts +8 -0
- package/dist/providers/local/index.d.ts +1 -0
- package/dist/providers/local/local-source-config.d.ts +1 -0
- package/dist/reporting/execution-tracker.d.ts +17 -7
- package/dist/reporting/run-aggregator.d.ts +5 -5
- package/dist/routes/admin-contexts.d.ts +47 -0
- package/dist/routes/admin-registrations.d.ts +2 -2
- package/dist/routes/github-webhook.d.ts +2 -2
- package/dist/secrets/context-secret-resolver.d.ts +30 -0
- package/dist/secrets/index.d.ts +1 -1
- package/dist/secrets/pg-secret-store.d.ts +3 -3
- package/dist/secrets/rbac.d.ts +1 -1
- package/dist/secrets/secret-resolver.d.ts +19 -19
- package/dist/security/comment-handler.d.ts +1 -1
- package/dist/server.js +1770 -1196
- package/dist/stale-detector/stale-run-detector.d.ts +1 -1
- package/dist/standalone.js +1649 -747
- package/dist/storage/blob-routes.d.ts +16 -0
- package/dist/ws/{dashboard-env-handler.d.ts → dashboard-context-handler.d.ts} +15 -15
- package/dist/ws/oidc-token-relay.d.ts +6 -0
- package/installer-image-digests.json +3 -3
- package/package.json +4 -4
- package/sbom.spdx.json +50 -50
- package/dist/cli/commands/environment.d.ts +0 -25
- package/dist/environments/binding-store.d.ts +0 -36
- package/dist/environments/environment-store.d.ts +0 -87
- package/dist/environments/protection/aggregate.d.ts +0 -43
- package/dist/environments/protection/branch-gate.d.ts +0 -5
- package/dist/environments/protection/concurrency-gate.d.ts +0 -7
- package/dist/environments/protection/reviewer-gate.d.ts +0 -7
- package/dist/environments/protection/trust-gate.d.ts +0 -7
- package/dist/environments/protection/wait-timer-gate.d.ts +0 -7
- package/dist/environments/variable-store.d.ts +0 -39
- package/dist/routes/admin-environments.d.ts +0 -47
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLI-secret overlay for `kici run` test dispatch.
|
|
3
3
|
*
|
|
4
|
-
* Wraps the orchestrator's
|
|
4
|
+
* Wraps the orchestrator's context `SecretResolver` and overlays the
|
|
5
5
|
* developer's CLI-uploaded local secrets on top of the env-resolved secrets,
|
|
6
6
|
* with CLI winning on collision. Passed to the shared dispatch core via
|
|
7
7
|
* `ProcessingDeps.secretResolver`, so the core's secret-resolution path is
|
|
8
8
|
* unchanged and oblivious to "test secrets".
|
|
9
9
|
*
|
|
10
|
-
* Precedence: env-resolved secrets → CLI context for the requested
|
|
10
|
+
* Precedence: env-resolved secrets → CLI context for the requested context
|
|
11
11
|
* → CLI flat. The CLI flat overlay is applied last so a CLI flat key always
|
|
12
12
|
* wins.
|
|
13
13
|
*/
|
|
@@ -21,12 +21,12 @@ export declare class DecoratingSecretResolver implements SecretResolverApi {
|
|
|
21
21
|
private readonly base;
|
|
22
22
|
private readonly cli;
|
|
23
23
|
constructor(base: SecretResolverApi, cli: CliSecrets);
|
|
24
|
-
resolveForJob(orgId: string,
|
|
24
|
+
resolveForJob(orgId: string, contextName: string): Promise<Record<string, string>>;
|
|
25
25
|
resolveNamed(orgId: string, scope: string, key: string, opts?: {
|
|
26
26
|
store?: string;
|
|
27
27
|
runId?: string;
|
|
28
28
|
jobId?: string;
|
|
29
29
|
}): Promise<string | null>;
|
|
30
|
-
resolveForJobWithMeta(orgId: string,
|
|
30
|
+
resolveForJobWithMeta(orgId: string, contextName: string): Promise<Record<string, ResolvedSecretMeta>>;
|
|
31
31
|
}
|
|
32
32
|
//# sourceMappingURL=decorating-secret-resolver.d.ts.map
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Handles everything that happens AFTER a workflow has been matched against an
|
|
5
5
|
* incoming webhook: payload storage, cache + build coordination, secret
|
|
6
|
-
* resolution, per-job
|
|
6
|
+
* resolution, per-job context evaluation, static job dispatch (cluster +
|
|
7
7
|
* single-orch paths), execution-tracker registration, deferred init dispatch
|
|
8
8
|
* for jobs with dynamic fields, and deferred dynamic-job-fn dispatch for
|
|
9
9
|
* `_type:'dynamic'` lock entries.
|
|
@@ -113,7 +113,7 @@ export interface WorkflowDispatchContext {
|
|
|
113
113
|
* Run-wide flat secrets layered onto EVERY dispatched job's `jobConfig.secrets`
|
|
114
114
|
* (env-declaring or not). Used by the test path to deliver `kici run --secret`
|
|
115
115
|
* / `--env` CLI flat secrets, which must reach a job regardless of whether it
|
|
116
|
-
* declares an `
|
|
116
|
+
* declares an `context:`. Merged UNDER the per-job env-resolved secrets so
|
|
117
117
|
* the CLI value wins on a key collision (matching the prior B1-env -> A-CLI
|
|
118
118
|
* precedence). Undefined for webhook runs.
|
|
119
119
|
*/
|
|
@@ -140,7 +140,7 @@ export interface DispatchMatchedWorkflowResult {
|
|
|
140
140
|
held?: boolean;
|
|
141
141
|
/**
|
|
142
142
|
* User-visible warnings aggregated from dispatched jobs — today, one per job
|
|
143
|
-
* whose bound test-run
|
|
143
|
+
* whose bound test-run context(s) were unavailable and skipped. Surfaced
|
|
144
144
|
* on the accepted trigger response so the CLI can print them.
|
|
145
145
|
*/
|
|
146
146
|
envWarnings?: string[];
|
|
@@ -36,8 +36,8 @@ export declare function evaluateInlineRecord(expression: string, event: object):
|
|
|
36
36
|
* failures are immediate dispatch failures (no init-job fallback).
|
|
37
37
|
*/
|
|
38
38
|
export declare function evaluateInlineFields(lockJob: LockJob, event: object): {
|
|
39
|
-
/** Resolved name per `
|
|
40
|
-
|
|
39
|
+
/** Resolved name per `contexts` element, aligned by index; undefined for static or impure-dynamic elements. */
|
|
40
|
+
inlineContextNames: Array<string | undefined>;
|
|
41
41
|
inlineEnv: Record<string, string> | undefined;
|
|
42
42
|
inlineConcurrencyGroup: string | undefined;
|
|
43
43
|
};
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* private registries.
|
|
5
5
|
*
|
|
6
6
|
* Each `tokenSecret` / `installEnv[]` entry uses the qualified
|
|
7
|
-
* `<
|
|
7
|
+
* `<context>:<secret-name>` syntax. The resolver:
|
|
8
8
|
*
|
|
9
|
-
* 1. Parses every qualified ref and groups by
|
|
10
|
-
* 2. Fires the per-
|
|
9
|
+
* 1. Parses every qualified ref and groups by context name.
|
|
10
|
+
* 2. Fires the per-context protection-rule pipeline once per unique env
|
|
11
11
|
* (branch / trust / concurrency / reviewer / wait-timer). A `reject`
|
|
12
12
|
* result fails the whole workflow dispatch with a clear reason; a
|
|
13
13
|
* `hold` / `wait` / `queue` result returns a structured `hold` decision
|
|
@@ -15,13 +15,13 @@
|
|
|
15
15
|
* run and resume it when the gate clears. On the resume path the caller
|
|
16
16
|
* sets `skipProtectionGate` so the gate (already satisfied) is bypassed
|
|
17
17
|
* and secrets are resolved directly.
|
|
18
|
-
* 3. Resolves secrets per
|
|
18
|
+
* 3. Resolves secrets per context via `secretResolver.resolveForJob`
|
|
19
19
|
* (which writes its own audit log lines).
|
|
20
20
|
* 4. Validates each registry URL scheme: HTTPS always allowed; `http://`
|
|
21
21
|
* allowed only for loopback / `*.local` hosts OR when the org operator
|
|
22
22
|
* has flipped `org_settings.allow_http_npm_registries=true`.
|
|
23
23
|
* 5. Strips the resolved auth entirely when the contributor-trust tier is
|
|
24
|
-
* not `trusted` (defense in depth: even if a misconfigured
|
|
24
|
+
* not `trusted` (defense in depth: even if a misconfigured context
|
|
25
25
|
* lets an unknown contributor through the protection-pipeline trust
|
|
26
26
|
* gate, this strip ensures fork PRs never see registry tokens — the
|
|
27
27
|
* install fails naturally because the deps are unreachable).
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
import type { ApproverClause, LockRegistry } from '@kici-dev/engine';
|
|
33
33
|
import type { TrustResolution } from '../security/trust-resolver.js';
|
|
34
34
|
import type { SecretResolverApi } from '../secrets/secret-resolver.js';
|
|
35
|
-
import type {
|
|
36
|
-
import { type JobDispatchContext } from '../
|
|
35
|
+
import type { ContextStore } from '../contexts/context-store.js';
|
|
36
|
+
import { type JobDispatchContext } from '../contexts/protection/pipeline.js';
|
|
37
37
|
/** Registry spec carried on the dispatch message (token already resolved). */
|
|
38
38
|
export interface NpmRegistrySpec {
|
|
39
39
|
url: string;
|
|
@@ -47,7 +47,7 @@ export interface ResolveInstallSecretsArgs {
|
|
|
47
47
|
allowHttpNpmRegistries: boolean;
|
|
48
48
|
resolvedOrgId: string;
|
|
49
49
|
trustResolution: TrustResolution | undefined;
|
|
50
|
-
|
|
50
|
+
contextStore: ContextStore | undefined;
|
|
51
51
|
secretResolver: SecretResolverApi | undefined;
|
|
52
52
|
protectionContext: JobDispatchContext;
|
|
53
53
|
/**
|
|
@@ -75,16 +75,16 @@ export type ResolveInstallSecretsResult = {
|
|
|
75
75
|
decision: 'hold';
|
|
76
76
|
/** The gate action that paused the dispatch. */
|
|
77
77
|
action: 'hold' | 'wait' | 'queue';
|
|
78
|
-
/** The
|
|
78
|
+
/** The context whose install gate held. */
|
|
79
79
|
envName: string;
|
|
80
|
-
/** Resolved
|
|
81
|
-
|
|
80
|
+
/** Resolved context id (for the held row). */
|
|
81
|
+
contextId: string;
|
|
82
82
|
/** Discriminates the release trigger: 'reviewer' | 'wait_timer' | 'concurrency' | 'security'. */
|
|
83
83
|
holdType: string;
|
|
84
|
-
queueType: '
|
|
84
|
+
queueType: 'context' | 'security';
|
|
85
85
|
requirement: InstallHoldRequirement;
|
|
86
86
|
};
|
|
87
|
-
/** Parse `<
|
|
87
|
+
/** Parse `<context>:<secret-name>`. Returns null on malformed input. */
|
|
88
88
|
export declare function parseQualifiedSecretRef(ref: string): {
|
|
89
89
|
envName: string;
|
|
90
90
|
secretName: string;
|
|
@@ -1,59 +1,59 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Multi-
|
|
2
|
+
* Multi-context resolution helpers for the dispatch path.
|
|
3
3
|
*
|
|
4
|
-
* A job binds an ordered list of
|
|
5
|
-
* module resolves that list into concrete
|
|
4
|
+
* A job binds an ordered list of contexts (`LockJob.contexts`). This
|
|
5
|
+
* module resolves that list into concrete context names (static values
|
|
6
6
|
* verbatim, pure-inline dynamic elements evaluated against the event) and folds
|
|
7
|
-
* the per-
|
|
7
|
+
* the per-context secrets/variables last-wins. It keeps the heavy fold logic
|
|
8
8
|
* out of `dispatchMatchedWorkflow`, which must stay under the function-length cap.
|
|
9
9
|
*/
|
|
10
|
-
import { type
|
|
10
|
+
import { type Context, type HostFacts, type LockJob } from '@kici-dev/engine';
|
|
11
11
|
import type { SecretResolverApi } from '../secrets/secret-resolver.js';
|
|
12
|
-
import type { VariableStore } from '../
|
|
12
|
+
import type { VariableStore } from '../contexts/variable-store.js';
|
|
13
13
|
/**
|
|
14
14
|
* Placeholder written into the persisted bound-env list for an impure dynamic
|
|
15
15
|
* element the orchestrator cannot resolve at dispatch. The agent's init eval
|
|
16
16
|
* later overwrites the list with the resolved name.
|
|
17
17
|
*/
|
|
18
18
|
export declare const DYNAMIC_ENV_PLACEHOLDER = "(dynamic)";
|
|
19
|
-
/** Ordered resolved
|
|
20
|
-
export interface
|
|
19
|
+
/** Ordered resolved context names plus whether any element still needs agent init. */
|
|
20
|
+
export interface ResolvedJobContexts {
|
|
21
21
|
/** Resolved static + pure-inline names, in order. */
|
|
22
22
|
names: string[];
|
|
23
23
|
/** True when an impure dynamic element must be resolved by an agent init job. */
|
|
24
24
|
needsInit: boolean;
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
|
-
* Resolve the ordered bound-
|
|
27
|
+
* Resolve the ordered bound-context names from a lock job. Static elements
|
|
28
28
|
* use their value verbatim; pure-inline dynamic elements use the matching
|
|
29
29
|
* pre-evaluated inline name (aligned by index); an impure dynamic element cannot
|
|
30
30
|
* be resolved here and flags `needsInit`.
|
|
31
31
|
*/
|
|
32
|
-
export declare function
|
|
32
|
+
export declare function resolveJobContextNames(lockJob: LockJob, inlineNames: ReadonlyArray<string | undefined>): ResolvedJobContexts;
|
|
33
33
|
/**
|
|
34
|
-
* Build the ordered bound-
|
|
35
|
-
* Unlike {@link
|
|
34
|
+
* Build the ordered bound-context display list for persistence at dispatch.
|
|
35
|
+
* Unlike {@link resolveJobContextNames}, this never drops an unresolved
|
|
36
36
|
* element: a static element uses its value, a pure-inline element uses its
|
|
37
37
|
* resolved name when known, and any element the orchestrator cannot resolve at
|
|
38
38
|
* dispatch (impure dynamic, or an unresolved pure-inline) becomes the
|
|
39
39
|
* `(dynamic)` placeholder — so the persisted column reflects every declared
|
|
40
|
-
* slot in order. Returns an empty array when the job binds no
|
|
40
|
+
* slot in order. Returns an empty array when the job binds no context.
|
|
41
41
|
*/
|
|
42
|
-
export declare function
|
|
43
|
-
/** Merged secrets/variables across an ordered list of resolved
|
|
42
|
+
export declare function buildJobContextDisplayNames(lockJob: LockJob, inlineNames: ReadonlyArray<string | undefined>): string[];
|
|
43
|
+
/** Merged secrets/variables across an ordered list of resolved contexts. */
|
|
44
44
|
export interface MultiEnvMergedData {
|
|
45
|
-
|
|
45
|
+
contextVars?: Record<string, string>;
|
|
46
46
|
jobSecrets?: Record<string, string>;
|
|
47
47
|
jobNamespacedSecrets?: Record<string, Record<string, string>>;
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
50
|
* Resolve and fold variables + secrets across the ordered list of matched
|
|
51
|
-
*
|
|
52
|
-
* single-env logic (longest-scope-path-wins preserved within each
|
|
53
|
-
* then folded in array order so a later
|
|
54
|
-
* Secrets are also returned namespaced per
|
|
51
|
+
* contexts, last-wins. Each context is resolved with the existing
|
|
52
|
+
* single-env logic (longest-scope-path-wins preserved within each context),
|
|
53
|
+
* then folded in array order so a later context overrides an earlier key.
|
|
54
|
+
* Secrets are also returned namespaced per context so qualified
|
|
55
55
|
* `<env>:<secret>` references still resolve. `entries` carries the matched
|
|
56
|
-
* `
|
|
56
|
+
* `Context` for each name (in order); variables resolve by context id.
|
|
57
57
|
*/
|
|
58
58
|
export declare function resolveMultiEnvMergedData(args: {
|
|
59
59
|
deps: {
|
|
@@ -63,9 +63,9 @@ export declare function resolveMultiEnvMergedData(args: {
|
|
|
63
63
|
orgId: string;
|
|
64
64
|
entries: ReadonlyArray<{
|
|
65
65
|
name: string;
|
|
66
|
-
env:
|
|
66
|
+
env: Context;
|
|
67
67
|
}>;
|
|
68
68
|
hostCtx?: HostFacts;
|
|
69
69
|
routingKey?: string;
|
|
70
70
|
}): Promise<MultiEnvMergedData>;
|
|
71
|
-
//# sourceMappingURL=job-
|
|
71
|
+
//# sourceMappingURL=job-contexts.d.ts.map
|
|
@@ -15,7 +15,14 @@ import type { RegistrationIndex } from '../registration/registration-index.js';
|
|
|
15
15
|
interface ManualScheduleDeps extends RerunDeps {
|
|
16
16
|
registrationIndex: RegistrationIndex;
|
|
17
17
|
}
|
|
18
|
-
export declare function handleManualSchedule(registrationId: string, triggeredBy: string | null, triggeredByAgentLabel: string | null, deps: ManualScheduleDeps
|
|
18
|
+
export declare function handleManualSchedule(registrationId: string, triggeredBy: string | null, triggeredByAgentLabel: string | null, deps: ManualScheduleDeps,
|
|
19
|
+
/**
|
|
20
|
+
* Platform-minted `requestId`. Stable across an HA relay failover re-send, so
|
|
21
|
+
* it is the idempotency key: after the read-only validation, the first
|
|
22
|
+
* coordinator to claim it creates the run and a failover re-send returns that
|
|
23
|
+
* same run instead of minting a second one.
|
|
24
|
+
*/
|
|
25
|
+
requestId: string): Promise<{
|
|
19
26
|
newRunId: string;
|
|
20
27
|
}>;
|
|
21
28
|
export declare function buildManualJobConfig(workflow: LockWorkflow, mat: MaterializedJob): {
|
|
@@ -46,10 +46,10 @@ import type { GlobalWorkflowPolicy } from '../security/global-workflow-policy.js
|
|
|
46
46
|
import type { EventLogWriter } from '../webhook/event-log.js';
|
|
47
47
|
import { EventLogSource } from '@kici-dev/engine';
|
|
48
48
|
import type { LockJob } from '@kici-dev/engine';
|
|
49
|
-
import type {
|
|
50
|
-
import type { VariableStore } from '../
|
|
49
|
+
import type { ContextStore } from '../contexts/context-store.js';
|
|
50
|
+
import type { VariableStore } from '../contexts/variable-store.js';
|
|
51
51
|
import type { TrustResolver, IdentityLink, PermissionLevel } from '../security/trust-resolver.js';
|
|
52
|
-
import type { HeldRunStore } from '../
|
|
52
|
+
import type { HeldRunStore } from '../contexts/held-runs.js';
|
|
53
53
|
import type { WorkflowDecision } from '@kici-dev/engine';
|
|
54
54
|
/**
|
|
55
55
|
* Pending dispatch context for jobs gated by the needs scheduler.
|
|
@@ -302,9 +302,9 @@ export interface ProcessingDeps {
|
|
|
302
302
|
secretKey?: string;
|
|
303
303
|
/** Log storage backend for persisting webhook payloads. Optional -- if not set, payload storage is skipped. */
|
|
304
304
|
logStorage?: LogStorage;
|
|
305
|
-
/**
|
|
306
|
-
|
|
307
|
-
/** Variable store for resolving
|
|
305
|
+
/** Context store for looking up deployment contexts. Optional -- if not set, context features are inactive. */
|
|
306
|
+
contextStore?: ContextStore;
|
|
307
|
+
/** Variable store for resolving context variables. Optional -- if not set, context vars are not merged. */
|
|
308
308
|
variableStore?: VariableStore;
|
|
309
309
|
/** Held run store for persisting protection rule holds. Optional -- if not set, holds are not persisted. */
|
|
310
310
|
heldRunStore?: HeldRunStore;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Kysely } from 'kysely';
|
|
2
|
+
import type { Database } from '../db/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Atomically claim a run-minting request by its Platform `requestId`. Returns
|
|
5
|
+
* the run id to use. `claimed: false` means a sibling coordinator already owns
|
|
6
|
+
* this requestId (a relay failover re-sent the same request): the caller MUST
|
|
7
|
+
* return `{ newRunId }` WITHOUT creating or dispatching a run, so one user
|
|
8
|
+
* click yields exactly one run.
|
|
9
|
+
*
|
|
10
|
+
* Shared by `run.rerun.request` and `run.manual_schedule.request` — both mint a
|
|
11
|
+
* fresh run and both ride the Platform's timeout-driven failover path. HA
|
|
12
|
+
* coordinator siblings share one orchestrator DB, so the `INSERT … ON CONFLICT
|
|
13
|
+
* (request_id) DO NOTHING` is the single point of arbitration: exactly one hop
|
|
14
|
+
* inserts and wins; the loser reads back the winner's `new_run_id`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function claimRequestId(db: Kysely<Database>, requestId: string): Promise<{
|
|
17
|
+
newRunId: string;
|
|
18
|
+
claimed: boolean;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Prune `request_idempotency` rows older than 1h. The request budget is ~10s,
|
|
22
|
+
* so a claimed requestId is never re-sent after an hour; keeping the table
|
|
23
|
+
* bounded avoids unbounded growth on a long-lived coordinator.
|
|
24
|
+
*
|
|
25
|
+
* @returns the number of rows deleted.
|
|
26
|
+
*/
|
|
27
|
+
export declare function pruneRequestIdempotency(db: Kysely<Database>): Promise<number>;
|
|
28
|
+
//# sourceMappingURL=request-idempotency.d.ts.map
|
package/dist/pipeline/rerun.d.ts
CHANGED
|
@@ -68,6 +68,14 @@ export interface RerunDeps {
|
|
|
68
68
|
coldStore: ColdStore | null;
|
|
69
69
|
}
|
|
70
70
|
export declare function handleRerun(originalRunId: string, triggeredBy: string | null, triggeredByAgentLabel: string | null, deps: RerunDeps,
|
|
71
|
+
/**
|
|
72
|
+
* Platform-minted `requestId` for this rerun. Stable across an HA relay
|
|
73
|
+
* failover re-send (the Platform re-sends the same message verbatim to a
|
|
74
|
+
* sibling coordinator on a timeout), so it is the idempotency key: after the
|
|
75
|
+
* read-only validation, the first coordinator to claim it creates the run and
|
|
76
|
+
* a failover re-send returns that same run instead of minting a second one.
|
|
77
|
+
*/
|
|
78
|
+
requestId: string,
|
|
71
79
|
/**
|
|
72
80
|
* Phase F — routing key for the original run, forwarded by Platform
|
|
73
81
|
* via the WS `run.rerun.request` payload. Required to address the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Kysely } from 'kysely';
|
|
2
2
|
import type { Database } from '../db/types.js';
|
|
3
3
|
import type { ProcessingDeps } from './processor.js';
|
|
4
|
-
import type { ReleaseSignal } from '../
|
|
4
|
+
import type { ReleaseSignal } from '../contexts/held-runs.js';
|
|
5
5
|
import { type WorkflowDispatchContext } from './dispatch-matched-workflow.js';
|
|
6
6
|
import { type SerializableWorkflowDispatchInputs } from './pending-workflow-context.js';
|
|
7
7
|
/**
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Resolves the lock file, matched decisions, and fixture-specific concerns
|
|
5
5
|
* (inline-vs-provider lock, decision selection, fixture-payload storage, the
|
|
6
|
-
* `allow_local_execution`
|
|
6
|
+
* `allow_local_execution` context gate, CLI-secret overlay, in-memory
|
|
7
7
|
* test-run marking), then dispatches each matched workflow through the SAME
|
|
8
8
|
* shared core as webhooks (`dispatchMatchedWorkflow`). The test path is a thin
|
|
9
9
|
* adapter — needs-DAG scheduling, `expansionMap` fan-out edges, `runsOnAll`
|
|
@@ -94,7 +94,7 @@ interface TestTriggerResult {
|
|
|
94
94
|
jobIds: string[];
|
|
95
95
|
/**
|
|
96
96
|
* User-visible warnings on an accepted run — today, one per job whose bound
|
|
97
|
-
* test-run
|
|
97
|
+
* test-run context(s) were unavailable (non-test or unconfigured) and
|
|
98
98
|
* skipped. Printed by the CLI on acceptance.
|
|
99
99
|
*/
|
|
100
100
|
warnings?: string[];
|
|
@@ -20,5 +20,12 @@ export declare function createProvenanceTrustRoot(opts?: {
|
|
|
20
20
|
issuer?: string | null;
|
|
21
21
|
fetchImpl?: typeof fetch;
|
|
22
22
|
ttlMs?: number;
|
|
23
|
+
/**
|
|
24
|
+
* In-process JWKS served directly (no HTTP fetch). Set for the offline local
|
|
25
|
+
* dev plane, whose `kici-local` issuer is not a URL — the plane's own signer
|
|
26
|
+
* is the key source, so a `kici-local` bundle verifies at ingest without a
|
|
27
|
+
* `.well-known/jwks.json` endpoint. When set, discovery/fetch is bypassed.
|
|
28
|
+
*/
|
|
29
|
+
staticJwks?: JSONWebKeySet;
|
|
23
30
|
}): ProvenanceTrustRoot;
|
|
24
31
|
//# sourceMappingURL=trust-root.d.ts.map
|
|
@@ -29,6 +29,14 @@ export interface ProviderBundle {
|
|
|
29
29
|
repoUrlBuilder?: RepoUrlBuilder;
|
|
30
30
|
contributorResolver?: ContributorResolver;
|
|
31
31
|
checkStatusPoster?: CheckStatusPoster;
|
|
32
|
+
/**
|
|
33
|
+
* Local `file://` in-place profile: this bundle's `repoBasePath` is the
|
|
34
|
+
* operator's real working tree, so a dispatched run against it skips the
|
|
35
|
+
* source-pack `__build__` job (the tree is used directly by the agent's
|
|
36
|
+
* `KICI_IN_PLACE` profile). Set only by `createLocalProviderBundle`. Undefined
|
|
37
|
+
* for every non-local (or non-in-place local) bundle.
|
|
38
|
+
*/
|
|
39
|
+
localInPlace?: boolean;
|
|
32
40
|
}
|
|
33
41
|
/**
|
|
34
42
|
* Registry mapping routing keys to their implementation bundles.
|
|
@@ -12,6 +12,7 @@ import { z } from 'zod';
|
|
|
12
12
|
export declare const LocalSourceConfigSchema: z.ZodObject<{
|
|
13
13
|
repoBasePath: z.ZodString;
|
|
14
14
|
cloneUrlBase: z.ZodOptional<z.ZodString>;
|
|
15
|
+
inPlace: z.ZodOptional<z.ZodBoolean>;
|
|
15
16
|
}, z.core.$strict>;
|
|
16
17
|
export type LocalSourceConfig = z.infer<typeof LocalSourceConfigSchema>;
|
|
17
18
|
//# sourceMappingURL=local-source-config.d.ts.map
|
|
@@ -125,8 +125,8 @@ export interface ExecutionTrackerDeps {
|
|
|
125
125
|
* jobs that never started. Persisted in execution_jobs.init_failure.
|
|
126
126
|
*/
|
|
127
127
|
initFailure?: InitFailure,
|
|
128
|
-
/** Ordered bound deployment-
|
|
129
|
-
|
|
128
|
+
/** Ordered bound deployment-context names for this job (multi-env jobs). */
|
|
129
|
+
contexts?: string[]) => void;
|
|
130
130
|
/**
|
|
131
131
|
* Optional callback to emit run.event messages to Platform.
|
|
132
132
|
* Fires at orchestrator lifecycle points (dispatch, agent assignment, job start/complete).
|
|
@@ -222,8 +222,8 @@ export declare class ExecutionTracker {
|
|
|
222
222
|
waveGated?: boolean;
|
|
223
223
|
waveMaxParallel?: number;
|
|
224
224
|
waveFailFast?: boolean;
|
|
225
|
-
|
|
226
|
-
|
|
225
|
+
contexts?: string[];
|
|
226
|
+
skippedContexts?: string[];
|
|
227
227
|
envWarning?: string;
|
|
228
228
|
}>, routingKey?: string,
|
|
229
229
|
/** Secret context names dispatched with jobs (for context-disable job lookup). */
|
|
@@ -311,8 +311,8 @@ export declare class ExecutionTracker {
|
|
|
311
311
|
baseJobName?: string;
|
|
312
312
|
variantKind?: string;
|
|
313
313
|
variantLabel?: string;
|
|
314
|
-
|
|
315
|
-
|
|
314
|
+
contexts?: string[];
|
|
315
|
+
skippedContexts?: string[];
|
|
316
316
|
envWarning?: string;
|
|
317
317
|
}>, dispatchedContexts?: string[],
|
|
318
318
|
/** Synthetic job ID to replace (e.g. needs-pending-deploy-{uuid}). */
|
|
@@ -481,7 +481,7 @@ export declare class ExecutionTracker {
|
|
|
481
481
|
deliveryId: string | null;
|
|
482
482
|
providerContext: Record<string, unknown>;
|
|
483
483
|
routingKey: string;
|
|
484
|
-
|
|
484
|
+
contextName?: string;
|
|
485
485
|
reason: string;
|
|
486
486
|
triggerEvent?: string;
|
|
487
487
|
commitMessage?: string;
|
|
@@ -533,6 +533,16 @@ export declare class ExecutionTracker {
|
|
|
533
533
|
* Used by LogWriter to construct log paths.
|
|
534
534
|
*/
|
|
535
535
|
getJobName(runId: string, jobId: string): string | undefined;
|
|
536
|
+
/**
|
|
537
|
+
* Find the runId of the in-memory run that owns a given dispatched jobId.
|
|
538
|
+
*
|
|
539
|
+
* The agent's `event.emit` message is job-scoped (it carries only the
|
|
540
|
+
* emitting jobId), but run context is keyed by runId. This maps job → run so
|
|
541
|
+
* `getExecutionContext(runId)` resolves for an agent-emitted custom event.
|
|
542
|
+
* In-memory only (matches `getExecutionContext`'s semantics); emit happens
|
|
543
|
+
* mid-execution, so the owning run is always live in `this.runs`.
|
|
544
|
+
*/
|
|
545
|
+
getRunIdForJob(jobId: string): string | undefined;
|
|
536
546
|
/**
|
|
537
547
|
* Get execution context for a run from in-memory state.
|
|
538
548
|
* Used by commit status reporting to access provider/repo/sha info.
|
|
@@ -64,8 +64,8 @@ export interface RunDetailJobRow {
|
|
|
64
64
|
agent_id: string | null;
|
|
65
65
|
error_message: string | null;
|
|
66
66
|
runs_on_labels: unknown;
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
contexts: unknown;
|
|
68
|
+
skipped_contexts: unknown;
|
|
69
69
|
env_warning: string | null;
|
|
70
70
|
outputs: unknown;
|
|
71
71
|
init_failure: unknown;
|
|
@@ -103,7 +103,7 @@ export declare function buildRunDetailJobs(jobs: RunDetailJobRow[], lookups: Run
|
|
|
103
103
|
}[];
|
|
104
104
|
initFailure?: {
|
|
105
105
|
scope: "job" | "run";
|
|
106
|
-
category: "secret_resolution" | "install_secrets" | "lock_resolution" | "build_coordination" | "
|
|
106
|
+
category: "secret_resolution" | "install_secrets" | "lock_resolution" | "build_coordination" | "context_rules" | "dynamic_eval" | "no_agent" | "matrix_expansion";
|
|
107
107
|
message: string;
|
|
108
108
|
jobName?: string | undefined;
|
|
109
109
|
} | undefined;
|
|
@@ -121,8 +121,8 @@ export declare function buildRunDetailJobs(jobs: RunDetailJobRow[], lookups: Run
|
|
|
121
121
|
orchestratorId: null;
|
|
122
122
|
errorMessage: string | null;
|
|
123
123
|
runsOnLabels: string[] | null;
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
contexts: string[] | null;
|
|
125
|
+
skippedContexts: string[] | null;
|
|
126
126
|
envWarning: string | null;
|
|
127
127
|
outputs: any;
|
|
128
128
|
secretOutputKeys: string[] | null;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin API routes for context management.
|
|
3
|
+
*
|
|
4
|
+
* POST /api/v1/admin/contexts — create (upsert)
|
|
5
|
+
* POST /api/v1/admin/contexts/:name/bind — bind a scope pattern
|
|
6
|
+
* PATCH /api/v1/admin/contexts/:name/policy — update policy fields
|
|
7
|
+
* GET /api/v1/admin/contexts?orgId=<id> — list contexts
|
|
8
|
+
* GET /api/v1/admin/contexts/:name?orgId=<id> — show env + vars + bindings
|
|
9
|
+
* DELETE /api/v1/admin/contexts/:name?orgId=<id> — delete env (cascades bindings/variables/overrides; pending held runs block with 409)
|
|
10
|
+
* POST /api/v1/admin/contexts/templates — create/update a template
|
|
11
|
+
* GET /api/v1/admin/contexts/:name/variables?orgId=<id> — list org-level variables
|
|
12
|
+
* PUT /api/v1/admin/contexts/:name/variables/:key?orgId=<id> — upsert variable
|
|
13
|
+
* DELETE /api/v1/admin/contexts/:name/variables/:key?orgId=<id> — delete variable
|
|
14
|
+
*
|
|
15
|
+
* Backs the `kici-admin context` dual-mode CLI. Offline (direct-DB) mode
|
|
16
|
+
* bypasses this router entirely — the CLI calls `*Direct` helpers from
|
|
17
|
+
* @kici-dev/shared. This HTTP surface exists so tooling with only an admin
|
|
18
|
+
* token (no DB reach) can do the same operations.
|
|
19
|
+
*
|
|
20
|
+
* All routes are protected by the admin auth middleware mounted in admin.ts
|
|
21
|
+
* (at `/api/v1/admin/*`). That middleware sets `role` + `userId` on the
|
|
22
|
+
* context, which we use for RBAC gating here.
|
|
23
|
+
*/
|
|
24
|
+
import { Hono } from 'hono';
|
|
25
|
+
import { type Kysely } from 'kysely';
|
|
26
|
+
import type { RbacEnforcer, Role } from '../secrets/rbac.js';
|
|
27
|
+
export interface AdminContextRoutesDeps {
|
|
28
|
+
db: Kysely<any>;
|
|
29
|
+
rbac: RbacEnforcer;
|
|
30
|
+
}
|
|
31
|
+
/** Hono env type for admin-contexts routes with context variables. */
|
|
32
|
+
type AdminEnvEnv = {
|
|
33
|
+
Variables: {
|
|
34
|
+
role: Role;
|
|
35
|
+
userId: string;
|
|
36
|
+
routingKey: string | null;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Create admin API routes for context management.
|
|
41
|
+
*
|
|
42
|
+
* @param deps - db (Kysely) + rbac enforcer
|
|
43
|
+
* @returns Hono app mounted at /api/v1/admin
|
|
44
|
+
*/
|
|
45
|
+
export declare function createAdminContextRoutes(deps: AdminContextRoutesDeps): Hono<AdminEnvEnv>;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=admin-contexts.d.ts.map
|
|
@@ -10,7 +10,7 @@ import type { RegistrationStore } from '../registration/registration-store.js';
|
|
|
10
10
|
import type { RegistrationIndex } from '../registration/registration-index.js';
|
|
11
11
|
import type { TokenManager } from '../secrets/token-manager.js';
|
|
12
12
|
import type { RbacEnforcer, Role } from '../secrets/rbac.js';
|
|
13
|
-
import type {
|
|
13
|
+
import type { ContextStore } from '../contexts/context-store.js';
|
|
14
14
|
/**
|
|
15
15
|
* Dependencies for admin registration routes.
|
|
16
16
|
*/
|
|
@@ -25,7 +25,7 @@ export interface AdminRegistrationRoutesDeps {
|
|
|
25
25
|
* provably-unsatisfiable environment list (missing/disabled env, or
|
|
26
26
|
* mutually-exclusive fixed branch/trigger/repo restrictions).
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
contextStore?: Pick<ContextStore, 'matchContext'>;
|
|
29
29
|
}
|
|
30
30
|
/** Hono env type for admin registration routes with context variables. */
|
|
31
31
|
type AdminRegEnv = {
|
|
@@ -14,8 +14,8 @@ export interface GithubWebhookRoutesDeps {
|
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* Whether the orchestrator serves the direct GitHub ingress route for a given
|
|
17
|
-
* operating mode. Hybrid
|
|
18
|
-
* is relay-only (no local GitHub source to serve).
|
|
17
|
+
* operating mode. Hybrid and independent modes serve a local GitHub source
|
|
18
|
+
* config; platform mode is relay-only (no local GitHub source to serve).
|
|
19
19
|
*/
|
|
20
20
|
export declare function shouldServeGithubIngress(mode: 'platform' | 'hybrid' | 'independent'): boolean;
|
|
21
21
|
/**
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared factory for the dispatch-time `SecretResolver` bound to the orchestrator's
|
|
3
|
+
* DB-backed context/binding/secret stores.
|
|
4
|
+
*
|
|
5
|
+
* Both boot paths use it: `server.ts` (platform/hybrid) always builds it, and
|
|
6
|
+
* `standalone.ts` (independent) builds it only when dispatch-time context-scoped
|
|
7
|
+
* secret resolution is explicitly opted in (the local dev plane). Keeping the
|
|
8
|
+
* ~one construction in one place stops the two call sites from drifting.
|
|
9
|
+
*/
|
|
10
|
+
import type { Kysely } from 'kysely';
|
|
11
|
+
import type { SecretStore } from '@kici-dev/engine';
|
|
12
|
+
import type { Logger } from '@kici-dev/shared';
|
|
13
|
+
import type { Database } from '../db/types.js';
|
|
14
|
+
import type { AuditLogger } from './audit-logger.js';
|
|
15
|
+
import type { PgSecretStore } from './pg-secret-store.js';
|
|
16
|
+
import { SecretResolver } from './secret-resolver.js';
|
|
17
|
+
export interface ContextSecretResolverDeps {
|
|
18
|
+
pgSecretStore: PgSecretStore;
|
|
19
|
+
backendStores: Map<string, SecretStore>;
|
|
20
|
+
db: Kysely<Database>;
|
|
21
|
+
auditLogger: AuditLogger;
|
|
22
|
+
logger: Logger;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Build a `SecretResolver` over the org's contexts, bindings, and registered
|
|
26
|
+
* secret backends. The `pg` backend decrypts through the master key; external
|
|
27
|
+
* backends (Vault) return plaintext, so their decrypt is identity.
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildContextSecretResolver(deps: ContextSecretResolverDeps): SecretResolver;
|
|
30
|
+
//# sourceMappingURL=context-secret-resolver.d.ts.map
|
package/dist/secrets/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export { AuditLogger } from './audit-logger.js';
|
|
|
9
9
|
export { loadMasterKey, loadOldMasterKey, loadSecretStoreConfig, type SecretStoreConfig, } from './config.js';
|
|
10
10
|
export { encrypt, decrypt, deriveKey, generateMasterKey, type EncryptedValue, } from '@kici-dev/shared';
|
|
11
11
|
export { VaultSecretStore, type VaultConfig } from './vault-secret-store.js';
|
|
12
|
-
export { SecretResolver, type SecretResolverDeps, type ResolvedSecretMeta, type
|
|
12
|
+
export { SecretResolver, type SecretResolverDeps, type ResolvedSecretMeta, type ContextStoreLike, type BindingStoreLike, type SecretStoreLike, } from './secret-resolver.js';
|
|
13
13
|
export { BackendSyncManager } from './backend-sync.js';
|
|
14
14
|
export { RbacEnforcer, PermissionDeniedError, type Role, type Permission } from './rbac.js';
|
|
15
15
|
export { TokenManager } from './token-manager.js';
|
|
@@ -12,7 +12,7 @@ import type { SecretStore } from '@kici-dev/engine';
|
|
|
12
12
|
import type { AuditLogger } from './audit-logger.js';
|
|
13
13
|
/**
|
|
14
14
|
* Thrown by `renameScope` when the named scope has no secret rows and no
|
|
15
|
-
*
|
|
15
|
+
* context binding — i.e. there is nothing to rename. Consumers map this to
|
|
16
16
|
* a 404 (admin HTTP route) or a structured not-found response (dashboard path).
|
|
17
17
|
*/
|
|
18
18
|
export declare class SecretScopeNotFoundError extends Error {
|
|
@@ -93,11 +93,11 @@ export declare class PgSecretStore implements SecretStore {
|
|
|
93
93
|
*/
|
|
94
94
|
createScope(orgId: string, scope: string): Promise<void>;
|
|
95
95
|
/**
|
|
96
|
-
* Rename a scope -- atomically update scoped_secrets and
|
|
96
|
+
* Rename a scope -- atomically update scoped_secrets and context_bindings.
|
|
97
97
|
*/
|
|
98
98
|
renameScope(orgId: string, oldScope: string, newScope: string): Promise<void>;
|
|
99
99
|
/**
|
|
100
|
-
* Delete a scope and all its secrets, plus any
|
|
100
|
+
* Delete a scope and all its secrets, plus any context bindings referencing it.
|
|
101
101
|
*/
|
|
102
102
|
deleteScope(orgId: string, scope: string): Promise<void>;
|
|
103
103
|
/**
|