@kici-dev/orchestrator 0.15.0 → 0.16.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.
Files changed (146) hide show
  1. package/dist/__test-helpers__/scratch-db.d.ts +16 -0
  2. package/dist/agent/registry.d.ts +1 -8
  3. package/dist/app-on-error.d.ts +1 -1
  4. package/dist/artifacts/artifact-store.d.ts +0 -2
  5. package/dist/audit/access-log.d.ts +1 -1
  6. package/dist/cache/source-cache.d.ts +1 -1
  7. package/dist/cache/user-cache.d.ts +0 -28
  8. package/dist/cli/api-client.d.ts +27 -1
  9. package/dist/cli/commands/access-log.d.ts +1 -1
  10. package/dist/cli/commands/cold-store-impl.d.ts +7 -84
  11. package/dist/cli/commands/db.d.ts +1 -0
  12. package/dist/cli/commands/orchestrator-service/status.d.ts +2 -0
  13. package/dist/cli/commands/org.d.ts +12 -0
  14. package/dist/cli/commands/scaler.d.ts +14 -0
  15. package/dist/cli/commands/secret.d.ts +1 -45
  16. package/dist/cli/commands/service-health.d.ts +21 -13
  17. package/dist/cli/commands/shared/cli-action.d.ts +17 -0
  18. package/dist/cli/commands/shared/db.d.ts +5 -5
  19. package/dist/cli/commands/shared/org-id.d.ts +5 -0
  20. package/dist/cli/commands/shared/service-verbs.d.ts +19 -0
  21. package/dist/cli/commands/shared/table.d.ts +3 -0
  22. package/dist/cli/commands/shared/unbound-context-warning.d.ts +2 -22
  23. package/dist/cli/commands/trust-policy.d.ts +7 -31
  24. package/dist/cli/kici-admin.d.ts +1 -1
  25. package/dist/cli.js +9863 -8201
  26. package/dist/cluster/coordinator.d.ts +2 -2
  27. package/dist/cluster/peer-client.d.ts +27 -1
  28. package/dist/cluster/peer-forget.d.ts +4 -9
  29. package/dist/cluster/peer-handler.d.ts +11 -1
  30. package/dist/cluster/peer-request-waiters.d.ts +26 -0
  31. package/dist/cluster/scaler-orphans-peer.d.ts +4 -9
  32. package/dist/cluster/scaler-reload-fanout.d.ts +29 -0
  33. package/dist/cluster/scaler-reload-peer.d.ts +16 -0
  34. package/dist/cluster/worker-cluster-settings.d.ts +1 -0
  35. package/dist/cold-store/load-access-log-range.d.ts +3 -3
  36. package/dist/cold-store/tables/access-log.d.ts +4 -12
  37. package/dist/cold-store/tables/event-log.d.ts +8 -19
  38. package/dist/cold-store/tables/execution-jobs.d.ts +7 -24
  39. package/dist/cold-store/tables/execution-runs.d.ts +6 -20
  40. package/dist/cold-store/tables/execution-steps.d.ts +8 -26
  41. package/dist/cold-store/tables/secret-audit-log.d.ts +4 -11
  42. package/dist/config/env-overlay.d.ts +3 -8
  43. package/dist/config/reload.d.ts +9 -2
  44. package/dist/config/schema.d.ts +2 -2
  45. package/dist/config/types.d.ts +2 -2
  46. package/dist/config.d.ts +13 -17
  47. package/dist/contexts/held-runs.d.ts +3 -6
  48. package/dist/dashboard/cursor.d.ts +12 -0
  49. package/dist/dashboard/handler.d.ts +5 -12
  50. package/dist/db/deferred-index-build.d.ts +42 -0
  51. package/dist/db/deferred-indexes.d.ts +3 -37
  52. package/dist/db/migrations/100_held_runs_hold_type_vocabulary.d.ts +3 -5
  53. package/dist/db/migrations/158_normalize_legacy_values.d.ts +4 -0
  54. package/dist/db/repos/org-ids-repo.d.ts +87 -0
  55. package/dist/db/schema-snapshot.generated.d.ts +3 -0
  56. package/dist/db/types.d.ts +5 -22
  57. package/dist/fault-injection-types.d.ts +0 -6
  58. package/dist/git/dispatch-git-auth.d.ts +6 -12
  59. package/dist/helpers/json.d.ts +3 -0
  60. package/dist/index.js +133 -136
  61. package/dist/metrics/prometheus.d.ts +0 -5
  62. package/dist/oidc/id-token-claims.d.ts +1 -1
  63. package/dist/oidc/resolve-signer.d.ts +2 -4
  64. package/dist/orchestrator-core.d.ts +10 -3
  65. package/dist/pipeline/global-eval-round.d.ts +2 -26
  66. package/dist/pipeline/install-secrets-resolver.d.ts +0 -3
  67. package/dist/pipeline/manual-schedule.d.ts +1 -7
  68. package/dist/provenance/dispatch-context.d.ts +5 -7
  69. package/dist/provenance/pending-attestations-repo.d.ts +1 -1
  70. package/dist/provenance/trust-root.d.ts +4 -5
  71. package/dist/provenance/verify-deferred-capture.d.ts +3 -3
  72. package/dist/provider-registry.d.ts +13 -40
  73. package/dist/providers/universal-git/ssh-auth.d.ts +0 -5
  74. package/dist/reporting/check-run-reporter.d.ts +8 -21
  75. package/dist/reporting/check-run-summary.d.ts +2 -2
  76. package/dist/reporting/execution-tracker.d.ts +1 -1
  77. package/dist/reporting/log-chunk-sink.d.ts +1 -1
  78. package/dist/reporting/run-summary-fields.d.ts +25 -0
  79. package/dist/reporting/s3-log-storage.d.ts +2 -2
  80. package/dist/routes/admin-access-log.d.ts +2 -9
  81. package/dist/routes/admin-backends.d.ts +2 -9
  82. package/dist/routes/admin-cluster-name.d.ts +2 -8
  83. package/dist/routes/admin-cluster-settings.d.ts +2 -8
  84. package/dist/routes/admin-config.d.ts +0 -3
  85. package/dist/routes/admin-contexts.d.ts +3 -11
  86. package/dist/routes/admin-db.d.ts +2 -9
  87. package/dist/routes/admin-env.d.ts +33 -0
  88. package/dist/routes/admin-event-dlq.d.ts +2 -9
  89. package/dist/routes/admin-event-inspect.d.ts +2 -9
  90. package/dist/routes/admin-event-log.d.ts +2 -9
  91. package/dist/routes/admin-events.d.ts +3 -13
  92. package/dist/routes/admin-held-runs.d.ts +2 -8
  93. package/dist/routes/admin-list-limit.d.ts +3 -0
  94. package/dist/routes/admin-maintenance.d.ts +2 -9
  95. package/dist/routes/admin-orchestrator-drain.d.ts +2 -9
  96. package/dist/routes/admin-org-settings.d.ts +2 -8
  97. package/dist/routes/admin-orgs.d.ts +27 -0
  98. package/dist/routes/admin-peer-forget.d.ts +2 -9
  99. package/dist/routes/admin-queue-execution.d.ts +3 -10
  100. package/dist/routes/admin-registrations.d.ts +3 -14
  101. package/dist/routes/admin-runs.d.ts +3 -14
  102. package/dist/routes/admin-scaler-orphans.d.ts +2 -9
  103. package/dist/routes/admin-scaler-reload.d.ts +41 -0
  104. package/dist/routes/admin-scheduled-jobs.d.ts +2 -9
  105. package/dist/routes/admin-signing-keys.d.ts +2 -9
  106. package/dist/routes/admin-sources.d.ts +2 -9
  107. package/dist/routes/admin-trust-policy.d.ts +2 -8
  108. package/dist/routes/admin.d.ts +15 -13
  109. package/dist/scaler/config.d.ts +12 -84
  110. package/dist/scaler/file-reload.d.ts +48 -0
  111. package/dist/scaler/manager.d.ts +47 -33
  112. package/dist/scaler/scaler-state-store.d.ts +5 -0
  113. package/dist/scaler/types.d.ts +1 -4
  114. package/dist/secrets/job-secret-gate.d.ts +2 -5
  115. package/dist/secrets/secret-resolver.d.ts +2 -4
  116. package/dist/security/trust-policy-gate.d.ts +0 -4
  117. package/dist/server.d.ts +6 -17
  118. package/dist/server.js +6693 -8005
  119. package/dist/standalone.js +5826 -6555
  120. package/dist/worker/reroute-dispatch.d.ts +1 -0
  121. package/dist/worker/reroute-spawn-control.d.ts +1 -3
  122. package/dist/worker-core.d.ts +9 -2
  123. package/dist/ws/agent-handler.d.ts +3 -3
  124. package/dist/ws/dashboard-access.d.ts +57 -0
  125. package/dist/ws/dashboard-backends-handler.d.ts +1 -6
  126. package/dist/ws/dashboard-context-handler.d.ts +10 -15
  127. package/dist/ws/dashboard-fleet-write-handler.d.ts +1 -6
  128. package/dist/ws/dashboard-global-workflows-handler.d.ts +1 -6
  129. package/dist/ws/dashboard-registrations-handler.d.ts +1 -7
  130. package/dist/ws/platform-client.d.ts +85 -330
  131. package/installer-image-digests.json +3 -3
  132. package/package.json +4 -4
  133. package/sbom.spdx.json +53 -53
  134. package/dist/cache/legacy-prefixes.d.ts +0 -19
  135. package/dist/cli/commands/agent-service/logs.d.ts +0 -14
  136. package/dist/cli/commands/agent-service/restart.d.ts +0 -12
  137. package/dist/cli/commands/agent-service/start.d.ts +0 -12
  138. package/dist/cli/commands/agent-service/stop.d.ts +0 -12
  139. package/dist/cli/commands/agent-service/uninstall.d.ts +0 -13
  140. package/dist/cli/commands/cache.d.ts +0 -51
  141. package/dist/cli/commands/orchestrator-service/logs.d.ts +0 -14
  142. package/dist/cli/commands/orchestrator-service/restart.d.ts +0 -12
  143. package/dist/cli/commands/orchestrator-service/start.d.ts +0 -12
  144. package/dist/cli/commands/orchestrator-service/stop.d.ts +0 -12
  145. package/dist/cli/commands/orchestrator-service/uninstall.d.ts +0 -13
  146. package/dist/git/inherited-secret.d.ts +0 -29
