@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.
Files changed (83) hide show
  1. package/dist/app.d.ts +13 -4
  2. package/dist/approvals/apply-decision.d.ts +1 -1
  3. package/dist/approvals/step-approval-bridge.d.ts +1 -1
  4. package/dist/cache/pending-inits.d.ts +4 -4
  5. package/dist/cli/api-client.d.ts +29 -4
  6. package/dist/cli/commands/context.d.ts +25 -0
  7. package/dist/cli/commands/debug-bundle.d.ts +1 -1
  8. package/dist/cli/commands/variable.d.ts +6 -6
  9. package/dist/cli/service/windows.d.ts +6 -0
  10. package/dist/cli.js +526 -340
  11. package/dist/config.d.ts +16 -0
  12. package/dist/contexts/binding-store.d.ts +36 -0
  13. package/dist/contexts/context-store.d.ts +87 -0
  14. package/dist/{environments → contexts}/held-runs.d.ts +15 -15
  15. package/dist/{environments → contexts}/index.d.ts +1 -1
  16. package/dist/contexts/protection/aggregate.d.ts +43 -0
  17. package/dist/contexts/protection/branch-gate.d.ts +5 -0
  18. package/dist/contexts/protection/concurrency-gate.d.ts +7 -0
  19. package/dist/{environments → contexts}/protection/pipeline.d.ts +3 -3
  20. package/dist/contexts/protection/reviewer-gate.d.ts +7 -0
  21. package/dist/{environments → contexts}/protection/satisfiability.d.ts +21 -21
  22. package/dist/contexts/protection/trust-gate.d.ts +7 -0
  23. package/dist/contexts/protection/wait-timer-gate.d.ts +7 -0
  24. package/dist/contexts/variable-store.d.ts +39 -0
  25. package/dist/dashboard/attestation-filters.d.ts +10 -8
  26. package/dist/dashboard/handler.d.ts +28 -2
  27. package/dist/db/migrations/067_environments_to_contexts.d.ts +36 -0
  28. package/dist/db/migrations/068_request_idempotency.d.ts +17 -0
  29. package/dist/db/types.d.ts +78 -59
  30. package/dist/github-app-name-refresher/github-app-name-refresher.d.ts +1 -1
  31. package/dist/index.js +21 -6
  32. package/dist/metrics/prometheus.d.ts +2 -0
  33. package/dist/oidc/id-token-claims.d.ts +63 -0
  34. package/dist/oidc/jwt.d.ts +15 -0
  35. package/dist/oidc/local-dev-signer.d.ts +31 -0
  36. package/dist/oidc/local-mint.d.ts +77 -0
  37. package/dist/oidc/oidc-mint-registration.d.ts +49 -0
  38. package/dist/pipeline/decorating-secret-resolver.d.ts +4 -4
  39. package/dist/pipeline/dispatch-matched-workflow.d.ts +3 -3
  40. package/dist/pipeline/inline-eval.d.ts +2 -2
  41. package/dist/pipeline/install-secrets-resolver.d.ts +13 -13
  42. package/dist/pipeline/{job-environments.d.ts → job-contexts.d.ts} +23 -23
  43. package/dist/pipeline/manual-schedule.d.ts +8 -1
  44. package/dist/pipeline/processor.d.ts +6 -6
  45. package/dist/pipeline/request-idempotency.d.ts +28 -0
  46. package/dist/pipeline/rerun.d.ts +8 -0
  47. package/dist/pipeline/resume-workflow.d.ts +1 -1
  48. package/dist/pipeline/test-pipeline.d.ts +2 -2
  49. package/dist/provenance/trust-root.d.ts +7 -0
  50. package/dist/provider-registry.d.ts +8 -0
  51. package/dist/providers/local/index.d.ts +1 -0
  52. package/dist/providers/local/local-source-config.d.ts +1 -0
  53. package/dist/reporting/execution-tracker.d.ts +17 -7
  54. package/dist/reporting/run-aggregator.d.ts +5 -5
  55. package/dist/routes/admin-contexts.d.ts +47 -0
  56. package/dist/routes/admin-registrations.d.ts +2 -2
  57. package/dist/routes/github-webhook.d.ts +2 -2
  58. package/dist/secrets/context-secret-resolver.d.ts +30 -0
  59. package/dist/secrets/index.d.ts +1 -1
  60. package/dist/secrets/pg-secret-store.d.ts +3 -3
  61. package/dist/secrets/rbac.d.ts +1 -1
  62. package/dist/secrets/secret-resolver.d.ts +19 -19
  63. package/dist/security/comment-handler.d.ts +1 -1
  64. package/dist/server.js +1770 -1196
  65. package/dist/stale-detector/stale-run-detector.d.ts +1 -1
  66. package/dist/standalone.js +1649 -747
  67. package/dist/storage/blob-routes.d.ts +16 -0
  68. package/dist/ws/{dashboard-env-handler.d.ts → dashboard-context-handler.d.ts} +15 -15
  69. package/dist/ws/oidc-token-relay.d.ts +6 -0
  70. package/installer-image-digests.json +3 -3
  71. package/package.json +4 -4
  72. package/sbom.spdx.json +50 -50
  73. package/dist/cli/commands/environment.d.ts +0 -25
  74. package/dist/environments/binding-store.d.ts +0 -36
  75. package/dist/environments/environment-store.d.ts +0 -87
  76. package/dist/environments/protection/aggregate.d.ts +0 -43
  77. package/dist/environments/protection/branch-gate.d.ts +0 -5
  78. package/dist/environments/protection/concurrency-gate.d.ts +0 -7
  79. package/dist/environments/protection/reviewer-gate.d.ts +0 -7
  80. package/dist/environments/protection/trust-gate.d.ts +0 -7
  81. package/dist/environments/protection/wait-timer-gate.d.ts +0 -7
  82. package/dist/environments/variable-store.d.ts +0 -39
  83. 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 environment `SecretResolver` and overlays the
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 environment
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, environmentName: string): Promise<Record<string, 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, environmentName: string): Promise<Record<string, ResolvedSecretMeta>>;
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 environment evaluation, static job dispatch (cluster +
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 `environment:`. Merged UNDER the per-job env-resolved secrets so
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 environment(s) were unavailable and skipped. Surfaced
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 `environments` element, aligned by index; undefined for static or impure-dynamic elements. */
40
- inlineEnvironmentNames: Array<string | undefined>;
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
- * `<environment>:<secret-name>` syntax. The resolver:
7
+ * `<context>:<secret-name>` syntax. The resolver:
8
8
  *
9
- * 1. Parses every qualified ref and groups by environment name.
10
- * 2. Fires the per-environment protection-rule pipeline once per unique env
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 environment via `secretResolver.resolveForJob`
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 environment
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 { EnvironmentStore } from '../environments/environment-store.js';
36
- import { type JobDispatchContext } from '../environments/protection/pipeline.js';
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
- environmentStore: EnvironmentStore | undefined;
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 environment whose install gate held. */
78
+ /** The context whose install gate held. */
79
79
  envName: string;
80
- /** Resolved environment id (for the held row). */
81
- environmentId: string;
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: 'environment' | 'security';
84
+ queueType: 'context' | 'security';
85
85
  requirement: InstallHoldRequirement;
86
86
  };
