@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
@@ -0,0 +1,36 @@
1
+ import { type Kysely } from 'kysely';
2
+ /**
3
+ * Rename the named-policy object from "environment" to "context" across the
4
+ * orchestrator schema. Data-preserving rename-in-place (never drop/recreate):
5
+ *
6
+ * Tables:
7
+ * - `environments` → `contexts`
8
+ * - `environment_bindings` → `context_bindings`
9
+ * - `environment_variables` → `context_variables`
10
+ * - `environment_source_overrides` → `context_source_overrides`
11
+ *
12
+ * Columns:
13
+ * - `context_bindings.environment_id` → `context_id`
14
+ * - `context_variables.environment_id` → `context_id`
15
+ * - `context_source_overrides.environment_id` → `context_id`
16
+ * - `held_runs.environment_id` → `context_id`
17
+ * - `execution_runs.environment` → `context`
18
+ * - `execution_runs.environment_id` → `context_id`
19
+ * - `execution_jobs.environments` → `contexts`
20
+ * - `execution_jobs.skipped_environments` → `skipped_contexts`
21
+ *
22
+ * Index:
23
+ * - `idx_execution_runs_environment_id` → `idx_execution_runs_context_id`
24
+ *
25
+ * Held-run enum values + defaults: `held_runs.queue_type` /
26
+ * `held_runs.trigger_source` default `'environment'` → `'context'` and existing
27
+ * `'environment'` rows are migrated to `'context'` (the `HeldRunQueueType` value
28
+ * rename).
29
+ *
30
+ * Foreign keys and remaining constraints/indexes follow the renamed tables and
31
+ * columns automatically (Postgres references them by identity, not name), so
32
+ * only the one hand-named index above needs an explicit rename.
33
+ */
34
+ export declare function up(db: Kysely<unknown>): Promise<void>;
35
+ export declare function down(db: Kysely<unknown>): Promise<void>;
36
+ //# sourceMappingURL=067_environments_to_contexts.d.ts.map
@@ -0,0 +1,17 @@
1
+ import { type Kysely } from 'kysely';
2
+ /**
3
+ * Add the `request_idempotency` claim table: a `request_id`-keyed record that
4
+ * makes run-minting dashboard requests (`run.rerun.request`,
5
+ * `run.manual_schedule.request`) idempotent on the Platform `requestId`. HA
6
+ * coordinator siblings share one orchestrator DB, so when the Platform relay
7
+ * fails over and re-sends the same request to a sibling, the atomic `INSERT …
8
+ * ON CONFLICT DO NOTHING` on `request_id` lets exactly one coordinator win —
9
+ * the loser returns the winner's `new_run_id` instead of minting a second run.
10
+ * Rows are pruned after 1h (far past the ~10s request budget) by the periodic
11
+ * cleanup tick.
12
+ *
13
+ * Idempotent: guarded on table existence.
14
+ */
15
+ export declare function up(db: Kysely<unknown>): Promise<void>;
16
+ export declare function down(db: Kysely<unknown>): Promise<void>;
17
+ //# sourceMappingURL=068_request_idempotency.d.ts.map
@@ -13,11 +13,11 @@ export interface Database {
13
13
  execution_steps: ExecutionStepTable;
14
14
  raft_state: RaftStateTable;
15
15
  secret_audit_log: SecretAuditLogTable;
16
- environments: EnvironmentsTable;
16
+ contexts: ContextsTable;
17
17
  scoped_secrets: ScopedSecretsTable;
18
- environment_bindings: EnvironmentBindingsTable;
19
- environment_variables: EnvironmentVariablesTable;
20
- environment_source_overrides: EnvironmentSourceOverridesTable;
18
+ context_bindings: ContextBindingsTable;
19
+ context_variables: ContextVariablesTable;
20
+ context_source_overrides: ContextSourceOverridesTable;
21
21
  held_runs: HeldRunsTable;
22
22
  held_run_approvals: HeldRunApprovalsTable;
23
23
  admin_tokens: AdminTokenTable;
@@ -52,7 +52,26 @@ export interface Database {
52
52
  pending_attestations: PendingAttestationsTable;
53
53
  remote_sources: RemoteSourcesTable;
54
54
  host_roster: HostRosterTable;
55
+ request_idempotency: RequestIdempotencyTable;
55
56
  }
57
+ /**
58
+ * Request idempotency claim table.
59
+ * Keyed on the Platform `requestId`; makes run-minting dashboard requests
60
+ * (`run.rerun.request`, `run.manual_schedule.request`) idempotent across an HA
61
+ * relay failover so a re-sent request returns the first coordinator's
62
+ * `new_run_id` instead of creating a second run. Pruned after 1h.
63
+ */
64
+ export interface RequestIdempotencyTable {
65
+ /** Platform-minted requestId for the run-minting request (primary key / idempotency key). */
66
+ request_id: string;
67
+ /** The run id the winning coordinator created for this requestId. */
68
+ new_run_id: string;
69
+ /** When the claim was recorded. */
70
+ created_at: Generated<Date>;
71
+ }
72
+ export type RequestIdempotency = Selectable<RequestIdempotencyTable>;
73
+ export type NewRequestIdempotency = Insertable<RequestIdempotencyTable>;
74
+ export type RequestIdempotencyUpdate = Updateable<RequestIdempotencyTable>;
56
75
  /**
57
76
  * Cluster metadata table
58
77
  * Key-value store for cluster-wide configuration (e.g. cluster_id).
@@ -288,10 +307,10 @@ export interface ExecutionRunTable {
288
307
  cancelled_by: string | null;
289
308
  /** Agent provenance label when the run was cancelled through an agent credential (null otherwise). */
290
309
  cancelled_by_agent_label: string | null;
291
- /** Environment name for this run (null if no environment applies) */
292
- environment: string | null;
293
- /** Matched environment id for this run (null if no/unresolved environment). */
294
- environment_id: string | null;
310
+ /** Context name for this run (null if no context applies) */
311
+ context: string | null;
312
+ /** Matched context id for this run (null if no/unresolved context). */
313
+ context_id: string | null;
295
314
  /** Trust tier of the contributor for PR runs (null for non-PR events) */
296
315
  trust_tier: string | null;
297
316
  /** Lock file source: 'head' or 'base' (null for non-PR events) */
@@ -397,17 +416,17 @@ export interface ExecutionJobTable {
397
416
  /** Aggregated step outputs JSONB (step-keyed map of outputs). Populated on job success. */
398
417
  outputs: string | null;
399
418
  /**
400
- * Ordered bound deployment-environment names for this job, JSON-encoded
419
+ * Ordered bound deployment-context names for this job, JSON-encoded
401
420
  * `string[]` (null when the job binds none). Written at dispatch and
402
- * overwritten with the agent-resolved list for dynamic environments.
421
+ * overwritten with the agent-resolved list for dynamic contexts.
403
422
  */
404
- environments: string | null;
423
+ contexts: string | null;
405
424
  /**
406
- * Bound environments skipped on a test/local run (non-test or unconfigured),
425
+ * Bound contexts skipped on a test/local run (non-test or unconfigured),
407
426
  * JSON-encoded `string[]`. NULL = nothing skipped.
408
427
  */
409
- skipped_environments: string | null;
410
- /** User-visible warning naming the skipped test-run environments. NULL = none. */
428
+ skipped_contexts: string | null;
429
+ /** User-visible warning naming the skipped test-run contexts. NULL = none. */
411
430
  env_warning: string | null;
412
431
  /** Whether all upstream needs edges are satisfied (dispatch gate). */
413
432
  needs_satisfied: Generated<boolean>;
@@ -561,20 +580,20 @@ export interface RaftStateTable {
561
580
  export type RaftState = Selectable<RaftStateTable>;
562
581
  export type RaftStateUpdate = Updateable<RaftStateTable>;
563
582
  /**
564
- * Environments table
565
- * Named deployment environments with concurrency, branch restrictions, and approval rules.
583
+ * Contexts table
584
+ * Named deployment contexts with concurrency, branch restrictions, and approval rules.
566
585
  * Scoped to an organization.
567
586
  */
568
- export interface EnvironmentsTable {
587
+ export interface ContextsTable {
569
588
  /** UUID primary key */
570
589
  id: Generated<string>;
571
590
  /** Organization ID */
572
591
  org_id: string;
573
- /** Environment name (unique within org) */
592
+ /** Context name (unique within org) */
574
593
  name: string;
575
- /** Environment type: 'fixed' | 'dynamic' */
594
+ /** Context type: 'fixed' | 'dynamic' */
576
595
  type: Generated<string>;
577
- /** Glob pattern for dynamic environments (null for fixed) */
596
+ /** Glob pattern for dynamic contexts (null for fixed) */
578
597
  glob_pattern: string | null;
579
598
  /** JSONB array of branch restriction patterns */
580
599
  branch_restrictions: Generated<string>;
@@ -596,30 +615,30 @@ export interface EnvironmentsTable {
596
615
  hold_expiry_seconds: Generated<number>;
597
616
  /** Minimum trust tier required for CI execution (null = no trust requirement) */
598
617
  minimum_trust: string | null;
599
- /** Whether this environment allows local (no-remote) executions. Default false. */
618
+ /** Whether this context allows local (no-remote) executions. Default false. */
600
619
  allow_local_execution: Generated<boolean>;
601
- /** Whether this environment is active */
620
+ /** Whether this context is active */
602
621
  enabled: Generated<boolean>;
603
- /** When this environment was created */
622
+ /** When this context was created */
604
623
  created_at: Generated<Date>;
605
- /** When this environment was last updated */
624
+ /** When this context was last updated */
606
625
  updated_at: Generated<Date>;
607
- /** Who created this environment */
626
+ /** Who created this context */
608
627
  created_by: string | null;
609
628
  }
610
- export type Environment = Selectable<EnvironmentsTable>;
611
- export type NewEnvironment = Insertable<EnvironmentsTable>;
612
- export type EnvironmentUpdate = Updateable<EnvironmentsTable>;
629
+ export type Context = Selectable<ContextsTable>;
630
+ export type NewContext = Insertable<ContextsTable>;
631
+ export type ContextUpdate = Updateable<ContextsTable>;
613
632
  /**
614
633
  * Scoped secrets table
615
- * Encrypted key-value pairs scoped to org + scope (e.g. environment name, repo pattern).
634
+ * Encrypted key-value pairs scoped to org + scope (e.g. context name, repo pattern).
616
635
  */
617
636
  export interface ScopedSecretsTable {
618
637
  /** UUID primary key */
619
638
  id: Generated<string>;
620
639
  /** Organization ID */
621
640
  org_id: string;
622
- /** Scope identifier (e.g. environment name, repo pattern) */
641
+ /** Scope identifier (e.g. context name, repo pattern) */
623
642
  scope: string;
624
643
  /** Secret key name */
625
644
  key: string;
@@ -638,16 +657,16 @@ export type ScopedSecret = Selectable<ScopedSecretsTable>;
638
657
  export type NewScopedSecret = Insertable<ScopedSecretsTable>;
639
658
  export type ScopedSecretUpdate = Updateable<ScopedSecretsTable>;
640
659
  /**
641
- * Environment bindings table
642
- * Links environments to scope patterns (e.g. workflow names, repo identifiers).
660
+ * Context bindings table
661
+ * Links contexts to scope patterns (e.g. workflow names, repo identifiers).
643
662
  */
644
- export interface EnvironmentBindingsTable {
663
+ export interface ContextBindingsTable {
645
664
  /** UUID primary key */
646
665
  id: Generated<string>;
647
666
  /** Organization ID */
648
667
  org_id: string;
649
- /** Environment ID (FK to environments.id, cascade delete) */
650
- environment_id: string;
668
+ /** Context ID (FK to contexts.id, cascade delete) */
669
+ context_id: string;
651
670
  /** Scope pattern for matching (e.g. workflow name glob, repo pattern) */
652
671
  scope_pattern: string;
653
672
  /**
@@ -659,19 +678,19 @@ export interface EnvironmentBindingsTable {
659
678
  /** When this binding was created */
660
679
  created_at: Generated<Date>;
661
680
  }
662
- export type EnvironmentBinding = Selectable<EnvironmentBindingsTable>;
663
- export type NewEnvironmentBinding = Insertable<EnvironmentBindingsTable>;
681
+ export type ContextBinding = Selectable<ContextBindingsTable>;
682
+ export type NewContextBinding = Insertable<ContextBindingsTable>;
664
683
  /**
665
- * Environment variables table
666
- * Non-secret key-value pairs attached to an environment.
684
+ * Context variables table
685
+ * Non-secret key-value pairs attached to a context.
667
686
  */
668
- export interface EnvironmentVariablesTable {
687
+ export interface ContextVariablesTable {
669
688
  /** UUID primary key */
670
689
  id: Generated<string>;
671
690
  /** Organization ID */
672
691
  org_id: string;
673
- /** Environment ID (FK to environments.id, cascade delete) */
674
- environment_id: string;
692
+ /** Context ID (FK to contexts.id, cascade delete) */
693
+ context_id: string;
675
694
  /** Variable key name */
676
695
  key: string;
677
696
  /** Variable value */
@@ -683,20 +702,20 @@ export interface EnvironmentVariablesTable {
683
702
  /** When this variable was last updated */
684
703
  updated_at: Generated<Date>;
685
704
  }
686
- export type EnvironmentVariable = Selectable<EnvironmentVariablesTable>;
687
- export type NewEnvironmentVariable = Insertable<EnvironmentVariablesTable>;
688
- export type EnvironmentVariableUpdate = Updateable<EnvironmentVariablesTable>;
705
+ export type ContextVariable = Selectable<ContextVariablesTable>;
706
+ export type NewContextVariable = Insertable<ContextVariablesTable>;
707
+ export type ContextVariableUpdate = Updateable<ContextVariablesTable>;
689
708
  /**
690
- * Environment source overrides table
691
- * Per-source (routing key) variable overrides within an environment.
709
+ * Context source overrides table
710
+ * Per-source (routing key) variable overrides within a context.
692
711
  */
693
- export interface EnvironmentSourceOverridesTable {
712
+ export interface ContextSourceOverridesTable {
694
713
  /** UUID primary key */
695
714
  id: Generated<string>;
696
715
  /** Organization ID */
697
716
  org_id: string;
698
- /** Environment ID (FK to environments.id, cascade delete) */
699
- environment_id: string;
717
+ /** Context ID (FK to contexts.id, cascade delete) */
718
+ context_id: string;
700
719
  /** Routing key for the source */
701
720
  routing_key: string;
702
721
  /** Override key name */
@@ -708,9 +727,9 @@ export interface EnvironmentSourceOverridesTable {
708
727
  /** When this override was last updated */
709
728
  updated_at: Generated<Date>;
710
729
  }
711
- export type EnvironmentSourceOverride = Selectable<EnvironmentSourceOverridesTable>;
712
- export type NewEnvironmentSourceOverride = Insertable<EnvironmentSourceOverridesTable>;
713
- export type EnvironmentSourceOverrideUpdate = Updateable<EnvironmentSourceOverridesTable>;
730
+ export type ContextSourceOverride = Selectable<ContextSourceOverridesTable>;
731
+ export type NewContextSourceOverride = Insertable<ContextSourceOverridesTable>;
732
+ export type ContextSourceOverrideUpdate = Updateable<ContextSourceOverridesTable>;
714
733
  /**
715
734
  * Held runs table
716
735
  * Tracks runs waiting for approval, wait timer, or concurrency slot.
@@ -724,13 +743,13 @@ export interface HeldRunsTable {
724
743
  run_id: string;
725
744
  /** Job ID within the run */
726
745
  job_id: string;
727
- /** Environment ID (FK to environments.id); null once the environment is deleted */
728
- environment_id: string | null;
746
+ /** Context ID (FK to contexts.id); null once the context is deleted */
747
+ context_id: string | null;
729
748
  /** Hold type: 'approval' | 'wait_timer' | 'concurrency' */
730
749
  hold_type: string;
731
750
  /** Hold status: 'pending' | 'approved' | 'rejected' | 'expired' | 'released' */
732
751
  status: Generated<string>;
733
- /** Queue type: 'environment' | 'security' */
752
+ /** Queue type: 'context' | 'security' */
734
753
  queue_type: Generated<string>;
735
754
  /** Reason for hold or resolution */
736
755
  reason: string | null;
@@ -744,13 +763,13 @@ export interface HeldRunsTable {
744
763
  resolved_at: Date | null;
745
764
  /**
746
765
  * Hold granularity: 'workflow' | 'job' | 'step' (engine `HoldScope`).
747
- * Existing environment holds are job-scoped, hence the 'job' default.
766
+ * Existing context holds are job-scoped, hence the 'job' default.
748
767
  */
749
768
  hold_scope: Generated<string>;
750
769
  /** Step index within the job for step-scoped holds; null otherwise. */
751
770
  step_index: number | null;
752
771
  /**
753
- * What created the hold: 'environment' (mandatory env policy) | 'explicit'
772
+ * What created the hold: 'context' (mandatory env policy) | 'explicit'
754
773
  * (SDK `approval`). Engine `TriggerSource`.
755
774
  */
756
775
  trigger_source: Generated<string>;
@@ -1303,7 +1322,7 @@ export interface SourcesTable {
1303
1322
  * is the source of truth for both `name` and `slug` on GitHub-App sources.
1304
1323
  */
1305
1324
  slug: string | null;
1306
- /** Customer/org identifier for secret and environment scoping */
1325
+ /** Customer/org identifier for secret and context scoping */
1307
1326
  customer_id: Generated<string>;
1308
1327
  /** When this source was created */
1309
1328
  created_at: Generated<Date>;
@@ -25,7 +25,7 @@ export interface RefreshableSourceStore {
25
25
  }>>;
26
26
  getSourceWithSecrets(routingKey: string): Promise<{
27
27
  provider: string;
28
- config: string;
28
+ config: string | Record<string, unknown>;
29
29
  privateKey: string;
30
30
  } | null>;
31
31
  updateSource(routingKey: string, updates: {
package/dist/index.js CHANGED
@@ -1574,20 +1574,35 @@ var AdminApiClient = class {
1574
1574
  async deleteSecret(orgId, scope, key) {
1575
1575
  return this.request("DELETE", `/api/v1/admin/secrets/${encodeURIComponent(orgId)}/${encodeURIComponent(scope)}/${encodeURIComponent(key)}`);
1576
1576
  }
1577
- async listVariables(orgId, environment) {
1577
+ /**
1578
+ * Create (or upsert) a deployment context. `allowLocalExecution` lets
1579
+ * CLI-initiated / local runs resolve secrets through this context.
1580
+ */
1581
+ async createContext(data) {
1582
+ return this.request("POST", `/api/v1/admin/contexts`, data);
1583
+ }
1584
+ /**
1585
+ * Bind a scope pattern to a context so its scoped secrets resolve at dispatch.
1586
+ * `hostPattern` defaults to `**` (every host) server-side.
1587
+ */
1588
+ async bindContext(data) {
1589
+ const { name, ...body } = data;
1590
+ return this.request("POST", `/api/v1/admin/contexts/${encodeURIComponent(name)}/bind`, body);
1591
+ }
1592
+ async listVariables(orgId, context) {
1578
1593
  const params = new URLSearchParams({ orgId });
1579
- return this.request("GET", `/api/v1/admin/environments/${encodeURIComponent(environment)}/variables?${params}`);
1594
+ return this.request("GET", `/api/v1/admin/contexts/${encodeURIComponent(context)}/variables?${params}`);
1580
1595
  }
1581
- async setVariable(orgId, environment, key, value, locked) {
1596
+ async setVariable(orgId, context, key, value, locked) {
1582
1597
  const params = new URLSearchParams({ orgId });
1583
- return this.request("PUT", `/api/v1/admin/environments/${encodeURIComponent(environment)}/variables/${encodeURIComponent(key)}?${params}`, {
1598
+ return this.request("PUT", `/api/v1/admin/contexts/${encodeURIComponent(context)}/variables/${encodeURIComponent(key)}?${params}`, {
1584
1599
  value,
1585
1600
  locked
1586
1601
  });
1587
1602
  }
1588
- async deleteVariable(orgId, environment, key) {
1603
+ async deleteVariable(orgId, context, key) {
1589
1604
  const params = new URLSearchParams({ orgId });
1590
- return this.request("DELETE", `/api/v1/admin/environments/${encodeURIComponent(environment)}/variables/${encodeURIComponent(key)}?${params}`);
1605
+ return this.request("DELETE", `/api/v1/admin/contexts/${encodeURIComponent(context)}/variables/${encodeURIComponent(key)}?${params}`);
1591
1606
  }
1592
1607
  async rotateKey() {
1593
1608
  return this.request("POST", "/api/v1/admin/rotate-key");
@@ -12,6 +12,8 @@ export declare function setPendingAttestations(value: number): void;
12
12
  export declare function setPendingAttestationOldestAgeSeconds(value: number): void;
13
13
  /** Set the current number of terminally-rejected deferred attestations. */
14
14
  export declare function setRejectedAttestations(value: number): void;
15
+ /** Record the collation-drift flag (1 = drift, 0 = clean) for a database. */
16
+ export declare function setDbCollationDrift(database: string, drifted: boolean): void;
15
17
  interface ScalerUsageRow {
16
18
  scaler: string;
17
19
  /** Backend type for this scaler (rollup dimension). `__global__` for the orchestrator-wide row. */
@@ -0,0 +1,63 @@
1
+ /**
2
+ * OIDC ID-token claims for the local dev-signed identity. Mirrors the Platform's
3
+ * `oidc/id-token-claims.ts` so a dev-signed bundle carries the exact same claim
4
+ * shape the agent's statement builder + the engine verifier already expect — the
5
+ * cross-check between the in-toto statement and the token claims is identical to
6
+ * the Platform-minted path. The only differences are the local sentinel issuer
7
+ * (`kici-local`) and the org anchor (`__default__`, the plane's default org).
8
+ */
9
+ import { AttestationOrigin, SourceOrigin } from '@kici-dev/engine';
10
+ /** The subset of an execution_runs row the claims need. */
11
+ export interface RunClaimSource {
12
+ run_id: string;
13
+ org_id: string;
14
+ repo_identifier: string | null;
15
+ ref: string | null;
16
+ sha: string | null;
17
+ workflow_name: string | null;
18
+ provider: string | null;
19
+ /** True when the run executed an uploaded local working tree (`kici run remote`). */
20
+ local_working_tree: boolean;
21
+ }
22
+ /** The subset of an execution_jobs row the claims need. */
23
+ export interface JobClaimSource {
24
+ run_id: string;
25
+ job_id: string;
26
+ orchestrator_id: string | null;
27
+ status: string;
28
+ }
29
+ export interface BuildClaimsOpts {
30
+ issuer: string;
31
+ audience: string;
32
+ nowSeconds: number;
33
+ ttlSeconds: number;
34
+ }
35
+ export interface IdTokenClaims {
36
+ iss: string;
37
+ sub: string;
38
+ aud: string;
39
+ iat: number;
40
+ nbf: number;
41
+ exp: number;
42
+ jti: string;
43
+ kici_run_id: string;
44
+ kici_job_id: string;
45
+ repository: string | null;
46
+ ref: string | null;
47
+ sha: string | null;
48
+ workflow_ref: string | null;
49
+ orchestrator_id: string | null;
50
+ org_id: string;
51
+ source_origin: SourceOrigin;
52
+ provider: string | null;
53
+ statement_hash: string | null;
54
+ attestation_origin: AttestationOrigin;
55
+ }
56
+ /**
57
+ * Build the OIDC ID-token claims for a build job from the orchestrator's own
58
+ * execution_runs/execution_jobs rows. The local dev plane only ever mints for a
59
+ * live (running) job, so `attestation_origin` is always `live` and
60
+ * `statement_hash` is null (the statement is cross-checked field-by-field).
61
+ */
62
+ export declare function buildIdTokenClaims(run: RunClaimSource, job: JobClaimSource, opts: BuildClaimsOpts): IdTokenClaims;
63
+ //# sourceMappingURL=id-token-claims.d.ts.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Compact-JWS assembly for the local dev-signed identity. Mirrors the Platform's
3
+ * `oidc/jwt.ts`: `jose.SignJWT` wants a local KeyLike, but our `LocalSigner`
4
+ * returns the JOSE-raw r||s ES256 signature directly, so we base64url-assemble
5
+ * the compact JWS (`header.payload.signature`) by hand.
6
+ */
7
+ import type { LocalSigner } from './local-dev-signer.js';
8
+ export interface JwsProtectedHeader {
9
+ alg: 'ES256';
10
+ kid: string;
11
+ typ: 'JWT';
12
+ }
13
+ /** Assemble a compact JWS from a protected header + payload, signed by `signer`. */
14
+ export declare function signCompactJws(signer: LocalSigner, protectedHeader: JwsProtectedHeader, payload: Record<string, unknown>): Promise<string>;
15
+ //# sourceMappingURL=jwt.d.ts.map
@@ -0,0 +1,31 @@
1
+ import { type JWK } from 'jose';
2
+ /** The fixed, non-prod dev-identity issuer. Never `https://api.kici.dev`. */
3
+ export declare const KICI_LOCAL_ISSUER = "kici-local";
4
+ /** Minimal signing seam mirrored from the Platform's `Signer` idiom. */
5
+ export interface LocalSigner {
6
+ readonly alg: 'ES256';
7
+ /** Sign `data`, returning the JOSE-raw (r||s) ES256 signature. */
8
+ sign(data: Uint8Array): Promise<Uint8Array>;
9
+ /** The public key as a JWK (kty EC, crv P-256, alg ES256, use sig, kid). */
10
+ getPublicJwk(): JWK;
11
+ /** RFC 7638 thumbprint of the public JWK — the token-header `kid`. */
12
+ getKid(): string;
13
+ }
14
+ /**
15
+ * In-process ES256 signer over a persisted EC P-256 private JWK. NEVER selected
16
+ * in a Platform-connected deployment; the local dev plane is its only caller.
17
+ */
18
+ export declare class LocalDevSigner implements LocalSigner {
19
+ private readonly privateKey;
20
+ private readonly publicJwk;
21
+ readonly alg: "ES256";
22
+ private constructor();
23
+ /** Build a signer from an EC P-256 private JWK (`{ kty, crv, x, y, d }`). */
24
+ static fromPrivateJwk(jwk: JWK): Promise<LocalDevSigner>;
25
+ /** Read + import the private JWK from `path` (the plane's 0600 key file). */
26
+ static fromFile(path: string): Promise<LocalDevSigner>;
27
+ sign(data: Uint8Array): Promise<Uint8Array>;
28
+ getPublicJwk(): JWK;
29
+ getKid(): string;
30
+ }
31
+ //# sourceMappingURL=local-dev-signer.d.ts.map
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Local dev-signed OIDC mint (independent mode only).
3
+ *
4
+ * The Platform-connected orchestrator relays `oidc.token.request` to the hosted
5
+ * Platform, which reads its own run/job rows and mints (`ws/oidc-token-relay.ts`
6
+ * → `oidc.mint.request`). The offline local dev plane has no Platform, so this
7
+ * module mints locally: it reads the orchestrator's OWN execution_runs/
8
+ * execution_jobs rows and signs claims with the in-process `LocalDevSigner`,
9
+ * issuer `kici-local`.
10
+ *
11
+ * Security: this path is registered ONLY when the orchestrator runs in
12
+ * `independent` mode with a `LocalDevSigner` present, and app.ts registers the
13
+ * Platform relay in preference (the local path is registered strictly in the
14
+ * `else` branch), so a Platform-connected orchestrator can never reach the local
15
+ * signer — it keeps minting via the Platform exactly as today. The agent never
16
+ * asserts its own claims; every identity claim is read server-side from the
17
+ * orchestrator's rows, and the job-ownership check is against dispatch state.
18
+ */
19
+ import type { Kysely } from 'kysely';
20
+ import { type OidcTokenResult } from '@kici-dev/engine/protocol/messages/oidc-token-relay';
21
+ import type { Database } from '../db/types.js';
22
+ import { type IdTokenClaims } from './id-token-claims.js';
23
+ import { type LocalSigner } from './local-dev-signer.js';
24
+ /** ID-token lifetime (seconds). Matches the Platform's 10-minute cap. */
25
+ export declare const LOCAL_ID_TOKEN_TTL_SECONDS = 600;
26
+ /** The org anchor stamped into a local-plane token (the plane's default org). */
27
+ export declare const LOCAL_ORG_ID = "__default__";
28
+ export declare class LocalMintRunNotFoundError extends Error {
29
+ }
30
+ export declare class LocalMintJobNotFoundError extends Error {
31
+ }
32
+ export declare class LocalMintJobNotActiveError extends Error {
33
+ }
34
+ export interface LocalMintDeps {
35
+ db: Kysely<Database>;
36
+ signer: LocalSigner;
37
+ orchestratorId: string;
38
+ /** Injectable clock (seconds). Defaults to wall-clock. */
39
+ nowSeconds?: () => number;
40
+ }
41
+ export interface LocalMintInput {
42
+ runId: string;
43
+ jobId: string;
44
+ audience: string;
45
+ }
46
+ export interface LocalMintResult {
47
+ token: string;
48
+ expiresIn: number;
49
+ jti: string;
50
+ claims: IdTokenClaims;
51
+ }
52
+ /**
53
+ * Mint a short-lived dev-signed ES256 ID token for (run, job). Every identity
54
+ * claim is read from the orchestrator's own run/job rows; the token is never
55
+ * logged.
56
+ */
57
+ export declare function mintLocalIdToken(deps: LocalMintDeps, input: LocalMintInput): Promise<LocalMintResult>;
58
+ /** Job-ownership resolver surface (the dispatcher's `resolveOwnedJob`). */
59
+ export interface LocalMintOwnershipResolver {
60
+ resolveOwnedJob(agentId: string, jobId: string): {
61
+ runId: string;
62
+ } | undefined;
63
+ }
64
+ export declare class LocalMintRejectedError extends Error {
65
+ }
66
+ export interface LocalOidcTokenHandlerDeps {
67
+ dispatcher: LocalMintOwnershipResolver;
68
+ mint: LocalMintDeps;
69
+ }
70
+ /**
71
+ * Build the agent.api handler for `OIDC_TOKEN_REQUEST_METHOD` in independent
72
+ * mode. Verifies the agent owns the named job (resolving its runId from the
73
+ * dispatcher — never trusting an agent-asserted value), then mints locally. A
74
+ * job the agent does not own is rejected without minting anything.
75
+ */
76
+ export declare function createLocalOidcTokenHandler(deps: LocalOidcTokenHandlerDeps): (agentId: string, params: Record<string, unknown>) => Promise<OidcTokenResult>;
77
+ //# sourceMappingURL=local-mint.d.ts.map
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Selects which OIDC-mint handler backs `OIDC_TOKEN_REQUEST_METHOD` — the
3
+ * anti-forgery choke point for dev-signed identity.
4
+ *
5
+ * The rule (enforced here, unit-tested in `oidc-mint-registration.test.ts`):
6
+ *
7
+ * 1. **Platform-connected** (platformUrl + token + client) → the **relay**
8
+ * handler, minting via the hosted Platform exactly as today.
9
+ * 2. **Offline local dev plane** (independent identity + a local signer, AND
10
+ * NOT Platform-connected) → the **local** dev-signed handler (`kici-local`).
11
+ * 3. Neither → **no** registration (the method returns "unknown method").
12
+ *
13
+ * Case 1 is checked FIRST, so the local signer is UNREACHABLE whenever a
14
+ * Platform connection exists — even if `KICI_INDEPENDENT_IDENTITY` is somehow
15
+ * also set. This guarantees no new forgeable mint path appears on a
16
+ * Platform-connected orchestrator.
17
+ */
18
+ import type { Kysely } from 'kysely';
19
+ import type { OidcTokenResult } from '@kici-dev/engine/protocol/messages/oidc-token-relay';
20
+ import type { Database } from '../db/types.js';
21
+ import { type MintPlatformClient } from '../ws/oidc-token-relay.js';
22
+ import { type LocalMintOwnershipResolver } from './local-mint.js';
23
+ import type { LocalSigner } from './local-dev-signer.js';
24
+ export type OidcMintHandler = (agentId: string, params: Record<string, unknown>) => Promise<OidcTokenResult>;
25
+ export interface OidcMintRegistration {
26
+ /** `relay` = Platform-minted; `local` = offline dev-signed (`kici-local`). */
27
+ kind: 'relay' | 'local';
28
+ handler: OidcMintHandler;
29
+ }
30
+ export interface OidcMintRegistrationInput {
31
+ platformUrl?: string;
32
+ platformToken?: string;
33
+ platformClient?: MintPlatformClient;
34
+ independentIdentity: boolean;
35
+ localOidcSigner?: LocalSigner;
36
+ dispatcher: LocalMintOwnershipResolver & {
37
+ resolveOwnedJob(agentId: string, jobId: string): {
38
+ runId: string;
39
+ } | undefined;
40
+ };
41
+ db: Kysely<Database>;
42
+ orchestratorId: string;
43
+ testMode: boolean;
44
+ testMintDeferAudience?: string;
45
+ testMintRejectAudience?: string;
46
+ }
47
+ /** Decide which mint handler (if any) backs `OIDC_TOKEN_REQUEST_METHOD`. */
48
+ export declare function selectOidcMintRegistration(input: OidcMintRegistrationInput): OidcMintRegistration | undefined;
49
+ //# sourceMappingURL=oidc-mint-registration.d.ts.map