@@ -14,6 +14,7 @@
14
14
  import type { Logger } from '@kici-dev/shared';
15
15
  import type { AppConfig, SharedConfig } from './types.js';
16
16
  import type { SharedConfigStore } from './shared-store.js';
17
+ import type { ScalerFileReloadResult } from '../scaler/file-reload.js';
17
18
  /**
18
19
  * Source of a reload trigger.
19
20
  */
@@ -29,6 +30,12 @@ export interface ReloadResult {
29
30
  restartRequired?: string[];
30
31
  /** Fields that were hot-reloaded */
31
32
  fieldsChanged?: string[];
33
+ /**
34
+ * The scaler config's own reload outcome, when this orchestrator runs one.
35
+ * `success` describes the orchestrator config only: a refused scaler file
36
+ * shows here as `rejected` while `success` stays true.
37
+ */
38
+ scaler?: ScalerFileReloadResult;
32
39
  }
33
40
  /**
34
41
  * Options for executeReload.
@@ -53,8 +60,8 @@ export interface ConfigReloaderDeps {
53
60
  sharedStore: SharedConfigStore | null;
54
61
  /** Called after successful reload when provider config changed */
55
62
  onProviderChange?: (newConfig: AppConfig, oldConfig: AppConfig) => Promise<void>;