87
- /** Parse `<environment>:<secret-name>`. Returns null on malformed input. */
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-environment resolution helpers for the dispatch path.
2
+ * Multi-context resolution helpers for the dispatch path.
3
3
  *
4
- * A job binds an ordered list of environments (`LockJob.environments`). This
5
- * module resolves that list into concrete environment names (static values
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-environment secrets/variables last-wins. It keeps the heavy fold logic
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 Environment, type HostFacts, type LockJob } from '@kici-dev/engine';
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 '../environments/variable-store.js';
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 environment names plus whether any element still needs agent init. */
20
- export interface ResolvedJobEnvironments {
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-environment names from a lock job. Static elements
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 resolveJobEnvironmentNames(lockJob: LockJob, inlineNames: ReadonlyArray<string | undefined>): ResolvedJobEnvironments;
32
+ export declare function resolveJobContextNames(lockJob: LockJob, inlineNames: ReadonlyArray<string | undefined>): ResolvedJobContexts;
33
33
  /**
34
- * Build the ordered bound-environment display list for persistence at dispatch.
35
- * Unlike {@link resolveJobEnvironmentNames}, this never drops an unresolved
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 environment.
40
+ * slot in order. Returns an empty array when the job binds no context.
41
41
  */
42
- export declare function buildJobEnvironmentDisplayNames(lockJob: LockJob, inlineNames: ReadonlyArray<string | undefined>): string[];
43
- /** Merged secrets/variables across an ordered list of resolved environments. */
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
- environmentVars?: Record<string, string>;
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
- * environments, last-wins. Each environment is resolved with the existing
52
- * single-env logic (longest-scope-path-wins preserved within each environment),
53
- * then folded in array order so a later environment overrides an earlier key.
54
- * Secrets are also returned namespaced per environment so qualified
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
- * `Environment` for each name (in order); variables resolve by environment id.
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: Environment;
66
+ env: Context;
67
67
  }>;
68
68
  hostCtx?: HostFacts;
69
69
  routingKey?: string;
70
70
  }): Promise<MultiEnvMergedData>;
71
- //# sourceMappingURL=job-environments.d.ts.map
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): Promise<{
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 { EnvironmentStore } from '../environments/environment-store.js';
50
- import type { VariableStore } from '../environments/variable-store.js';
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 '../environments/held-runs.js';
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
- /** Environment store for looking up deployment environments. Optional -- if not set, environment features are inactive. */
306
- environmentStore?: EnvironmentStore;
307
- /** Variable store for resolving environment variables. Optional -- if not set, environment vars are not merged. */
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
@@ -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 '../environments/held-runs.js';
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` environment gate, CLI-secret overlay, in-memory
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 environment(s) were unavailable (non-test or unconfigured) and
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.
@@ -29,5 +29,6 @@ export { LocalRepoUrlBuilder } from './repo-url-builder.js';
29
29
  export declare function createLocalProviderBundle(opts: {
30
30
  repoBasePath: string;
31
31
  cloneUrlBase?: string;
32
+ inPlace?: boolean;
32
33
  }): ProviderBundle;
33
34
  //# sourceMappingURL=index.d.ts.map
@@ -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-environment names for this job (multi-env jobs). */
129
- environments?: string[]) => void;
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
- environments?: string[];
226
- skippedEnvironments?: string[];
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
- environments?: string[];
315
- skippedEnvironments?: string[];
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
- environmentName?: string;
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
- environments: unknown;
68
- skipped_environments: unknown;
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" | "environment_rules" | "dynamic_eval" | "no_agent" | "matrix_expansion";
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
- environments: string[] | null;
125
- skippedEnvironments: string[] | null;
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 { EnvironmentStore } from '../environments/environment-store.js';
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
- environmentStore?: Pick<EnvironmentStore, 'matchEnvironment'>;
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 + independent run local source config; platform mode
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
@@ -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 EnvironmentStoreLike, type BindingStoreLike, type SecretStoreLike, } from './secret-resolver.js';
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
- * environment binding — i.e. there is nothing to rename. Consumers map this to
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 environment_bindings.
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 environment bindings referencing it.
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
  /**