@kici-dev/compiler 0.1.16 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/dist/auth/headless-detect.js +1 -1
  2. package/dist/cli-banner.js +1 -1
  3. package/dist/cli.js +56 -19
  4. package/dist/commands/approve.js +1 -1
  5. package/dist/commands/compile.js +5 -3
  6. package/dist/commands/diagnostics.d.ts +7 -0
  7. package/dist/commands/diagnostics.js +58 -0
  8. package/dist/commands/docs.js +1 -1
  9. package/dist/commands/drain-worker.js +1 -1
  10. package/dist/commands/endpoints.js +1 -1
  11. package/dist/commands/fixture.js +1 -1
  12. package/dist/commands/held-run-client.js +1 -1
  13. package/dist/commands/held-run-resolve.js +1 -1
  14. package/dist/commands/hook.js +1 -1
  15. package/dist/commands/index.d.ts +16 -4
  16. package/dist/commands/index.js +10 -4
  17. package/dist/commands/init.js +2 -2
  18. package/dist/commands/login.d.ts +0 -2
  19. package/dist/commands/login.js +1 -3
  20. package/dist/commands/logout.js +1 -1
  21. package/dist/commands/orchestrators.d.ts +25 -0
  22. package/dist/commands/orchestrators.js +115 -0
  23. package/dist/commands/org.js +1 -1
  24. package/dist/commands/reject.js +1 -1
  25. package/dist/commands/run.d.ts +2 -9
  26. package/dist/commands/run.js +256 -315
  27. package/dist/commands/runs/cancel.d.ts +6 -0
  28. package/dist/commands/runs/cancel.js +32 -0
  29. package/dist/commands/runs/list.d.ts +6 -0
  30. package/dist/commands/runs/list.js +49 -0
  31. package/dist/commands/runs/logs.d.ts +7 -0
  32. package/dist/commands/runs/logs.js +67 -0
  33. package/dist/commands/runs/rerun.d.ts +5 -0
  34. package/dist/commands/runs/rerun.js +21 -0
  35. package/dist/commands/runs/show.d.ts +5 -0
  36. package/dist/commands/runs/show.js +65 -0
  37. package/dist/commands/secrets-list.d.ts +7 -9
  38. package/dist/commands/secrets-list.js +40 -64
  39. package/dist/commands/test.d.ts +4 -0
  40. package/dist/commands/test.js +1 -1
  41. package/dist/commands/types.d.ts +3 -5
  42. package/dist/commands/types.js +13 -37
  43. package/dist/commands/verify-attestation.d.ts +12 -0
  44. package/dist/commands/verify-attestation.js +69 -0
  45. package/dist/commands/watch.js +1 -1
  46. package/dist/commands/workflows.js +14 -34
  47. package/dist/errors/capability-gap.js +1 -1
  48. package/dist/errors/formatter.js +1 -1
  49. package/dist/errors/index.js +1 -1
  50. package/dist/execution/executor.js +1 -1
  51. package/dist/execution/index.js +1 -1
  52. package/dist/execution/sdk-alias.js +1 -1
  53. package/dist/execution/ts-loader.js +1 -1
  54. package/dist/fixtures/compiler.js +1 -1
  55. package/dist/fixtures/defaults/index.js +1 -1
  56. package/dist/format.js +1 -1
  57. package/dist/generators/secrets-dts.js +2 -2
  58. package/dist/hooks/detector.js +1 -1
  59. package/dist/hooks/index.js +1 -1
  60. package/dist/hooks/installer.js +1 -1
  61. package/dist/hooks/templates.js +1 -1
  62. package/dist/index.js +1 -1
  63. package/dist/llm-context/llms-full.txt +1047 -132
  64. package/dist/llm-context/llms.txt +4 -1
  65. package/dist/local-executor/dag-scheduler.js +1 -1
  66. package/dist/local-executor/index.js +1 -1
  67. package/dist/local-executor/job-runner.js +37 -16
  68. package/dist/local-executor/materializer.js +1 -1
  69. package/dist/local-executor/output-streamer.js +1 -1
  70. package/dist/local-executor/payload-generator.js +1 -1
  71. package/dist/local-executor/picker.js +1 -1
  72. package/dist/local-executor/secret-loader.js +1 -1
  73. package/dist/local-executor/to-event-payload.js +1 -1
  74. package/dist/local-executor/types.js +1 -1
  75. package/dist/local-executor/workflow-lock.js +0 -0
  76. package/dist/lockfile/generator.d.ts +7 -5
  77. package/dist/lockfile/generator.js +21 -18
  78. package/dist/lockfile/hash-files.js +1 -1
  79. package/dist/lockfile/hasher.js +1 -1
  80. package/dist/lockfile/index.js +1 -1
  81. package/dist/lockfile/purity-analyzer.js +1 -1
  82. package/dist/postinstall.js +1 -1
  83. package/dist/provenance-trust-root.d.ts +14 -0
  84. package/dist/provenance-trust-root.js +49 -0
  85. package/dist/remote/config.d.ts +6 -2
  86. package/dist/remote/config.js +7 -4
  87. package/dist/remote/dashboard-client.d.ts +92 -0
  88. package/dist/remote/dashboard-client.js +168 -0
  89. package/dist/remote/encryption.js +3 -4
  90. package/dist/remote/history.js +1 -1
  91. package/dist/remote/oauth.js +1 -1
  92. package/dist/remote/oidc-discovery.js +1 -1
  93. package/dist/remote/output/json.js +1 -1
  94. package/dist/remote/output/junit.js +1 -1
  95. package/dist/remote/output/streaming.js +1 -1
  96. package/dist/remote/output/summary.js +1 -1
  97. package/dist/remote/platform-client.d.ts +142 -0
  98. package/dist/remote/platform-client.js +187 -0
  99. package/dist/remote/prod-defaults.js +1 -1
  100. package/dist/remote/render.d.ts +11 -0
  101. package/dist/remote/render.js +48 -0
  102. package/dist/remote/secret-upload.js +1 -1
  103. package/dist/remote/uploader.d.ts +9 -0
  104. package/dist/remote/uploader.js +51 -4
  105. package/dist/templates/agents-md.d.ts +1 -1
  106. package/dist/templates/agents-md.js +8 -3
  107. package/dist/templates/index.js +1 -1
  108. package/dist/templates/package-json.js +4 -5
  109. package/dist/templates/tsconfig-json.js +1 -1
  110. package/dist/templates/workflows/hello-world.js +2 -2
  111. package/dist/templates/workflows/hello-world.ts +1 -1
  112. package/dist/templates/workflows/pr-checks.js +3 -3
  113. package/dist/templates/workflows/pr-checks.ts +2 -2
  114. package/dist/test-runner/dry-run.js +1 -1
  115. package/dist/test-runner/event-types.js +1 -1
  116. package/dist/test-runner/git-detector.js +1 -1
  117. package/dist/test-runner/index.js +1 -1
  118. package/dist/test-runner/job-executor.js +1 -1
  119. package/dist/test-runner/output-formatter.js +1 -1
  120. package/dist/test-runner/payload-builder.js +1 -1
  121. package/dist/test-runner/rule-evaluator.js +1 -1
  122. package/dist/test-runner/secrets-file.js +1 -1
  123. package/dist/test-runner/step-context.js +10 -6
  124. package/dist/types.d.ts +8 -5
  125. package/dist/types.js +2 -1
  126. package/dist/validation/index.js +1 -1
  127. package/dist/validation/validator.js +1 -1
  128. package/dist/workflows/hello-world.ts +1 -1
  129. package/dist/workflows/pr-checks.ts +2 -2
  130. package/package.json +5 -4
  131. package/sbom.spdx.json +68 -38
  132. package/dist/commands/cancel.js +0 -124
  133. package/dist/commands/status.js +0 -212
  134. package/dist/remote/client.js +0 -203
  135. package/dist/remote/observer.js +0 -174
  136. /package/dist/{chunk-gOLHoazu.js → chunk-BTugEXQM.js} +0 -0
