@kici-dev/orchestrator 0.9.1 → 0.10.0
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/__test-helpers__/test-db.d.ts +14 -1
- package/dist/agent/dispatcher.d.ts +137 -41
- package/dist/agent/registry.d.ts +79 -2
- package/dist/app.d.ts +2 -0
- package/dist/cancel/cancel-held-run.d.ts +68 -0
- package/dist/cancel/cancel-route-answer.d.ts +21 -0
- package/dist/cancel/cancel-run.d.ts +32 -0
- package/dist/cli/api-client.d.ts +3 -0
- package/dist/cli/commands/context.d.ts +3 -1
- package/dist/cli/commands/runs.d.ts +7 -0
- package/dist/cli/commands/shared/unbound-context-warning.d.ts +43 -0
- package/dist/cli/commands/signing-key.d.ts +22 -1
- package/dist/cli.js +1273 -715
- package/dist/cluster/cluster-settings-reader.d.ts +1 -1
- package/dist/cluster/coordinator.d.ts +2 -0
- package/dist/cluster/live-coordinator-peer.d.ts +13 -0
- package/dist/config.d.ts +9 -0
- package/dist/contexts/context-store.d.ts +3 -2
- package/dist/contexts/protection/satisfiability.d.ts +6 -3
- package/dist/db/migrations/145_execution_runs_workflow_provenance.d.ts +4 -0
- package/dist/db/migrations/146_pending_job_contexts_context_resolution.d.ts +4 -0
- package/dist/db/migrations/147_sealed_job_secrets.d.ts +19 -0
- package/dist/db/migrations/148_cluster_settings_sealed_secrets_retry_backoff_ms.d.ts +21 -0
- package/dist/db/migrations/149_workflow_registrations_dep_cache_key.d.ts +4 -0
- package/dist/db/migrations/150_execution_runs_status_epoch.d.ts +18 -0
- package/dist/db/migrations/151_workflow_registrations_dep_cache_key_sha.d.ts +4 -0
- package/dist/db/repos/signing-keys-repo.d.ts +48 -3
- package/dist/db/types.d.ts +81 -1
- package/dist/git/clone-token-auth.d.ts +7 -0
- package/dist/git/dispatch-git-auth.d.ts +63 -0
- package/dist/lockfile-validate.d.ts +4 -2
- package/dist/metrics/prometheus.d.ts +1 -1
- package/dist/oidc/id-token-claims.d.ts +10 -0
- package/dist/oidc/oidc-mint-registration.d.ts +2 -0
- package/dist/oidc/orchestrator-mint.d.ts +25 -4
- package/dist/oidc/reconcile-signing-key.d.ts +31 -6
- package/dist/oidc/resolve-signer.d.ts +12 -6
- package/dist/pipeline/decorating-secret-resolver.d.ts +5 -3
- package/dist/pipeline/dispatch-matched-workflow.d.ts +105 -13
- package/dist/pipeline/dispatch-matched-workflow.test-helpers.d.ts +121 -0
- package/dist/pipeline/global-dispatch-identity.d.ts +76 -0
- package/dist/pipeline/global-dispatch.d.ts +91 -0
- package/dist/pipeline/global-eval-round.d.ts +56 -4
- package/dist/pipeline/global-round-hold.d.ts +41 -0
- package/dist/pipeline/held-context-data.d.ts +143 -0
- package/dist/pipeline/held-round-registrations.d.ts +40 -0
- package/dist/pipeline/install-gate.d.ts +93 -0
- package/dist/pipeline/install-secrets-resolver.d.ts +28 -13
- package/dist/pipeline/job-contexts.d.ts +21 -6
- package/dist/pipeline/pending-workflow-context.d.ts +15 -3
- package/dist/pipeline/process-webhook.d.ts +38 -1
- package/dist/pipeline/processor.d.ts +20 -0
- package/dist/pipeline/rerun-global.d.ts +28 -0
- package/dist/pipeline/rerun-inputs.d.ts +88 -0
- package/dist/pipeline/rerun.d.ts +25 -2
- package/dist/pipeline/resume-workflow.d.ts +36 -2
- package/dist/pipeline/unbound-job-context.d.ts +34 -0
- package/dist/pipeline/workflow-lock-at-sha.d.ts +67 -0
- package/dist/provenance/backfill-run.d.ts +5 -0
- package/dist/providers/github/check-status-poster.d.ts +4 -16
- package/dist/queue/job-queue.d.ts +127 -10
- package/dist/queue/terminalize-unroutable.d.ts +37 -4
- package/dist/registration/registration-index.d.ts +13 -1
- package/dist/registration/registration-store.d.ts +10 -1
- package/dist/reporting/execution-tracker.d.ts +149 -8
- package/dist/reporting/log-chunk-sink.d.ts +1 -1
- package/dist/reporting/log-writer.d.ts +14 -0
- package/dist/reporting/step-log-path.d.ts +8 -0
- package/dist/reporting/step-log-reader.d.ts +21 -3
- package/dist/routes/admin-signing-keys.d.ts +33 -0
- package/dist/scaler/agent-fit.d.ts +159 -0
- package/dist/scaler/container-routing.d.ts +16 -16
- package/dist/scaler/manager.d.ts +23 -17
- package/dist/secrets/context-secret-resolver.d.ts +1 -1
- package/dist/secrets/index.d.ts +1 -1
- package/dist/secrets/job-secret-gate.d.ts +25 -3
- package/dist/secrets/job-secret-seal.d.ts +36 -0
- package/dist/secrets/master-key-rotation.d.ts +7 -3
- package/dist/secrets/secret-resolver.d.ts +42 -23
- package/dist/server.js +27690 -23447
- package/dist/standalone.js +58162 -53103
- package/dist/worker/in-memory-job-queue.d.ts +12 -3
- package/dist/worker/reroute-dispatch.d.ts +35 -0
- package/dist/ws/agent-handler.d.ts +23 -10
- package/dist/ws/git-credential-relay.d.ts +16 -3
- package/installer-image-digests.json +3 -3
- package/package.json +4 -4
- package/sbom.spdx.json +53 -53
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Kysely } from 'kysely';
|
|
2
2
|
import type { Database } from '../db/types.js';
|
|
3
3
|
/** Numeric columns on cluster_settings readable via {@link ClusterSettingsReader}. */
|
|
4
|
-
export type ClusterNumberColumn = 'max_github_payload_bytes' | 'event_log_max_payload_bytes' | 'lock_file_max_bytes' | 'webhook_dedup_ttl_ms' | 'event_router_event_ttl_seconds' | 'event_router_max_dispatch_attempts' | 'queue_max_depth' | 'reroute_flap_grace_ms' | 'max_fanout_hosts' | 'event_router_rate_limit_per_workflow_per_minute' | 'cache_max_tarball_bytes' | 'cache_ttl_days' | 'lockfile_cache_max' | 'lockfile_cache_max_bytes' | 'lockfile_cache_ttl_ms' | 'content_cache_max' | 'content_cache_max_bytes' | 'content_cache_ttl_ms' | 'global_eval_round_timeout_ms' | 'global_eval_candidate_timeout_ms' | 'global_eval_cache_max' | 'global_eval_wait_timeout_ms' | 'check_run_tracking_ttl_days' | 'run_retention_days' | 'audit_retention_days' | 'provenance_retention_days' | 'held_run_retention_days' | 'concurrency_wait_timeout_ms' | 'agent_token_ttl_ms' | 'ownership_db_check_timeout_ms' | 'unroutable_grace_ms' | 'ingest_overflow_claim_timeout_ms' | 'scaler_reap_interval_ms' | 'scaler_reap_stranded_timeout_ms' | 'scaler_reap_reattempt_interval_ms' | 'scaler_claim_retention_ms' | 'scaler_provision_backoff_base_ms' | 'scaler_provision_backoff_max_ms' | 'scaler_provision_max_consecutive_failures';
|
|
4
|
+
export type ClusterNumberColumn = 'max_github_payload_bytes' | 'event_log_max_payload_bytes' | 'lock_file_max_bytes' | 'webhook_dedup_ttl_ms' | 'event_router_event_ttl_seconds' | 'event_router_max_dispatch_attempts' | 'queue_max_depth' | 'reroute_flap_grace_ms' | 'max_fanout_hosts' | 'event_router_rate_limit_per_workflow_per_minute' | 'cache_max_tarball_bytes' | 'cache_ttl_days' | 'lockfile_cache_max' | 'lockfile_cache_max_bytes' | 'lockfile_cache_ttl_ms' | 'content_cache_max' | 'content_cache_max_bytes' | 'content_cache_ttl_ms' | 'global_eval_round_timeout_ms' | 'global_eval_candidate_timeout_ms' | 'global_eval_cache_max' | 'global_eval_wait_timeout_ms' | 'check_run_tracking_ttl_days' | 'run_retention_days' | 'audit_retention_days' | 'provenance_retention_days' | 'held_run_retention_days' | 'concurrency_wait_timeout_ms' | 'agent_token_ttl_ms' | 'ownership_db_check_timeout_ms' | 'sealed_secrets_retry_backoff_ms' | 'unroutable_grace_ms' | 'ingest_overflow_claim_timeout_ms' | 'scaler_reap_interval_ms' | 'scaler_reap_stranded_timeout_ms' | 'scaler_reap_reattempt_interval_ms' | 'scaler_claim_retention_ms' | 'scaler_provision_backoff_base_ms' | 'scaler_provision_backoff_max_ms' | 'scaler_provision_max_consecutive_failures';
|
|
5
5
|
/** Text columns on cluster_settings readable via {@link ClusterSettingsReader}. */
|
|
6
6
|
export type ClusterStringColumn = 'dashboard_verified_issuer';
|
|
7
7
|
/** Boolean columns on cluster_settings readable via {@link ClusterSettingsReader}. */
|
|
@@ -33,6 +33,8 @@ export interface RunContext {
|
|
|
33
33
|
traceId?: string;
|
|
34
34
|
/** Pre-resolved clone token for workers without provider credentials. */
|
|
35
35
|
cloneToken?: string;
|
|
36
|
+
/** Pre-resolved clone token for the workflow repository of an organization-wide job. */
|
|
37
|
+
workflowCloneToken?: string;
|
|
36
38
|
}
|
|
37
39
|
export interface JobToRoute {
|
|
38
40
|
jobName: string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether this coordinator has a live coordinator peer.
|
|
3
|
+
*
|
|
4
|
+
* `PeerRegistry` flips `connected` the instant a peer WS closes, with no grace
|
|
5
|
+
* of its own, so sampling it alone reads a link blip between two healthy
|
|
6
|
+
* coordinators as a dead peer. That is the same hazard `shouldDeferReroutedJob`
|
|
7
|
+
* and `adopterIsLive` guard against, and it is answered the same way: a
|
|
8
|
+
* coordinator peer counts while it is connected or was last heard from within
|
|
9
|
+
* the flap grace. Worker peers never count: they do not drain the shared queue.
|
|
10
|
+
*/
|
|
11
|
+
import type { PeerRegistry } from './peer-registry.js';
|
|
12
|
+
export declare function hasLiveCoordinatorPeer(peers: Pick<PeerRegistry, 'getCoordinatorPeers'>, nowMs: number, flapGraceMs: number): boolean;
|
|
13
|
+
//# sourceMappingURL=live-coordinator-peer.d.ts.map
|
package/dist/config.d.ts
CHANGED
|
@@ -15,6 +15,12 @@
|
|
|
15
15
|
* and PgSecretStore, not through config. See SourceStore and SourceManager.
|
|
16
16
|
*/
|
|
17
17
|
import { z } from 'zod';
|
|
18
|
+
/**
|
|
19
|
+
* Default for `sealed_secrets_retry_backoff_ms`: how long a coordinator stops
|
|
20
|
+
* offering a queued job it put back because it could not open its seal. The
|
|
21
|
+
* config default below and the job queue's own fallback both read this.
|
|
22
|
+
*/
|
|
23
|
+
export declare const DEFAULT_SEALED_SECRETS_RETRY_BACKOFF_MS = 60000;
|
|
18
24
|
/**
|
|
19
25
|
* Validation scope for orchestrator config: a running orchestrator (`runtime`)
|
|
20
26
|
* vs a build-artifact (agent packaging) operation (`packaging`). Packaging only
|
|
@@ -73,6 +79,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
73
79
|
concurrencyWaitTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
74
80
|
dispatchAckTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
75
81
|
ownershipDbCheckTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
82
|
+
sealedSecretsRetryBackoffMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
76
83
|
ingestMaxConcurrency: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
77
84
|
ingestMaxQueueDepth: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
78
85
|
ingestCodelTargetMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
@@ -282,6 +289,7 @@ export declare const packagingConfigSchema: z.ZodObject<{
|
|
|
282
289
|
concurrencyWaitTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
283
290
|
dispatchAckTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
284
291
|
ownershipDbCheckTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
292
|
+
sealedSecretsRetryBackoffMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
285
293
|
ingestMaxConcurrency: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
286
294
|
ingestMaxQueueDepth: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
287
295
|
ingestCodelTargetMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
@@ -524,6 +532,7 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
|
|
|
524
532
|
concurrencyWaitTimeoutMs: number;
|
|
525
533
|
dispatchAckTimeoutMs: number;
|
|
526
534
|
ownershipDbCheckTimeoutMs: number;
|
|
535
|
+
sealedSecretsRetryBackoffMs: number;
|
|
527
536
|
ingestMaxConcurrency: number;
|
|
528
537
|
ingestMaxQueueDepth: number;
|
|
529
538
|
ingestCodelTargetMs: number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Kysely } from 'kysely';
|
|
2
|
+
import { ContextType } from '@kici-dev/engine';
|
|
2
3
|
import type { ConcurrencyStrategy, Context as EngineContext, MinimumTrust } from '@kici-dev/engine';
|
|
3
4
|
import type { Database, Context } from '../db/types.js';
|
|
4
5
|
/** Thrown by `delete` when pending held runs reference the context. */
|
|
@@ -15,7 +16,7 @@ export declare function toContext(row: Context): EngineContext;
|
|
|
15
16
|
/** Fields accepted when creating a context. */
|
|
16
17
|
export interface ContextCreateInput {
|
|
17
18
|
name: string;
|
|
18
|
-
type?:
|
|
19
|
+
type?: ContextType;
|
|
19
20
|
globPattern?: string | null;
|
|
20
21
|
branchRestrictions?: string[];
|
|
21
22
|
triggerTypeFilters?: string[];
|
|
@@ -44,7 +45,7 @@ export interface ContextCreateInput {
|
|
|
44
45
|
*/
|
|
45
46
|
export interface ContextUpdateInput {
|
|
46
47
|
name?: string;
|
|
47
|
-
type?:
|
|
48
|
+
type?: ContextType;
|
|
48
49
|
globPattern?: string | null;
|
|
49
50
|
branchRestrictions?: string[] | null;
|
|
50
51
|
triggerTypeFilters?: string[];
|
|
@@ -52,13 +52,16 @@ export interface UnsatisfiableBinding {
|
|
|
52
52
|
export declare function checkBindingSatisfiable(jobName: string, envs: ReadonlyArray<Context | undefined>, envNames: readonly string[]): UnsatisfiableBinding | null;
|
|
53
53
|
/** Minimal lock-workflow shape needed to walk its jobs for satisfiability. */
|
|
54
54
|
interface SatisfiabilityLockWorkflow {
|
|
55
|
+
/** Workflow-level context names, bound by every job before its own. */
|
|
56
|
+
contexts?: readonly unknown[];
|
|
55
57
|
jobs?: readonly unknown[];
|
|
56
58
|
}
|
|
57
59
|
/**
|
|
58
60
|
* Walk every workflow's static jobs and reject the registration when a bound
|
|
59
|
-
* context list
|
|
60
|
-
*
|
|
61
|
-
*
|
|
61
|
+
* context list — the workflow-level names plus the job's own — is provably
|
|
62
|
+
* unsatisfiable (a disabled context, or mutually-exclusive fixed
|
|
63
|
+
* branch/trigger/repo restrictions among the resolved contexts — missing names
|
|
64
|
+
* are lenient, never rejected). Dynamic elements
|
|
62
65
|
* are skipped (unresolvable at registration); the all-must-pass semantics keep
|
|
63
66
|
* the static subset's exclusivity sound. Throws the first
|
|
64
67
|
* `UnsatisfiableBinding.message` so the registration route / direct helper
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* Hold the secret fields of a stored job encrypted under the orchestrator
|
|
4
|
+
* master key, beside the plain JSON column that keeps every other field.
|
|
5
|
+
*
|
|
6
|
+
* Adds a nullable `sealed_secrets text` column to the three tables a job waits
|
|
7
|
+
* in: `dispatch_queue` (its `job_config`), `pending_job_contexts` (its
|
|
8
|
+
* `job_input`), and `pending_workflow_contexts` (its `context`).
|
|
9
|
+
*
|
|
10
|
+
* Nullable and unbackfilled: NULL on every row written before this column
|
|
11
|
+
* existed, and on every row an orchestrator without a master key writes. Such
|
|
12
|
+
* a row keeps its secret fields in the plain column and reads back unchanged.
|
|
13
|
+
*
|
|
14
|
+
* Idempotent: each column is added only when missing.
|
|
15
|
+
*/
|
|
16
|
+
export declare const SEALED_SECRETS_TABLES: readonly ['dispatch_queue', 'pending_job_contexts', 'pending_workflow_contexts'];
|
|
17
|
+
export declare function up(db: Kysely<unknown>): Promise<void>;
|
|
18
|
+
export declare function down(db: Kysely<unknown>): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=147_sealed_job_secrets.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* Add `cluster_settings.sealed_secrets_retry_backoff_ms` (nullable bigint).
|
|
4
|
+
*
|
|
5
|
+
* How long a coordinator leaves a queued job alone after it claimed the job and
|
|
6
|
+
* could not open its sealed secrets: the job was sealed with a master key this
|
|
7
|
+
* coordinator does not hold. During a rolling key rotation a coordinator that
|
|
8
|
+
* holds the key can take the job in that window; after it, this coordinator can
|
|
9
|
+
* claim the job again, and each claim spends another dispatch attempt, so a job
|
|
10
|
+
* no coordinator can open still fails.
|
|
11
|
+
*
|
|
12
|
+
* Cluster-global (every coordinator drains the same queue), so it lives on
|
|
13
|
+
* `cluster_settings` rather than `org_settings`. NULL ⇒ the orchestrator's own
|
|
14
|
+
* configured default applies.
|
|
15
|
+
*
|
|
16
|
+
* Idempotent: guarded on column existence; a re-run on a DB that already has the
|
|
17
|
+
* column is a no-op.
|
|
18
|
+
*/
|
|
19
|
+
export declare function up(db: Kysely<unknown>): Promise<void>;
|
|
20
|
+
export declare function down(db: Kysely<unknown>): Promise<void>;
|
|
21
|
+
//# sourceMappingURL=148_cluster_settings_sealed_secrets_retry_backoff_ms.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
|
+
/**
|
|
3
|
+
* Add `execution_runs.status_epoch` (integer, NOT NULL, default 0).
|
|
4
|
+
*
|
|
5
|
+
* The run's status generation. It starts at 0, and the tracker raises it each
|
|
6
|
+
* time a run leaves a terminal status: a run failed before a job it had already
|
|
7
|
+
* dispatched reported in, and the run continues. Every `execution.status` frame
|
|
8
|
+
* carries it, so the Platform can keep a finished run finished against a
|
|
9
|
+
* non-terminal frame that arrives late, and still follow a real reopen.
|
|
10
|
+
*
|
|
11
|
+
* A constant default adds the column without rewriting the table, and every
|
|
12
|
+
* existing row reads 0: none of them was reopened under this counter.
|
|
13
|
+
*
|
|
14
|
+
* Idempotent: guarded on the column's existence, so re-running is a no-op.
|
|
15
|
+
*/
|
|
16
|
+
export declare function up(db: Kysely<unknown>): Promise<void>;
|
|
17
|
+
export declare function down(db: Kysely<unknown>): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=150_execution_runs_status_epoch.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Kysely } from 'kysely';
|
|
2
2
|
import type { Database, OrchestratorSigningKeyRow } from '../types.js';
|
|
3
3
|
export interface UpsertActiveInput {
|
|
4
4
|
kid: string;
|
|
@@ -9,6 +9,31 @@ export interface UpsertActiveInput {
|
|
|
9
9
|
signer_kind: string;
|
|
10
10
|
key_ref: string | null;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Advisory-lock name taken (`pg_advisory_xact_lock(hashtext(...))`) by every
|
|
14
|
+
* writer that changes which key is `active` or revokes a key: `activateIfCurrent`,
|
|
15
|
+
* `upsertActive` and `revoke`. Holding it for the whole transaction makes
|
|
16
|
+
* "read the active key, then write" atomic across orchestrator nodes sharing the
|
|
17
|
+
* database, and orders a revoke against a key switch.
|
|
18
|
+
*/
|
|
19
|
+
export declare const ACTIVE_SIGNING_KEY_LOCK = "orchestrator-signing-key-active";
|
|
20
|
+
/**
|
|
21
|
+
* The columns a key listing may expose: identity, lifecycle and custody
|
|
22
|
+
* metadata. Never the public JWK or the wrapped private key.
|
|
23
|
+
*/
|
|
24
|
+
export declare const SIGNING_KEY_METADATA_COLUMNS: readonly ['kid', 'status', 'alg', 'signer_kind', 'key_ref', 'activated_at', 'created_at'];
|
|
25
|
+
/** One row of {@link OrchestratorSigningKeyRepo.listTrustedMetadata}. */
|
|
26
|
+
export type SigningKeyMetadataRow = Pick<OrchestratorSigningKeyRow, (typeof SIGNING_KEY_METADATA_COLUMNS)[number]>;
|
|
27
|
+
/** Outcome of {@link OrchestratorSigningKeyRepo.activateIfCurrent}. */
|
|
28
|
+
export interface ActivateIfCurrentResult {
|
|
29
|
+
/** True when this call activated `input.kid`. */
|
|
30
|
+
activated: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The active row after the call: the new row when `activated`, otherwise the
|
|
33
|
+
* row that was active when the lock was taken (null when none was).
|
|
34
|
+
*/
|
|
35
|
+
active: OrchestratorSigningKeyRow | null;
|
|
36
|
+
}
|
|
12
37
|
/**
|
|
13
38
|
* Repository for the orchestrator's provenance signing keys. Ports the Platform's
|
|
14
39
|
* `signing-keys-repo.ts` status model (activate / retire / revoke) and adds
|
|
@@ -17,18 +42,38 @@ export interface UpsertActiveInput {
|
|
|
17
42
|
export declare class OrchestratorSigningKeyRepo {
|
|
18
43
|
private readonly db;
|
|
19
44
|
constructor(db: Kysely<Database>);
|
|
45
|
+
private lockActiveKey;
|
|
46
|
+
private readActiveRow;
|
|
20
47
|
/** Public keys served in the JWKS / trusted for verification (everything except revoked). */
|
|
21
48
|
listTrusted(): Promise<OrchestratorSigningKeyRow[]>;
|
|
49
|
+
/**
|
|
50
|
+
* The same keys as {@link listTrusted}, in the same order, with only the
|
|
51
|
+
* {@link SIGNING_KEY_METADATA_COLUMNS}. Backs `kici-admin signing-key list`.
|
|
52
|
+
*/
|
|
53
|
+
listTrustedMetadata(): Promise<SigningKeyMetadataRow[]>;
|
|
22
54
|
/** The single currently-active key row, or null when none is active. */
|
|
23
55
|
getActiveRow(): Promise<OrchestratorSigningKeyRow | null>;
|
|
56
|
+
/**
|
|
57
|
+
* Activate the freshly generated key `input` only if the active key is still
|
|
58
|
+
* the one the caller last read (`expectedActiveKid`; null = none was active).
|
|
59
|
+
* The read and the write run under {@link ACTIVE_SIGNING_KEY_LOCK}, so of
|
|
60
|
+
* several nodes that each read "no key" and each generated one, exactly one
|
|
61
|
+
* activates; every other call returns the winner's row untouched. A replaced
|
|
62
|
+
* key is demoted to `retiring`.
|
|
63
|
+
*/
|
|
64
|
+
activateIfCurrent(expectedActiveKid: string | null, input: UpsertActiveInput): Promise<ActivateIfCurrentResult>;
|
|
24
65
|
/**
|
|
25
66
|
* Activate `input.kid`. If it is already active, no-op. Otherwise demote any
|
|
26
67
|
* current active key to `retiring`, upsert this kid as `active`, in one
|
|
27
|
-
* transaction. Returns true when a NEW
|
|
28
|
-
* Refuses to reactivate a `revoked` kid.
|
|
68
|
+
* transaction under {@link ACTIVE_SIGNING_KEY_LOCK}. Returns true when a NEW
|
|
69
|
+
* kid was activated (caller audits). Refuses to reactivate a `revoked` kid.
|
|
29
70
|
*/
|
|
30
71
|
upsertActive(input: UpsertActiveInput): Promise<boolean>;
|
|
31
72
|
retire(kid: string): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Mark `kid` revoked, under {@link ACTIVE_SIGNING_KEY_LOCK} so a concurrent
|
|
75
|
+
* key switch either sees the revoke or finishes before it.
|
|
76
|
+
*/
|
|
32
77
|
revoke(kid: string, reason: string): Promise<void>;
|
|
33
78
|
}
|
|
34
79
|
//# sourceMappingURL=signing-keys-repo.d.ts.map
|
package/dist/db/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ColumnType, Generated, Insertable, Selectable, Updateable } from 'kysely';
|
|
2
2
|
import type { ApprovalRequirement, ApproverClause, InitFailure, StepApprovalPayload } from '@kici-dev/engine';
|
|
3
3
|
import type { PrecursorResult } from '../cache/precursor-result.js';
|
|
4
|
+
import type { DeferredContextResolution } from '../pipeline/held-context-data.js';
|
|
4
5
|
/**
|
|
5
6
|
* Job kind stored in `execution_jobs.job_kind`. `Standard` runs steps on an
|
|
6
7
|
* agent; `Gate` is an invoke gate that summons source-repo runs; `Proxy`
|
|
@@ -231,8 +232,15 @@ export interface DispatchQueueTable {
|
|
|
231
232
|
/** JSONB array of runs-on labels for agent matching.
|
|
232
233
|
* Insert: JSON.stringify(labels), Select: auto-parsed by pg driver. */
|
|
233
234
|
runs_on_labels: string;
|
|
234
|
-
/** JSON-encoded Record of the
|
|
235
|
+
/** JSON-encoded Record of the job configuration, without the fields in `sealed_secrets` */
|
|
235
236
|
job_config: string;
|
|
237
|
+
/**
|
|
238
|
+
* The secret fields of the stored job, AES-256-GCM encrypted under the
|
|
239
|
+
* orchestrator master key (`secrets/job-secret-seal.ts`). NULL when there is
|
|
240
|
+
* nothing to seal, when no master key is configured, and on a row written
|
|
241
|
+
* before the column existed: those rows keep the fields in the plain column.
|
|
242
|
+
*/
|
|
243
|
+
sealed_secrets: ColumnType<string | null, string | null | undefined, string | null>;
|
|
236
244
|
/** Repository clone URL */
|
|
237
245
|
repo_url: string;
|
|
238
246
|
/** Git ref (branch/tag) */
|
|
@@ -506,6 +514,13 @@ export interface ExecutionRunTable {
|
|
|
506
514
|
* cancelled and for one that entered `cancelling` before the column existed.
|
|
507
515
|
*/
|
|
508
516
|
cancelling_at: ColumnType<Date | null, Date | null | undefined, Date | null>;
|
|
517
|
+
/**
|
|
518
|
+
* The run's status generation (migration 150). Starts at 0 and rises by one
|
|
519
|
+
* each time the run leaves a terminal status to continue. Forwarded on every
|
|
520
|
+
* `execution.status` frame as `statusEpoch`, so the Platform can tell a
|
|
521
|
+
* reopen from a frame that arrives late after the run finished.
|
|
522
|
+
*/
|
|
523
|
+
status_epoch: Generated<number>;
|
|
509
524
|
/** Total execution duration in milliseconds */
|
|
510
525
|
duration_ms: number | null;
|
|
511
526
|
/**
|
|
@@ -627,6 +642,18 @@ export interface ExecutionRunTable {
|
|
|
627
642
|
* repository that defines it rather than from the one it ran against.
|
|
628
643
|
*/
|
|
629
644
|
workflow_repo_identifier: string | null;
|
|
645
|
+
/**
|
|
646
|
+
* Commit of the workflow repository the run dispatched, when the workflow is
|
|
647
|
+
* defined in another repository (`workflow_repo_identifier` set). A re-run
|
|
648
|
+
* dispatches this exact commit. NULL on every per-repository run.
|
|
649
|
+
*/
|
|
650
|
+
workflow_sha: string | null;
|
|
651
|
+
/**
|
|
652
|
+
* The workflow repository's registered branch, when the workflow is defined
|
|
653
|
+
* in another repository. The git-credential relay checks context branch rules
|
|
654
|
+
* against it. NULL on every per-repository run.
|
|
655
|
+
*/
|
|
656
|
+
workflow_branch: string | null;
|
|
630
657
|
/**
|
|
631
658
|
* True when this row records a global evaluation round rather than a
|
|
632
659
|
* workflow.
|
|
@@ -1638,6 +1665,31 @@ export interface WorkflowRegistrationsTable {
|
|
|
1638
1665
|
default_branch: ColumnType<string | null, string | null | undefined, string | null>;
|
|
1639
1666
|
/** Source file path for this workflow (e.g. ".kici/workflows/deploy.ts") */
|
|
1640
1667
|
source_file: ColumnType<string | null, string | null | undefined, string | null>;
|
|
1668
|
+
/**
|
|
1669
|
+
* `lockfileHash` of the lock file that last registered this workflow: the
|
|
1670
|
+
* package-manager lockfile hash that keys the dependency cache. A run dispatched
|
|
1671
|
+
* from the registration probes the dependency cache with it.
|
|
1672
|
+
*
|
|
1673
|
+
* NULL when that lock file records none, and on rows written before migration
|
|
1674
|
+
* 149. NULL means the run installs its dependencies on the agent.
|
|
1675
|
+
*/
|
|
1676
|
+
lockfile_hash: ColumnType<string | null, string | null | undefined, string | null>;
|
|
1677
|
+
/**
|
|
1678
|
+
* `siblingsDigest` of the lock file that last registered this workflow: the
|
|
1679
|
+
* in-repo `workspace:` sibling closure, part of the dependency-cache key next to
|
|
1680
|
+
* `lockfile_hash`. NULL when that lock file records none.
|
|
1681
|
+
*/
|
|
1682
|
+
siblings_digest: ColumnType<string | null, string | null | undefined, string | null>;
|
|
1683
|
+
/**
|
|
1684
|
+
* The `commit_sha` written together with `lockfile_hash` and `siblings_digest`.
|
|
1685
|
+
* The key is used only while this equals `commit_sha`: a writer that does not
|
|
1686
|
+
* know the key columns moves `commit_sha` without them, and the key it leaves
|
|
1687
|
+
* behind belongs to an older lock file.
|
|
1688
|
+
*
|
|
1689
|
+
* NULL on rows written before migration 151 and on rows registered with no
|
|
1690
|
+
* commit; such a row uses no key.
|
|
1691
|
+
*/
|
|
1692
|
+
dep_cache_key_sha: ColumnType<string | null, string | null | undefined, string | null>;
|
|
1641
1693
|
/** Whether this is a global workflow (triggers across all repos under same routing key) */
|
|
1642
1694
|
is_global: ColumnType<boolean, boolean | undefined, boolean>;
|
|
1643
1695
|
/**
|
|
@@ -2211,6 +2263,12 @@ export interface ClusterSettingsTable {
|
|
|
2211
2263
|
* violation. NULL ⇒ the orchestrator's configured default.
|
|
2212
2264
|
*/
|
|
2213
2265
|
ownership_db_check_timeout_ms: ColumnType<string | null, number | null | undefined, number | null>;
|
|
2266
|
+
/**
|
|
2267
|
+
* How long a coordinator leaves a queued job alone after it could not open the
|
|
2268
|
+
* job's sealed secrets, before claiming it again. NULL ⇒ the orchestrator's
|
|
2269
|
+
* configured default.
|
|
2270
|
+
*/
|
|
2271
|
+
sealed_secrets_retry_backoff_ms: ColumnType<string | null, number | null | undefined, number | null>;
|
|
2214
2272
|
/**
|
|
2215
2273
|
* Verified-tier origin the dashboard fetches the orchestrator's X25519
|
|
2216
2274
|
* dashboard-encryption public key from (and always displays) under the
|
|
@@ -2248,6 +2306,21 @@ export interface PendingJobContextsTable {
|
|
|
2248
2306
|
* instead of dispatching to an agent. NULL for every ordinary job.
|
|
2249
2307
|
*/
|
|
2250
2308
|
invoke_config: ColumnType<string | null, string | null | undefined, string | null>;
|
|
2309
|
+
/**
|
|
2310
|
+
* For a job bound to a context, what the dispatch of the stored job resolves
|
|
2311
|
+
* the job's context variables and secrets from (context names, org, routing
|
|
2312
|
+
* key, host facts, registry-auth inputs) as JSONB. Never a secret value. NULL
|
|
2313
|
+
* for a job with no bound context, and for a row stored before the column
|
|
2314
|
+
* existed, whose `job_input` still carries its resolved context data.
|
|
2315
|
+
*/
|
|
2316
|
+
context_resolution: ColumnType<DeferredContextResolution | null, string | null | undefined, string | null>;
|
|
2317
|
+
/**
|
|
2318
|
+
* The secret fields of the stored job, AES-256-GCM encrypted under the
|
|
2319
|
+
* orchestrator master key (`secrets/job-secret-seal.ts`). NULL when there is
|
|
2320
|
+
* nothing to seal, when no master key is configured, and on a row written
|
|
2321
|
+
* before the column existed: those rows keep the fields in the plain column.
|
|
2322
|
+
*/
|
|
2323
|
+
sealed_secrets: ColumnType<string | null, string | null | undefined, string | null>;
|
|
2251
2324
|
/** When this context was stored */
|
|
2252
2325
|
created_at: Generated<Date>;
|
|
2253
2326
|
}
|
|
@@ -2266,6 +2339,13 @@ export interface PendingWorkflowContextsTable {
|
|
|
2266
2339
|
org_id: string;
|
|
2267
2340
|
/** Serializable WorkflowDispatchContext inputs as JSONB */
|
|
2268
2341
|
context: ColumnType<Record<string, unknown>, string, string>;
|
|
2342
|
+
/**
|
|
2343
|
+
* The secret fields of the stored job, AES-256-GCM encrypted under the
|
|
2344
|
+
* orchestrator master key (`secrets/job-secret-seal.ts`). NULL when there is
|
|
2345
|
+
* nothing to seal, when no master key is configured, and on a row written
|
|
2346
|
+
* before the column existed: those rows keep the fields in the plain column.
|
|
2347
|
+
*/
|
|
2348
|
+
sealed_secrets: ColumnType<string | null, string | null | undefined, string | null>;
|
|
2269
2349
|
/** When this context was stored */
|
|
2270
2350
|
created_at: Generated<Date>;
|
|
2271
2351
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The structured clone auth a bare clone token stands for.
|
|
3
|
+
*/
|
|
4
|
+
import type { ProviderGitAuth } from '@kici-dev/engine';
|
|
5
|
+
/** Basic-auth envelope for a provider clone token (`x-access-token` user, GitHub convention). */
|
|
6
|
+
export declare function cloneTokenGitAuth(token: string): ProviderGitAuth;
|
|
7
|
+
//# sourceMappingURL=clone-token-auth.d.ts.map
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ProviderGitAuth } from '@kici-dev/engine';
|
|
2
|
+
import type { ProviderBundle, ProviderRegistry } from '../provider-registry.js';
|
|
3
|
+
/** Auth the dispatch message carries; every field is optional on the wire. */
|
|
4
|
+
export interface DispatchCloneAuth {
|
|
5
|
+
/** Bare source-repository token, kept for agents that read only `token`. */
|
|
6
|
+
token?: string;
|
|
7
|
+
sourceAuth?: ProviderGitAuth;
|
|
8
|
+
workflowAuth?: ProviderGitAuth;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Mint structured auth (and a bare token when it is basic auth) for one
|
|
12
|
+
* repository through one bundle. Providers that implement `issueGitAuth()`
|
|
13
|
+
* return the auth kind directly; otherwise a clone token is wrapped in a
|
|
14
|
+
* basic-auth envelope.
|
|
15
|
+
*/
|
|
16
|
+
export declare function mintRepoGitAuth(bundle: ProviderBundle, repoIdentifier: string, providerContext: unknown): Promise<{
|
|
17
|
+
token: string | null;
|
|
18
|
+
structuredAuth: ProviderGitAuth | null;
|
|
19
|
+
}>;
|
|
20
|
+
/** The job fields the auth resolution reads. */
|
|
21
|
+
export interface DispatchAuthJob {
|
|
22
|
+
id: string;
|
|
23
|
+
repoUrl: string;
|
|
24
|
+
routingKey: string;
|
|
25
|
+
providerContext: unknown;
|
|
26
|
+
jobConfig: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The git host of a clone URL: the URL host, or the host of an scp-style
|
|
30
|
+
* `[user@]host:path` remote. `undefined` when neither form parses.
|
|
31
|
+
*/
|
|
32
|
+
export declare function gitHostOf(url: string): string | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Why a global job must not be dispatched with this auth, or `undefined` when
|
|
35
|
+
* it may.
|
|
36
|
+
*
|
|
37
|
+
* The agent falls back across the two clones: it clones the source repository
|
|
38
|
+
* with `sourceAuth ?? workflowAuth ?? token` and the workflow repository with
|
|
39
|
+
* `workflowAuth ?? sourceAuth ?? token`. When only one repository's credential is
|
|
40
|
+
* present, the other clone sends it to that repository's host. On the same host
|
|
41
|
+
* that is a credential the host issued; on another host it hands one provider's
|
|
42
|
+
* credential to another, so the job is refused instead. A job with no source URL
|
|
43
|
+
* clones nothing from a host, and neither does a `file:` clone, so pairing one
|
|
44
|
+
* credential with a local repository is never refused.
|
|
45
|
+
*/
|
|
46
|
+
export declare function crossHostAuthRefusal(jobConfig: Record<string, unknown>, repoUrl: string, auth: DispatchCloneAuth): string | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Resolve the clone auth of one dispatch: the source repository's through the
|
|
49
|
+
* job's bundle, and for a global job the workflow repository's through its own
|
|
50
|
+
* bundle. Returns a refusal message when the job must not be dispatched.
|
|
51
|
+
*/
|
|
52
|
+
export declare function resolveDispatchCloneAuth(args: {
|
|
53
|
+
providerRegistry: ProviderRegistry;
|
|
54
|
+
/** The bundle of the job's routing key; undefined for an overlay (local) run. */
|
|
55
|
+
bundle: ProviderBundle | undefined;
|
|
56
|
+
repoIdentifier: string;
|
|
57
|
+
job: DispatchAuthJob;
|
|
58
|
+
}): Promise<{
|
|
59
|
+
auth: DispatchCloneAuth;
|
|
60
|
+
} | {
|
|
61
|
+
refused: string;
|
|
62
|
+
}>;
|
|
63
|
+
//# sourceMappingURL=dispatch-git-auth.d.ts.map
|
|
@@ -18,9 +18,11 @@ export declare function parseLockDocument(raw: string, repoIdentifier: string, r
|
|
|
18
18
|
* `schemaVersion` is at or above this codebase's `BREAKING_FLOOR` and whose
|
|
19
19
|
* required reader version is at or below this orchestrator's `SCHEMA_VERSION`.
|
|
20
20
|
* Both out-of-window cases throw a `LockFileParseError` (the established
|
|
21
|
-
* corrupt-lock signal) carrying operator-actionable guidance.
|
|
21
|
+
* corrupt-lock signal) carrying operator-actionable guidance. `readerVersion`
|
|
22
|
+
* is the schema version this orchestrator reads, overridable so a test can pose
|
|
23
|
+
* as an older orchestrator.
|
|
22
24
|
*/
|
|
23
|
-
export declare function assertLockFileSchemaCompatible(lockFile: LockFile, repoIdentifier: string, ref: string): void;
|
|
25
|
+
export declare function assertLockFileSchemaCompatible(lockFile: LockFile, repoIdentifier: string, ref: string, readerVersion?: number): void;
|
|
24
26
|
/**
|
|
25
27
|
* Walk every static job's runsOn / excludeLabels / runsOnAll matchers and throw
|
|
26
28
|
* if any element is not a valid LabelMatcher. Dynamic job generators carry no
|
|
@@ -642,7 +642,7 @@ export declare const installSecretsContributorStrippedTotal: import("@openteleme
|
|
|
642
642
|
*/
|
|
643
643
|
export declare const containerRegistryAuthContributorStrippedTotal: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
|
|
644
644
|
/**
|
|
645
|
-
* Per-environment latency of `secretResolver.
|
|
645
|
+
* Per-environment latency of `secretResolver.resolveForContext` calls in the
|
|
646
646
|
* install-secrets path. Buckets mirror `triggerMatchDurationSeconds`:
|
|
647
647
|
* 1ms → 5s covers fast Postgres reads through pathological Vault timeouts.
|
|
648
648
|
*
|
|
@@ -14,6 +14,11 @@ export interface RunClaimSource {
|
|
|
14
14
|
run_id: string;
|
|
15
15
|
org_id: string;
|
|
16
16
|
repo_identifier: string | null;
|
|
17
|
+
/**
|
|
18
|
+
* `owner/repo` of the repository that defines the workflow, when that is not
|
|
19
|
+
* `repo_identifier` (a global workflow). NULL for a same-repository run.
|
|
20
|
+
*/
|
|
21
|
+
workflow_repo_identifier: string | null;
|
|
17
22
|
ref: string | null;
|
|
18
23
|
sha: string | null;
|
|
19
24
|
workflow_name: string | null;
|
|
@@ -77,6 +82,11 @@ export interface IdTokenClaims extends EventClaims {
|
|
|
77
82
|
kici_run_id: string;
|
|
78
83
|
kici_job_id: string;
|
|
79
84
|
repository: string | null;
|
|
85
|
+
/**
|
|
86
|
+
* The repository that defines the workflow. Equals `repository` for a
|
|
87
|
+
* same-repository run; names the workflow repository for a global workflow.
|
|
88
|
+
*/
|
|
89
|
+
workflow_repository: string | null;
|
|
80
90
|
ref: string | null;
|
|
81
91
|
sha: string | null;
|
|
82
92
|
workflow_ref: string | null;
|
|
@@ -40,6 +40,8 @@ export interface OidcMintRegistrationInput {
|
|
|
40
40
|
* first mint (leader-election-race-safe).
|
|
41
41
|
*/
|
|
42
42
|
resolveOrchestratorSigner?: () => Promise<Signer | null>;
|
|
43
|
+
/** Whether this node is the Raft leader; named when a mint defers for want of a key. */
|
|
44
|
+
isLeader?: () => boolean;
|
|
43
45
|
/** The orchestrator's own provenance issuer identity (config.provenanceSigningIssuer). */
|
|
44
46
|
provenanceSigningIssuer?: string;
|
|
45
47
|
dispatcher: LocalMintOwnershipResolver & {
|
|
@@ -21,6 +21,21 @@ import type { Signer } from './signer.js';
|
|
|
21
21
|
export declare const DEFAULT_ORG_ID = "__default__";
|
|
22
22
|
/** ID-token lifetime (seconds). */
|
|
23
23
|
export declare const ORCHESTRATOR_ID_TOKEN_TTL_SECONDS = 600;
|
|
24
|
+
/**
|
|
25
|
+
* Longest an agent mint waits for the provenance signer before it answers
|
|
26
|
+
* `{ deferred: true, code: 'unavailable' }`. Half the agent's `agent.api`
|
|
27
|
+
* timeout, so the deferred answer crosses the WebSocket and sandbox hops and
|
|
28
|
+
* reaches the step before the agent gives up on the call.
|
|
29
|
+
*/
|
|
30
|
+
export declare const ORCHESTRATOR_MINT_SIGNER_WAIT_MS: number;
|
|
31
|
+
/**
|
|
32
|
+
* Minimum spacing between two warnings about mints deferred for want of a
|
|
33
|
+
* signing key. The first deferral after a signer was last available warns at
|
|
34
|
+
* once; later ones within the interval are counted into the next warning.
|
|
35
|
+
*/
|
|
36
|
+
export declare const MINT_DEFER_WARN_INTERVAL_MS = 60000;
|
|
37
|
+
/** Logged when an agent mint defers because no provenance signing key is ready. */
|
|
38
|
+
export declare const MINT_DEFERRED_NO_SIGNER_MESSAGE = "provenance signing key is not provisioned; deferring the identity-token mint";
|
|
24
39
|
export declare class OrchestratorMintRunNotFoundError extends Error {
|
|
25
40
|
}
|
|
26
41
|
export declare class OrchestratorMintJobNotFoundError extends Error {
|
|
@@ -77,12 +92,18 @@ export declare class OrchestratorMintSignerUnavailableError extends Error {
|
|
|
77
92
|
export interface OrchestratorOidcTokenHandlerDeps {
|
|
78
93
|
dispatcher: OrchestratorMintOwnershipResolver;
|
|
79
94
|
/**
|
|
80
|
-
* Lazily resolve the orchestrator's signing key.
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
95
|
+
* Lazily resolve the orchestrator's signing key. May return null while the
|
|
96
|
+
* key is still being reconciled. The handler waits at most
|
|
97
|
+
* {@link ORCHESTRATOR_MINT_SIGNER_WAIT_MS} for it; a null or a later answer
|
|
98
|
+
* defers the mint.
|
|
84
99
|
*/
|
|
85
100
|
resolveSigner: () => Promise<Signer | null>;
|
|
101
|
+
/**
|
|
102
|
+
* Whether this node is the Raft leader, named in the deferral warning so an
|
|
103
|
+
* operator can tell a non-leader waiting on the leader from a leader that
|
|
104
|
+
* could not create the key.
|
|
105
|
+
*/
|
|
106
|
+
isLeader?: () => boolean;
|
|
86
107
|
/** Mint deps except the signer (supplied lazily via `resolveSigner`). */
|
|
87
108
|
mint: Omit<OrchestratorMintDeps, 'signer'>;
|
|
88
109
|
/**
|