56
- /** Called to reload scaler configuration */
57
- onScalerReload?: () => Promise<void>;
63
+ /** Called to reload scaler configuration; its outcome is returned as `ReloadResult.scaler`. */
64
+ onScalerReload?: () => Promise<ScalerFileReloadResult | void>;
58
65
  /** Called when Platform connection settings changed */
59
66
  onPlatformReconnect?: (newConfig: AppConfig) => Promise<void>;
60
67
  /** Atomic swap callback -- replaces the config reference */
@@ -109,7 +109,7 @@ export declare const sharedConfigSchema: z.ZodObject<{
109
109
  coordinator: "coordinator";
110
110
  worker: "worker";
111
111
  }>>;
112
- coordinatorUrl: z.ZodOptional<z.ZodString>;
112
+ coordinatorUrls: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodString]>>;
113
113
  peerStaleTimeoutMs: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
114
114
  peerDiscovery: z.ZodOptional<z.ZodEnum<{
115
115
  platform: "platform";
@@ -201,7 +201,7 @@ export declare const appConfigSchema: z.ZodObject<{
201
201
  coordinator: "coordinator";
202
202
  worker: "worker";
203
203
  }>>;
204
- coordinatorUrl: z.ZodOptional<z.ZodString>;
204
+ coordinatorUrls: z.ZodDefault<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodPipe<z.ZodString, z.ZodTransform<string[], string>>]>>;
205
205
  peerStaleTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