@@ -0,0 +1,6 @@
1
+ export interface RunsCancelOptions {
2
+ force?: boolean;
3
+ branch?: string;
4
+ }
5
+ export declare function runsCancelCommand(runId: string | undefined, options?: RunsCancelOptions): Promise<boolean>;
6
+ //# sourceMappingURL=cancel.d.ts.map
@@ -0,0 +1,32 @@
1
+ import "../../chunk-BTugEXQM.js";
2
+ import { DashboardClient, DashboardClientError } from "../../remote/dashboard-client.js";
3
+ import pc from "picocolors";
4
+ import { logger, toErrorMessage } from "@kici-dev/core";
5
+ //#region src/commands/runs/cancel.ts
6
+ /** kici runs cancel — cancel a run or all in-progress runs on a branch. */
7
+ async function runsCancelCommand(runId, options = {}) {
8
+ try {
9
+ const client = await DashboardClient.load();
10
+ if (options.branch) {
11
+ logger.info(`Cancelling all in-progress runs on branch ${pc.cyan(options.branch)}...`);
12
+ const { cancelledRuns = 0 } = await client.cancelByBranch(options.branch);
13
+ console.log(cancelledRuns === 0 ? pc.yellow(`No in-progress runs found on branch ${options.branch}.`) : pc.green(`Cancelled ${cancelledRuns} run${cancelledRuns !== 1 ? "s" : ""} on branch ${options.branch}.`));
14
+ return true;
15
+ }
16
+ if (!runId) {
17
+ logger.error(pc.red("Please provide a run ID or use --branch to cancel by branch."));
18
+ return false;
19
+ }
20
+ logger.info(`${options.force ? "Force-cancelling" : "Cancelling"} run ${pc.cyan(runId)}...`);
21
+ const { cancelledJobs = 0 } = await client.cancelRun(runId, options.force ?? false);
22
+ console.log(pc.green(`Run ${runId} cancelled (${cancelledJobs} job${cancelledJobs !== 1 ? "s" : ""} affected).`));
23
+ return true;
24
+ } catch (err) {
25
+ logger.error(pc.red(err instanceof DashboardClientError ? err.message : toErrorMessage(err)));
26
+ return false;
27
+ }
28
+ }
29
+ //#endregion
30
+ export { runsCancelCommand };
31
+
32
+ //# sourceMappingURL=cancel.js.map
@@ -0,0 +1,6 @@
1
+ import { type RunsListFilters } from '../../remote/dashboard-client.js';
2
+ export interface RunsListOptions extends RunsListFilters {
3
+ json?: boolean;
4
+ }
5
+ export declare function runsListCommand(options?: RunsListOptions): Promise<boolean>;
6
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1,49 @@
1
+ import "../../chunk-BTugEXQM.js";
2
+ import { DashboardClient, DashboardClientError } from "../../remote/dashboard-client.js";
3
+ import { colorStatus, formatDuration as formatDuration$1, relativeTime, renderTable } from "../../remote/render.js";
4
+ import pc from "picocolors";
5
+ import { logger, toErrorMessage } from "@kici-dev/core";
6
+ //#region src/commands/runs/list.ts
7
+ /** kici runs list — mirrors the dashboard Runs page list. */
8
+ async function runsListCommand(options = {}) {
9
+ try {
10
+ const client = await DashboardClient.load();
11
+ const { json, ...filters } = options;
12
+ const page = await client.listRuns(filters);
13
+ if (json) {
14
+ console.log(JSON.stringify(page, null, 2));
15
+ return true;
16
+ }
17
+ if (page.runs.length === 0) {
18
+ console.log(pc.gray("No runs found."));
19
+ return true;
20
+ }
21
+ const rows = page.runs.map((r) => [
22
+ r.runId,
23
+ r.workflowName ?? "—",
24
+ colorStatus(r.status),
25
+ r.ref ?? "—",
26
+ r.triggerEvent ?? "—",
27
+ relativeTime(r.startedAt ?? void 0),
28
+ r.durationMs ? formatDuration$1(r.durationMs) : "—"
29
+ ]);
30
+ console.log(renderTable([
31
+ "run-id",
32
+ "workflow",
33
+ "status",
34
+ "branch",
35
+ "trigger",
36
+ "started",
37
+ "duration"
38
+ ], rows));
39
+ console.log(pc.gray(`\nPage ${page.page} · ${page.runs.length} of ${page.total}${page.hasMore ? " (more — use --page)" : ""}`));
40
+ return true;
41
+ } catch (err) {
42
+ logger.error(pc.red(err instanceof DashboardClientError ? err.message : toErrorMessage(err)));
43
+ return false;
44
+ }
45
+ }
46
+ //#endregion
47
+ export { runsListCommand };
48
+
49
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1,7 @@
1
+ export interface RunsLogsOptions {
2
+ job?: string;
3
+ follow?: boolean;
4
+ json?: boolean;
5
+ }
6
+ export declare function runsLogsCommand(runId: string, options?: RunsLogsOptions): Promise<boolean>;
7
+ //# sourceMappingURL=logs.d.ts.map
@@ -0,0 +1,67 @@
1
+ import "../../chunk-BTugEXQM.js";
2
+ import { DashboardClient, DashboardClientError } from "../../remote/dashboard-client.js";
3
+ import { colorStatus } from "../../remote/render.js";
4
+ import pc from "picocolors";
5
+ import { logger, toErrorMessage } from "@kici-dev/core";
6
+ import { TERMINAL_RUN_STATES } from "@kici-dev/engine";
7
+ //#region src/commands/runs/logs.ts
8
+ /** kici runs logs — step logs for a run (replaces `kici status --logs`). */
9
+ const POLL_INTERVAL_MS = 2e3;
10
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
11
+ async function runsLogsCommand(runId, options = {}) {
12
+ try {
13
+ const client = await DashboardClient.load();
14
+ if (options.json) {
15
+ const out = await collectAllLogs(client, runId, (await client.getRunDetail(runId)).jobs, options.job);
16
+ console.log(JSON.stringify(out, null, 2));
17
+ return true;
18
+ }
19
+ if (options.follow) return await followLogs(client, runId, options.job);
20
+ await printAllLogs(client, runId, (await client.getRunDetail(runId)).jobs, options.job);
21
+ return true;
22
+ } catch (err) {
23
+ logger.error(pc.red(err instanceof DashboardClientError ? err.message : toErrorMessage(err)));
24
+ return false;
25
+ }
26
+ }
27
+ function selectJobs(jobs, jobFilter) {
28
+ return jobFilter ? jobs.filter((j) => j.jobName === jobFilter) : jobs;
29
+ }
30
+ async function printAllLogs(client, runId, jobs, jobFilter) {
31
+ for (const j of selectJobs(jobs, jobFilter)) for (const s of j.steps ?? []) {
32
+ console.log(pc.bold(`\n=== ${j.jobName} › ${s.stepName} `) + colorStatus(s.status) + pc.bold(" ==="));
33
+ const logs = await client.getStepLogs(runId, j.jobId, s.stepIndex);
34
+ for (const line of logs.lines) console.log(line);
35
+ }
36
+ }
37
+ async function collectAllLogs(client, runId, jobs, jobFilter) {
38
+ const out = {};
39
+ for (const j of selectJobs(jobs, jobFilter)) for (const s of j.steps ?? []) out[`${j.jobName}/${s.stepName}`] = (await client.getStepLogs(runId, j.jobId, s.stepIndex)).lines;
40
+ return out;
41
+ }
42
+ async function followLogs(client, runId, jobFilter) {
43
+ const printed = {};
44
+ for (;;) {
45
+ const run = await client.getRun(runId);
46
+ const detail = await client.getRunDetail(runId);
47
+ for (const j of selectJobs(detail.jobs, jobFilter)) for (const s of j.steps ?? []) {
48
+ const key = `${j.jobId}:${s.stepIndex}`;
49
+ const logs = await client.getStepLogs(runId, j.jobId, s.stepIndex);
50
+ const seen = printed[key] ?? 0;
51
+ if (logs.lines.length > seen) {
52
+ if (seen === 0) console.log(pc.bold(`\n=== ${j.jobName} › ${s.stepName} ===`));
53
+ for (const line of logs.lines.slice(seen)) console.log(line);
54
+ printed[key] = logs.lines.length;
55
+ }
56
+ }
57
+ if (TERMINAL_RUN_STATES.has(run.status)) {
58
+ console.log(pc.gray(`\nrun ${colorStatus(run.status)}`));
59
+ return true;
60
+ }
61
+ await sleep(POLL_INTERVAL_MS);
62
+ }
63
+ }
64
+ //#endregion
65
+ export { runsLogsCommand };
66
+
67
+ //# sourceMappingURL=logs.js.map
@@ -0,0 +1,5 @@
1
+ export interface RunsRerunOptions {
2
+ json?: boolean;
3
+ }
4
+ export declare function runsRerunCommand(runId: string, options?: RunsRerunOptions): Promise<boolean>;
5
+ //# sourceMappingURL=rerun.d.ts.map
@@ -0,0 +1,21 @@
1
+ import "../../chunk-BTugEXQM.js";
2
+ import { DashboardClient, DashboardClientError } from "../../remote/dashboard-client.js";
3
+ import pc from "picocolors";
4
+ import { logger, toErrorMessage } from "@kici-dev/core";
5
+ //#region src/commands/runs/rerun.ts
6
+ /** kici runs rerun — re-trigger a run (mirrors the dashboard rerun button). */
7
+ async function runsRerunCommand(runId, options = {}) {
8
+ try {
9
+ const out = await (await DashboardClient.load()).rerunRun(runId);
10
+ if (options.json) console.log(JSON.stringify(out, null, 2));
11
+ else console.log(pc.green(`Rerun queued: ${pc.bold(out.newRunId)}`));
12
+ return true;
13
+ } catch (err) {
14
+ logger.error(pc.red(err instanceof DashboardClientError ? err.message : toErrorMessage(err)));
15
+ return false;
16
+ }
17
+ }
18
+ //#endregion
19
+ export { runsRerunCommand };
20
+
21
+ //# sourceMappingURL=rerun.js.map
@@ -0,0 +1,5 @@
1
+ export interface RunsShowOptions {
2
+ json?: boolean;
3
+ }
4
+ export declare function runsShowCommand(runId: string, options?: RunsShowOptions): Promise<boolean>;
5
+ //# sourceMappingURL=show.d.ts.map
@@ -0,0 +1,65 @@
1
+ import "../../chunk-BTugEXQM.js";
2
+ import { DashboardClient, DashboardClientError } from "../../remote/dashboard-client.js";
3
+ import { RunHistory } from "../../remote/history.js";
4
+ import { colorStatus, formatDuration as formatDuration$1, relativeTime } from "../../remote/render.js";
5
+ import pc from "picocolors";
6
+ import { logger, toErrorMessage } from "@kici-dev/core";
7
+ //#region src/commands/runs/show.ts
8
+ /** kici runs show — run summary + jobs/steps tree (replaces `kici status`). */
9
+ async function runsShowCommand(runId, options = {}) {
10
+ try {
11
+ const client = await DashboardClient.load();
12
+ let run;
13
+ try {
14
+ run = await client.getRun(runId);
15
+ } catch (err) {
16
+ if (err instanceof DashboardClientError && err.kind === "not_found") return await showLocalFallback(runId, options.json ?? false);
17
+ throw err;
18
+ }
19
+ const detail = await client.getRunDetail(runId);
20
+ if (options.json) {
21
+ console.log(JSON.stringify({
22
+ run,
23
+ detail
24
+ }, null, 2));
25
+ return true;
26
+ }
27
+ printHeader(run);
28
+ printJobs(detail.jobs);
29
+ return true;
30
+ } catch (err) {
31
+ logger.error(pc.red(err instanceof DashboardClientError ? err.message : toErrorMessage(err)));
32
+ return false;
33
+ }
34
+ }
35
+ function printHeader(run) {
36
+ const f = (v) => v == null ? "—" : v;
37
+ console.log(pc.bold(`\nRun ${run.runId}`) + ` ${colorStatus(run.status)}`);
38
+ console.log(pc.gray(` workflow=${f(run.workflowName)} repo=${f(run.repoIdentifier)} branch=${f(run.ref)} sha=${f(run.sha)} trigger=${f(run.triggerEvent)} by=${f(run.triggeredBy)}`));
39
+ console.log(pc.gray(` started=${relativeTime(run.startedAt ?? void 0)}`));
40
+ }
41
+ function printJobs(jobs) {
42
+ for (const j of jobs) {
43
+ console.log(`\n ${pc.bold(j.jobName)} ${colorStatus(j.status)} ` + pc.gray(j.durationMs ? formatDuration$1(j.durationMs) : ""));
44
+ for (const s of j.steps ?? []) console.log(pc.gray(" └─ ") + `${s.stepName} ${colorStatus(s.status)} ` + pc.gray(`${s.durationMs ? formatDuration$1(s.durationMs) : ""}${s.exitCode != null ? ` exit=${s.exitCode}` : ""}`));
45
+ }
46
+ }
47
+ async function showLocalFallback(runId, json) {
48
+ const history = new RunHistory();
49
+ await history.load();
50
+ const entry = history.getEntry(runId);
51
+ if (!entry) {
52
+ logger.error(pc.red(`Run not found: ${runId} (no remote run and no local history).`));
53
+ return false;
54
+ }
55
+ if (json) console.log(JSON.stringify(entry, null, 2));
56
+ else {
57
+ logger.info(pc.yellow("Run not found on the Platform. Showing local history:\n"));
58
+ console.log(JSON.stringify(entry, null, 2));
59
+ }
60
+ return true;
61
+ }
62
+ //#endregion
63
+ export { runsShowCommand };
64
+
65
+ //# sourceMappingURL=show.js.map
@@ -1,16 +1,14 @@
1
1
  export interface SecretsListOptions {
2
- /** Orchestrator endpoint override (defaults to global config). */
2
+ /** Reserved for future use; the command targets the Platform via the active org. */
3
3
  endpoint?: string;
4
4
  }
