@kici-dev/orchestrator 0.1.7 → 0.1.9

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.
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Resolves the command a service unit should run.
3
+ *
4
+ * A `npm install -g kici-admin` install exposes only the `kici-admin` /
5
+ * `kici-agent` CLI bins — the long-running orchestrator and agent servers are
6
+ * separate module entry points (`dist/server.js` / `dist/standalone.js`) that
7
+ * must be launched with `node <script>`. These helpers turn an install's
8
+ * options into the `{ executablePath, args }` pair the platform service
9
+ * managers write into the unit's run command.
10
+ */
11
+ /** Server entry point variant for the orchestrator. */
12
+ export type ServerEntry = 'server' | 'standalone';
13
+ /** Resolved run command for a service unit. */
14
+ export interface ServiceExecutable {
15
+ /** Program the unit runs (the Node binary, or an explicit self-launching binary). */
16
+ executablePath: string;
17
+ /** Arguments passed to the program (the resolved server script, or none). */
18
+ args: string[];
19
+ }
20
+ /**
21
+ * Pick the orchestrator server entry from an env file's `KICI_MODE`.
22
+ * `independent` runs the standalone server; `platform` / `hybrid` / unset run
23
+ * the Platform-connected server.
24
+ */
25
+ export declare function selectServerEntry(envFileContent: string): ServerEntry;
26
+ /**
27
+ * Build the `{ executablePath, args }` for a service unit.
28
+ * - An explicit `binary` is run directly (assumed self-launching), no args.
29
+ * - Otherwise the Node binary runs the resolved server `entryScript`.
30
+ */
31
+ export declare function resolveServiceExecutable(opts: {
32
+ binary?: string;
33
+ nodePath: string;
34
+ entryScript?: string;
35
+ }): ServiceExecutable;
36
+ //# sourceMappingURL=entrypoint.d.ts.map
@@ -30,6 +30,12 @@ export interface ServiceConfig {
30
30
  description: string;
31
31
  /** Path to the executable binary. */
32
32
  executablePath: string;
33
+ /**
34
+ * Arguments passed to {@link executablePath} in the unit's run command.
35
+ * For a Node-launched server this is the resolved server script path
36
+ * (e.g. `["/opt/kici/dist/server.js"]`); empty for a self-launching binary.
37
+ */
38
+ args?: string[];
33
39
  /** Path to the environment file (.env). */
34
40
  envFilePath: string;
35
41
  /** Working directory for the service process. */
package/dist/cli.js CHANGED
@@ -24,6 +24,7 @@ import * as path$1 from "node:path";
24
24
  import path from "node:path";
25
25
  import archiver from "archiver";
26
26
  import JSZip from "jszip";
27
+ import { fileURLToPath } from "node:url";
27
28
  import { confirm, input, password, select } from "@inquirer/prompts";
28
29
  import { pipeline } from "node:stream/promises";
29
30
  import "pg";
@@ -6176,8 +6177,11 @@ var init_systemd = __esmMin((() => {
6176
6177
  lines.push("");
6177
6178
  lines.push("[Service]");
6178
6179
  lines.push("Type=simple");
6179
- lines.push(`ExecStart=${config.executablePath}`);
6180
+ const execArgs = config.args?.length ? ` ${config.args.join(" ")}` : "";
6181
+ lines.push(`ExecStart=${config.executablePath}${execArgs}`);
6180
6182
  lines.push(`EnvironmentFile=${config.envFilePath}`);
6183
+ const execBinDir = path.dirname(config.executablePath);
6184
+ lines.push(`Environment=PATH=${execBinDir}:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin`);
6181
6185
  lines.push(`WorkingDirectory=${config.workingDirectory}`);
6182
6186
  if (!config.isUserLevel && config.user) {
6183
6187
  lines.push(`User=${config.user}`);
@@ -6373,6 +6377,7 @@ var init_launchd = __esmMin((() => {
6373
6377
  lines.push(" <key>ProgramArguments</key>");
6374
6378
  lines.push(" <array>");
6375
6379
  lines.push(` <string>${this.escapeXml(config.executablePath)}</string>`);
6380
+ for (const arg of config.args ?? []) lines.push(` <string>${this.escapeXml(arg)}</string>`);
6376
6381
  lines.push(" </array>");
6377
6382
  lines.push(" <key>WorkingDirectory</key>");
6378
6383
  lines.push(` <string>${this.escapeXml(config.workingDirectory)}</string>`);
@@ -6819,6 +6824,7 @@ var init_windows = __esmMin((() => {
6819
6824
  }
6820
6825
  }
6821
6826
  cmdParts.push("--", `"${config.executablePath}"`);
6827
+ for (const arg of config.args ?? []) cmdParts.push(`"${arg}"`);
6822
6828
  execSync(cmdParts.join(" "), { stdio: "pipe" });
6823
6829
  execSync(`sc.exe config ${config.name} start= auto`, { stdio: "pipe" });
6824
6830
  const actions = config.restartPolicy.delays.map((d) => `restart/${d * 1e3}`).join("/");
@@ -7095,6 +7101,33 @@ async function createServiceManager(platform) {
7095
7101
  }
7096
7102
  }
7097
7103
  //#endregion
7104
+ //#region src/cli/service/entrypoint.ts
7105
+ /**
7106
+ * Pick the orchestrator server entry from an env file's `KICI_MODE`.
7107
+ * `independent` runs the standalone server; `platform` / `hybrid` / unset run
7108
+ * the Platform-connected server.
7109
+ */
7110
+ function selectServerEntry(envFileContent) {
7111
+ const match = envFileContent.match(/^[ \t]*KICI_MODE[ \t]*=[ \t]*(\S+)/m);
7112
+ return match && match[1].trim() === "independent" ? "standalone" : "server";
7113
+ }
7114
+ /**
7115
+ * Build the `{ executablePath, args }` for a service unit.
7116
+ * - An explicit `binary` is run directly (assumed self-launching), no args.
7117
+ * - Otherwise the Node binary runs the resolved server `entryScript`.
7118
+ */
7119
+ function resolveServiceExecutable(opts) {
7120
+ if (opts.binary) return {
7121
+ executablePath: opts.binary,
7122
+ args: []
7123
+ };
7124
+ if (!opts.entryScript) throw new Error("resolveServiceExecutable: entryScript is required when no binary is given");
7125
+ return {
7126
+ executablePath: opts.nodePath,
7127
+ args: [opts.entryScript]
7128
+ };
7129
+ }
7130
+ //#endregion
7098
7131
  //#region src/cli/wizard/prompts.ts
7099
7132
  /**
7100
7133
  * Shared prompt utilities for the setup wizards.
@@ -7369,7 +7402,12 @@ function registerOrchestratorInstall(orchestrator) {
7369
7402
  fs.appendFileSync(envFilePath, `\nKICI_DATABASE_URL=${devDbUrl}\n`);
7370
7403
  console.log(`Appended KICI_DATABASE_URL to ${envFilePath}`);
7371
7404
  }
7372
- const executablePath = opts.binary ? path.resolve(opts.binary) : process.argv[0];
7405
+ const entryScript = opts.binary ? void 0 : fileURLToPath(import.meta.resolve(`@kici-dev/orchestrator/${selectServerEntry(fs.readFileSync(envFilePath, "utf-8"))}`));
7406
+ const { executablePath, args } = resolveServiceExecutable({
7407
+ binary: opts.binary ? path.resolve(opts.binary) : void 0,
7408
+ nodePath: process.execPath,
7409
+ entryScript
7410
+ });
7373
7411
  if (userLevel) try {
7374
7412
  const envContent = fs.readFileSync(envFilePath, "utf-8");
7375
7413
  if (envContent.includes("firecracker") || envContent.includes("FIRECRACKER")) {
@@ -7383,6 +7421,7 @@ function registerOrchestratorInstall(orchestrator) {
7383
7421
  displayName: "KiCI Orchestrator",
7384
7422
  description: "KiCI CI/CD workflow orchestrator service",
7385
7423
  executablePath,
7424
+ args,
7386
7425
  envFilePath,
7387
7426
  workingDirectory: configDir,
7388
7427
  isUserLevel: userLevel,
@@ -7459,7 +7498,7 @@ function registerOrchestratorStart(orchestrator) {
7459
7498
  displayName: "KiCI Orchestrator",
7460
7499
  description: "KiCI CI/CD workflow orchestrator service",
7461
7500
  executablePath: "",
7462
- envFilePath: `${configDir}${serviceName}.env`,
7501
+ envFilePath: path.join(configDir, `${serviceName}.env`),
7463
7502
  workingDirectory: configDir,
7464
7503
  isUserLevel: userLevel,
7465
7504
  restartPolicy: DEFAULT_RESTART_POLICY
package/dist/config.d.ts CHANGED
@@ -57,6 +57,7 @@ declare const configSchema: z.ZodObject<{
57
57
  cacheBuildTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
58
58
  cacheMaxTarballBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
59
59
  webhookPayloadDir: z.ZodOptional<z.ZodString>;
60
+ dataDir: z.ZodOptional<z.ZodString>;
60
61
  scalerConfigPath: z.ZodOptional<z.ZodString>;
61
62
  scalerConfigDir: z.ZodOptional<z.ZodString>;
62
63
  machineLedgerDir: z.ZodOptional<z.ZodString>;
@@ -238,6 +239,7 @@ export declare const envDef: import("@kici-dev/shared/env").DefineEnvResult<{
238
239
  cacheStorageFsBaseUrl?: string | undefined;
239
240
  logStorageS3Bucket?: string | undefined;
240
241
  webhookPayloadDir?: string | undefined;
242
+ dataDir?: string | undefined;
241
243
  scalerConfigPath?: string | undefined;
242
244
  scalerConfigDir?: string | undefined;
243
245
  machineLedgerDir?: string | undefined;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Resolve the writable base directory for orchestrator-local data (execution
3
+ * log storage, cache).
4
+ *
5
+ * A system-level orchestrator owns `/var/lib/kici`; a user-level install
6
+ * (e.g. `kici-admin orchestrator install --user-level`) does not and cannot
7
+ * write there. Mirrors the scaler-ledger resolution in machine-ledger.ts so
8
+ * both pieces of orchestrator state degrade the same way: explicit override →
9
+ * `/var/lib/kici` if writable → XDG state dir → tmpdir.
10
+ */
11
+ /**
12
+ * Return the first candidate directory that can be created and written to.
13
+ *
14
+ * Each candidate is `mkdir -p`'d and probed with a sentinel write (removed
15
+ * immediately) so "exists but not writable" is caught the same as "cannot be
16
+ * created". Throws if none are usable.
17
+ */
18
+ export declare function firstWritableDir(candidates: string[]): string;
19
+ /**
20
+ * Resolve the orchestrator data root.
21
+ *
22
+ * 1. `explicit` (KICI_DATA_DIR) wins — created if missing.
23
+ * 2. `/var/lib/kici` if writable (system-level install).
24
+ * 3. `${XDG_STATE_HOME:-$HOME/.local/state}/kici` (user-level install).
25
+ * 4. `${tmpdir}/kici-data` (last resort, e.g. CI sandboxes).
26
+ *
27
+ * Callers append their own subdir (e.g. `${dataDir}/cache/logs`).
28
+ */
29
+ export declare function resolveDataDir(explicit: string | undefined): string;
30
+ //# sourceMappingURL=data-dir.d.ts.map
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { type ToolRequirement } from '@kici-dev/shared';
10
10
  import type { AgentTokenStore } from '../agent/token-store.js';
11
- import type { ScalerBackend, ManagedAgent, LabelSetConfig, LogCapture, ResourceRequest, EffectiveLimits, ScalerEventCallback, ValidationResult } from './types.js';
11
+ import type { ScalerBackend, ManagedAgent, LabelSetConfig, LogCapture, ResourceRequest, EffectiveLimits, ScalerEventCallback, ValidationResult, ScalerEntry } from './types.js';
12
12
  /**
13
13
  * Result of runtime detection.
14
14
  */
@@ -93,10 +93,16 @@ export declare class ContainerScalerBackend implements ScalerBackend {
93
93
  private ensureIsolatedNetwork;
94
94
  /**
95
95
  * Declare required tools for a container scaler entry.
96
- * Container runtime socket and nftables are validated during create() — no
97
- * additional tool declarations needed here.
96
+ *
97
+ * For the auto-detect case (no explicit socketPath / remote host) the
98
+ * orchestrator must have a local container runtime — docker OR podman — on
99
+ * PATH, otherwise the scaler cannot spawn agent containers. Declaring it
100
+ * here lets the startup tool-validation gate fail fast with a clear error
101
+ * instead of the first job hanging. When a socketPath or remote host is
102
+ * configured the binary need not be on PATH (the runtime may be remote), so
103
+ * reachability is validated later in create().
98
104
  */
99
- static getRequiredTools(): ToolRequirement[];
105
+ static getRequiredTools(entry: ScalerEntry): ToolRequirement[];
100
106
  /**
101
107
  * Create a ContainerScalerBackend with auto-detected or configured socket.
102
108
  * Throws if no container runtime is found and no host is configured.
package/dist/server.js CHANGED
@@ -18,7 +18,7 @@ import picomatch from "picomatch";
18
18
  import vm from "node:vm";
19
19
  import { EventEmitter } from "node:events";
20
20
  import { DASHBOARD_WRITE_OPERATIONS_BY_NAME, dashboardWritePolicyMapSchema, isDashboardWriteOperationEnabled, resolveFullPolicyView, resolveFullPolicyView as resolveFullPolicyView$1 } from "@kici-dev/engine/protocol/dashboard-write-operations";
21
- import { chmodSync, closeSync, createReadStream, createWriteStream, mkdtempSync, openSync, promises, readFileSync, rmSync, statSync, unlinkSync, unwatchFile, watchFile, writeFileSync } from "node:fs";
21
+ import { chmodSync, closeSync, createReadStream, createWriteStream, mkdirSync, mkdtempSync, openSync, promises, readFileSync, rmSync, statSync, unlinkSync, unwatchFile, watchFile, writeFileSync } from "node:fs";
22
22
  import { Cron } from "croner";
23
23
  import Vault from "hashi-vault-js";
24
24
  import "pg";
@@ -421,6 +421,7 @@ var init_config$5 = __esmMin((() => {
421
421
  cacheBuildTimeoutMs: z.coerce.number().default(6e5),
422
422
  cacheMaxTarballBytes: z.coerce.number().default(524288e3),
423
423
  webhookPayloadDir: z.string().optional(),
424
+ dataDir: z.string().optional(),
424
425
  scalerConfigPath: z.string().optional(),
425
426
  scalerConfigDir: z.string().optional(),
426
427
  machineLedgerDir: z.string().optional(),
@@ -605,6 +606,7 @@ var init_config$5 = __esmMin((() => {
605
606
  workerConcurrency: "KICI_WORKER_CONCURRENCY",
606
607
  concurrencyWaitTimeoutMs: "KICI_CONCURRENCY_WAIT_TIMEOUT_MS",
607
608
  webhookPayloadDir: "KICI_WEBHOOK_PAYLOAD_DIR",
609
+ dataDir: "KICI_DATA_DIR",
608
610
  scalerConfigPath: "KICI_SCALER_CONFIG_PATH",
609
611
  scalerConfigDir: "KICI_SCALER_CONFIG_DIR",
610
612
  machineLedgerDir: "KICI_MACHINE_LEDGER_DIR",
@@ -15149,7 +15151,7 @@ var init_peer_client = __esmMin((() => {
15149
15151
  init_peer_crypto();
15150
15152
  init_peer_credentials();
15151
15153
  logger$73 = createLogger({ prefix: "peer-client" });
15152
- SOFTWARE_VERSION$1 = "0.1.7";
15154
+ SOFTWARE_VERSION$1 = "0.1.9";
15153
15155
  PeerClient$1 = class {
15154
15156
  ws = null;
15155
15157
  _state = "disconnected";
@@ -16612,7 +16614,7 @@ var init_peer_handler = __esmMin((() => {
16612
16614
  init_peer_crypto();
16613
16615
  init_join_token();
16614
16616
  logger$72 = createLogger({ prefix: "peer-handler" });
16615
- SOFTWARE_VERSION = "0.1.7";
16617
+ SOFTWARE_VERSION = "0.1.9";
16616
16618
  RATE_LIMIT_MAX = 5;
16617
16619
  RATE_LIMIT_WINDOW_MS = 6e4;
16618
16620
  }));
@@ -18172,6 +18174,59 @@ var init_global_workflow_policy = __esmMin((() => {
18172
18174
  };
18173
18175
  }));
18174
18176
  //#endregion
18177
+ //#region src/data-dir.ts
18178
+ /**
18179
+ * Resolve the writable base directory for orchestrator-local data (execution
18180
+ * log storage, cache).
18181
+ *
18182
+ * A system-level orchestrator owns `/var/lib/kici`; a user-level install
18183
+ * (e.g. `kici-admin orchestrator install --user-level`) does not and cannot
18184
+ * write there. Mirrors the scaler-ledger resolution in machine-ledger.ts so
18185
+ * both pieces of orchestrator state degrade the same way: explicit override →
18186
+ * `/var/lib/kici` if writable → XDG state dir → tmpdir.
18187
+ */
18188
+ /**
18189
+ * Return the first candidate directory that can be created and written to.
18190
+ *
18191
+ * Each candidate is `mkdir -p`'d and probed with a sentinel write (removed
18192
+ * immediately) so "exists but not writable" is caught the same as "cannot be
18193
+ * created". Throws if none are usable.
18194
+ */
18195
+ function firstWritableDir(candidates) {
18196
+ for (const dir of candidates) try {
18197
+ mkdirSync(dir, { recursive: true });
18198
+ const sentinel = join(dir, `.write-probe-${process.pid}`);
18199
+ writeFileSync(sentinel, "probe");
18200
+ rmSync(sentinel, { force: true });
18201
+ return dir;
18202
+ } catch {
18203
+ continue;
18204
+ }
18205
+ throw new Error(`data-dir: no writable directory among candidates: ${candidates.join(", ")}`);
18206
+ }
18207
+ /**
18208
+ * Resolve the orchestrator data root.
18209
+ *
18210
+ * 1. `explicit` (KICI_DATA_DIR) wins — created if missing.
18211
+ * 2. `/var/lib/kici` if writable (system-level install).
18212
+ * 3. `${XDG_STATE_HOME:-$HOME/.local/state}/kici` (user-level install).
18213
+ * 4. `${tmpdir}/kici-data` (last resort, e.g. CI sandboxes).
18214
+ *
18215
+ * Callers append their own subdir (e.g. `${dataDir}/cache/logs`).
18216
+ */
18217
+ function resolveDataDir(explicit) {
18218
+ if (explicit) {
18219
+ mkdirSync(explicit, { recursive: true });
18220
+ return explicit;
18221
+ }
18222
+ return firstWritableDir([
18223
+ "/var/lib/kici",
18224
+ join(process.env.XDG_STATE_HOME ?? join(homedir(), ".local", "state"), "kici"),
18225
+ join(tmpdir(), "kici-data")
18226
+ ]);
18227
+ }
18228
+ var init_data_dir = __esmMin((() => {}));
18229
+ //#endregion
18175
18230
  //#region src/config/reload.ts
18176
18231
  /**
18177
18232
  * Compute a list of top-level config fields that differ between old and new config.
@@ -34049,14 +34104,14 @@ var init_admin_config = __esmMin((() => {
34049
34104
  function createHealthRoutes$1(deps = {}) {
34050
34105
  return createHealthRoutes({
34051
34106
  livenessInfo: () => ({
34052
- version: "0.1.7",
34053
- buildDate: "2026-05-26T13:18:35.789Z",
34054
- buildCommit: "4c0abe030",
34055
- sdkVersion: "0.1.7",
34107
+ version: "0.1.9",
34108
+ buildDate: "2026-05-26T16:38:18.222Z",
34109
+ buildCommit: "54278bfb2",
34110
+ sdkVersion: "0.1.9",
34056
34111
  sdkBundleHash: "675aafe4de03e677785ef2794d8f34951b14e2bd1e6f0ea825953d6c2abfe128",
34057
- sharedVersion: "0.1.7",
34112
+ sharedVersion: "0.1.9",
34058
34113
  sharedBundleHash: "36a23a454fd75ec35f258d39f254543ec0451c6b543fe3618ce427e6e6369aae",
34059
- engineVersion: "0.1.7",
34114
+ engineVersion: "0.1.9",
34060
34115
  engineBundleHash: "b704538612ec796a5668765bd55e0eaeaf1bad8a2afa508f9e20ad7b9eb61d21"
34061
34116
  }),
34062
34117
  readinessCheck: deps.db ? async () => {
@@ -34091,7 +34146,7 @@ function createCapabilitiesRoutes() {
34091
34146
  const app = new Hono();
34092
34147
  app.get("/api/v1/capabilities", (c) => {
34093
34148
  const manifest = {
34094
- orchestratorVersion: "0.1.7",
34149
+ orchestratorVersion: "0.1.9",
34095
34150
  protocolVersion: PROTOCOL_VERSION,
34096
34151
  minProtocolVersion: MIN_PROTOCOL_VERSION
34097
34152
  };
@@ -36452,11 +36507,22 @@ var init_container_backend = __esmMin((() => {
36452
36507
  }
36453
36508
  /**
36454
36509
  * Declare required tools for a container scaler entry.
36455
- * Container runtime socket and nftables are validated during create() — no
36456
- * additional tool declarations needed here.
36510
+ *
36511
+ * For the auto-detect case (no explicit socketPath / remote host) the
36512
+ * orchestrator must have a local container runtime — docker OR podman — on
36513
+ * PATH, otherwise the scaler cannot spawn agent containers. Declaring it
36514
+ * here lets the startup tool-validation gate fail fast with a clear error
36515
+ * instead of the first job hanging. When a socketPath or remote host is
36516
+ * configured the binary need not be on PATH (the runtime may be remote), so
36517
+ * reachability is validated later in create().
36457
36518
  */
36458
- static getRequiredTools() {
36459
- return [];
36519
+ static getRequiredTools(entry) {
36520
+ if (entry.host || entry.socketPath) return [];
36521
+ return [{
36522
+ type: "any-path-binary",
36523
+ names: ["docker", "podman"],
36524
+ reason: `container scaler "${entry.name}" needs a local container runtime to spawn agents. Install Docker or Podman, or set socketPath / host in scalers.yaml for a remote runtime.`
36525
+ }];
36460
36526
  }
36461
36527
  /**
36462
36528
  * Create a ContainerScalerBackend with auto-detected or configured socket.
@@ -36780,6 +36846,11 @@ var init_bare_metal_backend = __esmMin((() => {
36780
36846
  mode: "executable",
36781
36847
  reason: `agent binary for bare-metal scaler "${entry.name}"`
36782
36848
  }));
36849
+ requirements.push({
36850
+ type: "path-binary",
36851
+ name: "node",
36852
+ reason: `bare-metal scaler "${entry.name}" spawns the kici-agent node script. node must be on the orchestrator's PATH (it is forwarded to spawned agents). Ensure the orchestrator service's PATH includes your node install (e.g. the systemd unit's Environment=PATH covers the mise/nvm node bin dir).`
36853
+ });
36783
36854
  const sandboxViaGlobalEnv = process.env.KICI_AGENT_ENV_KICI_SANDBOX === "true";
36784
36855
  const sandboxViaLabelSet = entry.labelSets.some((ls) => ls.env && ls.env.KICI_SANDBOX === "true");
36785
36856
  if (sandboxViaGlobalEnv || sandboxViaLabelSet) requirements.push({
@@ -47162,7 +47233,7 @@ async function initializeScaler(config, db, tokenStore) {
47162
47233
  }
47163
47234
  const toolErrors = validateRequiredTools(scalerConfig.scalers.flatMap((s) => {
47164
47235
  switch (s.type) {
47165
- case "container": return ContainerScalerBackend.getRequiredTools();
47236
+ case "container": return ContainerScalerBackend.getRequiredTools(s);
47166
47237
  case "bare-metal": return BareMetalScalerBackend.getRequiredTools(s);
47167
47238
  case "firecracker": return FirecrackerScalerBackend.getRequiredTools(s);
47168
47239
  default: return [];
@@ -48154,7 +48225,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
48154
48225
  forcePathStyle: config.storage.forcePathStyle
48155
48226
  } : {
48156
48227
  type: "filesystem",
48157
- basePath: (config.webhookPayloadDir ?? "/var/lib/kici/cache") + "/logs"
48228
+ basePath: (config.webhookPayloadDir ?? resolveDataDir(config.dataDir) + "/cache") + "/logs"
48158
48229
  });
48159
48230
  const observerRegistry = new ObserverRegistry();
48160
48231
  let executionTrackerRef = null;
@@ -48954,6 +49025,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
48954
49025
  }
48955
49026
  var logger$2;
48956
49027
  var init_orchestrator_core = __esmMin((() => {
49028
+ init_data_dir();
48957
49029
  init_reload();
48958
49030
  init_resolver();
48959
49031
  init_client();
@@ -50226,13 +50298,13 @@ var init_worker_core = __esmMin((() => {
50226
50298
  init_agent_handler();
50227
50299
  init_worker_status();
50228
50300
  init_agent_heartbeat();
50229
- ORCHESTRATOR_VERSION$1 = "0.1.7";
50230
- WORKER_BUILD_COMMIT = "4c0abe030";
50231
- WORKER_SDK_VERSION = "0.1.7";
50301
+ ORCHESTRATOR_VERSION$1 = "0.1.9";
50302
+ WORKER_BUILD_COMMIT = "54278bfb2";
50303
+ WORKER_SDK_VERSION = "0.1.9";
50232
50304
  WORKER_SDK_BUNDLE_HASH = "675aafe4de03e677785ef2794d8f34951b14e2bd1e6f0ea825953d6c2abfe128";
50233
- WORKER_SHARED_VERSION = "0.1.7";
50305
+ WORKER_SHARED_VERSION = "0.1.9";
50234
50306
  WORKER_SHARED_BUNDLE_HASH = "36a23a454fd75ec35f258d39f254543ec0451c6b543fe3618ce427e6e6369aae";
50235
- WORKER_ENGINE_VERSION = "0.1.7";
50307
+ WORKER_ENGINE_VERSION = "0.1.9";
50236
50308
  WORKER_ENGINE_BUNDLE_HASH = "b704538612ec796a5668765bd55e0eaeaf1bad8a2afa508f9e20ad7b9eb61d21";
50237
50309
  logger$1 = createLogger({ prefix: "worker" });
50238
50310
  DRAIN_TIMEOUT_MS = 3e5;
@@ -50254,13 +50326,13 @@ var init_worker_core = __esmMin((() => {
50254
50326
  * Graceful shutdown in reverse order:
50255
50327
  * Platform client -> agent WS -> heartbeat -> HTTP -> DB
50256
50328
  */
50257
- const ORCHESTRATOR_VERSION = "0.1.7";
50258
- const BUILD_COMMIT = "4c0abe030";
50259
- const SDK_VERSION = "0.1.7";
50329
+ const ORCHESTRATOR_VERSION = "0.1.9";
50330
+ const BUILD_COMMIT = "54278bfb2";
50331
+ const SDK_VERSION = "0.1.9";
50260
50332
  const SDK_BUNDLE_HASH = "675aafe4de03e677785ef2794d8f34951b14e2bd1e6f0ea825953d6c2abfe128";
50261
- const SHARED_VERSION = "0.1.7";
50333
+ const SHARED_VERSION = "0.1.9";
50262
50334
  const SHARED_BUNDLE_HASH = "36a23a454fd75ec35f258d39f254543ec0451c6b543fe3618ce427e6e6369aae";
50263
- const ENGINE_VERSION = "0.1.7";
50335
+ const ENGINE_VERSION = "0.1.9";
50264
50336
  const ENGINE_BUNDLE_HASH = "b704538612ec796a5668765bd55e0eaeaf1bad8a2afa508f9e20ad7b9eb61d21";
50265
50337
  const otelSdk = initTelemetry({
50266
50338
  serviceName: "kici-orchestrator",
@@ -8,7 +8,7 @@ import { X509Certificate, createCipheriv, createDecipheriv, createHmac, createPr
8
8
  import { z } from "zod";
9
9
  import { LOGGER_ENV_VARS, defineEnv, validateUnknownKiciVars } from "@kici-dev/shared/env";
10
10
  import WebSocket from "ws";
11
- import { chmodSync, closeSync, createReadStream, createWriteStream, mkdtempSync, openSync, promises, readFileSync, rmSync, statSync, unlinkSync, unwatchFile, watchFile, writeFileSync } from "node:fs";
11
+ import { chmodSync, closeSync, createReadStream, createWriteStream, mkdirSync, mkdtempSync, openSync, promises, readFileSync, rmSync, statSync, unlinkSync, unwatchFile, watchFile, writeFileSync } from "node:fs";
12
12
  import { ALLOWED_SYSTEM_VARS, AccessLogAction, AccessLogOutcome, AccessLogSource, AccessLogTargetType, ActorType, CheckRunConclusion, EventLogSource, EventLogStatus, ExecutionJobStatus, ExecutionRunStatus, ExecutionStepStatus, KICI_AGENT_ENV_PREFIX, KNOWN_ROLES, MIN_PROTOCOL_VERSION, PROTOCOL_VERSION, PayloadOmittedReason, RegisterableTriggerType, SCHEMA_VERSION, ScalerBackendType, SourceSubtype, TERMINAL_JOB_STATES, TERMINAL_RUN_STATES, WS_CLOSE_AGENT_AUTH_FAILED, WS_CLOSE_AUTH_TIMEOUT, WS_CLOSE_GOING_AWAY, WS_CLOSE_HEARTBEAT_TIMEOUT, WS_CLOSE_INVALID_MESSAGE, WS_CLOSE_PROTOCOL_ERROR, WS_CLOSE_RUN_NOT_FOUND, WS_CLOSE_UNAUTHORIZED, WS_MAX_PAYLOAD_BYTES, WsRateLimiter, accessLogWarmSqlCase, agentAuthRequestSchema, agentToOrchestratorMessageSchema, agentTypeLabel, createWorkflowDecision, deriveOsArchLabels, flattenActor, getAccessLogColdDays, getSecretAuditLogColdDays, isLockDynamicJobFn, isLockInlineValue, isLockStaticJob, matchAllWorkflows, minAccessLogWarmDays, minSecretAuditLogWarmDays, observeSubscribeSchema, peerAuthRequestSchema, peerFromPeerMessageSchema, peerHelloResponseSchema, peerHelloSchema, resolveRoleLabels, scalerLabel, secretAuditLogWarmSqlCase, shouldRecordAccess, shouldRecordSecretResolve, testEventSchema } from "@kici-dev/engine";
13
13
  import { access, appendFile, chmod, constants, copyFile, link, mkdir, mkdtemp, open, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
14
14
  import { dirname, join, relative, resolve } from "node:path";
@@ -175,6 +175,7 @@ var init_config$5 = __esmMin((() => {
175
175
  cacheBuildTimeoutMs: z.coerce.number().default(6e5),
176
176
  cacheMaxTarballBytes: z.coerce.number().default(524288e3),
177
177
  webhookPayloadDir: z.string().optional(),
178
+ dataDir: z.string().optional(),
178
179
  scalerConfigPath: z.string().optional(),
179
180
  scalerConfigDir: z.string().optional(),
180
181
  machineLedgerDir: z.string().optional(),
@@ -359,6 +360,7 @@ var init_config$5 = __esmMin((() => {
359
360
  workerConcurrency: "KICI_WORKER_CONCURRENCY",
360
361
  concurrencyWaitTimeoutMs: "KICI_CONCURRENCY_WAIT_TIMEOUT_MS",
361
362
  webhookPayloadDir: "KICI_WEBHOOK_PAYLOAD_DIR",
363
+ dataDir: "KICI_DATA_DIR",
362
364
  scalerConfigPath: "KICI_SCALER_CONFIG_PATH",
363
365
  scalerConfigDir: "KICI_SCALER_CONFIG_DIR",
364
366
  machineLedgerDir: "KICI_MACHINE_LEDGER_DIR",
@@ -1038,7 +1040,7 @@ var init_peer_client = __esmMin((() => {
1038
1040
  init_peer_crypto();
1039
1041
  init_peer_credentials();
1040
1042
  logger$85 = createLogger({ prefix: "peer-client" });
1041
- SOFTWARE_VERSION$1 = "0.1.7";
1043
+ SOFTWARE_VERSION$1 = "0.1.9";
1042
1044
  PeerClient$1 = class {
1043
1045
  ws = null;
1044
1046
  _state = "disconnected";
@@ -2501,7 +2503,7 @@ var init_peer_handler = __esmMin((() => {
2501
2503
  init_peer_crypto();
2502
2504
  init_join_token();
2503
2505
  logger$84 = createLogger({ prefix: "peer-handler" });
2504
- SOFTWARE_VERSION = "0.1.7";
2506
+ SOFTWARE_VERSION = "0.1.9";
2505
2507
  RATE_LIMIT_MAX = 5;
2506
2508
  RATE_LIMIT_WINDOW_MS = 6e4;
2507
2509
  }));
@@ -3739,6 +3741,59 @@ var init_cluster = __esmMin((() => {
3739
3741
  init_health_api();
3740
3742
  }));
3741
3743
  //#endregion
3744
+ //#region src/data-dir.ts
3745
+ /**
3746
+ * Resolve the writable base directory for orchestrator-local data (execution
3747
+ * log storage, cache).
3748
+ *
3749
+ * A system-level orchestrator owns `/var/lib/kici`; a user-level install
3750
+ * (e.g. `kici-admin orchestrator install --user-level`) does not and cannot
3751
+ * write there. Mirrors the scaler-ledger resolution in machine-ledger.ts so
3752
+ * both pieces of orchestrator state degrade the same way: explicit override →
3753
+ * `/var/lib/kici` if writable → XDG state dir → tmpdir.
3754
+ */
3755
+ /**
3756
+ * Return the first candidate directory that can be created and written to.
3757
+ *
3758
+ * Each candidate is `mkdir -p`'d and probed with a sentinel write (removed
3759
+ * immediately) so "exists but not writable" is caught the same as "cannot be
3760
+ * created". Throws if none are usable.
3761
+ */
3762
+ function firstWritableDir(candidates) {
3763
+ for (const dir of candidates) try {
3764
+ mkdirSync(dir, { recursive: true });
3765
+ const sentinel = join(dir, `.write-probe-${process.pid}`);
3766
+ writeFileSync(sentinel, "probe");
3767
+ rmSync(sentinel, { force: true });
3768
+ return dir;
3769
+ } catch {
3770
+ continue;
3771
+ }
3772
+ throw new Error(`data-dir: no writable directory among candidates: ${candidates.join(", ")}`);
3773
+ }
3774
+ /**
3775
+ * Resolve the orchestrator data root.
3776
+ *
3777
+ * 1. `explicit` (KICI_DATA_DIR) wins — created if missing.
3778
+ * 2. `/var/lib/kici` if writable (system-level install).
3779
+ * 3. `${XDG_STATE_HOME:-$HOME/.local/state}/kici` (user-level install).
3780
+ * 4. `${tmpdir}/kici-data` (last resort, e.g. CI sandboxes).
3781
+ *
3782
+ * Callers append their own subdir (e.g. `${dataDir}/cache/logs`).
3783
+ */
3784
+ function resolveDataDir(explicit) {
3785
+ if (explicit) {
3786
+ mkdirSync(explicit, { recursive: true });
3787
+ return explicit;
3788
+ }
3789
+ return firstWritableDir([
3790
+ "/var/lib/kici",
3791
+ join(process.env.XDG_STATE_HOME ?? join(homedir(), ".local", "state"), "kici"),
3792
+ join(tmpdir(), "kici-data")
3793
+ ]);
3794
+ }
3795
+ var init_data_dir = __esmMin((() => {}));
3796
+ //#endregion
3742
3797
  //#region src/metrics/prometheus.ts
3743
3798
  /** Set the current number of active agents. */
3744
3799
  function setAgentsActive(value) {
@@ -21536,14 +21591,14 @@ var init_admin_config = __esmMin((() => {
21536
21591
  function createHealthRoutes$1(deps = {}) {
21537
21592
  return createHealthRoutes({
21538
21593
  livenessInfo: () => ({
21539
- version: "0.1.7",
21540
- buildDate: "2026-05-26T13:18:35.789Z",
21541
- buildCommit: "4c0abe030",
21542
- sdkVersion: "0.1.7",
21594
+ version: "0.1.9",
21595
+ buildDate: "2026-05-26T16:38:18.222Z",
21596
+ buildCommit: "54278bfb2",
21597
+ sdkVersion: "0.1.9",
21543
21598
  sdkBundleHash: "675aafe4de03e677785ef2794d8f34951b14e2bd1e6f0ea825953d6c2abfe128",
21544
- sharedVersion: "0.1.7",
21599
+ sharedVersion: "0.1.9",
21545
21600
  sharedBundleHash: "36a23a454fd75ec35f258d39f254543ec0451c6b543fe3618ce427e6e6369aae",
21546
- engineVersion: "0.1.7",
21601
+ engineVersion: "0.1.9",
21547
21602
  engineBundleHash: "b704538612ec796a5668765bd55e0eaeaf1bad8a2afa508f9e20ad7b9eb61d21"
21548
21603
  }),
21549
21604
  readinessCheck: deps.db ? async () => {
@@ -21578,7 +21633,7 @@ function createCapabilitiesRoutes() {
21578
21633
  const app = new Hono();
21579
21634
  app.get("/api/v1/capabilities", (c) => {
21580
21635
  const manifest = {
21581
- orchestratorVersion: "0.1.7",
21636
+ orchestratorVersion: "0.1.9",
21582
21637
  protocolVersion: PROTOCOL_VERSION,
21583
21638
  minProtocolVersion: MIN_PROTOCOL_VERSION
21584
21639
  };
@@ -28795,11 +28850,22 @@ var init_container_backend = __esmMin((() => {
28795
28850
  }
28796
28851
  /**
28797
28852
  * Declare required tools for a container scaler entry.
28798
- * Container runtime socket and nftables are validated during create() — no
28799
- * additional tool declarations needed here.
28853
+ *
28854
+ * For the auto-detect case (no explicit socketPath / remote host) the
28855
+ * orchestrator must have a local container runtime — docker OR podman — on
28856
+ * PATH, otherwise the scaler cannot spawn agent containers. Declaring it
28857
+ * here lets the startup tool-validation gate fail fast with a clear error
28858
+ * instead of the first job hanging. When a socketPath or remote host is
28859
+ * configured the binary need not be on PATH (the runtime may be remote), so
28860
+ * reachability is validated later in create().
28800
28861
  */
28801
- static getRequiredTools() {
28802
- return [];
28862
+ static getRequiredTools(entry) {
28863
+ if (entry.host || entry.socketPath) return [];
28864
+ return [{
28865
+ type: "any-path-binary",
28866
+ names: ["docker", "podman"],
28867
+ reason: `container scaler "${entry.name}" needs a local container runtime to spawn agents. Install Docker or Podman, or set socketPath / host in scalers.yaml for a remote runtime.`
28868
+ }];
28803
28869
  }
28804
28870
  /**
28805
28871
  * Create a ContainerScalerBackend with auto-detected or configured socket.
@@ -29123,6 +29189,11 @@ var init_bare_metal_backend = __esmMin((() => {
29123
29189
  mode: "executable",
29124
29190
  reason: `agent binary for bare-metal scaler "${entry.name}"`
29125
29191
  }));
29192
+ requirements.push({
29193
+ type: "path-binary",
29194
+ name: "node",
29195
+ reason: `bare-metal scaler "${entry.name}" spawns the kici-agent node script. node must be on the orchestrator's PATH (it is forwarded to spawned agents). Ensure the orchestrator service's PATH includes your node install (e.g. the systemd unit's Environment=PATH covers the mise/nvm node bin dir).`
29196
+ });
29126
29197
  const sandboxViaGlobalEnv = process.env.KICI_AGENT_ENV_KICI_SANDBOX === "true";
29127
29198
  const sandboxViaLabelSet = entry.labelSets.some((ls) => ls.env && ls.env.KICI_SANDBOX === "true");
29128
29199
  if (sandboxViaGlobalEnv || sandboxViaLabelSet) requirements.push({
@@ -40755,7 +40826,7 @@ async function initializeScaler(config, db, tokenStore) {
40755
40826
  }
40756
40827
  const toolErrors = validateRequiredTools(scalerConfig.scalers.flatMap((s) => {
40757
40828
  switch (s.type) {
40758
- case "container": return ContainerScalerBackend.getRequiredTools();
40829
+ case "container": return ContainerScalerBackend.getRequiredTools(s);
40759
40830
  case "bare-metal": return BareMetalScalerBackend.getRequiredTools(s);
40760
40831
  case "firecracker": return FirecrackerScalerBackend.getRequiredTools(s);
40761
40832
  default: return [];
@@ -41747,7 +41818,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
41747
41818
  forcePathStyle: config.storage.forcePathStyle
41748
41819
  } : {
41749
41820
  type: "filesystem",
41750
- basePath: (config.webhookPayloadDir ?? "/var/lib/kici/cache") + "/logs"
41821
+ basePath: (config.webhookPayloadDir ?? resolveDataDir(config.dataDir) + "/cache") + "/logs"
41751
41822
  });
41752
41823
  const observerRegistry = new ObserverRegistry();
41753
41824
  let executionTrackerRef = null;
@@ -42547,6 +42618,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
42547
42618
  }
42548
42619
  var logger$2;
42549
42620
  var init_orchestrator_core = __esmMin((() => {
42621
+ init_data_dir();
42550
42622
  init_reload();
42551
42623
  init_resolver();
42552
42624
  init_client();
@@ -43705,13 +43777,13 @@ var init_worker_core = __esmMin((() => {
43705
43777
  init_agent_handler();
43706
43778
  init_worker_status();
43707
43779
  init_agent_heartbeat();
43708
- ORCHESTRATOR_VERSION$1 = "0.1.7";
43709
- WORKER_BUILD_COMMIT = "4c0abe030";
43710
- WORKER_SDK_VERSION = "0.1.7";
43780
+ ORCHESTRATOR_VERSION$1 = "0.1.9";
43781
+ WORKER_BUILD_COMMIT = "54278bfb2";
43782
+ WORKER_SDK_VERSION = "0.1.9";
43711
43783
  WORKER_SDK_BUNDLE_HASH = "675aafe4de03e677785ef2794d8f34951b14e2bd1e6f0ea825953d6c2abfe128";
43712
- WORKER_SHARED_VERSION = "0.1.7";
43784
+ WORKER_SHARED_VERSION = "0.1.9";
43713
43785
  WORKER_SHARED_BUNDLE_HASH = "36a23a454fd75ec35f258d39f254543ec0451c6b543fe3618ce427e6e6369aae";
43714
- WORKER_ENGINE_VERSION = "0.1.7";
43786
+ WORKER_ENGINE_VERSION = "0.1.9";
43715
43787
  WORKER_ENGINE_BUNDLE_HASH = "b704538612ec796a5668765bd55e0eaeaf1bad8a2afa508f9e20ad7b9eb61d21";
43716
43788
  logger$1 = createLogger({ prefix: "worker" });
43717
43789
  DRAIN_TIMEOUT_MS = 3e5;
@@ -43736,13 +43808,13 @@ var init_worker_core = __esmMin((() => {
43736
43808
  * Graceful shutdown:
43737
43809
  * agent WS -> heartbeat -> HTTP -> DB
43738
43810
  */
43739
- const ORCHESTRATOR_VERSION = "0.1.7";
43740
- const BUILD_COMMIT = "4c0abe030";
43741
- const SDK_VERSION = "0.1.7";
43811
+ const ORCHESTRATOR_VERSION = "0.1.9";
43812
+ const BUILD_COMMIT = "54278bfb2";
43813
+ const SDK_VERSION = "0.1.9";
43742
43814
  const SDK_BUNDLE_HASH = "675aafe4de03e677785ef2794d8f34951b14e2bd1e6f0ea825953d6c2abfe128";
43743
- const SHARED_VERSION = "0.1.7";
43815
+ const SHARED_VERSION = "0.1.9";
43744
43816
  const SHARED_BUNDLE_HASH = "36a23a454fd75ec35f258d39f254543ec0451c6b543fe3618ce427e6e6369aae";
43745
- const ENGINE_VERSION = "0.1.7";
43817
+ const ENGINE_VERSION = "0.1.9";
43746
43818
  const ENGINE_BUNDLE_HASH = "b704538612ec796a5668765bd55e0eaeaf1bad8a2afa508f9e20ad7b9eb61d21";
43747
43819
  const otelSdk = initTelemetry({
43748
43820
  serviceName: "kici-orchestrator",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kici-dev/orchestrator",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Customer-deployable orchestrator for the KiCI CI/CD stack. Receives webhook events (direct or via Platform relay), matches triggers against the lock file, and dispatches jobs to connected agents.",
5
5
  "keywords": [
6
6
  "kici",
@@ -43,7 +43,9 @@
43
43
  "import": "./dist/index.js",
44
44
  "types": "./dist/index.d.ts"
45
45
  },
46
- "./cli": "./dist/cli.js"
46
+ "./cli": "./dist/cli.js",
47
+ "./server": "./dist/server.js",
48
+ "./standalone": "./dist/standalone.js"
47
49
  },
48
50
  "build": {
49
51
  "entries": {
@@ -80,8 +82,8 @@
80
82
  "ws": "^8.20.0",
81
83
  "yaml": "^2.8.3",
82
84
  "zod": "^4.3.6",
83
- "@kici-dev/engine": "0.1.7",
84
- "@kici-dev/shared": "0.1.7"
85
+ "@kici-dev/engine": "0.1.9",
86
+ "@kici-dev/shared": "0.1.9"
85
87
  },
86
88
  "kici": {
87
89
  "metrics": {
package/sbom.spdx.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "spdxVersion": "SPDX-2.3",
3
3
  "dataLicense": "CC0-1.0",
4
4
  "SPDXID": "SPDXRef-DOCUMENT",
5
- "name": "@kici-dev/orchestrator@0.1.7",
6
- "documentNamespace": "https://kici.dev/sbom/%40kici-dev%2Forchestrator/0.1.7/4ec68fa2-15a1-43a2-9a19-4c7a17f679fb",
5
+ "name": "@kici-dev/orchestrator@0.1.9",
6
+ "documentNamespace": "https://kici.dev/sbom/%40kici-dev%2Forchestrator/0.1.9/ba441a14-82fe-4153-ab6c-224a79dfea78",
7
7
  "creationInfo": {
8
- "created": "2026-05-26T14:00:41Z",
8
+ "created": "2026-05-26T16:49:21Z",
9
9
  "creators": [
10
10
  "Tool: kici-sbom-generator"
11
11
  ]
@@ -1477,9 +1477,9 @@
1477
1477
  "homepage": "https://ericsmekens.github.io/jsep/tree/master/packages/regex#readme"
1478
1478
  },
1479
1479
  {
1480
- "SPDXID": "SPDXRef-Package--kici-dev-engine-0.1.7",
1480
+ "SPDXID": "SPDXRef-Package--kici-dev-engine-0.1.9",
1481
1481
  "name": "@kici-dev/engine",
1482
- "versionInfo": "0.1.7",
1482
+ "versionInfo": "0.1.9",
1483
1483
  "downloadLocation": "NOASSERTION",
1484
1484
  "filesAnalyzed": false,
1485
1485
  "licenseConcluded": "NOASSERTION",
@@ -1490,7 +1490,7 @@
1490
1490
  {
1491
1491
  "referenceCategory": "PACKAGE-MANAGER",
1492
1492
  "referenceType": "purl",
1493
- "referenceLocator": "pkg:npm/%40kici-dev/engine@0.1.7"
1493
+ "referenceLocator": "pkg:npm/%40kici-dev/engine@0.1.9"
1494
1494
  }
1495
1495
  ],
1496
1496
  "description": "Shared business logic for the KiCI CI/CD stack: protocol, triggers, state machine, and provider interfaces used by the Platform relay, orchestrator, and compiler.",
@@ -1499,7 +1499,7 @@
1499
1499
  {
1500
1500
  "SPDXID": "SPDXRef-RootPackage",
1501
1501
  "name": "@kici-dev/orchestrator",
1502
- "versionInfo": "0.1.7",
1502
+ "versionInfo": "0.1.9",
1503
1503
  "downloadLocation": "NOASSERTION",
1504
1504
  "filesAnalyzed": false,
1505
1505
  "licenseConcluded": "NOASSERTION",
@@ -1510,16 +1510,16 @@
1510
1510
  {
1511
1511
  "referenceCategory": "PACKAGE-MANAGER",
1512
1512
  "referenceType": "purl",
1513
- "referenceLocator": "pkg:npm/%40kici-dev/orchestrator@0.1.7"
1513
+ "referenceLocator": "pkg:npm/%40kici-dev/orchestrator@0.1.9"
1514
1514
  }
1515
1515
  ],
1516
1516
  "description": "Customer-deployable orchestrator for the KiCI CI/CD stack. Receives webhook events (direct or via Platform relay), matches triggers against the lock file, and dispatches jobs to connected agents.",
1517
1517
  "homepage": "https://kici.dev"
1518
1518
  },
1519
1519
  {
1520
- "SPDXID": "SPDXRef-Package--kici-dev-shared-0.1.7",
1520
+ "SPDXID": "SPDXRef-Package--kici-dev-shared-0.1.9",
1521
1521
  "name": "@kici-dev/shared",
1522
- "versionInfo": "0.1.7",
1522
+ "versionInfo": "0.1.9",
1523
1523
  "downloadLocation": "NOASSERTION",
1524
1524
  "filesAnalyzed": false,
1525
1525
  "licenseConcluded": "NOASSERTION",
@@ -1530,7 +1530,7 @@
1530
1530
  {
1531
1531
  "referenceCategory": "PACKAGE-MANAGER",
1532
1532
  "referenceType": "purl",
1533
- "referenceLocator": "pkg:npm/%40kici-dev/shared@0.1.7"
1533
+ "referenceLocator": "pkg:npm/%40kici-dev/shared@0.1.9"
1534
1534
  }
1535
1535
  ],
1536
1536
  "description": "Shared utilities for the KiCI CI/CD stack — logging, zx setup, crypto, telemetry, health and metrics routes. No business logic.",
@@ -10682,17 +10682,17 @@
10682
10682
  "relationshipType": "DEPENDS_ON"
10683
10683
  },
10684
10684
  {
10685
- "spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.7",
10685
+ "spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.9",
10686
10686
  "relatedSpdxElement": "SPDXRef-Package-jsonpath-plus-10.4.0",
10687
10687
  "relationshipType": "DEPENDS_ON"
10688
10688
  },
10689
10689
  {
10690
- "spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.7",
10690
+ "spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.9",
10691
10691
  "relatedSpdxElement": "SPDXRef-Package-picomatch-4.0.4",
10692
10692
  "relationshipType": "DEPENDS_ON"
10693
10693
  },
10694
10694
  {
10695
- "spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.7",
10695
+ "spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.9",
10696
10696
  "relatedSpdxElement": "SPDXRef-Package-zod-4.3.6",
10697
10697
  "relationshipType": "DEPENDS_ON"
10698
10698
  },
@@ -10728,12 +10728,12 @@
10728
10728
  },
10729
10729
  {
10730
10730
  "spdxElementId": "SPDXRef-RootPackage",
10731
- "relatedSpdxElement": "SPDXRef-Package--kici-dev-engine-0.1.7",
10731
+ "relatedSpdxElement": "SPDXRef-Package--kici-dev-engine-0.1.9",
10732
10732
  "relationshipType": "DEPENDS_ON"
10733
10733
  },
10734
10734
  {
10735
10735
  "spdxElementId": "SPDXRef-RootPackage",
10736
- "relatedSpdxElement": "SPDXRef-Package--kici-dev-shared-0.1.7",
10736
+ "relatedSpdxElement": "SPDXRef-Package--kici-dev-shared-0.1.9",
10737
10737
  "relationshipType": "DEPENDS_ON"
10738
10738
  },
10739
10739
  {
@@ -10837,102 +10837,102 @@
10837
10837
  "relationshipType": "DEPENDS_ON"
10838
10838
  },
10839
10839
  {
10840
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10840
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10841
10841
  "relatedSpdxElement": "SPDXRef-Package--aws-sdk-client-s3-3.1038.0",
10842
10842
  "relationshipType": "DEPENDS_ON"
10843
10843
  },
10844
10844
  {
10845
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10845
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10846
10846
  "relatedSpdxElement": "SPDXRef-Package--opentelemetry-api-1.9.1",
10847
10847
  "relationshipType": "DEPENDS_ON"
10848
10848
  },
10849
10849
  {
10850
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10850
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10851
10851
  "relatedSpdxElement": "SPDXRef-Package--opentelemetry-exporter-metrics-otlp-http-0.217.0",
10852
10852
  "relationshipType": "DEPENDS_ON"
10853
10853
  },
10854
10854
  {
10855
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10855
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10856
10856
  "relatedSpdxElement": "SPDXRef-Package--opentelemetry-exporter-prometheus-0.217.0",
10857
10857
  "relationshipType": "DEPENDS_ON"
10858
10858
  },
10859
10859
  {
10860
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10860
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10861
10861
  "relatedSpdxElement": "SPDXRef-Package--opentelemetry-exporter-trace-otlp-http-0.217.0",
10862
10862
  "relationshipType": "DEPENDS_ON"
10863
10863
  },
10864
10864
  {
10865
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10865
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10866
10866
  "relatedSpdxElement": "SPDXRef-Package--opentelemetry-instrumentation-runtime-node-0.28.0",
10867
10867
  "relationshipType": "DEPENDS_ON"
10868
10868
  },
10869
10869
  {
10870
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10870
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10871
10871
  "relatedSpdxElement": "SPDXRef-Package--opentelemetry-resources-2.7.0",
10872
10872
  "relationshipType": "DEPENDS_ON"
10873
10873
  },
10874
10874
  {
10875
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10875
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10876
10876
  "relatedSpdxElement": "SPDXRef-Package--opentelemetry-sdk-node-0.217.0",
10877
10877
  "relationshipType": "DEPENDS_ON"
10878
10878
  },
10879
10879
  {
10880
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10880
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10881
10881
  "relatedSpdxElement": "SPDXRef-Package--opentelemetry-semantic-conventions-1.40.0",
10882
10882
  "relationshipType": "DEPENDS_ON"
10883
10883
  },
10884
10884
  {
10885
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10885
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10886
10886
  "relatedSpdxElement": "SPDXRef-Package-diff-7.0.0",
10887
10887
  "relationshipType": "DEPENDS_ON"
10888
10888
  },
10889
10889
  {
10890
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10890
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10891
10891
  "relatedSpdxElement": "SPDXRef-Package-hono-4.12.18",
10892
10892
  "relationshipType": "DEPENDS_ON"
10893
10893
  },
10894
10894
  {
10895
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10895
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10896
10896
  "relatedSpdxElement": "SPDXRef-Package-kysely-0.29.0",
10897
10897
  "relationshipType": "DEPENDS_ON"
10898
10898
  },
10899
10899
  {
10900
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10900
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10901
10901
  "relatedSpdxElement": "SPDXRef-Package-oxc-transform-0.128.0",
10902
10902
  "relationshipType": "DEPENDS_ON"
10903
10903
  },
10904
10904
  {
10905
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10905
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10906
10906
  "relatedSpdxElement": "SPDXRef-Package-pg-8.20.0",
10907
10907
  "relationshipType": "DEPENDS_ON"
10908
10908
  },
10909
10909
  {
10910
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10910
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10911
10911
  "relatedSpdxElement": "SPDXRef-Package-picocolors-1.1.1",
10912
10912
  "relationshipType": "DEPENDS_ON"
10913
10913
  },
10914
10914
  {
10915
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10915
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10916
10916
  "relatedSpdxElement": "SPDXRef-Package-winston-daily-rotate-file-5.0.0",
10917
10917
  "relationshipType": "DEPENDS_ON"
10918
10918
  },
10919
10919
  {
10920
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10920
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10921
10921
  "relatedSpdxElement": "SPDXRef-Package-winston-3.19.0",
10922
10922
  "relationshipType": "DEPENDS_ON"
10923
10923
  },
10924
10924
  {
10925
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10925
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10926
10926
  "relatedSpdxElement": "SPDXRef-Package-yaml-2.8.3",
10927
10927
  "relationshipType": "DEPENDS_ON"
10928
10928
  },
10929
10929
  {
10930
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10930
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10931
10931
  "relatedSpdxElement": "SPDXRef-Package-zod-4.3.6",
10932
10932
  "relationshipType": "DEPENDS_ON"
10933
10933
  },
10934
10934
  {
10935
- "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.7",
10935
+ "spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.9",
10936
10936
  "relatedSpdxElement": "SPDXRef-Package-zx-8.8.5",
10937
10937
  "relationshipType": "DEPENDS_ON"
10938
10938
  },