206
206
  peerDiscovery: z.ZodDefault<z.ZodEnum<{
207
207
  platform: "platform";
@@ -187,8 +187,8 @@ export interface AppConfig {
187
187
  peerMaxReconnectDelayMs: number;
188
188
  /** Cluster role: coordinator (full orchestrator) or worker (delegated execution). */
189
189
  role: 'coordinator' | 'worker';
190
- /** URL of the coordinator to connect to when role=worker. */
191
- coordinatorUrl?: string;
190
+ /** URLs of every coordinator to connect to when role=worker. */
191
+ coordinatorUrls: string[];
192
192
  /** Stale peer timeout in ms. */
193
193
  peerStaleTimeoutMs: number;
194
194
  /** Whether this coordinator dials Platform-announced peers. */
package/dist/config.d.ts CHANGED
@@ -1,15 +1,9 @@
1
1
  /**
2
- * Orchestrator configuration.
2
+ * Orchestrator startup configuration, read from `KICI_*` environment variables.
3
3
  *
4
- * This is a thin backward-compatible wrapper around the new config resolution
5
- * chain (config/resolver.ts). It preserves the existing synchronous loadConfig()
6
- * API so that no other files need changing.
7
- *
8
- * The new config system lives in config/ and supports:
9
- * - YAML config files (config/loader.ts)
10
- * - Shared DB config store (config/shared-store.ts)
11
- * - 4-layer resolution: env > YAML > DB > defaults (config/resolver.ts)
12
- * - KICI_ env var mapping (config/env-overlay.ts)
4
+ * The runtime config reloader lives in config/: YAML files (config/loader.ts),
5
+ * the shared DB config store (config/shared-store.ts), the env overlay
6
+ * (config/env-overlay.ts) and the resolution chain (config/resolver.ts).
13
7
  *
14
8
  * Provider configuration (GitHub Apps, etc.) is managed via the `sources` table
15
9
  * and PgSecretStore, not through config. See SourceStore and SourceManager.
@@ -122,7 +116,6 @@ declare const configSchema: z.ZodObject<{
122
116
  filesystem: "filesystem";
123
117
  s3: "s3";
124
118
  }>>;
125
- cacheStoragePath: z.ZodOptional<z.ZodString>;
126
119
  cacheStorageS3Bucket: z.ZodOptional<z.ZodString>;
127
120
  cacheStorageS3Prefix: z.ZodDefault<z.ZodString>;
128
121
  cacheStorageS3Region: z.ZodOptional<z.ZodString>;
@@ -240,7 +233,6 @@ declare const configSchema: z.ZodObject<{
240
233
  coordinator: "coordinator";
241
234
  worker: "worker";
242
235
  }>>;
243
- coordinatorUrl: z.ZodOptional<z.ZodString>;
244
236
  coordinatorUrls: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string[], string | undefined>>;
245
237
  peerStaleTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
246
238
  electionGracePeriodMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
@@ -340,7 +332,6 @@ export declare const packagingConfigSchema: z.ZodObject<{
340
332
  filesystem: "filesystem";
341
333
  s3: "s3";
342
334
  }>>;
343
- cacheStoragePath: z.ZodOptional<z.ZodString>;
344
335
  cacheStorageS3Bucket: z.ZodOptional<z.ZodString>;
345
336
  cacheStorageS3Prefix: z.ZodDefault<z.ZodString>;
346
337
  cacheStorageS3Region: z.ZodOptional<z.ZodString>;
@@ -458,7 +449,6 @@ export declare const packagingConfigSchema: z.ZodObject<{
458
449
  coordinator: "coordinator";
459
450
  worker: "worker";
460
451
  }>>;
461
- coordinatorUrl: z.ZodOptional<z.ZodString>;
462
452
  coordinatorUrls: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string[], string | undefined>>;
463
453
  peerStaleTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
464
454
  electionGracePeriodMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
@@ -479,7 +469,7 @@ export declare const packagingConfigSchema: z.ZodObject<{
479
469
  export type AppConfig = z.infer<typeof configSchema> & {
480
470
  /** Unique identifier for this orchestrator instance, generated at startup */
481
471
  instanceId: string;
482
- /** Object storage settings (populated from legacy env vars or SharedConfig) */
472
+ /** Object storage settings (populated from the KICI_STORAGE_* env vars or SharedConfig) */
483
473
  storage?: {
484
474
  type?: 's3' | 'filesystem';
485
475
  bucket?: string;
@@ -585,7 +575,6 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
585
575
  scalerProvisionBackoffMaxMs: number;
586
576
  scalerProvisionMaxConsecutiveFailures: number;
587
577
  cacheStorageType?: "filesystem" | "s3" | undefined;
588
- cacheStoragePath?: string | undefined;
589
578
  cacheStorageS3Bucket?: string | undefined;
590
579
  cacheStorageS3Prefix: string;
591
580
  cacheStorageS3Region?: string | undefined;
@@ -676,7 +665,6 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
676
665
  peerHeartbeatIntervalMs: number;
677
666
  peerMaxReconnectDelayMs: number;
678
667
  role: "coordinator" | "worker";
679
- coordinatorUrl?: string | undefined;
680
668
  coordinatorUrls: string[];
681
669
  peerStaleTimeoutMs: number;
682
670
  electionGracePeriodMs: number;
@@ -685,6 +673,14 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
685
673
  trustedProxies: string[];
686
674
  };
687
675
  }>;
676
+ /**
677
+ * Load the startup orchestrator configuration from environment variables.
678
+ *
679
+ * It reads `process.env` through the names declared in `envDef`
680
+ * (KICI_DATABASE_URL, KICI_PORT, …) and refuses unknown `KICI_*` names. The
681
+ * config reloader (`config/resolver.ts`) layers the YAML file and the shared
682
+ * DB config store on top at runtime.
683
+ */
688
684
  export declare function loadConfig(scope?: ConfigScope): AppConfig;
689
685
  export {};
690
686
  //# sourceMappingURL=config.d.ts.map
@@ -279,12 +279,9 @@ export declare class HeldRunStore {
279
279
  * incidental: `expireOverdue` is not scope-filtered, so a released-but-not-yet-
280
280
  * resumed row would otherwise be expired out from under its resume.
281
281
  *
282
- * The filter matches every persisted spelling of the timer hold type, so a row
283
- * an un-upgraded orchestrator wrote as `wait_timer` still resumes rather than
284
- * falling through to the expire-and-fail sweep. It deliberately does NOT
285
- * filter on `hold_scope`: a job-scoped timer hold used to be excluded here,
286
- * which left it with no release path at all — created, never released,
287
- * eventually expired, its job never dispatched.
282
+ * The filter deliberately does NOT filter on `hold_scope`: a job-scoped timer
283
+ * hold used to be excluded here, which left it with no release path at all —
284
+ * created, never released, eventually expired, its job never dispatched.
288
285
  */
289
286
  releaseDueWaitHolds(): Promise<ReleaseSignal[]>;
290
287
  /**
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Opaque pagination cursors for the dashboard list handlers:
3
+ * base64url(JSON(fields)), every field a string.
4
+ */
5
+ /** Encode `fields` as a cursor. Key order follows the object literal. */
6
+ export declare function encodeCursor(fields: Record<string, string>): string;
7
+ /**
8
+ * Decode a cursor into exactly `keys`. Returns null when the cursor is not
9
+ * base64url JSON or any key is missing or not a string; other keys are dropped.
10
+ */
11
+ export declare function decodeCursor<K extends string>(raw: string, keys: readonly K[]): Record<K, string> | null;
12
+ //# sourceMappingURL=cursor.d.ts.map
@@ -14,7 +14,7 @@ interface DashboardHandlerDeps {
14
14
  * The orchestrator's own provenance issuer (`KICI_ORCHESTRATOR_PROVENANCE_ISSUER`)
15
15
  * when it owns signing. Surfaced on attestations-list responses so the Platform
16
16
  * returns it as `trustedIssuer` — the dashboard / CLI verify against the
17
- * orchestrator that actually signed the bundles, not the Platform's own issuer.
17
+ * orchestrator that signed the bundles.
18
18
  */
19
19
  provenanceSigningIssuer?: string | null;
20
20
  /**
@@ -127,6 +127,7 @@ export declare class DashboardHandler {
127
127
  private readonly send;
128
128
  private readonly orchestratorId;
129
129
  private readonly accessLog;
130
+ private readonly access;
130
131
  private orgId;
131
132
  private routingKey;
132
133
  private readonly onRerun;
@@ -142,7 +143,7 @@ export declare class DashboardHandler {
142
143
  * Update the bound orgId + routingKey. Called from server.ts after resolving
143
144
  * the single tenant org from the `sources` / `generic_webhook_sources` table.
144
145
  *
145
- * NOTE: this binding is the **fallback** for `recordAccess`. Run-targeted
146
+ * NOTE: this binding is the **fallback** access_log scope. Run-targeted
146
147
  * handlers resolve the run-owning org per-request via `resolveOrgForRun`;
147
148
  * the bound pair is consulted only when the per-target lookup yields no
148
149
  * result (e.g. cold-archived run, deleted source). On a multi-tenant
@@ -190,14 +191,6 @@ export declare class DashboardHandler {
190
191
  * has the operation switched off.
191
192
  */
192
193
  private enforcePolicy;
193
- /**
194
- * Write an access_log row for a handler invocation. The caller resolves
195
- * the run-owning org via `resolveOrgForRun` (or the registration / event-
196
- * log equivalents) and threads it in here so each row carries the org
197
- * that owns the target — not the handler-bound (multi-tenant: non-
198
- * deterministic) pair. Best-effort; the writer swallows failures.
199
- */
200
- private recordAccess;
201
194
  /**
202
195
  * Handle a dashboard.run.detail request.
203
196
  * Queries execution_jobs and execution_steps for the given runId,
@@ -337,14 +330,14 @@ export declare class DashboardHandler {
337
330
  * Handle a dashboard.attestations.list request: list the run's provenance
338
331
  * attestations, inlining each stored bundle from object storage so the
339
332
  * dashboard verifies it client-side. Mirrors `handleStepLogs` (per-run org
340
- * resolution + `recordAccess` + `send`). Rows whose bundle can't be read are
333
+ * resolution + `access.recordIn` + `send`). Rows whose bundle can't be read are
341
334
  * skipped (best-effort) rather than failing the whole list.
342
335
  */
343
336
  handleAttestationsList(msg: DashboardAttestationsListRequest): Promise<void>;
344
337
  /**
345
338
  * Handle a dashboard.artifacts.list request: list the run's named artifacts
346
339
  * with a presigned GET per entry. Mirrors `handleAttestationsList` (per-run
347
- * org resolution + `recordAccess` + `send`). Org is resolved server-side from
340
+ * org resolution + `access.recordIn` + `send`). Org is resolved server-side from
348
341
  * the run row, never the wire, so the listing cannot cross tenants.
349
342
  */
350
343
  handleArtifactsList(msg: DashboardArtifactsListRequest): Promise<void>;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Builds the deferred indexes (`deferred-indexes.ts`) after boot, each one
3
+ * `CONCURRENTLY` on its own connection.
4
+ */
5
+ import type pg from 'pg';
6
+ import { type Logger } from '@kici-dev/shared';
7
+ import { type DeferredIndex } from './deferred-indexes.js';
8
+ /**
9
+ * Distinct from the migrator's `543210001`: an index build must not block, or
10
+ * be blocked by, a peer applying migrations.
11
+ */
12
+ export declare const DEFERRED_INDEX_LOCK_KEY = 543210002;
13
+ /**
14
+ * Drop a leftover invalid index before rebuilding it.
15
+ *
16
+ * An interrupted `CREATE INDEX CONCURRENTLY` leaves the index in place marked
17
+ * invalid: it is not used by the planner, and `IF NOT EXISTS` sees it and
18
+ * skips. Without this, the very first failed build would make the retry a
19
+ * permanent no-op — the opposite of the "retries on the next boot" contract.
20
+ */
21
+ export declare function dropIfInvalid(client: Pick<pg.Client, 'query'>, name: string, logger: Logger): Promise<void>;
22
+ export interface BuildDeferredIndexesResult {
23
+ built: string[];
24
+ failed: string[];
25
+ }
26
+ /**
27
+ * Build every deferred index on one dedicated connection.
28
+ *
29
+ * The connection is taken straight from `pg` rather than from the serving
30
+ * pool: `CREATE INDEX CONCURRENTLY` must run outside a transaction and must
31
+ * not inherit a statement timeout, and a concurrent build on a large table
32
+ * would otherwise hold a serving connection for its whole duration.
33
+ *
34
+ * The advisory lock is `pg_try_advisory_lock`, not the blocking form: when a
35
+ * peer is already building, this instance has nothing to wait for.
36
+ */
37
+ export declare function buildDeferredIndexes(databaseUrl: string, opts?: {
38
+ logger?: Logger;
39
+ indexes?: ReadonlyArray<DeferredIndex>;
40
+ pg?: typeof import('pg');
41
+ }): Promise<BuildDeferredIndexesResult>;
42
+ //# sourceMappingURL=deferred-index-build.d.ts.map
@@ -16,15 +16,10 @@
16
16
  * a failed build retries on the next boot.
17
17
  *
18
18
  * A repository check enforces that new indexes on those tables land here
19
- * rather than in a migration.
19
+ * rather than in a migration. The build itself is `deferred-index-build.ts`;
20
+ * this module holds only the list, so a CLI can read it without loading the
21
+ * orchestrator's metrics.
20
22
  */
21
- import type pg from 'pg';
22
- import { type Logger } from '@kici-dev/shared';
23
- /**
24
- * Distinct from the migrator's `543210001`: an index build must not block, or
25
- * be blocked by, a peer applying migrations.
26
- */
27
- export declare const DEFERRED_INDEX_LOCK_KEY = 543210002;
28
23
  export interface DeferredIndex {
29
24
  /** Index name, matching the one the SQL creates. */
30
25
  name: string;
@@ -40,33 +35,4 @@ export interface DeferredIndex {
40
35
  * prefixed by an organization or routing key.
41
36
  */
42
37
  export declare const DEFERRED_INDEXES: ReadonlyArray<DeferredIndex>;
43
- /**
44
- * Drop a leftover invalid index before rebuilding it.
45
- *
46
- * An interrupted `CREATE INDEX CONCURRENTLY` leaves the index in place marked
47
- * invalid: it is not used by the planner, and `IF NOT EXISTS` sees it and
48
- * skips. Without this, the very first failed build would make the retry a
49
- * permanent no-op — the opposite of the "retries on the next boot" contract.
50
- */
51
- export declare function dropIfInvalid(client: Pick<pg.Client, 'query'>, name: string, logger: Logger): Promise<void>;
52
- export interface BuildDeferredIndexesResult {
53
- built: string[];
54
- failed: string[];
55
- }
56
- /**
57
- * Build every deferred index on one dedicated connection.
58
- *
59
- * The connection is taken straight from `pg` rather than from the serving
60
- * pool: `CREATE INDEX CONCURRENTLY` must run outside a transaction and must
61
- * not inherit a statement timeout, and a concurrent build on a large table
62
- * would otherwise hold a serving connection for its whole duration.
63
- *
64
- * The advisory lock is `pg_try_advisory_lock`, not the blocking form: when a
65
- * peer is already building, this instance has nothing to wait for.
66
- */
67
- export declare function buildDeferredIndexes(databaseUrl: string, opts?: {
68
- logger?: Logger;
69
- indexes?: ReadonlyArray<DeferredIndex>;
70
- pg?: typeof import('pg');
71
- }): Promise<BuildDeferredIndexesResult>;
72
38
  //# sourceMappingURL=deferred-indexes.d.ts.map
@@ -8,11 +8,9 @@ import { type Kysely } from 'kysely';
8
8
  * unknown-type badge — and two semantically identical wait holds render
9
9
  * differently depending on which gate produced them.
10
10
  *
11
- * Writers emit the gate vocabulary; this backfills the history. The read path
12
- * also normalizes (`normalizePersistedHoldType`) and the wait-hold release
13
- * sweep matches both spellings, so a row written by an un-upgraded
14
- * orchestrator behaves correctly whether or not this has run — the two sides
15
- * deploy independently.
11
+ * Writers emit the gate vocabulary; this backfills the history. Migration 158
12
+ * re-applies the same rewrite, after which the readers match the gate
13
+ * vocabulary only.
16
14
  *
17
15
  * Idempotent: a second run matches no rows.
18
16
  */
@@ -0,0 +1,4 @@
1
+ import { type Kysely } from 'kysely';
2
+ export declare function up(db: Kysely<unknown>): Promise<void>;
3
+ export declare function down(): Promise<void>;
4
+ //# sourceMappingURL=158_normalize_legacy_values.d.ts.map
@@ -0,0 +1,87 @@
1
+ /**
2
+ * The org ids this orchestrator holds data for, and which data names each one.
3
+ *
4
+ * The org-scoped kici-admin commands (`secret`, `context`, `variable`,
5
+ * `remote-source`, `org-settings`, `trust-policy`, `registration`) take an org
6
+ * id. This module answers "which org ids exist here" from the configuration and
7
+ * anchor tables, for both `GET /api/v1/admin/org-ids` and
8
+ * `kici-admin org list --database-url`, so the two transports cannot disagree.
9
+ */
10
+ import { type Kysely } from 'kysely';
11
+ import { z } from 'zod';
12
+ import type { Database } from '../types.js';
13
+ /**
14
+ * Where an org id was found. `platform` is the live Platform connection, which
15
+ * only the admin API can see; every other value names a table.
16
+ */
17
+ export declare const OrgIdSource: z.ZodEnum<{
18
+ context: "context";
19
+ "generic-source": "generic-source";
20
+ "org-settings": "org-settings";
21
+ platform: "platform";
22
+ registration: "registration";
23
+ "remote-source": "remote-source";
24
+ secret: "secret";
25
+ source: "source";
26
+ "trust-policy": "trust-policy";
27
+ }>;
28
+ export type OrgIdSource = z.infer<typeof OrgIdSource>;
29
+ /**
30
+ * The orchestrator's Platform attachment: `attached` once the Platform named
31
+ * the org on `auth.success`, `pending` while a Platform client has not
32
+ * authenticated yet, `none` when no Platform client runs (independent mode).
33
+ */
34
+ export declare const PlatformAttachment: z.ZodEnum<{
35
+ attached: "attached";
36
+ none: "none";
37
+ pending: "pending";
38
+ }>;
39
+ export type PlatformAttachment = z.infer<typeof PlatformAttachment>;
40
+ /** One org id and the data that names it. */
41
+ export interface HeldOrg {
42
+ orgId: string;
43
+ sources: OrgIdSource[];
44
+ }
45
+ /**
46
+ * Body of `GET /api/v1/admin/org-ids`. The two Platform fields are absent when the
47
+ * listing was read from the database directly: only the running orchestrator
48
+ * knows its connection.
49
+ */
50
+ export interface OrgListResponse {
51
+ platformAttachment?: PlatformAttachment;
52
+ attachedOrgId?: string | null;
53
+ orgs: HeldOrg[];
54
+ }
55
+ /** The admin API path of the listing. */
56
+ export declare const ORG_LIST_PATH = "/api/v1/admin/org-ids";
57
+ interface OrgIdTable {
58
+ table: keyof Database;
59
+ column: 'org_id' | 'customer_id';
60
+ source: Exclude<OrgIdSource, 'platform'>;
61
+ /** Skip soft-deleted rows (`deleted_at IS NULL`). */
62
+ liveOnly?: boolean;
63
+ }
64
+ /** The configuration and anchor tables an org-scoped command reads by org id. */
65
+ export declare const ORG_ID_TABLES: readonly OrgIdTable[];
66
+ /**
67
+ * Every other table with an `org_id` or `customer_id` column, and why the
68
+ * listing does not read it. A schema test fails when a migration adds an
69
+ * org-keyed table that is in neither this map nor {@link ORG_ID_TABLES}.
70
+ */
71
+ export declare const ORG_ID_TABLES_NOT_LISTED: Readonly<Record<string, string>>;
72
+ /** Group `(org id, source)` rows per org: org ids in byte order, sources in enum order. */
73
+ export declare function groupOrgIdRows(rows: ReadonlyArray<{
74
+ org_id: string;
75
+ source: OrgIdSource;
76
+ }>): HeldOrg[];
77
+ /** Add the Platform-attached org to a listing, with the `platform` source. */
78
+ export declare function withPlatformOrg(orgs: readonly HeldOrg[], attachedOrgId: string | null): HeldOrg[];
79
+ /** The attachment the admin API reports, from the Platform client's org id reader. */
80
+ export declare function readPlatformAttachment(getPlatformOrgId: (() => string | undefined) | undefined): {
81
+ platformAttachment: PlatformAttachment;
82
+ attachedOrgId: string | null;
83
+ };
84
+ /** Every org id the listed tables hold, in one round trip. */
85
+ export declare function listHeldOrgIds(db: Kysely<Database>): Promise<HeldOrg[]>;
86
+ export {};
87
+ //# sourceMappingURL=org-ids-repo.d.ts.map
@@ -0,0 +1,3 @@
1
+ import type { SchemaFingerprint } from '@kici-dev/shared';
2
+ export declare const SCHEMA_SNAPSHOT: SchemaFingerprint;
3
+ //# sourceMappingURL=schema-snapshot.generated.d.ts.map
@@ -1212,8 +1212,7 @@ export interface HeldRunsTable {
1212
1212
  /**
1213
1213
  * Hold type — an engine `HoldType` member ('reviewer' | 'timer' |
1214
1214
  * 'concurrency' | 'security'). Stays `string` so a row written by a
1215
- * different orchestrator version is never rejected; read it through
1216
- * `normalizePersistedHoldType`.
1215
+ * different orchestrator version is never rejected.
1217
1216
  */
1218
1217
  hold_type: string;
1219
1218
  /** Hold status: 'pending' | 'approved' | 'rejected' | 'expired' | 'released' */
@@ -1244,7 +1243,8 @@ export interface HeldRunsTable {
1244
1243
  trigger_source: Generated<string>;
1245
1244
  /**
1246
1245
  * Normalized `ApprovalRequirement` (clauses + expiresAt + reason) the hold
1247
- * must satisfy. Null for legacy rows that predate the approval model.
1246
+ * must satisfy. Null for a hold with no requirement: security, wait and queue
1247
+ * holds, which `security-hold-check.ts` tells apart on this column.
1248
1248
  */
1249
1249
  approval_requirement: ColumnType<ApprovalRequirement | null, ApprovalRequirement | string | null | undefined, ApprovalRequirement | string | null>;
1250
1250
  /**
@@ -2082,25 +2082,8 @@ export interface OrgTrustPolicyTable {
2082
2082
  customer_id: string;
2083
2083
  /** How to treat a pull request opened from a fork: ignore | hold | allow */
2084
2084
  fork_policy: string;
2085
- /**
2086
- * The coarse, hours-granularity view of the security-hold window.
2087
- *
2088
- * Retained and always written, because it is the only window an older peer or
2089
- * CLI can read. This build derives it from `approval_expiry_seconds` on every
2090
- * write (rounded up, never below 1), so the two columns cannot disagree.
2091
- */
2092
- approval_expiry_hours: number;
2093
- /**
2094
- * How long a security hold stays approvable before it expires, in seconds —
2095
- * the authoritative window, and the only granularity that can express a
2096
- * sub-hour hold.
2097
- *
2098
- * Nullable: NULL means no seconds value was ever written (a row predating the
2099
- * column, or one written by an older build), and every reader falls back to
2100
- * `approval_expiry_hours * 3600`. Same convention as
2101
- * `contexts.hold_expiry_seconds`.
2102
- */
2103
- approval_expiry_seconds: ColumnType<number | null, number | null | undefined, number | null>;
2085
+ /** How long a security hold stays approvable before it expires, in seconds. */
2086
+ approval_expiry_seconds: number;
2104
2087
  /** Which side last wrote this row: platform | local */
2105
2088
  source: string;
2106
2089
  /** When this policy was last written */
@@ -9,7 +9,6 @@
9
9
  * TS2307s. Only the declaration lives here — its one dependency is a type from
10
10
  * `@kici-dev/engine`, so nothing test-only is pulled along with it.
11
11
  */
12
- import type { OrchCapabilities } from '@kici-dev/engine';
13
12
  /**
14
13
  * The set of synthetic faults a test-only entrypoint can inject into the
15
14
  * orchestrator. Every field is optional: an absent field means "no fault at
@@ -44,10 +43,5 @@ export interface OrchestratorFaultInjection {
44
43
  * the first coordinator slow enough that the Platform relay fails over.
45
44
  */
46
45
  beforeRerun?: () => Promise<void>;
47
- /**
48
- * Transform the advertised capability manifest — used to reproduce an older
49
- * / sourceless orchestrator that predates a given dashboard capability.
50
- */
51
- capabilitiesTransform?: (c: OrchCapabilities) => OrchCapabilities;
52
46
  }
53
47
  //# sourceMappingURL=fault-injection-types.d.ts.map
@@ -2,21 +2,15 @@ import type { ProviderGitAuth } from '@kici-dev/engine';
2
2
  import type { ProviderBundle, ProviderRegistry } from '../provider-registry.js';
3
3
  /** Auth the dispatch message carries; every field is optional on the wire. */
4
4
  export interface DispatchCloneAuth {
5
- /** Bare source-repository token, kept for agents that read only `token`. */
6
- token?: string;
7
5
  sourceAuth?: ProviderGitAuth;
8
6
  workflowAuth?: ProviderGitAuth;
9
7
  }
10
8
  /**
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.
9
+ * Mint structured auth for one repository through one bundle. Providers that
10
+ * implement `issueGitAuth()` return the auth kind directly; otherwise a clone
11
+ * token is wrapped in a basic-auth envelope.
15
12
  */
16
- export declare function mintRepoGitAuth(bundle: ProviderBundle, repoIdentifier: string, providerContext: unknown): Promise<{
17
- token: string | null;
18
- structuredAuth: ProviderGitAuth | null;
19
- }>;
13
+ export declare function mintRepoGitAuth(bundle: ProviderBundle, repoIdentifier: string, providerContext: unknown): Promise<ProviderGitAuth | null>;
20
14
  /** The job fields the auth resolution reads. */
21
15
  export interface DispatchAuthJob {
22
16
  id: string;
@@ -35,8 +29,8 @@ export declare function gitHostOf(url: string): string | undefined;
35
29
  * it may.
36
30
  *
37
31
  * 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
32
+ * with `sourceAuth ?? workflowAuth` and the workflow repository with
33
+ * `workflowAuth ?? sourceAuth`. When only one repository's credential is
40
34
  * present, the other clone sends it to that repository's host. On the same host
41
35
  * that is a credential the host issued; on another host it hands one provider's
42
36
  * credential to another, so the job is refused instead. A job with no source URL
@@ -0,0 +1,3 @@
1
+ /** Parse JSON, returning null for empty, nullish or invalid input. */
2
+ export declare function safeJsonParse(value: string | null | undefined): unknown;
3
+ //# sourceMappingURL=json.d.ts.map