5
5
  /**
6
- * List test-available secret contexts from the orchestrator.
6
+ * List test-available secret contexts through the Platform.
7
7
  *
8
- * Loads the global config for auth token and active org, calls
9
- * GET /api/v1/admin/environments?orgId=<org>&includeSecrets=true,
10
- * filters to envs with allow_local_execution=true, and displays a
11
- * table of names, key names, and flags.
12
- *
13
- * Values are never exposed -- only key names.
8
+ * Calls GET /api/v1/orgs/:orgId/environments?includeSecrets=true (relayed to
9
+ * the org's orchestrator), filters to environments with
10
+ * allowLocalExecution=true, and displays a table of names, key names, and
11
+ * flags. Values are never exposed -- only key names.
14
12
  */
15
- export declare function secretsListCommand(options: SecretsListOptions): Promise<boolean>;
13
+ export declare function secretsListCommand(_options?: SecretsListOptions): Promise<boolean>;
16
14
  //# sourceMappingURL=secrets-list.d.ts.map
@@ -1,84 +1,60 @@
1
- import "../chunk-gOLHoazu.js";
2
- import { loadGlobalConfig } from "../remote/config.js";
1
+ import "../chunk-BTugEXQM.js";
2
+ import { DashboardClient, DashboardClientError } from "../remote/dashboard-client.js";
3
3
  import pc from "picocolors";
