@kici-dev/agent 0.1.24 → 0.1.25
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/execution/sandbox/ipc-protocol.d.ts +27 -6
- package/dist/index.js +8 -2
- package/dist/provenance/attest.d.ts +27 -4
- package/dist/provenance/statement-builder.d.ts +50 -0
- package/dist/server.js +115 -67
- package/dist/workflow-runner.js +144 -13
- package/dist/ws/orchestrator-client.d.ts +6 -0
- package/package.json +5 -5
- package/sbom.spdx.json +62 -62
|
@@ -216,12 +216,16 @@ export interface StepApprovalRequestIpc {
|
|
|
216
216
|
};
|
|
217
217
|
}
|
|
218
218
|
/** Which provenance upload operation to relay. */
|
|
219
|
-
export type ProvenanceRequestOp = 'requestUploadUrl' | 'complete';
|
|
219
|
+
export type ProvenanceRequestOp = 'requestUploadUrl' | 'complete' | 'defer';
|
|
220
220
|
/**
|
|
221
221
|
* Request a provenance bundle upload operation (runner -> agent). The agent
|
|
222
|
-
* relays it over the WS as a `provenance.upload.request` / `.complete`
|
|
223
|
-
* the response back as a {@link ProvenanceResponseIpc}.
|
|
224
|
-
* {@link CacheRequestIpc} relay pattern.
|
|
222
|
+
* relays it over the WS as a `provenance.upload.request` / `.complete` /
|
|
223
|
+
* `.defer` and pipes the response back as a {@link ProvenanceResponseIpc}.
|
|
224
|
+
* Mirrors the {@link CacheRequestIpc} relay pattern.
|
|
225
|
+
*
|
|
226
|
+
* `defer` captures a frozen, DSSE-signed statement for later minting (the
|
|
227
|
+
* transient mint-failure path): no upload happens; the orchestrator persists
|
|
228
|
+
* the envelope in its deferred-attestation outbox instead.
|
|
225
229
|
*/
|
|
226
230
|
export interface ProvenanceRequestIpc {
|
|
227
231
|
type: 'provenance.request';
|
|
@@ -231,10 +235,18 @@ export interface ProvenanceRequestIpc {
|
|
|
231
235
|
op: ProvenanceRequestOp;
|
|
232
236
|
/** Primary subject digest (lowercase hex) — the storage-key discriminator. */
|
|
233
237
|
subjectDigest: string;
|
|
234
|
-
/** Caller-supplied artifact name. `complete` only. */
|
|
238
|
+
/** Caller-supplied artifact name. `complete` + `defer` only. */
|
|
235
239
|
subjectName?: string;
|
|
236
|
-
/** Bundle media type. `complete` only. */
|
|
240
|
+
/** Bundle media type. `complete` + `defer` only. */
|
|
237
241
|
mediaType?: string;
|
|
242
|
+
/** Requested token audience. `defer` only. */
|
|
243
|
+
audience?: string;
|
|
244
|
+
/** SHA-256 of the frozen DSSE statement payload. `defer` only. */
|
|
245
|
+
statementHash?: string;
|
|
246
|
+
/** Frozen, DSSE-signed statement envelope. `defer` only. */
|
|
247
|
+
dsseEnvelope?: unknown;
|
|
248
|
+
/** Ephemeral public key JWK the envelope was signed with. `defer` only. */
|
|
249
|
+
publicKey?: unknown;
|
|
238
250
|
}
|
|
239
251
|
export type RunnerToAgentMessage = ReadyMessage | StepStartMessage | StepCompleteMessage | LogLineMessage | StepSecretMountMessage | JobCompleteMessage | EventEmitRequest | ConcurrencyReportMessage | AgentApiRequestIpc | CacheRequestIpc | ProvenanceRequestIpc | StepApprovalRequestIpc;
|
|
240
252
|
/** Instruct the workflow runner to execute a job. */
|
|
@@ -466,6 +478,15 @@ export interface JobExecutionRequest {
|
|
|
466
478
|
event?: Record<string, unknown>;
|
|
467
479
|
/** Git provider that originated the triggering event (e.g. 'github', 'forgejo'). */
|
|
468
480
|
provider?: string;
|
|
481
|
+
/**
|
|
482
|
+
* Platform provenance issuer, threaded from the orchestrator for a deferred
|
|
483
|
+
* attestation's frozen `builder.id`. Best-effort: absent when the orchestrator
|
|
484
|
+
* has no issuer wired (e.g. never authenticated to the Platform), in which
|
|
485
|
+
* case the frozen statement records an unknown issuer honestly. Not
|
|
486
|
+
* verification load-bearing — a deferred bundle's later token binds to the
|
|
487
|
+
* frozen statement by hash, and the authoritative org id lives in that token.
|
|
488
|
+
*/
|
|
489
|
+
provenanceIssuer?: string;
|
|
469
490
|
/** Whether to checkout the repo (default: true). */
|
|
470
491
|
checkout?: boolean;
|
|
471
492
|
/** Whether this job is part of a developer-initiated run triggered by `kici run`. */
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,14 @@ import https from "node:https";
|
|
|
20
20
|
import http from "node:http";
|
|
21
21
|
import "node:url";
|
|
22
22
|
var __defProp = Object.defineProperty;
|
|
23
|
-
var __esmMin = (fn, res) => () =>
|
|
23
|
+
var __esmMin = (fn, res, err) => () => {
|
|
24
|
+
if (err) throw err[0];
|
|
25
|
+
try {
|
|
26
|
+
return fn && (res = fn(fn = 0)), res;
|
|
27
|
+
} catch (e) {
|
|
28
|
+
throw err = [e], e;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
24
31
|
var __exportAll = (all, no_symbols) => {
|
|
25
32
|
let target = {};
|
|
26
33
|
for (var name in all) __defProp(target, name, {
|
|
@@ -30,7 +37,6 @@ var __exportAll = (all, no_symbols) => {
|
|
|
30
37
|
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
31
38
|
return target;
|
|
32
39
|
};
|
|
33
|
-
import.meta.url;
|
|
34
40
|
//#endregion
|
|
35
41
|
//#region src/config.ts
|
|
36
42
|
/** Execution mode for the agent's sandbox backend. Mirrors the runtime enum. */
|
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import { type KiciBundle } from '@kici-dev/engine/provenance/bundle';
|
|
2
2
|
import type { OidcTokenResult } from '@kici-dev/engine/protocol/messages/oidc-token-relay';
|
|
3
|
-
import { type ProvenanceSubject } from './statement-builder.js';
|
|
3
|
+
import { type LocalBuildContext, type ProvenanceSubject } from './statement-builder.js';
|
|
4
|
+
/** The frozen, DSSE-signed attestation the agent reports for later fulfilment. */
|
|
5
|
+
export interface DeferredAttestationReport {
|
|
6
|
+
subjectName: string;
|
|
7
|
+
subjectDigest: string;
|
|
8
|
+
audience: string;
|
|
9
|
+
mediaType: string;
|
|
10
|
+
statementHash: string;
|
|
11
|
+
dsseEnvelope: KiciBundle['dsseEnvelope'];
|
|
12
|
+
publicKey: Record<string, unknown>;
|
|
13
|
+
}
|
|
4
14
|
export interface AttestDeps {
|
|
5
|
-
/** P1.4 relay: returns a KiCI ID token
|
|
15
|
+
/** P1.4 relay: returns a minted KiCI ID token or a transient `deferred` signal. */
|
|
6
16
|
getIdToken: (opts: {
|
|
7
17
|
audience: string;
|
|
8
18
|
}) => Promise<OidcTokenResult>;
|
|
9
19
|
/** Upload the serialized bundle; returns the storage key it was written to. */
|
|
10
20
|
persist: (bundle: KiciBundle, subjectDigest: string) => Promise<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Report a frozen, DSSE-signed statement for later minting (the transient
|
|
23
|
+
* mint-failure path). Required only when the relay may defer; the live path
|
|
24
|
+
* never calls it.
|
|
25
|
+
*/
|
|
26
|
+
reportDeferred?: (report: DeferredAttestationReport) => Promise<void>;
|
|
27
|
+
/** Agent-local job facts used to freeze a statement when the mint defers. */
|
|
28
|
+
localContext?: LocalBuildContext;
|
|
11
29
|
builderVersions: {
|
|
12
30
|
'kici-agent': string;
|
|
13
31
|
'kici-orchestrator': string;
|
|
@@ -19,11 +37,16 @@ export interface AttestInput {
|
|
|
19
37
|
subject: ProvenanceSubject;
|
|
20
38
|
audience?: string;
|
|
21
39
|
}
|
|
22
|
-
|
|
40
|
+
/** A minted-and-uploaded attestation, or a deferred one captured for later. */
|
|
41
|
+
export type AttestResult = {
|
|
23
42
|
storageKey: string;
|
|
24
43
|
bundle: KiciBundle;
|
|
25
44
|
subjectDigest: string;
|
|
26
|
-
}
|
|
45
|
+
} | {
|
|
46
|
+
deferred: true;
|
|
47
|
+
statementHash: string;
|
|
48
|
+
subjectDigest: string;
|
|
49
|
+
};
|
|
27
50
|
export declare function attestProvenance(deps: AttestDeps, input: AttestInput): Promise<AttestResult>;
|
|
28
51
|
/**
|
|
29
52
|
* Pick the primary digest (`sha256` preferred) as the storage-key discriminator.
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* statement's identity equals the token's identity by construction.
|
|
6
6
|
*/
|
|
7
7
|
import { type KiciProvenanceStatement } from '@kici-dev/engine/provenance/schema';
|
|
8
|
+
import type { SourceOrigin } from '@kici-dev/engine';
|
|
8
9
|
/** The KiCI identity-token claims the builder reads (Platform server-truth). */
|
|
9
10
|
export interface ProvenanceTokenClaims {
|
|
10
11
|
iss: string;
|
|
@@ -15,6 +16,12 @@ export interface ProvenanceTokenClaims {
|
|
|
15
16
|
kici_run_id: string;
|
|
16
17
|
kici_job_id: string;
|
|
17
18
|
orchestrator_id?: string | null;
|
|
19
|
+
/** Authoritative origin: the customer's public org id (Platform-asserted). */
|
|
20
|
+
org_id?: string;
|
|
21
|
+
/** Source-origin brand: triggered vs run-remote (local working-tree overlay). */
|
|
22
|
+
source_origin?: SourceOrigin;
|
|
23
|
+
/** Informational source provider (github / gitlab / bitbucket / local). */
|
|
24
|
+
provider?: string | null;
|
|
18
25
|
}
|
|
19
26
|
/** Caller-supplied artifact subject: a name plus a lowercase-hex digest map. */
|
|
20
27
|
export interface ProvenanceSubject {
|
|
@@ -33,6 +40,49 @@ export interface BuildStatementInput {
|
|
|
33
40
|
/** ISO-8601 timestamp with offset. */
|
|
34
41
|
finishedOn: string;
|
|
35
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Agent-local job context used to freeze a provenance statement for a deferred
|
|
45
|
+
* attestation. When the Platform mint fails transiently there is no identity
|
|
46
|
+
* token to read claims from, so the statement is built from facts the agent
|
|
47
|
+
* already holds about the job it just ran. Only the identity token is deferred;
|
|
48
|
+
* these attested facts are sealed (DSSE-signed) at build time.
|
|
49
|
+
*/
|
|
50
|
+
export interface LocalBuildContext {
|
|
51
|
+
repository: string;
|
|
52
|
+
ref: string;
|
|
53
|
+
sha: string | null;
|
|
54
|
+
workflowRef: string;
|
|
55
|
+
runId: string;
|
|
56
|
+
jobId: string;
|
|
57
|
+
orgId?: string;
|
|
58
|
+
sourceOrigin?: SourceOrigin;
|
|
59
|
+
/**
|
|
60
|
+
* Platform provenance issuer for the `builder.id`. The agent does not always
|
|
61
|
+
* know it at build time (the orchestrator may be disconnected — that is why
|
|
62
|
+
* the mint deferred), so it is best-effort; an empty string yields a
|
|
63
|
+
* `/orchestrator/unknown` builder id. This field is not verification
|
|
64
|
+
* load-bearing for a deferred bundle: the later token binds to the frozen
|
|
65
|
+
* statement by hash, not by field-for-field cross-check.
|
|
66
|
+
*/
|
|
67
|
+
issuer: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Build a frozen SLSA v1.0 provenance statement from agent-local job context,
|
|
71
|
+
* for a deferred attestation (no minted identity token yet). Marks
|
|
72
|
+
* `attestationOrigin: 'deferred'` in the internal parameters. The caller
|
|
73
|
+
* DSSE-signs the returned statement immediately and computes its statement hash
|
|
74
|
+
* — the binding the later OIDC mint commits to (truth-contract property 2).
|
|
75
|
+
*/
|
|
76
|
+
export declare function buildLocalProvenanceStatement(input: {
|
|
77
|
+
context: LocalBuildContext;
|
|
78
|
+
subject: ProvenanceSubject;
|
|
79
|
+
builderVersions: {
|
|
80
|
+
'kici-agent': string;
|
|
81
|
+
'kici-orchestrator': string;
|
|
82
|
+
};
|
|
83
|
+
startedOn: string;
|
|
84
|
+
finishedOn: string;
|
|
85
|
+
}): KiciProvenanceStatement;
|
|
36
86
|
/** Build a KiCI SLSA v1.0 provenance statement (validates against the P1.1 schema). */
|
|
37
87
|
export declare function buildProvenanceStatement(input: BuildStatementInput): KiciProvenanceStatement;
|
|
38
88
|
//# sourceMappingURL=statement-builder.d.ts.map
|
package/dist/server.js
CHANGED
|
@@ -15,7 +15,7 @@ import { LOGGER_ENV_VARS, defineEnv, validateUnknownKiciVars } from "@kici-dev/s
|
|
|
15
15
|
import { ALLOWED_SYSTEM_VARS, CacheRunEventType, CacheStepType, ExecutionJobStatus, ExecutionStepStatus, InitFailureCategory, KNOWN_ROLES, PROTOCOL_VERSION, SANDBOX_DEFAULT_VARS, WS_CLOSE_AGENT_AUTH_FAILED, WS_MAX_PAYLOAD_BYTES, applyIncludeExclude, deriveOsArchLabels, expandMatrix, heartbeatSchema, hostLabel, mergeAutoLabels, orchestratorToAgentMessageSchema, parseHostPropertyAssignments, resolveRoleLabels, resolveWhenToRunOn, validateNoReservedLabels } from "@kici-dev/engine";
|
|
16
16
|
import { execFile, execFileSync, execSync, fork, spawn } from "node:child_process";
|
|
17
17
|
import WebSocket from "ws";
|
|
18
|
-
import * as fs$
|
|
18
|
+
import * as fs$1 from "node:fs";
|
|
19
19
|
import fs, { existsSync } from "node:fs";
|
|
20
20
|
import { ZipArchive } from "archiver";
|
|
21
21
|
import path, { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
@@ -23,7 +23,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
23
23
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
24
24
|
import { format, promisify } from "node:util";
|
|
25
25
|
import { gcStaleTmpDirs } from "@kici-dev/core/tmp-gc";
|
|
26
|
-
import
|
|
26
|
+
import fsPromises, { access, lstat, mkdir, mkdtemp, readFile, readdir, realpath, rm, unlink, writeFile } from "node:fs/promises";
|
|
27
27
|
import Docker from "dockerode";
|
|
28
28
|
import { buildKiciApi, buildNeedsContext, isDynamicGroupRef, isDynamicJobFn, isParallelGroup, isStaticArray, isStaticObject } from "@kici-dev/sdk";
|
|
29
29
|
import { c, x } from "tar";
|
|
@@ -36,7 +36,14 @@ import { PNPM_IGNORE_BUILD_GATE_ARG, PackageManager, YarnFlavor, detectPackageMa
|
|
|
36
36
|
import { parse, stringify } from "yaml";
|
|
37
37
|
import { createInterface } from "node:readline";
|
|
38
38
|
var __defProp = Object.defineProperty;
|
|
39
|
-
var __esmMin = (fn, res) => () =>
|
|
39
|
+
var __esmMin = (fn, res, err) => () => {
|
|
40
|
+
if (err) throw err[0];
|
|
41
|
+
try {
|
|
42
|
+
return fn && (res = fn(fn = 0)), res;
|
|
43
|
+
} catch (e) {
|
|
44
|
+
throw err = [e], e;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
40
47
|
var __exportAll = (all, no_symbols) => {
|
|
41
48
|
let target = {};
|
|
42
49
|
for (var name in all) __defProp(target, name, {
|
|
@@ -46,7 +53,6 @@ var __exportAll = (all, no_symbols) => {
|
|
|
46
53
|
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
47
54
|
return target;
|
|
48
55
|
};
|
|
49
|
-
import.meta.url;
|
|
50
56
|
//#endregion
|
|
51
57
|
//#region src/config.ts
|
|
52
58
|
/** Execution mode for the agent's sandbox backend. Mirrors the runtime enum. */
|
|
@@ -222,7 +228,7 @@ async function buildAgentMiniBundle(opts) {
|
|
|
222
228
|
uptime: os$1.uptime()
|
|
223
229
|
}, null, 2), { name: "system/info.json" });
|
|
224
230
|
if (opts.metricsText) archive.append(opts.metricsText, { name: "system/metrics.txt" });
|
|
225
|
-
if (opts.logDir && fs$
|
|
231
|
+
if (opts.logDir && fs$1.existsSync(opts.logDir)) await addLogsToArchive(archive, opts.logDir, opts.logWindowHours);
|
|
226
232
|
await archive.finalize();
|
|
227
233
|
await done;
|
|
228
234
|
return Buffer.concat(chunks);
|
|
@@ -722,6 +728,13 @@ var OrchestratorClient = class OrchestratorClient {
|
|
|
722
728
|
requestId: request.requestId
|
|
723
729
|
};
|
|
724
730
|
}
|
|
731
|
+
if (request.op === "defer") {
|
|
732
|
+
this.sendProvenanceUploadDefer(jobId, request);
|
|
733
|
+
return {
|
|
734
|
+
type: "provenance.response",
|
|
735
|
+
requestId: request.requestId
|
|
736
|
+
};
|
|
737
|
+
}
|
|
725
738
|
const uploadUrl = await this.requestProvenanceUploadUrl(jobId, request.subjectDigest);
|
|
726
739
|
return {
|
|
727
740
|
type: "provenance.response",
|
|
@@ -730,6 +743,25 @@ var OrchestratorClient = class OrchestratorClient {
|
|
|
730
743
|
};
|
|
731
744
|
}
|
|
732
745
|
/**
|
|
746
|
+
* Capture a frozen, DSSE-signed attestation for later minting (transient
|
|
747
|
+
* mint-failure path). Fire-and-forget: the orchestrator persists it into the
|
|
748
|
+
* deferred-attestation outbox and the job stays green.
|
|
749
|
+
*/
|
|
750
|
+
sendProvenanceUploadDefer(jobId, request) {
|
|
751
|
+
this.sendDirect({
|
|
752
|
+
type: "provenance.upload.defer",
|
|
753
|
+
messageId: randomUUID(),
|
|
754
|
+
jobId,
|
|
755
|
+
subjectName: request.subjectName,
|
|
756
|
+
subjectDigest: request.subjectDigest,
|
|
757
|
+
audience: request.audience,
|
|
758
|
+
mediaType: request.mediaType,
|
|
759
|
+
statementHash: request.statementHash,
|
|
760
|
+
dsseEnvelope: request.dsseEnvelope,
|
|
761
|
+
publicKey: request.publicKey
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
733
765
|
* Relay a step-level approval request to the orchestrator. Sends a
|
|
734
766
|
* `step.approval-request` WS message and resolves with the orchestrator's
|
|
735
767
|
* `step.approval-resolved` mapped onto the IPC response shape. No client-side
|
|
@@ -1310,14 +1342,14 @@ var init_console_capture = __esmMin((() => {
|
|
|
1310
1342
|
init_console_capture();
|
|
1311
1343
|
function safe(name, fallback = "unknown") {
|
|
1312
1344
|
switch (name) {
|
|
1313
|
-
case "version": return "0.1.
|
|
1314
|
-
case "buildCommit": return "
|
|
1315
|
-
case "sdkVersion": return "0.1.
|
|
1316
|
-
case "sdkBundleHash": return "
|
|
1317
|
-
case "sharedVersion": return "0.1.
|
|
1318
|
-
case "sharedBundleHash": return "
|
|
1319
|
-
case "engineVersion": return "0.1.
|
|
1320
|
-
case "engineBundleHash": return "
|
|
1345
|
+
case "version": return "0.1.25";
|
|
1346
|
+
case "buildCommit": return "15e8e4155";
|
|
1347
|
+
case "sdkVersion": return "0.1.25";
|
|
1348
|
+
case "sdkBundleHash": return "e06bd1acf349ba365bdb357f3d865e0cbb4ad4604a0270b707a681a4f440954e";
|
|
1349
|
+
case "sharedVersion": return "0.1.25";
|
|
1350
|
+
case "sharedBundleHash": return "2394db0d8560b2cebf220c0e2d8993c75083aaf70a5917c35099b24feb3a22ba";
|
|
1351
|
+
case "engineVersion": return "0.1.25";
|
|
1352
|
+
case "engineBundleHash": return "c3320e812b8593d692f3fbf5eafe83507270028f7a1174c607881105dd702654";
|
|
1321
1353
|
default: return fallback;
|
|
1322
1354
|
}
|
|
1323
1355
|
}
|
|
@@ -1951,7 +1983,7 @@ async function buildAssetDigestFromResolvedPaths(workDir, resolvedPaths) {
|
|
|
1951
1983
|
for (const rel of resolvedPaths) {
|
|
1952
1984
|
const abs = path.join(workDir, rel);
|
|
1953
1985
|
try {
|
|
1954
|
-
const content = await
|
|
1986
|
+
const content = await fsPromises.readFile(abs, "utf-8");
|
|
1955
1987
|
parts.push(`${rel}\n${content}`);
|
|
1956
1988
|
} catch {
|
|
1957
1989
|
parts.push(`${rel}\n`);
|
|
@@ -1976,7 +2008,7 @@ async function loadWorkflowSource(workDir, sourceFile, expectedContentHash, reso
|
|
|
1976
2008
|
ensureLoaderHookRegistered();
|
|
1977
2009
|
const filePath = path.join(workDir, sourceFile);
|
|
1978
2010
|
if (expectedContentHash) {
|
|
1979
|
-
const rawSource = await
|
|
2011
|
+
const rawSource = await fsPromises.readFile(filePath, "utf-8");
|
|
1980
2012
|
let assetDigest;
|
|
1981
2013
|
if (resolvedHashFiles?.length) assetDigest = await buildAssetDigestFromResolvedPaths(workDir, resolvedHashFiles);
|
|
1982
2014
|
const actualHash = computeContentHash(rawSource, assetDigest);
|
|
@@ -2080,8 +2112,8 @@ async function extractStepsFromDynamicJob(workflow, dynamicIndex, jobName, event
|
|
|
2080
2112
|
}
|
|
2081
2113
|
var AGENT_SDK_VERSION, AGENT_SDK_BUNDLE_HASH, hookRegistered;
|
|
2082
2114
|
var init_workflow_loader = __esmMin((() => {
|
|
2083
|
-
AGENT_SDK_VERSION = "0.1.
|
|
2084
|
-
AGENT_SDK_BUNDLE_HASH = "
|
|
2115
|
+
AGENT_SDK_VERSION = "0.1.25";
|
|
2116
|
+
AGENT_SDK_BUNDLE_HASH = "e06bd1acf349ba365bdb357f3d865e0cbb4ad4604a0270b707a681a4f440954e";
|
|
2085
2117
|
hookRegistered = false;
|
|
2086
2118
|
}));
|
|
2087
2119
|
//#endregion
|
|
@@ -2247,24 +2279,24 @@ function resolveOrchestratorUrl(url) {
|
|
|
2247
2279
|
* have nothing to race; the defensive `rm` covers re-runs.
|
|
2248
2280
|
*/
|
|
2249
2281
|
async function moveScratchIntoRepo(scratchDir, workDir) {
|
|
2250
|
-
for (const child of await
|
|
2282
|
+
for (const child of await fsPromises.readdir(scratchDir)) if (child === ".kici") {
|
|
2251
2283
|
const kiciScratch = join(scratchDir, ".kici");
|
|
2252
|
-
for (const sub of await
|
|
2284
|
+
for (const sub of await fsPromises.readdir(kiciScratch)) await moveInto(join(kiciScratch, sub), join(workDir, ".kici", sub));
|
|
2253
2285
|
} else await moveInto(join(scratchDir, child), join(workDir, child));
|
|
2254
2286
|
}
|
|
2255
2287
|
/** Move `src` to `dest`, creating the parent and clearing any stale dest. */
|
|
2256
2288
|
async function moveInto(src, dest) {
|
|
2257
2289
|
await mkdir(dirname(dest), { recursive: true });
|
|
2258
|
-
await
|
|
2290
|
+
await fsPromises.rm(dest, {
|
|
2259
2291
|
recursive: true,
|
|
2260
2292
|
force: true
|
|
2261
2293
|
});
|
|
2262
|
-
await
|
|
2294
|
+
await fsPromises.rename(src, dest);
|
|
2263
2295
|
}
|
|
2264
2296
|
/** Best-effort cleanup of a settled scratch dir; logs and continues on failure. */
|
|
2265
2297
|
async function cleanupScratch(scratchDir) {
|
|
2266
2298
|
try {
|
|
2267
|
-
await
|
|
2299
|
+
await fsPromises.rm(scratchDir, {
|
|
2268
2300
|
recursive: true,
|
|
2269
2301
|
force: true
|
|
2270
2302
|
});
|
|
@@ -2298,7 +2330,7 @@ async function restoreDeps(workDir, depsUrl, depsHash) {
|
|
|
2298
2330
|
const kiciDir = join(workDir, ".kici");
|
|
2299
2331
|
if (depsUrl.startsWith("file://")) {
|
|
2300
2332
|
const localPath = fileURLToPath(depsUrl);
|
|
2301
|
-
const data = await
|
|
2333
|
+
const data = await fsPromises.readFile(localPath);
|
|
2302
2334
|
if (depsHash) {
|
|
2303
2335
|
const actualHash = computeHash(data);
|
|
2304
2336
|
if (actualHash !== depsHash) throw new Error(`Dep tarball hash mismatch: expected ${depsHash}, got ${actualHash}`);
|
|
@@ -2457,7 +2489,7 @@ async function restoreSource(workDir, sourceTarUrl) {
|
|
|
2457
2489
|
let data;
|
|
2458
2490
|
if (sourceTarUrl.startsWith("file://")) {
|
|
2459
2491
|
const localPath = fileURLToPath(sourceTarUrl);
|
|
2460
|
-
data = await
|
|
2492
|
+
data = await fsPromises.readFile(localPath);
|
|
2461
2493
|
} else if (sourceTarUrl.startsWith("http://") || sourceTarUrl.startsWith("https://")) data = await downloadUrl(sourceTarUrl);
|
|
2462
2494
|
else throw new Error(`Unsupported source tarball URL scheme: ${sourceTarUrl}`);
|
|
2463
2495
|
await extractSourceTarball(data, workDir);
|
|
@@ -2665,37 +2697,53 @@ async function sshPush(reach, privateKey, localBytes, remotePath, opts = {}, dep
|
|
|
2665
2697
|
/**
|
|
2666
2698
|
* Start a per-call ephemeral ssh-agent, load the key via stdin (never a file),
|
|
2667
2699
|
* run `body` with `SSH_AUTH_SOCK` in env, and kill the agent in `finally`.
|
|
2700
|
+
*
|
|
2701
|
+
* The agent is bound to a socket inside a private `kici-bootstrap-ssh-*`
|
|
2702
|
+
* directory (`ssh-agent -a <dir>/agent.sock`) rather than the default
|
|
2703
|
+
* `/tmp/ssh-XXXX`. `ssh-agent` daemonizes into its own session, so it does NOT
|
|
2704
|
+
* die with this process — a SIGKILL of the agent (routine when an ephemeral
|
|
2705
|
+
* bring-up runner is torn down) skips the `finally` and orphans the daemon.
|
|
2706
|
+
* The namespaced socket path is how `kici-leak-sweep` reaps such orphans
|
|
2707
|
+
* precisely: it can distinguish a KiCI bring-up agent from an operator's login
|
|
2708
|
+
* agent, which a bare `/tmp/ssh-XXXX` socket cannot. The private dir is removed
|
|
2709
|
+
* in an outer `finally` so the normal path leaves nothing behind.
|
|
2668
2710
|
*/
|
|
2669
2711
|
async function withEphemeralAgent(privateKey, spawnFn, body) {
|
|
2670
2712
|
const baseEnv = { ...process.env };
|
|
2671
|
-
const
|
|
2672
|
-
|
|
2673
|
-
const sock = parseAgentSocket(start.stdout);
|
|
2674
|
-
const pid = parseAgentPid(start.stdout);
|
|
2675
|
-
const agentEnv = {
|
|
2676
|
-
...baseEnv,
|
|
2677
|
-
SSH_AUTH_SOCK: sock,
|
|
2678
|
-
...pid ? { SSH_AGENT_PID: pid } : {},
|
|
2679
|
-
SSH_ASKPASS: "/bin/false",
|
|
2680
|
-
DISPLAY: ""
|
|
2681
|
-
};
|
|
2713
|
+
const agentDir = await mkdtemp(join(tmpdir(), "kici-bootstrap-ssh-"));
|
|
2714
|
+
const sock = join(agentDir, "agent.sock");
|
|
2682
2715
|
try {
|
|
2683
|
-
const
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2716
|
+
const start = await spawnFn("ssh-agent", [
|
|
2717
|
+
"-a",
|
|
2718
|
+
sock,
|
|
2719
|
+
"-s"
|
|
2720
|
+
], { env: baseEnv });
|
|
2721
|
+
if (start.exitCode !== 0) throw new Error(`ssh-agent start failed: exit ${start.exitCode}\n${start.stderr}`);
|
|
2722
|
+
const pid = parseAgentPid(start.stdout);
|
|
2723
|
+
const agentEnv = {
|
|
2724
|
+
...baseEnv,
|
|
2725
|
+
SSH_AUTH_SOCK: sock,
|
|
2726
|
+
...pid ? { SSH_AGENT_PID: pid } : {},
|
|
2727
|
+
SSH_ASKPASS: "/bin/false",
|
|
2728
|
+
DISPLAY: ""
|
|
2729
|
+
};
|
|
2730
|
+
try {
|
|
2731
|
+
const add = await spawnFn("ssh-add", ["-"], {
|
|
2732
|
+
env: agentEnv,
|
|
2733
|
+
stdin: privateKey.endsWith("\n") ? privateKey : `${privateKey}\n`
|
|
2734
|
+
});
|
|
2735
|
+
if (add.exitCode !== 0) throw new Error(`ssh-add failed: exit ${add.exitCode}\n${add.stderr}`);
|
|
2736
|
+
return await body(agentEnv);
|
|
2737
|
+
} finally {
|
|
2738
|
+
await spawnFn("ssh-agent", ["-k"], { env: agentEnv }).catch(() => {});
|
|
2739
|
+
}
|
|
2689
2740
|
} finally {
|
|
2690
|
-
await
|
|
2741
|
+
await rm(agentDir, {
|
|
2742
|
+
recursive: true,
|
|
2743
|
+
force: true
|
|
2744
|
+
}).catch(() => {});
|
|
2691
2745
|
}
|
|
2692
2746
|
}
|
|
2693
|
-
/** Extract `SSH_AUTH_SOCK=<path>;` from `ssh-agent -s` output. */
|
|
2694
|
-
function parseAgentSocket(out) {
|
|
2695
|
-
const m = out.match(/SSH_AUTH_SOCK=([^;\n]+)/);
|
|
2696
|
-
if (!m) throw new Error("ssh-agent -s did not emit SSH_AUTH_SOCK");
|
|
2697
|
-
return m[1];
|
|
2698
|
-
}
|
|
2699
2747
|
/** Extract `SSH_AGENT_PID=<n>;` from `ssh-agent -s` output (best-effort). */
|
|
2700
2748
|
function parseAgentPid(out) {
|
|
2701
2749
|
return out.match(/SSH_AGENT_PID=([^;\n]+)/)?.[1];
|
|
@@ -2921,7 +2969,7 @@ async function serializeJob(job, generatedNames, ctx, staticNames, allowedGroups
|
|
|
2921
2969
|
*/
|
|
2922
2970
|
function resolveNeeds(needs, generatedNames, staticNames, allowedGroups) {
|
|
2923
2971
|
if (!needs || needs.length === 0) return [];
|
|
2924
|
-
const allNames = new Set([...generatedNames, ...staticNames]);
|
|
2972
|
+
const allNames = /* @__PURE__ */ new Set([...generatedNames, ...staticNames]);
|
|
2925
2973
|
return needs.map((dep) => {
|
|
2926
2974
|
if (typeof dep === "string") {
|
|
2927
2975
|
if (!allNames.has(dep)) throw new Error(`Job dependency '${dep}' not found in workflow jobs (checked: ${generatedNames.size} generated, ${staticNames.size} static)`);
|
|
@@ -3318,7 +3366,7 @@ function decryptBuffer(encrypted, aesKey) {
|
|
|
3318
3366
|
*/
|
|
3319
3367
|
async function applyOverlay(config) {
|
|
3320
3368
|
const { tarballUrl, cliPublicKey, orchestratorPrivateKey, repoDir } = config;
|
|
3321
|
-
const tmpDir = await
|
|
3369
|
+
const tmpDir = await fsPromises.mkdtemp(path.join(os.tmpdir(), "kici-overlay-"));
|
|
3322
3370
|
try {
|
|
3323
3371
|
logger$7.info("Downloading overlay tarball", { url: tarballUrl.replace(/\?.*$/, "?[redacted]") });
|
|
3324
3372
|
let encryptedData;
|
|
@@ -3332,7 +3380,7 @@ async function applyOverlay(config) {
|
|
|
3332
3380
|
const decryptedData = decryptBuffer(encryptedData, aesKey);
|
|
3333
3381
|
logger$7.info("Extracting overlay tarball", { size: decryptedData.length });
|
|
3334
3382
|
const extractDir = path.join(tmpDir, "extracted");
|
|
3335
|
-
await
|
|
3383
|
+
await fsPromises.mkdir(extractDir, { recursive: true });
|
|
3336
3384
|
try {
|
|
3337
3385
|
const readable = Readable.from(decryptedData);
|
|
3338
3386
|
await new Promise((resolve, reject) => {
|
|
@@ -3347,7 +3395,7 @@ async function applyOverlay(config) {
|
|
|
3347
3395
|
const manifestPath = path.join(extractDir, ".kici-overlay-tmp", "manifest.json");
|
|
3348
3396
|
let manifestContent;
|
|
3349
3397
|
try {
|
|
3350
|
-
manifestContent = await
|
|
3398
|
+
manifestContent = await fsPromises.readFile(manifestPath, "utf-8");
|
|
3351
3399
|
} catch {
|
|
3352
3400
|
throw new Error("Overlay manifest not found: expected .kici-overlay-tmp/manifest.json in tarball");
|
|
3353
3401
|
}
|
|
@@ -3368,15 +3416,15 @@ async function applyOverlay(config) {
|
|
|
3368
3416
|
for (const file of checksumFiles) {
|
|
3369
3417
|
const srcPath = path.join(extractDir, file);
|
|
3370
3418
|
const destPath = path.join(repoDir, file);
|
|
3371
|
-
await
|
|
3372
|
-
await
|
|
3419
|
+
await fsPromises.mkdir(path.dirname(destPath), { recursive: true });
|
|
3420
|
+
await fsPromises.copyFile(srcPath, destPath);
|
|
3373
3421
|
filesApplied++;
|
|
3374
3422
|
}
|
|
3375
3423
|
let filesDeleted = 0;
|
|
3376
3424
|
for (const file of manifest.deletions) {
|
|
3377
3425
|
const targetPath = path.join(repoDir, file);
|
|
3378
3426
|
try {
|
|
3379
|
-
await
|
|
3427
|
+
await fsPromises.unlink(targetPath);
|
|
3380
3428
|
filesDeleted++;
|
|
3381
3429
|
} catch {
|
|
3382
3430
|
logger$7.debug("Deletion target not found, skipping", { file });
|
|
@@ -3392,7 +3440,7 @@ async function applyOverlay(config) {
|
|
|
3392
3440
|
verified: true
|
|
3393
3441
|
};
|
|
3394
3442
|
} finally {
|
|
3395
|
-
await
|
|
3443
|
+
await fsPromises.rm(tmpDir, {
|
|
3396
3444
|
recursive: true,
|
|
3397
3445
|
force: true
|
|
3398
3446
|
}).catch(() => {});
|
|
@@ -5814,7 +5862,7 @@ var job_runner_exports = /* @__PURE__ */ __exportAll({
|
|
|
5814
5862
|
*/
|
|
5815
5863
|
async function fileExists(p) {
|
|
5816
5864
|
try {
|
|
5817
|
-
await
|
|
5865
|
+
await fsPromises.access(p);
|
|
5818
5866
|
return true;
|
|
5819
5867
|
} catch {
|
|
5820
5868
|
return false;
|
|
@@ -5930,11 +5978,11 @@ var init_job_runner = __esmMin((() => {
|
|
|
5930
5978
|
async execute(dispatch) {
|
|
5931
5979
|
const { runId: _runId, jobId, jobConfig: _jobConfig } = dispatch;
|
|
5932
5980
|
const abortController = new AbortController();
|
|
5933
|
-
const workDir = await
|
|
5981
|
+
const workDir = await fsPromises.mkdtemp(join(tmpdir(), "kici-"));
|
|
5934
5982
|
const completionPromise = this.runJob(dispatch, workDir, abortController).finally(async () => {
|
|
5935
5983
|
this.activeJobs.delete(jobId);
|
|
5936
5984
|
this.activeSandbox = null;
|
|
5937
|
-
await
|
|
5985
|
+
await fsPromises.rm(workDir, {
|
|
5938
5986
|
recursive: true,
|
|
5939
5987
|
force: true
|
|
5940
5988
|
}).catch(() => {});
|
|
@@ -6896,14 +6944,14 @@ var init_job_runner = __esmMin((() => {
|
|
|
6896
6944
|
*/
|
|
6897
6945
|
init_console_capture();
|
|
6898
6946
|
init_npm_resolver();
|
|
6899
|
-
const AGENT_VERSION = "0.1.
|
|
6900
|
-
const BUILD_COMMIT = "
|
|
6901
|
-
const SDK_VERSION = "0.1.
|
|
6902
|
-
const SDK_BUNDLE_HASH = "
|
|
6903
|
-
const SHARED_VERSION = "0.1.
|
|
6904
|
-
const SHARED_BUNDLE_HASH = "
|
|
6905
|
-
const ENGINE_VERSION = "0.1.
|
|
6906
|
-
const ENGINE_BUNDLE_HASH = "
|
|
6947
|
+
const AGENT_VERSION = "0.1.25";
|
|
6948
|
+
const BUILD_COMMIT = "15e8e4155";
|
|
6949
|
+
const SDK_VERSION = "0.1.25";
|
|
6950
|
+
const SDK_BUNDLE_HASH = "e06bd1acf349ba365bdb357f3d865e0cbb4ad4604a0270b707a681a4f440954e";
|
|
6951
|
+
const SHARED_VERSION = "0.1.25";
|
|
6952
|
+
const SHARED_BUNDLE_HASH = "2394db0d8560b2cebf220c0e2d8993c75083aaf70a5917c35099b24feb3a22ba";
|
|
6953
|
+
const ENGINE_VERSION = "0.1.25";
|
|
6954
|
+
const ENGINE_BUNDLE_HASH = "c3320e812b8593d692f3fbf5eafe83507270028f7a1174c607881105dd702654";
|
|
6907
6955
|
initTelemetry({
|
|
6908
6956
|
serviceName: "kici-agent",
|
|
6909
6957
|
otlpEndpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT
|
package/dist/workflow-runner.js
CHANGED
|
@@ -13,6 +13,7 @@ import { OIDC_TOKEN_REQUEST_METHOD } from "@kici-dev/engine/protocol/messages/oi
|
|
|
13
13
|
import { computeBackoffDelay, sha256File as sha256File$1 } from "@kici-dev/core";
|
|
14
14
|
import { calculateJwkThumbprint, decodeJwt, exportJWK, generateKeyPair } from "jose";
|
|
15
15
|
import { IN_TOTO_PAYLOAD_TYPE, KICI_PROVENANCE_AUDIENCE, KICI_PROVENANCE_BUNDLE_MEDIA_TYPE } from "@kici-dev/engine/provenance/bundle";
|
|
16
|
+
import { computeStatementHash } from "@kici-dev/engine/provenance/statement-hash";
|
|
16
17
|
import { IN_TOTO_STATEMENT_TYPE, KICI_WORKFLOW_BUILD_TYPE, SLSA_PROVENANCE_PREDICATE_TYPE } from "@kici-dev/engine/provenance/schema";
|
|
17
18
|
import { buildDsseEnvelope, dssePae } from "@kici-dev/engine/provenance/dsse";
|
|
18
19
|
import https from "node:https";
|
|
@@ -29,7 +30,14 @@ import { promisify } from "node:util";
|
|
|
29
30
|
import { PNPM_IGNORE_BUILD_GATE_ARG, PackageManager, YarnFlavor, detectPackageManagerFromManifests, detectYarnFlavor } from "@kici-dev/shared/package-manager";
|
|
30
31
|
import { parse, stringify } from "yaml";
|
|
31
32
|
var __defProp = Object.defineProperty;
|
|
32
|
-
var __esmMin = (fn, res) => () =>
|
|
33
|
+
var __esmMin = (fn, res, err) => () => {
|
|
34
|
+
if (err) throw err[0];
|
|
35
|
+
try {
|
|
36
|
+
return fn && (res = fn(fn = 0)), res;
|
|
37
|
+
} catch (e) {
|
|
38
|
+
throw err = [e], e;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
33
41
|
var __exportAll = (all, no_symbols) => {
|
|
34
42
|
let target = {};
|
|
35
43
|
for (var name in all) __defProp(target, name, {
|
|
@@ -39,7 +47,6 @@ var __exportAll = (all, no_symbols) => {
|
|
|
39
47
|
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
40
48
|
return target;
|
|
41
49
|
};
|
|
42
|
-
import.meta.url;
|
|
43
50
|
//#endregion
|
|
44
51
|
//#region src/provenance/statement-builder.ts
|
|
45
52
|
/**
|
|
@@ -48,6 +55,53 @@ import.meta.url;
|
|
|
48
55
|
* entirely from the JWT claims (Platform-minted, unforgeable), so the
|
|
49
56
|
* statement's identity equals the token's identity by construction.
|
|
50
57
|
*/
|
|
58
|
+
/**
|
|
59
|
+
* Build a frozen SLSA v1.0 provenance statement from agent-local job context,
|
|
60
|
+
* for a deferred attestation (no minted identity token yet). Marks
|
|
61
|
+
* `attestationOrigin: 'deferred'` in the internal parameters. The caller
|
|
62
|
+
* DSSE-signs the returned statement immediately and computes its statement hash
|
|
63
|
+
* — the binding the later OIDC mint commits to (truth-contract property 2).
|
|
64
|
+
*/
|
|
65
|
+
function buildLocalProvenanceStatement(input) {
|
|
66
|
+
const c = input.context;
|
|
67
|
+
return {
|
|
68
|
+
_type: IN_TOTO_STATEMENT_TYPE,
|
|
69
|
+
subject: [{
|
|
70
|
+
name: input.subject.name,
|
|
71
|
+
digest: input.subject.digest
|
|
72
|
+
}],
|
|
73
|
+
predicateType: SLSA_PROVENANCE_PREDICATE_TYPE,
|
|
74
|
+
predicate: {
|
|
75
|
+
buildDefinition: {
|
|
76
|
+
buildType: KICI_WORKFLOW_BUILD_TYPE,
|
|
77
|
+
externalParameters: { workflow: {
|
|
78
|
+
repository: c.repository,
|
|
79
|
+
ref: c.ref,
|
|
80
|
+
path: c.workflowRef
|
|
81
|
+
} },
|
|
82
|
+
internalParameters: {
|
|
83
|
+
...c.sha ? { commit: c.sha } : {},
|
|
84
|
+
runId: c.runId,
|
|
85
|
+
jobId: c.jobId,
|
|
86
|
+
...c.orgId ? { orgId: c.orgId } : {},
|
|
87
|
+
...c.sourceOrigin ? { sourceOrigin: c.sourceOrigin } : {},
|
|
88
|
+
attestationOrigin: "deferred"
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
runDetails: {
|
|
92
|
+
builder: {
|
|
93
|
+
id: `${c.issuer}/orchestrator/unknown`,
|
|
94
|
+
version: input.builderVersions
|
|
95
|
+
},
|
|
96
|
+
metadata: {
|
|
97
|
+
invocationId: c.runId,
|
|
98
|
+
startedOn: input.startedOn,
|
|
99
|
+
finishedOn: input.finishedOn
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
51
105
|
/** Build a KiCI SLSA v1.0 provenance statement (validates against the P1.1 schema). */
|
|
52
106
|
function buildProvenanceStatement(input) {
|
|
53
107
|
const c = input.tokenClaims;
|
|
@@ -61,15 +115,20 @@ function buildProvenanceStatement(input) {
|
|
|
61
115
|
predicate: {
|
|
62
116
|
buildDefinition: {
|
|
63
117
|
buildType: KICI_WORKFLOW_BUILD_TYPE,
|
|
64
|
-
externalParameters: {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
118
|
+
externalParameters: {
|
|
119
|
+
workflow: {
|
|
120
|
+
repository: c.repository ?? "",
|
|
121
|
+
ref: c.ref ?? "",
|
|
122
|
+
path: c.workflow_ref ?? ""
|
|
123
|
+
},
|
|
124
|
+
...c.provider ? { provider: c.provider } : {}
|
|
125
|
+
},
|
|
69
126
|
internalParameters: {
|
|
70
127
|
...c.sha ? { commit: c.sha } : {},
|
|
71
128
|
runId: c.kici_run_id,
|
|
72
|
-
jobId: c.kici_job_id
|
|
129
|
+
jobId: c.kici_job_id,
|
|
130
|
+
...c.org_id ? { orgId: c.org_id } : {},
|
|
131
|
+
...c.source_origin ? { sourceOrigin: c.source_origin } : {}
|
|
73
132
|
}
|
|
74
133
|
},
|
|
75
134
|
runDetails: {
|
|
@@ -127,7 +186,9 @@ async function signStatementDsse(payloadType, statementBytes) {
|
|
|
127
186
|
async function attestProvenance(deps, input) {
|
|
128
187
|
const audience = input.audience ?? KICI_PROVENANCE_AUDIENCE;
|
|
129
188
|
const subjectDigest = subjectDigestString(input.subject);
|
|
130
|
-
const
|
|
189
|
+
const tokenResult = await deps.getIdToken({ audience });
|
|
190
|
+
if ("deferred" in tokenResult) return deferAttestation(deps, input, subjectDigest, audience);
|
|
191
|
+
const { token } = tokenResult;
|
|
131
192
|
const claims = decodeJwt(token);
|
|
132
193
|
const now = (deps.now ?? (() => (/* @__PURE__ */ new Date()).toISOString()))();
|
|
133
194
|
const statement = buildProvenanceStatement({
|
|
@@ -153,6 +214,39 @@ async function attestProvenance(deps, input) {
|
|
|
153
214
|
};
|
|
154
215
|
}
|
|
155
216
|
/**
|
|
217
|
+
* Freeze + DSSE-sign the provenance statement from agent-local job facts and
|
|
218
|
+
* report it for later minting. The step does NOT throw — the job completes
|
|
219
|
+
* green and the attestation surfaces as `deferred`.
|
|
220
|
+
*/
|
|
221
|
+
async function deferAttestation(deps, input, subjectDigest, audience) {
|
|
222
|
+
if (!deps.reportDeferred || !deps.localContext) throw new Error("provenance mint deferred but no reportDeferred/localContext wired to capture it");
|
|
223
|
+
const now = (deps.now ?? (() => (/* @__PURE__ */ new Date()).toISOString()))();
|
|
224
|
+
const statement = buildLocalProvenanceStatement({
|
|
225
|
+
context: deps.localContext,
|
|
226
|
+
subject: input.subject,
|
|
227
|
+
builderVersions: deps.builderVersions,
|
|
228
|
+
startedOn: now,
|
|
229
|
+
finishedOn: now
|
|
230
|
+
});
|
|
231
|
+
const statementBytes = new TextEncoder().encode(JSON.stringify(statement));
|
|
232
|
+
const { envelope, publicJwk } = await signStatementDsse(IN_TOTO_PAYLOAD_TYPE, statementBytes);
|
|
233
|
+
const statementHash = await computeStatementHash(statementBytes);
|
|
234
|
+
await deps.reportDeferred({
|
|
235
|
+
subjectName: input.subject.name,
|
|
236
|
+
subjectDigest,
|
|
237
|
+
audience,
|
|
238
|
+
mediaType: KICI_PROVENANCE_BUNDLE_MEDIA_TYPE,
|
|
239
|
+
statementHash,
|
|
240
|
+
dsseEnvelope: envelope,
|
|
241
|
+
publicKey: publicJwk
|
|
242
|
+
});
|
|
243
|
+
return {
|
|
244
|
+
deferred: true,
|
|
245
|
+
statementHash,
|
|
246
|
+
subjectDigest
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
156
250
|
* Pick the primary digest (`sha256` preferred) as the storage-key discriminator.
|
|
157
251
|
* Throws when the subject carries no digest: an empty digest set would otherwise
|
|
158
252
|
* yield an `undefined` storage-key segment (`provenance/<run>/<job>/undefined.kici.json`)
|
|
@@ -3399,8 +3493,8 @@ function logSubprocessStreams(e, tokens) {
|
|
|
3399
3493
|
* no Rolldown step at runtime. `@kici-dev/sdk` and host-repo deps resolve via
|
|
3400
3494
|
* Node's normal ESM lookup against `.kici/node_modules/`.
|
|
3401
3495
|
*/
|
|
3402
|
-
const AGENT_SDK_VERSION = "0.1.
|
|
3403
|
-
const AGENT_SDK_BUNDLE_HASH = "
|
|
3496
|
+
const AGENT_SDK_VERSION = "0.1.25";
|
|
3497
|
+
const AGENT_SDK_BUNDLE_HASH = "e06bd1acf349ba365bdb357f3d865e0cbb4ad4604a0270b707a681a4f440954e";
|
|
3404
3498
|
/**
|
|
3405
3499
|
* Register the `@kici-dev/core/ts-loader-hook` oxc-transform ESM loader hook so
|
|
3406
3500
|
* subsequent dynamic `import()` calls for `.ts` / `.tsx` files transform on the
|
|
@@ -3762,7 +3856,7 @@ async function applyOverlay(config) {
|
|
|
3762
3856
|
*/
|
|
3763
3857
|
init_download();
|
|
3764
3858
|
init_dep_restore();
|
|
3765
|
-
const AGENT_VERSION = "0.1.
|
|
3859
|
+
const AGENT_VERSION = "0.1.25";
|
|
3766
3860
|
process.on("uncaughtException", (err) => {
|
|
3767
3861
|
process.stderr.write(`[workflow-runner] UNCAUGHT EXCEPTION: ${err.message}\n`);
|
|
3768
3862
|
if (err.stack) process.stderr.write(`[workflow-runner] Stack: ${err.stack}\n`);
|
|
@@ -4269,9 +4363,20 @@ async function relayProvenanceIpc(request) {
|
|
|
4269
4363
|
return response;
|
|
4270
4364
|
}
|
|
4271
4365
|
/**
|
|
4366
|
+
* Extract an `owner/repo` identifier from a git clone URL for a deferred
|
|
4367
|
+
* statement's `externalParameters.workflow.repository` (the live path reads this
|
|
4368
|
+
* from the minted token claim; the deferred path has no token yet).
|
|
4369
|
+
*/
|
|
4370
|
+
function extractRepoIdentifier(repoUrl) {
|
|
4371
|
+
const match = repoUrl.match(/(?:github|gitlab|bitbucket)\.\w+\/([^/]+\/[^/.]+)/);
|
|
4372
|
+
return match ? match[1] : "unknown/unknown";
|
|
4373
|
+
}
|
|
4374
|
+
/**
|
|
4272
4375
|
* Build the `ctx.attestProvenance` step helper. Resolves a `path` subject to a
|
|
4273
4376
|
* SHA-256 digest, threads the identity token via the supplied OIDC getter, and
|
|
4274
|
-
* persists the bundle over the IPC -> WS provenance-upload relay.
|
|
4377
|
+
* persists the bundle over the IPC -> WS provenance-upload relay. On a transient
|
|
4378
|
+
* mint failure the statement is frozen + reported for later minting (deferred);
|
|
4379
|
+
* the step still completes.
|
|
4275
4380
|
*/
|
|
4276
4381
|
function buildAttestProvenanceFn(request, workDir, getIdToken) {
|
|
4277
4382
|
return async (opts) => {
|
|
@@ -4288,6 +4393,27 @@ function buildAttestProvenanceFn(request, workDir, getIdToken) {
|
|
|
4288
4393
|
"kici-agent": AGENT_VERSION,
|
|
4289
4394
|
"kici-orchestrator": "unknown"
|
|
4290
4395
|
},
|
|
4396
|
+
localContext: {
|
|
4397
|
+
repository: extractRepoIdentifier(request.repoUrl),
|
|
4398
|
+
ref: request.ref,
|
|
4399
|
+
sha: request.sha || null,
|
|
4400
|
+
workflowRef: request.workflowRef ?? request.workflowName,
|
|
4401
|
+
runId: request.runId,
|
|
4402
|
+
jobId: request.jobId,
|
|
4403
|
+
issuer: request.provenanceIssuer ?? ""
|
|
4404
|
+
},
|
|
4405
|
+
reportDeferred: async (report) => {
|
|
4406
|
+
await relayProvenanceIpc({
|
|
4407
|
+
op: "defer",
|
|
4408
|
+
subjectDigest: report.subjectDigest,
|
|
4409
|
+
subjectName: report.subjectName,
|
|
4410
|
+
mediaType: report.mediaType,
|
|
4411
|
+
audience: report.audience,
|
|
4412
|
+
statementHash: report.statementHash,
|
|
4413
|
+
dsseEnvelope: report.dsseEnvelope,
|
|
4414
|
+
publicKey: report.publicKey
|
|
4415
|
+
});
|
|
4416
|
+
},
|
|
4291
4417
|
persist: async (bundle, subjectDigest) => {
|
|
4292
4418
|
const urlResponse = await relayProvenanceIpc({
|
|
4293
4419
|
op: "requestUploadUrl",
|
|
@@ -4307,6 +4433,11 @@ function buildAttestProvenanceFn(request, workDir, getIdToken) {
|
|
|
4307
4433
|
subject,
|
|
4308
4434
|
...opts.audience !== void 0 && { audience: opts.audience }
|
|
4309
4435
|
});
|
|
4436
|
+
if ("deferred" in result) return {
|
|
4437
|
+
deferred: true,
|
|
4438
|
+
subjectDigest: result.subjectDigest,
|
|
4439
|
+
statementHash: result.statementHash
|
|
4440
|
+
};
|
|
4310
4441
|
return {
|
|
4311
4442
|
storageKey: result.storageKey,
|
|
4312
4443
|
subjectDigest: result.subjectDigest,
|
|
@@ -250,6 +250,12 @@ export declare class OrchestratorClient {
|
|
|
250
250
|
* returns the result on the IPC response shape.
|
|
251
251
|
*/
|
|
252
252
|
relayProvenance(jobId: string, request: ProvenanceRequestIpc): Promise<ProvenanceResponseIpc>;
|
|
253
|
+
/**
|
|
254
|
+
* Capture a frozen, DSSE-signed attestation for later minting (transient
|
|
255
|
+
* mint-failure path). Fire-and-forget: the orchestrator persists it into the
|
|
256
|
+
* deferred-attestation outbox and the job stays green.
|
|
257
|
+
*/
|
|
258
|
+
sendProvenanceUploadDefer(jobId: string, request: ProvenanceRequestIpc): void;
|
|
253
259
|
/**
|
|
254
260
|
* Relay a step-level approval request to the orchestrator. Sends a
|
|
255
261
|
* `step.approval-request` WS message and resolves with the orchestrator's
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kici-dev/agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
4
4
|
"description": "Customer-deployable agent for the KiCI CI/CD stack. Connects to an orchestrator, clones the workflow repo, executes steps, and streams logs back.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ci",
|
|
@@ -64,10 +64,10 @@
|
|
|
64
64
|
"yaml": "^2.9.0",
|
|
65
65
|
"zod": "^4.4.3",
|
|
66
66
|
"zx": "^8.8.5",
|
|
67
|
-
"@kici-dev/
|
|
68
|
-
"@kici-dev/
|
|
69
|
-
"@kici-dev/
|
|
70
|
-
"@kici-dev/
|
|
67
|
+
"@kici-dev/core": "0.1.25",
|
|
68
|
+
"@kici-dev/engine": "0.1.25",
|
|
69
|
+
"@kici-dev/sdk": "0.1.25",
|
|
70
|
+
"@kici-dev/shared": "0.1.25"
|
|
71
71
|
},
|
|
72
72
|
"kici": {
|
|
73
73
|
"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/agent@0.1.
|
|
6
|
-
"documentNamespace": "https://kici.dev/sbom/%40kici-dev%2Fagent/0.1.
|
|
5
|
+
"name": "@kici-dev/agent@0.1.25",
|
|
6
|
+
"documentNamespace": "https://kici.dev/sbom/%40kici-dev%2Fagent/0.1.25/0c3ee967-8ee9-47da-bc53-89a597d05c47",
|
|
7
7
|
"creationInfo": {
|
|
8
|
-
"created": "2026-
|
|
8
|
+
"created": "2026-07-05T08:32:53Z",
|
|
9
9
|
"creators": [
|
|
10
10
|
"Tool: kici-sbom-generator"
|
|
11
11
|
]
|
|
@@ -816,7 +816,7 @@
|
|
|
816
816
|
{
|
|
817
817
|
"SPDXID": "SPDXRef-RootPackage",
|
|
818
818
|
"name": "@kici-dev/agent",
|
|
819
|
-
"versionInfo": "0.1.
|
|
819
|
+
"versionInfo": "0.1.25",
|
|
820
820
|
"downloadLocation": "NOASSERTION",
|
|
821
821
|
"filesAnalyzed": false,
|
|
822
822
|
"licenseConcluded": "NOASSERTION",
|
|
@@ -827,16 +827,16 @@
|
|
|
827
827
|
{
|
|
828
828
|
"referenceCategory": "PACKAGE-MANAGER",
|
|
829
829
|
"referenceType": "purl",
|
|
830
|
-
"referenceLocator": "pkg:npm/%40kici-dev/agent@0.1.
|
|
830
|
+
"referenceLocator": "pkg:npm/%40kici-dev/agent@0.1.25"
|
|
831
831
|
}
|
|
832
832
|
],
|
|
833
833
|
"description": "Customer-deployable agent for the KiCI CI/CD stack. Connects to an orchestrator, clones the workflow repo, executes steps, and streams logs back.",
|
|
834
834
|
"homepage": "https://kici.dev"
|
|
835
835
|
},
|
|
836
836
|
{
|
|
837
|
-
"SPDXID": "SPDXRef-Package--kici-dev-core-0.1.
|
|
837
|
+
"SPDXID": "SPDXRef-Package--kici-dev-core-0.1.25",
|
|
838
838
|
"name": "@kici-dev/core",
|
|
839
|
-
"versionInfo": "0.1.
|
|
839
|
+
"versionInfo": "0.1.25",
|
|
840
840
|
"downloadLocation": "NOASSERTION",
|
|
841
841
|
"filesAnalyzed": false,
|
|
842
842
|
"licenseConcluded": "NOASSERTION",
|
|
@@ -847,16 +847,16 @@
|
|
|
847
847
|
{
|
|
848
848
|
"referenceCategory": "PACKAGE-MANAGER",
|
|
849
849
|
"referenceType": "purl",
|
|
850
|
-
"referenceLocator": "pkg:npm/%40kici-dev/core@0.1.
|
|
850
|
+
"referenceLocator": "pkg:npm/%40kici-dev/core@0.1.25"
|
|
851
851
|
}
|
|
852
852
|
],
|
|
853
853
|
"description": "Light shared utilities for the KiCI stack (logging, errors, formatting, crypto, zx init, the TypeScript ESM loader hook). No server-side dependencies.",
|
|
854
854
|
"homepage": "https://kici.dev"
|
|
855
855
|
},
|
|
856
856
|
{
|
|
857
|
-
"SPDXID": "SPDXRef-Package--kici-dev-engine-0.1.
|
|
857
|
+
"SPDXID": "SPDXRef-Package--kici-dev-engine-0.1.25",
|
|
858
858
|
"name": "@kici-dev/engine",
|
|
859
|
-
"versionInfo": "0.1.
|
|
859
|
+
"versionInfo": "0.1.25",
|
|
860
860
|
"downloadLocation": "NOASSERTION",
|
|
861
861
|
"filesAnalyzed": false,
|
|
862
862
|
"licenseConcluded": "NOASSERTION",
|
|
@@ -867,16 +867,16 @@
|
|
|
867
867
|
{
|
|
868
868
|
"referenceCategory": "PACKAGE-MANAGER",
|
|
869
869
|
"referenceType": "purl",
|
|
870
|
-
"referenceLocator": "pkg:npm/%40kici-dev/engine@0.1.
|
|
870
|
+
"referenceLocator": "pkg:npm/%40kici-dev/engine@0.1.25"
|
|
871
871
|
}
|
|
872
872
|
],
|
|
873
873
|
"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.",
|
|
874
874
|
"homepage": "https://kici.dev"
|
|
875
875
|
},
|
|
876
876
|
{
|
|
877
|
-
"SPDXID": "SPDXRef-Package--kici-dev-sdk-0.1.
|
|
877
|
+
"SPDXID": "SPDXRef-Package--kici-dev-sdk-0.1.25",
|
|
878
878
|
"name": "@kici-dev/sdk",
|
|
879
|
-
"versionInfo": "0.1.
|
|
879
|
+
"versionInfo": "0.1.25",
|
|
880
880
|
"downloadLocation": "NOASSERTION",
|
|
881
881
|
"filesAnalyzed": false,
|
|
882
882
|
"licenseConcluded": "NOASSERTION",
|
|
@@ -887,16 +887,16 @@
|
|
|
887
887
|
{
|
|
888
888
|
"referenceCategory": "PACKAGE-MANAGER",
|
|
889
889
|
"referenceType": "purl",
|
|
890
|
-
"referenceLocator": "pkg:npm/%40kici-dev/sdk@0.1.
|
|
890
|
+
"referenceLocator": "pkg:npm/%40kici-dev/sdk@0.1.25"
|
|
891
891
|
}
|
|
892
892
|
],
|
|
893
893
|
"description": "TypeScript SDK for defining KiCI workflows. Import into `.kici/workflows/*.ts` to declare workflows, jobs, steps, triggers, rules, and matrix configurations.",
|
|
894
894
|
"homepage": "https://kici.dev"
|
|
895
895
|
},
|
|
896
896
|
{
|
|
897
|
-
"SPDXID": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
897
|
+
"SPDXID": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
898
898
|
"name": "@kici-dev/shared",
|
|
899
|
-
"versionInfo": "0.1.
|
|
899
|
+
"versionInfo": "0.1.25",
|
|
900
900
|
"downloadLocation": "NOASSERTION",
|
|
901
901
|
"filesAnalyzed": false,
|
|
902
902
|
"licenseConcluded": "NOASSERTION",
|
|
@@ -907,7 +907,7 @@
|
|
|
907
907
|
{
|
|
908
908
|
"referenceCategory": "PACKAGE-MANAGER",
|
|
909
909
|
"referenceType": "purl",
|
|
910
|
-
"referenceLocator": "pkg:npm/%40kici-dev/shared@0.1.
|
|
910
|
+
"referenceLocator": "pkg:npm/%40kici-dev/shared@0.1.25"
|
|
911
911
|
}
|
|
912
912
|
],
|
|
913
913
|
"description": "Shared utilities for the KiCI CI/CD stack — logging, zx setup, crypto, telemetry, health and metrics routes. No business logic.",
|
|
@@ -6209,22 +6209,22 @@
|
|
|
6209
6209
|
},
|
|
6210
6210
|
{
|
|
6211
6211
|
"spdxElementId": "SPDXRef-RootPackage",
|
|
6212
|
-
"relatedSpdxElement": "SPDXRef-Package--kici-dev-core-0.1.
|
|
6212
|
+
"relatedSpdxElement": "SPDXRef-Package--kici-dev-core-0.1.25",
|
|
6213
6213
|
"relationshipType": "DEPENDS_ON"
|
|
6214
6214
|
},
|
|
6215
6215
|
{
|
|
6216
6216
|
"spdxElementId": "SPDXRef-RootPackage",
|
|
6217
|
-
"relatedSpdxElement": "SPDXRef-Package--kici-dev-engine-0.1.
|
|
6217
|
+
"relatedSpdxElement": "SPDXRef-Package--kici-dev-engine-0.1.25",
|
|
6218
6218
|
"relationshipType": "DEPENDS_ON"
|
|
6219
6219
|
},
|
|
6220
6220
|
{
|
|
6221
6221
|
"spdxElementId": "SPDXRef-RootPackage",
|
|
6222
|
-
"relatedSpdxElement": "SPDXRef-Package--kici-dev-sdk-0.1.
|
|
6222
|
+
"relatedSpdxElement": "SPDXRef-Package--kici-dev-sdk-0.1.25",
|
|
6223
6223
|
"relationshipType": "DEPENDS_ON"
|
|
6224
6224
|
},
|
|
6225
6225
|
{
|
|
6226
6226
|
"spdxElementId": "SPDXRef-RootPackage",
|
|
6227
|
-
"relatedSpdxElement": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6227
|
+
"relatedSpdxElement": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6228
6228
|
"relationshipType": "DEPENDS_ON"
|
|
6229
6229
|
},
|
|
6230
6230
|
{
|
|
@@ -6278,192 +6278,192 @@
|
|
|
6278
6278
|
"relationshipType": "DEPENDS_ON"
|
|
6279
6279
|
},
|
|
6280
6280
|
{
|
|
6281
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.
|
|
6281
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.25",
|
|
6282
6282
|
"relatedSpdxElement": "SPDXRef-Package-oxc-transform-0.135.0",
|
|
6283
6283
|
"relationshipType": "DEPENDS_ON"
|
|
6284
6284
|
},
|
|
6285
6285
|
{
|
|
6286
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.
|
|
6286
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.25",
|
|
6287
6287
|
"relatedSpdxElement": "SPDXRef-Package-picocolors-1.1.1",
|
|
6288
6288
|
"relationshipType": "DEPENDS_ON"
|
|
6289
6289
|
},
|
|
6290
6290
|
{
|
|
6291
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.
|
|
6291
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.25",
|
|
6292
6292
|
"relatedSpdxElement": "SPDXRef-Package-winston-daily-rotate-file-5.0.0",
|
|
6293
6293
|
"relationshipType": "DEPENDS_ON"
|
|
6294
6294
|
},
|
|
6295
6295
|
{
|
|
6296
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.
|
|
6296
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.25",
|
|
6297
6297
|
"relatedSpdxElement": "SPDXRef-Package-winston-3.19.0",
|
|
6298
6298
|
"relationshipType": "DEPENDS_ON"
|
|
6299
6299
|
},
|
|
6300
6300
|
{
|
|
6301
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.
|
|
6301
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.25",
|
|
6302
6302
|
"relatedSpdxElement": "SPDXRef-Package-zod-4.4.3",
|
|
6303
6303
|
"relationshipType": "DEPENDS_ON"
|
|
6304
6304
|
},
|
|
6305
6305
|
{
|
|
6306
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.
|
|
6306
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-core-0.1.25",
|
|
6307
6307
|
"relatedSpdxElement": "SPDXRef-Package-zx-8.8.5",
|
|
6308
6308
|
"relationshipType": "DEPENDS_ON"
|
|
6309
6309
|
},
|
|
6310
6310
|
{
|
|
6311
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.
|
|
6311
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.25",
|
|
6312
6312
|
"relatedSpdxElement": "SPDXRef-Package-jose-6.2.3",
|
|
6313
6313
|
"relationshipType": "DEPENDS_ON"
|
|
6314
6314
|
},
|
|
6315
6315
|
{
|
|
6316
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.
|
|
6316
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.25",
|
|
6317
6317
|
"relatedSpdxElement": "SPDXRef-Package-jsonpath-plus-10.4.0",
|
|
6318
6318
|
"relationshipType": "DEPENDS_ON"
|
|
6319
6319
|
},
|
|
6320
6320
|
{
|
|
6321
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.
|
|
6321
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.25",
|
|
6322
6322
|
"relatedSpdxElement": "SPDXRef-Package-picomatch-4.0.4",
|
|
6323
6323
|
"relationshipType": "DEPENDS_ON"
|
|
6324
6324
|
},
|
|
6325
6325
|
{
|
|
6326
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.
|
|
6326
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.25",
|
|
6327
6327
|
"relatedSpdxElement": "SPDXRef-Package-safe-regex-2.1.1",
|
|
6328
6328
|
"relationshipType": "DEPENDS_ON"
|
|
6329
6329
|
},
|
|
6330
6330
|
{
|
|
6331
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.
|
|
6331
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-engine-0.1.25",
|
|
6332
6332
|
"relatedSpdxElement": "SPDXRef-Package-zod-4.4.3",
|
|
6333
6333
|
"relationshipType": "DEPENDS_ON"
|
|
6334
6334
|
},
|
|
6335
6335
|
{
|
|
6336
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-sdk-0.1.
|
|
6337
|
-
"relatedSpdxElement": "SPDXRef-Package--kici-dev-core-0.1.
|
|
6336
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-sdk-0.1.25",
|
|
6337
|
+
"relatedSpdxElement": "SPDXRef-Package--kici-dev-core-0.1.25",
|
|
6338
6338
|
"relationshipType": "DEPENDS_ON"
|
|
6339
6339
|
},
|
|
6340
6340
|
{
|
|
6341
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-sdk-0.1.
|
|
6342
|
-
"relatedSpdxElement": "SPDXRef-Package--kici-dev-engine-0.1.
|
|
6341
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-sdk-0.1.25",
|
|
6342
|
+
"relatedSpdxElement": "SPDXRef-Package--kici-dev-engine-0.1.25",
|
|
6343
6343
|
"relationshipType": "DEPENDS_ON"
|
|
6344
6344
|
},
|
|
6345
6345
|
{
|
|
6346
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-sdk-0.1.
|
|
6346
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-sdk-0.1.25",
|
|
6347
6347
|
"relatedSpdxElement": "SPDXRef-Package-micromatch-4.0.8",
|
|
6348
6348
|
"relationshipType": "DEPENDS_ON"
|
|
6349
6349
|
},
|
|
6350
6350
|
{
|
|
6351
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-sdk-0.1.
|
|
6351
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-sdk-0.1.25",
|
|
6352
6352
|
"relatedSpdxElement": "SPDXRef-Package-zod-4.4.3",
|
|
6353
6353
|
"relationshipType": "DEPENDS_ON"
|
|
6354
6354
|
},
|
|
6355
6355
|
{
|
|
6356
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-sdk-0.1.
|
|
6356
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-sdk-0.1.25",
|
|
6357
6357
|
"relatedSpdxElement": "SPDXRef-Package-zx-8.8.5",
|
|
6358
6358
|
"relationshipType": "DEPENDS_ON"
|
|
6359
6359
|
},
|
|
6360
6360
|
{
|
|
6361
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6361
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6362
6362
|
"relatedSpdxElement": "SPDXRef-Package--aws-sdk-client-s3-3.1064.0",
|
|
6363
6363
|
"relationshipType": "DEPENDS_ON"
|
|
6364
6364
|
},
|
|
6365
6365
|
{
|
|
6366
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6367
|
-
"relatedSpdxElement": "SPDXRef-Package--kici-dev-core-0.1.
|
|
6366
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6367
|
+
"relatedSpdxElement": "SPDXRef-Package--kici-dev-core-0.1.25",
|
|
6368
6368
|
"relationshipType": "DEPENDS_ON"
|
|
6369
6369
|
},
|
|
6370
6370
|
{
|
|
6371
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6371
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6372
6372
|
"relatedSpdxElement": "SPDXRef-Package--opentelemetry-api-1.9.1",
|
|
6373
6373
|
"relationshipType": "DEPENDS_ON"
|
|
6374
6374
|
},
|
|
6375
6375
|
{
|
|
6376
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6376
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6377
6377
|
"relatedSpdxElement": "SPDXRef-Package--opentelemetry-exporter-metrics-otlp-http-0.218.0",
|
|
6378
6378
|
"relationshipType": "DEPENDS_ON"
|
|
6379
6379
|
},
|
|
6380
6380
|
{
|
|
6381
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6381
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6382
6382
|
"relatedSpdxElement": "SPDXRef-Package--opentelemetry-exporter-prometheus-0.218.0",
|
|
6383
6383
|
"relationshipType": "DEPENDS_ON"
|
|
6384
6384
|
},
|
|
6385
6385
|
{
|
|
6386
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6386
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6387
6387
|
"relatedSpdxElement": "SPDXRef-Package--opentelemetry-exporter-trace-otlp-http-0.218.0",
|
|
6388
6388
|
"relationshipType": "DEPENDS_ON"
|
|
6389
6389
|
},
|
|
6390
6390
|
{
|
|
6391
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6391
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6392
6392
|
"relatedSpdxElement": "SPDXRef-Package--opentelemetry-instrumentation-runtime-node-0.31.0",
|
|
6393
6393
|
"relationshipType": "DEPENDS_ON"
|
|
6394
6394
|
},
|
|
6395
6395
|
{
|
|
6396
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6396
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6397
6397
|
"relatedSpdxElement": "SPDXRef-Package--opentelemetry-resources-2.7.1",
|
|
6398
6398
|
"relationshipType": "DEPENDS_ON"
|
|
6399
6399
|
},
|
|
6400
6400
|
{
|
|
6401
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6401
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6402
6402
|
"relatedSpdxElement": "SPDXRef-Package--opentelemetry-sdk-node-0.218.0",
|
|
6403
6403
|
"relationshipType": "DEPENDS_ON"
|
|
6404
6404
|
},
|
|
6405
6405
|
{
|
|
6406
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6406
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6407
6407
|
"relatedSpdxElement": "SPDXRef-Package--opentelemetry-semantic-conventions-1.41.1",
|
|
6408
6408
|
"relationshipType": "DEPENDS_ON"
|
|
6409
6409
|
},
|
|
6410
6410
|
{
|
|
6411
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6411
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6412
6412
|
"relatedSpdxElement": "SPDXRef-Package-archiver-8.0.0",
|
|
6413
6413
|
"relationshipType": "DEPENDS_ON"
|
|
6414
6414
|
},
|
|
6415
6415
|
{
|
|
6416
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6416
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6417
6417
|
"relatedSpdxElement": "SPDXRef-Package-diff-9.0.0",
|
|
6418
6418
|
"relationshipType": "DEPENDS_ON"
|
|
6419
6419
|
},
|
|
6420
6420
|
{
|
|
6421
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6421
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6422
6422
|
"relatedSpdxElement": "SPDXRef-Package-hono-4.12.25",
|
|
6423
6423
|
"relationshipType": "DEPENDS_ON"
|
|
6424
6424
|
},
|
|
6425
6425
|
{
|
|
6426
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6426
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6427
6427
|
"relatedSpdxElement": "SPDXRef-Package-kysely-0.29.2",
|
|
6428
6428
|
"relationshipType": "DEPENDS_ON"
|
|
6429
6429
|
},
|
|
6430
6430
|
{
|
|
6431
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6431
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6432
6432
|
"relatedSpdxElement": "SPDXRef-Package-oxc-transform-0.135.0",
|
|
6433
6433
|
"relationshipType": "DEPENDS_ON"
|
|
6434
6434
|
},
|
|
6435
6435
|
{
|
|
6436
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6436
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6437
6437
|
"relatedSpdxElement": "SPDXRef-Package-pg-8.21.0",
|
|
6438
6438
|
"relationshipType": "DEPENDS_ON"
|
|
6439
6439
|
},
|
|
6440
6440
|
{
|
|
6441
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6441
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6442
6442
|
"relatedSpdxElement": "SPDXRef-Package-picocolors-1.1.1",
|
|
6443
6443
|
"relationshipType": "DEPENDS_ON"
|
|
6444
6444
|
},
|
|
6445
6445
|
{
|
|
6446
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6446
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6447
6447
|
"relatedSpdxElement": "SPDXRef-Package-winston-daily-rotate-file-5.0.0",
|
|
6448
6448
|
"relationshipType": "DEPENDS_ON"
|
|
6449
6449
|
},
|
|
6450
6450
|
{
|
|
6451
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6451
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6452
6452
|
"relatedSpdxElement": "SPDXRef-Package-winston-3.19.0",
|
|
6453
6453
|
"relationshipType": "DEPENDS_ON"
|
|
6454
6454
|
},
|
|
6455
6455
|
{
|
|
6456
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6456
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6457
6457
|
"relatedSpdxElement": "SPDXRef-Package-yaml-2.9.0",
|
|
6458
6458
|
"relationshipType": "DEPENDS_ON"
|
|
6459
6459
|
},
|
|
6460
6460
|
{
|
|
6461
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6461
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6462
6462
|
"relatedSpdxElement": "SPDXRef-Package-zod-4.4.3",
|
|
6463
6463
|
"relationshipType": "DEPENDS_ON"
|
|
6464
6464
|
},
|
|
6465
6465
|
{
|
|
6466
|
-
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.
|
|
6466
|
+
"spdxElementId": "SPDXRef-Package--kici-dev-shared-0.1.25",
|
|
6467
6467
|
"relatedSpdxElement": "SPDXRef-Package-zx-8.8.5",
|
|
6468
6468
|
"relationshipType": "DEPENDS_ON"
|
|
6469
6469
|
},
|