4
4
  import { toErrorMessage } from "@kici-dev/core";
5
5
  //#region src/commands/secrets-list.ts
6
6
  /**
7
- * List test-available secret contexts from the orchestrator.
7
+ * List test-available secret contexts through the Platform.
8
8
  *
9
- * Loads the global config for auth token and active org, calls
10
- * GET /api/v1/admin/environments?orgId=<org>&includeSecrets=true,
11
- * filters to envs with allow_local_execution=true, and displays a
12
- * table of names, key names, and flags.
13
- *
14
- * Values are never exposed -- only key names.
9
+ * Calls GET /api/v1/orgs/:orgId/environments?includeSecrets=true (relayed to
10
+ * the org's orchestrator), filters to environments with
11
+ * allowLocalExecution=true, and displays a table of names, key names, and
12
+ * flags. Values are never exposed -- only key names.
15
13
  */
16
- async function secretsListCommand(options) {
14
+ async function secretsListCommand(_options = {}) {
17
15
  try {
18
- const config = await loadGlobalConfig();
19
- if (!config.token) {
20
- console.error(pc.red("Not authenticated. Run `kici login` first."));
21
- return false;
22
- }
23
- const endpoint = options.endpoint ?? config.endpoint;
24
- if (!endpoint) {
25
- console.error(pc.red("No orchestrator endpoint configured. Run `kici login --endpoint <url>` first."));
26
- return false;
27
- }
28
- if (!config.activeOrgId) {
29
- console.error(pc.red("No active organization. Run `kici org list` then `kici org use <name>` first."));
30
- return false;
31
- }
32
- const url = `${endpoint.replace(/\/+$/, "")}/api/v1/admin/environments?orgId=${encodeURIComponent(config.activeOrgId)}&includeSecrets=true`;
33
- const res = await fetch(url, { headers: { Authorization: `Bearer ${config.token}` } });
34
- if (res.status === 401) {
35
- console.error(pc.red("Authentication failed. Check your API key with `kici login`."));
36
- return false;
37
- }
38
- if (res.status === 403) {
39
- console.error(pc.red("Permission denied. Your API key does not have secret.read access."));
40
- return false;
41
- }
42
- if (!res.ok) {
43
- const text = await res.text();
44
- console.error(pc.red(`Failed to fetch contexts: ${res.status} ${text}`));
45
- return false;
46
- }
47
- const contexts = ((await res.json()).environments ?? []).filter((e) => e.allow_local_execution);
16
+ const contexts = (await (await DashboardClient.load()).listEnvironments(true)).filter((e) => e.allowLocalExecution);
48
17
  if (contexts.length === 0) {
49
18
  console.log(pc.yellow("No test-available secret contexts found."));
50
19
  console.log(pc.gray("Enable test runs (allowLocalExecution) on an environment to make its secrets available for test runs."));
51
20
  return true;
52
21
  }
53
- console.log(pc.bold("\nTest-available secret contexts:\n"));
54
- const ctxKeys = (c) => c.secret_keys ?? [];
55
- const nameWidth = Math.max(7, ...contexts.map((c) => c.name.length));
56
- const keysWidth = Math.max(4, ...contexts.map((c) => {
57
- const k = ctxKeys(c);
58
- return k.length > 0 ? k.join(", ").length : 4;
59
- }));
60
- const flagsWidth = Math.max(5, ...contexts.map((c) => c.enabled ? 0 : 8));
61
- const pad = (s, w) => s.padEnd(w);
62
- const hr = (w) => "─".repeat(w);
63
- console.log(`\u250c${hr(nameWidth + 2)}\u252c${hr(keysWidth + 2)}\u252c${hr(flagsWidth + 2)}\u2510`);
64
- console.log(`\u2502 ${pad("Context", nameWidth)} \u2502 ${pad("Keys", keysWidth)} \u2502 ${pad("Flags", flagsWidth)} \u2502`);
65
- console.log(`\u251c${hr(nameWidth + 2)}\u253c${hr(keysWidth + 2)}\u253c${hr(flagsWidth + 2)}\u2524`);
66
- for (const ctx of contexts) {
67
- const k = ctxKeys(ctx);
68
- const keys = k.length > 0 ? k.join(", ") : pc.gray("none");
69
- const keysRaw = k.length > 0 ? k.join(", ") : "none";
70
- const flagStr = ctx.enabled ? "" : "disabled";
71
- console.log(`\u2502 ${pad(ctx.name, nameWidth)} \u2502 ${keys}${" ".repeat(Math.max(0, keysWidth - keysRaw.length))} \u2502 ${pad(flagStr, flagsWidth)} \u2502`);
72
- }
73
- console.log(`\u2514${hr(nameWidth + 2)}\u2534${hr(keysWidth + 2)}\u2534${hr(flagsWidth + 2)}\u2518`);
74
- console.log("");
22
+ renderContextTable(contexts);
75
23
  return true;
76
24
  } catch (err) {
77
- const message = toErrorMessage(err);
78
- console.error(pc.red(`Failed to list secrets: ${message}`));
25
+ if (err instanceof DashboardClientError) {
26
+ console.error(pc.red(err.message));
27
+ return false;
28
+ }
29
+ console.error(pc.red(`Failed to list secrets: ${toErrorMessage(err)}`));
79
30
  return false;
80
31
  }
81
32
  }
33
+ /** Render the secret-context table to stdout. */
34
+ function renderContextTable(contexts) {
35
+ console.log(pc.bold("\nTest-available secret contexts:\n"));
36
+ const ctxKeys = (c) => c.secretKeys ?? [];
37
+ const nameWidth = Math.max(7, ...contexts.map((c) => c.name.length));
38
+ const keysWidth = Math.max(4, ...contexts.map((c) => {
39
+ const k = ctxKeys(c);
40
+ return k.length > 0 ? k.join(", ").length : 4;
41
+ }));
42
+ const flagsWidth = Math.max(5, ...contexts.map((c) => c.enabled ? 0 : 8));
43
+ const pad = (s, w) => s.padEnd(w);
44
+ const hr = (w) => "─".repeat(w);
45
+ console.log(`┌${hr(nameWidth + 2)}┬${hr(keysWidth + 2)}┬${hr(flagsWidth + 2)}┐`);
46
+ console.log(`│ ${pad("Context", nameWidth)} │ ${pad("Keys", keysWidth)} │ ${pad("Flags", flagsWidth)} │`);
47
+ console.log(`├${hr(nameWidth + 2)}┼${hr(keysWidth + 2)}┼${hr(flagsWidth + 2)}┤`);
48
+ for (const ctx of contexts) {
49
+ const k = ctxKeys(ctx);
50
+ const keys = k.length > 0 ? k.join(", ") : pc.gray("none");
51
+ const keysRaw = k.length > 0 ? k.join(", ") : "none";
52
+ const flagStr = ctx.enabled ? "" : "disabled";
53
+ console.log(`│ ${pad(ctx.name, nameWidth)} │ ${keys}${" ".repeat(Math.max(0, keysWidth - keysRaw.length))} │ ${pad(flagStr, flagsWidth)} │`);
54
+ }
55
+ console.log(`└${hr(nameWidth + 2)}┴${hr(keysWidth + 2)}┴${hr(flagsWidth + 2)}┘`);
56
+ console.log("");
57
+ }
82
58
  //#endregion
83
59
  export { secretsListCommand };
84
60
 
@@ -34,6 +34,10 @@ export interface RemoteRunOptions extends TestOptions {
34
34
  history?: boolean;
35
35
  /** --env KEY=VALUE flag values, uploaded as per-run secrets. */
36
36
  envFlags?: string[];
37
+ /** Target organization id (overrides config.activeOrgId). */
38
+ org?: string;
39
+ /** Target orchestrator cluster name (overrides the per-org default). */
40
+ orchestrator?: string;
37
41
  }
38
42
  /** Result of a single remote fixture run */
39
43
  export interface RemoteRunResult {
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { discoverWorkflows, resolveKiciDir } from "../execution/executor.js";
3
3
  import "../execution/index.js";
4
4
  import { transformTriggers } from "../lockfile/generator.js";
@@ -1,18 +1,16 @@
1
1
  export interface TypesOptions {
2
2
  /** Path to .kici directory (defaults to .kici) */
3
3
  kiciDir?: string;
4
- /** Orchestrator endpoint override (defaults to global config) */
5
- endpoint?: string;
6
4
  }
7
5
  /**
8
6
  * Generate TypeScript declarations for environment secrets.
9
7
  *
10
- * Fetches environment metadata from the orchestrator and generates
11
- * .kici/types/secrets.d.ts with module augmentation for
8
+ * Fetches environment metadata (with secret key names) through the Platform
9
+ * and generates .kici/types/secrets.d.ts with module augmentation for
12
10
  * KnownSecretKeys and EnvironmentSecrets.
13
11
  *
14
12
  * @param options - Command options
15
13
  * @returns true on success, false on error
16
14
  */
17
- export declare function typesCommand(options: TypesOptions): Promise<boolean>;
15
+ export declare function typesCommand(options?: TypesOptions): Promise<boolean>;
18
16
  //# sourceMappingURL=types.d.ts.map
@@ -1,5 +1,6 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { loadGlobalConfig } from "../remote/config.js";
3
+ import { DashboardClient, DashboardClientError } from "../remote/dashboard-client.js";
3
4
  import { generateSecretsDts } from "../generators/secrets-dts.js";
4
5
  import path from "node:path";
5
6
  import pc from "picocolors";
@@ -9,50 +10,22 @@ import { toErrorMessage } from "@kici-dev/core";
9
10
  /**
10
11
  * Generate TypeScript declarations for environment secrets.
11
12
  *
12
- * Fetches environment metadata from the orchestrator and generates
13
- * .kici/types/secrets.d.ts with module augmentation for
13
+ * Fetches environment metadata (with secret key names) through the Platform
14
+ * and generates .kici/types/secrets.d.ts with module augmentation for
14
15
  * KnownSecretKeys and EnvironmentSecrets.
15
16
  *
16
17
  * @param options - Command options
17
18
  * @returns true on success, false on error
18
19
  */
19
- async function typesCommand(options) {
20
+ async function typesCommand(options = {}) {
20
21
  try {
21
22
  const config = await loadGlobalConfig();
22
- if (!config.token) {
23
- console.error(pc.red("Not authenticated. Run `kici login` first to connect to your orchestrator."));
24
- return false;
25
- }
26
- const endpoint = options.endpoint ?? config.endpoint;
27
- if (!endpoint) {
28
- console.error(pc.red("No orchestrator endpoint configured. Run `kici login --endpoint <url>` first."));
29
- return false;
30
- }
31
- if (!config.activeOrgId) {
32
- console.error(pc.red("No active organization. Run `kici org list` then `kici org use <name>` first."));
33
- return false;
34
- }
35
- const url = `${endpoint.replace(/\/+$/, "")}/api/v1/admin/environments?orgId=${encodeURIComponent(config.activeOrgId)}&includeSecrets=true`;
36
- const res = await fetch(url, { headers: { Authorization: `Bearer ${config.token}` } });
37
- if (res.status === 401) {
38
- console.error(pc.red("Authentication failed. Check your API key with `kici login`."));
39
- return false;
40
- }
41
- if (res.status === 403) {
42
- console.error(pc.red("Permission denied. Your API key does not have environments.read access."));
43
- return false;
44
- }
45
- if (!res.ok) {
46
- const text = await res.text();
47
- console.error(pc.red(`Failed to fetch environments: ${res.status} ${text}`));
48
- return false;
49
- }
50
23
  const dtsContent = generateSecretsDts({
51
- environments: ((await res.json()).environments ?? []).map((e) => ({
24
+ environments: (await DashboardClient.fromConfig(config).listEnvironments(true)).map((e) => ({
52
25
  name: e.name,
53
- keys: e.secret_keys ?? []
26
+ keys: e.secretKeys ?? []
54
27
  })),
55
- endpoint: endpoint.replace(/\/+$/, ""),
28
+ endpoint: (config.platformEndpoint ?? config.endpoint ?? "kici Platform").replace(/\/+$/, ""),
56
29
  generatedAt: /* @__PURE__ */ new Date()
57
30
  });
58
31
  const kiciDir = options.kiciDir ?? ".kici";
@@ -63,8 +36,11 @@ async function typesCommand(options) {
63
36
  console.log(pc.green("Types generated") + pc.dim(` ${outputPath}`));
64
37
  return true;
65
38
  } catch (err) {
66
- const message = toErrorMessage(err);
67
- console.error(pc.red(`Failed to generate types: ${message}`));
39
+ if (err instanceof DashboardClientError) {
40
+ console.error(pc.red(err.message));
41
+ return false;
42
+ }
43
+ console.error(pc.red(`Failed to generate types: ${toErrorMessage(err)}`));
68
44
  return false;
69
45
  }
70
46
  }
@@ -0,0 +1,12 @@
1
+ export interface VerifyAttestationOptions {
2
+ /** Path or `http(s)` URL to the attestation bundle JSON. Required. */
3
+ bundle?: string;
4
+ /** Trusted issuer URL (online discovery) or a self-contained `{ issuer, jwks }` file. Required. */
5
+ trustRoot?: string;
6
+ /** Expected token audience (defaults to the KiCI provenance audience). */
7
+ audience?: string;
8
+ /** Emit the structured `VerifyResult` as JSON instead of human output. */
9
+ json?: boolean;
10
+ }
11
+ export declare function verifyAttestationCommand(artifact: string | undefined, options?: VerifyAttestationOptions): Promise<boolean>;
12
+ //# sourceMappingURL=verify-attestation.d.ts.map
@@ -0,0 +1,69 @@
1
+ import "../chunk-BTugEXQM.js";
2
+ import { resolveTrustRoot } from "../provenance-trust-root.js";
3
+ import pc from "picocolors";
4
+ import { readFile } from "node:fs/promises";
5
+ import { logger, sha256File, toErrorMessage } from "@kici-dev/core";
6
+ import { KICI_PROVENANCE_AUDIENCE } from "@kici-dev/engine/provenance/bundle";
7
+ import { verifyKiciBundle } from "@kici-dev/engine/provenance/verify";
8
+ //#region src/commands/verify-attestation.ts
9
+ /**
10
+ * `kici verify-attestation [artifact] --bundle <path|url> --trust-root <url|file>`
11
+ *
12
+ * Offline verification of a KiCI-signed provenance bundle: read the bundle,
13
+ * resolve the trusted issuer + JWKS out-of-band (`--trust-root`), optionally
14
+ * digest the artifact, and hand everything to the shared browser-safe
15
+ * `verifyKiciBundle` core in `@kici-dev/engine`. The engine owns all crypto;
16
+ * this command is the thin Node wrapper (fs / fetch / artifact digest / output).
17
+ *
18
+ * Returns a boolean (verified) so `cli.ts` can map it to an exit code (0/1).
19
+ */
20
+ async function verifyAttestationCommand(artifact, options = {}) {
21
+ try {
22
+ if (!options.bundle) {
23
+ logger.error(pc.red("Error: --bundle <path|url> is required"));
24
+ return false;
25
+ }
26
+ if (!options.trustRoot) {
27
+ logger.error(pc.red("Error: --trust-root <url|file> is required"));
28
+ return false;
29
+ }
30
+ const bundle = JSON.parse(await readBundle(options.bundle));
31
+ const { issuer, jwks } = await resolveTrustRoot(options.trustRoot);
32
+ const expectedDigest = artifact ? {
33
+ alg: "sha256",
34
+ hex: await sha256File(artifact)
35
+ } : void 0;
36
+ const result = await verifyKiciBundle({
37
+ bundle,
38
+ jwks,
39
+ expectedIssuer: issuer,
40
+ expectedAudience: options.audience ?? KICI_PROVENANCE_AUDIENCE,
41
+ expectedDigest
42
+ });
43
+ if (options.json) {
44
+ console.log(JSON.stringify(result, null, 2));
45
+ return result.verified;
46
+ }
47
+ if (result.verified) {
48
+ logger.info(`${pc.green("PASS")} provenance verified (issuer ${issuer})`);
49
+ const c = result.claims ?? {};
50
+ logger.info(pc.gray(` repository=${c.repository} ref=${c.ref} sha=${c.sha} run=${c.kici_run_id} job=${c.kici_job_id}`));
51
+ } else logger.error(`${pc.red("FAIL")} provenance NOT verified: ${result.failures.join(", ")}`);
52
+ return result.verified;
53
+ } catch (error) {
54
+ logger.error(pc.red(`Error: ${toErrorMessage(error)}`));
55
+ return false;
56
+ }
57
+ }
58
+ async function readBundle(bundlePathOrUrl) {
59
+ if (/^https?:\/\//.test(bundlePathOrUrl)) {
60
+ const res = await fetch(bundlePathOrUrl);
61
+ if (!res.ok) throw new Error(`failed to fetch bundle: ${res.status}`);
62
+ return res.text();
63
+ }
64
+ return readFile(bundlePathOrUrl, "utf-8");
65
+ }
66
+ //#endregion
67
+ export { verifyAttestationCommand };
68
+
69
+ //# sourceMappingURL=verify-attestation.js.map
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { resolveKiciDir } from "../execution/executor.js";
3
3
  import "../execution/index.js";
4
4
  import { compileCommand } from "./compile.js";