@kici-dev/compiler 0.1.23 → 0.1.24
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/cli.js +15 -5
- package/dist/commands/index.d.ts +4 -2
- package/dist/commands/index.js +3 -2
- package/dist/commands/init.js +2 -2
- package/dist/commands/pat.d.ts +27 -0
- package/dist/commands/pat.js +76 -0
- package/dist/commands/preview.d.ts +88 -0
- package/dist/commands/{test.js → preview.js} +15 -14
- package/dist/commands/run.d.ts +11 -1
- package/dist/commands/run.js +34 -7
- package/dist/commands/verify-attestation.d.ts +4 -1
- package/dist/commands/verify-attestation.js +26 -10
- package/dist/generators/secrets-dts.js +2 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/llm-context/llms-architecture.txt +3 -3
- package/dist/llm-context/llms-cli.txt +149 -26
- package/dist/llm-context/llms-features.txt +107 -5
- package/dist/llm-context/llms-full.txt +390 -46
- package/dist/llm-context/llms-getting-started.txt +6 -6
- package/dist/llm-context/llms-sdk.txt +125 -6
- package/dist/llm-context/llms.txt +7 -5
- package/dist/local-executor/index.js +2 -1
- package/dist/local-executor/job-runner.js +3 -3
- package/dist/lockfile/generator.d.ts +10 -2
- package/dist/lockfile/generator.js +106 -52
- package/dist/remote/history.d.ts +1 -1
- package/dist/remote/history.js +1 -1
- package/dist/remote/local-repo-identity.d.ts +32 -0
- package/dist/remote/local-repo-identity.js +74 -0
- package/dist/remote/prod-defaults.d.ts +8 -0
- package/dist/remote/prod-defaults.js +9 -1
- package/dist/templates/agents-md.d.ts +1 -1
- package/dist/templates/agents-md.js +2 -2
- package/dist/templates/package-json.js +1 -1
- package/dist/test-runner/step-context.d.ts +1 -1
- package/dist/test-runner/step-context.js +2 -1
- package/dist/types.d.ts +33 -6
- package/dist/types.js +5 -1
- package/package.json +4 -7
- package/sbom.spdx.json +35 -35
|
@@ -26,7 +26,7 @@ Why the lock file must stay in sync with workflow source, how to commit both tog
|
|
|
26
26
|
|
|
27
27
|
### [CLI reference](https://docs.kici.dev/user/cli-reference/)
|
|
28
28
|
|
|
29
|
-
All CLI commands provided by `@kici-dev/compiler`: `kici compile` (with watch mode and check mode), `kici run` (local and remote execution), `kici
|
|
29
|
+
All CLI commands provided by `@kici-dev/compiler`: `kici compile` (with watch mode and check mode), `kici run` (local and remote execution), `kici preview` (event simulation with dry-run, filtering, debug output, and custom payloads), `kici login`/`logout`/`org` (authentication and org management), `kici diagnostics` (infrastructure tree) and `kici runs` (`list`/`show`/`logs`/`rerun`/`cancel` — run management), `kici secrets` (secret listing), `kici types` (type generation), `kici fixture` (generate test payloads), `kici init` (interactive project scaffolding), `kici hook` (pre-commit hook installation), `kici endpoints` (webhook entrypoints), and `kici workflows` (workflow listing). Includes environment variables and exit codes.
|
|
30
30
|
|
|
31
31
|
### [Workflow patterns](https://docs.kici.dev/user/workflow-patterns/)
|
|
32
32
|
|
|
@@ -249,10 +249,10 @@ The lock file (`kici.lock.json`) is a JSON representation of your workflow that
|
|
|
249
249
|
|
|
250
250
|
## Preview trigger matching
|
|
251
251
|
|
|
252
|
-
Use `kici
|
|
252
|
+
Use `kici preview` to preview which workflows match a trigger event (dry-run, no execution):
|
|
253
253
|
|
|
254
254
|
```bash
|
|
255
|
-
npx kici
|
|
255
|
+
npx kici preview pr:open
|
|
256
256
|
```
|
|
257
257
|
|
|
258
258
|
Expected output (simplified):
|
|
@@ -418,14 +418,14 @@ Or add the flag to your root `package.json`:
|
|
|
418
418
|
|
|
419
419
|
## Authoring KiCI workflows with LLM coding agents
|
|
420
420
|
|
|
421
|
-
KiCI is LLM-ready by design. Because workflows are real, typed TypeScript, coding agents reason over the SDK's `.d.ts` signatures instead of guessing a bespoke YAML DSL — and they verify their own pipelines with the same `kici
|
|
421
|
+
KiCI is LLM-ready by design. Because workflows are real, typed TypeScript, coding agents reason over the SDK's `.d.ts` signatures instead of guessing a bespoke YAML DSL — and they verify their own pipelines with the same `kici preview` and `kici run local` loop you use, so there's no push-to-find-out round-trip. First-class agent context ships in the box, so an agent is briefed the moment it opens the project.
|
|
422
422
|
|
|
423
423
|
KiCI ships first-class context for LLM coding agents (Claude Code, Cursor, Aider, etc.). When you scaffold a project with `kici init`, the CLI writes `.kici/AGENTS.md`, a one-page briefing that tells the agent:
|
|
424
424
|
|
|
425
425
|
- where the SDK type declarations live (`node_modules/@kici-dev/sdk/dist/index.d.ts`)
|
|
426
426
|
- the five canonical authoring patterns with runnable examples
|
|
427
427
|
- the anti-patterns that catch agents off-guard (no YAML, no `/dist/...` imports, no top-level `await`)
|
|
428
|
-
- the local commands the agent should drive (`kici compile --check`, `kici
|
|
428
|
+
- the local commands the agent should drive (`kici compile --check`, `kici preview`, `kici run local`, `kici docs llm`)
|
|
429
429
|
|
|
430
430
|
If you don't want the file, pass `--no-agents-md` to `kici init`, or delete the file afterwards — KiCI never reads it at runtime.
|
|
431
431
|
|
|
@@ -516,7 +516,7 @@ If you're not sure, pick Docker / Podman.
|
|
|
516
516
|
|
|
517
517
|
## Looking for the laptop-only path?
|
|
518
518
|
|
|
519
|
-
Both quickstarts deploy a real orchestrator + agent. If you only want to write a workflow and dry-run it on your laptop with no infrastructure, [Getting started](https://docs.kici.dev/user/getting-started/) covers `kici
|
|
519
|
+
Both quickstarts deploy a real orchestrator + agent. If you only want to write a workflow and dry-run it on your laptop with no infrastructure, [Getting started](https://docs.kici.dev/user/getting-started/) covers `kici preview` and `kici run local` instead.
|
|
520
520
|
|
|
521
521
|
---
|
|
522
522
|
|
|
@@ -2650,7 +2650,7 @@ const deploy = job('deploy', {
|
|
|
2650
2650
|
|
|
2651
2651
|
**Important:** `needs` must be declared explicitly. Output chaining does not auto-infer dependencies -- you must list job dependencies in `needs` even if you access their outputs via `.result`.
|
|
2652
2652
|
|
|
2653
|
-
Cross-job output chaining works in both local
|
|
2653
|
+
Cross-job output chaining works in both local execution (`kici run local`) and remote pipeline execution. The orchestrator's needs-aware dispatch scheduler guarantees upstream jobs reach a terminal state before downstream jobs dispatch, and upstream outputs are transported to the downstream agent sandbox via the `upstreamJobOutputs` field on `job.dispatch`. See [needs-scheduler](https://docs.kici.dev/architecture/execution/needs-scheduler/) for the full dispatch semantics.
|
|
2654
2654
|
|
|
2655
2655
|
### Job dependencies (`needs`)
|
|
2656
2656
|
|
|
@@ -3316,6 +3316,88 @@ The caller never has to branch on outcome — `result.result` is always a `Bucke
|
|
|
3316
3316
|
|
|
3317
3317
|
---
|
|
3318
3318
|
|
|
3319
|
+
## SDK reference: parallel
|
|
3320
|
+
|
|
3321
|
+
Source: https://docs.kici.dev/user/sdk/parallel/
|
|
3322
|
+
|
|
3323
|
+
`parallel([...steps], opts?)` runs a group of independent steps **concurrently**
|
|
3324
|
+
within one job, behind a join barrier: execution continues past the group only
|
|
3325
|
+
once every child has settled. Each child is its own observable step — it gets its
|
|
3326
|
+
own logs, status, timing, and retry — instead of being hidden inside one step's
|
|
3327
|
+
`Promise.all`.
|
|
3328
|
+
|
|
3329
|
+
```ts
|
|
3330
|
+
import { workflow, job, step, parallel, push } from '@kici-dev/sdk';
|
|
3331
|
+
|
|
3332
|
+
export default workflow('ci', {
|
|
3333
|
+
on: push(),
|
|
3334
|
+
jobs: [
|
|
3335
|
+
job('checks', {
|
|
3336
|
+
runsOn: 'kici:os:linux',
|
|
3337
|
+
steps: [
|
|
3338
|
+
checkout,
|
|
3339
|
+
// lint, typecheck, and the unit tests have no ordering between them,
|
|
3340
|
+
// so they run together — the job's wall-clock is the slowest child,
|
|
3341
|
+
// not the sum of all three.
|
|
3342
|
+
parallel([lint, typecheck, unitTests], { failFast: true }),
|
|
3343
|
+
deploy,
|
|
3344
|
+
],
|
|
3345
|
+
}),
|
|
3346
|
+
],
|
|
3347
|
+
});
|
|
3348
|
+
```
|
|
3349
|
+
|
|
3350
|
+
`parallel(...)` returns a `ParallelGroup` that sits in the ordinary flat
|
|
3351
|
+
`steps: [...]` array — there is no new `job` field. A group's children are
|
|
3352
|
+
**sequential steps only**; groups cannot be nested.
|
|
3353
|
+
|
|
3354
|
+
## Options
|
|
3355
|
+
|
|
3356
|
+
`parallel(steps, opts?)` accepts:
|
|
3357
|
+
|
|
3358
|
+
- **`failFast?: boolean`** — default `true`. When a child fails, the in-flight
|
|
3359
|
+
siblings are cancelled immediately and the job fails. With `failFast: false`
|
|
3360
|
+
every child runs to completion first, then the job fails if any child failed.
|
|
3361
|
+
- **`maxParallel?: number`** — default unlimited. Caps how many children run at
|
|
3362
|
+
once; children waiting for a slot report a `pending` status until they launch.
|
|
3363
|
+
- **`name?: string`** — a label for the group's dashboard band.
|
|
3364
|
+
|
|
3365
|
+
A child marked `continueOnError: true` never trips fail-fast and never fails the
|
|
3366
|
+
job — it still shows a `failed` status badge, but the group treats it as
|
|
3367
|
+
non-fatal.
|
|
3368
|
+
|
|
3369
|
+
## Statuses
|
|
3370
|
+
|
|
3371
|
+
Parallel steps introduce two step statuses:
|
|
3372
|
+
|
|
3373
|
+
- **`pending`** — a child queued behind `maxParallel`, not yet launched.
|
|
3374
|
+
- **`cancelled`** — a sibling aborted by fail-fast. A cancelled step is **not** a
|
|
3375
|
+
failure: only the child that actually failed fails the job; the cancelled
|
|
3376
|
+
siblings render in gray (distinct from the red failing step) on the dashboard.
|
|
3377
|
+
|
|
3378
|
+
Children may also complete **out of order** — the fastest child finishes first
|
|
3379
|
+
regardless of array position. A later sequential step can read a parallel child's
|
|
3380
|
+
`.result` after the barrier; children within a group cannot read each other's
|
|
3381
|
+
results (there is no ordering inside the group).
|
|
3382
|
+
|
|
3383
|
+
## Scope: nests inside job-level fan-out
|
|
3384
|
+
|
|
3385
|
+
`parallel()`'s `failFast` / `maxParallel` are **step-group** scopes — they govern
|
|
3386
|
+
only the steps inside the group. They are a different layer from the **job-level**
|
|
3387
|
+
`failFast` / `maxParallel` on a matrix / `runsOnAll` fan-out, which govern how a
|
|
3388
|
+
job's child _jobs_ spread across the matrix or host roster. A `parallel()` group
|
|
3389
|
+
inside a fan-out job nests its concurrency inside each fan-out child.
|
|
3390
|
+
|
|
3391
|
+
## Local vs remote execution
|
|
3392
|
+
|
|
3393
|
+
Run remotely (the orchestrator + agent), parallel children execute concurrently
|
|
3394
|
+
and each surfaces as its own dashboard step. `kici run local` executes the same
|
|
3395
|
+
children in array order in its single-process model — the results are identical,
|
|
3396
|
+
only the wall-clock and the live fail-fast cancellation differ. Use a remote run
|
|
3397
|
+
to observe the concurrent timeline.
|
|
3398
|
+
|
|
3399
|
+
---
|
|
3400
|
+
|
|
3319
3401
|
## SDK reference: rules, matrix, dynamic jobs
|
|
3320
3402
|
|
|
3321
3403
|
Source: https://docs.kici.dev/user/sdk/rules-matrix-dynamic/
|
|
@@ -4214,7 +4296,7 @@ interface StepContext<TInputs = Record<string, unknown>> {
|
|
|
4214
4296
|
rawPayload?: Record<string, unknown>;
|
|
4215
4297
|
/** Which git provider triggered this workflow (e.g. 'github', 'gitlab') */
|
|
4216
4298
|
provider?: string;
|
|
4217
|
-
/** Whether this execution was triggered by `kici
|
|
4299
|
+
/** Whether this execution was triggered by `kici run remote` (developer-initiated remote run) */
|
|
4218
4300
|
isTestRun: boolean;
|
|
4219
4301
|
/** The resolved deployment environment name for this job (undefined without environment) */
|
|
4220
4302
|
environment?: string;
|
|
@@ -4611,7 +4693,7 @@ Tools that require a file path on disk (sops `SOPS_AGE_KEY_FILE`, kubectl `KUBEC
|
|
|
4611
4693
|
|
|
4612
4694
|
### Local test mode secrets
|
|
4613
4695
|
|
|
4614
|
-
When running `kici
|
|
4696
|
+
When running `kici preview`, you can provide secrets locally without an orchestrator.
|
|
4615
4697
|
|
|
4616
4698
|
#### .kici/.secrets file
|
|
4617
4699
|
|
|
@@ -4639,10 +4721,10 @@ Override or supplement file-based secrets with CLI flags:
|
|
|
4639
4721
|
|
|
4640
4722
|
```bash
|
|
4641
4723
|
# Inject flat secrets (repeatable)
|
|
4642
|
-
kici
|
|
4724
|
+
kici preview push --secret DEPLOY_TOKEN=my-token --secret API_KEY=my-key
|
|
4643
4725
|
|
|
4644
4726
|
# Inject context-scoped secrets (repeatable)
|
|
4645
|
-
kici
|
|
4727
|
+
kici preview push --context production.DB_PASSWORD=prod-secret --context npm-publish.NPM_TOKEN=abc123
|
|
4646
4728
|
```
|
|
4647
4729
|
|
|
4648
4730
|
**Precedence:** CLI flags override `.kici/.secrets` file values. Context secrets are auto-flattened into `ctx.secrets` using the same merge logic as production (last context wins).
|
|
@@ -5197,6 +5279,7 @@ interface ScheduleConfigInput {
|
|
|
5197
5279
|
cron: string; // Required: cron expression (5-field)
|
|
5198
5280
|
timezone?: string; // Timezone for cron evaluation (default: 'UTC')
|
|
5199
5281
|
description?: string; // Human-readable description of the schedule
|
|
5282
|
+
inputs?: DispatchInputsMap; // Optional: defaults-only typed inputs (see below)
|
|
5200
5283
|
}
|
|
5201
5284
|
```
|
|
5202
5285
|
|
|
@@ -5207,6 +5290,41 @@ schedule({ cron: '0 9 * * 1', timezone: 'America/New_York' }); // Monday 9am ET
|
|
|
5207
5290
|
schedule({ cron: '*/15 * * * *', description: 'health check every 15 min' });
|
|
5208
5291
|
```
|
|
5209
5292
|
|
|
5293
|
+
#### Schedule inputs (defaults-only)
|
|
5294
|
+
|
|
5295
|
+
A `schedule()` trigger may declare typed `inputs`. A cron or dashboard
|
|
5296
|
+
"run now" fire carries **no operator-supplied values**, so each input resolves
|
|
5297
|
+
from its declared **default** and is exposed to steps and rules as
|
|
5298
|
+
`ctx.dispatchInputs` — the same surface as [typed dispatch inputs](https://docs.kici.dev/user/sdk/triggers/#typed-dispatch-inputs).
|
|
5299
|
+
|
|
5300
|
+
Because there is no operator to supply a value, every schedule input must
|
|
5301
|
+
declare a `.default()` **or** be `.optional()`. An input that is neither is
|
|
5302
|
+
rejected at `kici compile` time.
|
|
5303
|
+
|
|
5304
|
+
```typescript
|
|
5305
|
+
import { workflow, job, schedule, z } from '@kici-dev/sdk';
|
|
5306
|
+
|
|
5307
|
+
export default workflow('nightly', {
|
|
5308
|
+
on: schedule({
|
|
5309
|
+
cron: '0 3 * * *',
|
|
5310
|
+
inputs: { mode: z.enum(['full', 'quick']).default('full') },
|
|
5311
|
+
}),
|
|
5312
|
+
jobs: [
|
|
5313
|
+
job('build', {
|
|
5314
|
+
runsOn: 'default',
|
|
5315
|
+
run: async (ctx) => {
|
|
5316
|
+
ctx.log(`mode = ${ctx.dispatchInputs.mode}`); // "full" on every fire
|
|
5317
|
+
},
|
|
5318
|
+
}),
|
|
5319
|
+
],
|
|
5320
|
+
});
|
|
5321
|
+
```
|
|
5322
|
+
|
|
5323
|
+
You can also share a typed handle via `defineDispatchInputs(...)` and read it
|
|
5324
|
+
back with `.from(ctx)`, exactly as with `dispatch()`. The allowed input types
|
|
5325
|
+
are the same closed subset documented under
|
|
5326
|
+
[typed dispatch inputs](https://docs.kici.dev/user/sdk/triggers/#typed-dispatch-inputs).
|
|
5327
|
+
|
|
5210
5328
|
### lifecycle()
|
|
5211
5329
|
|
|
5212
5330
|
Create a lifecycle trigger for cross-workflow orchestration events. Returns a frozen `LifecycleTriggerConfig`.
|
|
@@ -5535,7 +5653,7 @@ If `check()` throws while polling, the error is logged and polling continues —
|
|
|
5535
5653
|
|
|
5536
5654
|
Source: https://docs.kici.dev/user/sdk-reference/
|
|
5537
5655
|
|
|
5538
|
-
Reference documentation for `@kici-dev/sdk`. The reference is split across
|
|
5656
|
+
Reference documentation for `@kici-dev/sdk`. The reference is split across the per-topic pages below.
|
|
5539
5657
|
|
|
5540
5658
|
| Page | Covers |
|
|
5541
5659
|
| ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -5547,6 +5665,7 @@ Reference documentation for `@kici-dev/sdk`. The reference is split across five
|
|
|
5547
5665
|
| [Runtime](https://docs.kici.dev/user/sdk/runtime/) | Types index, `StepContext`, secrets, and fixtures. |
|
|
5548
5666
|
| [Idempotent helpers](https://docs.kici.dev/user/sdk/idempotent/) | `idempotent()`, `idempotentStep()`, and the check-mode-aware `checkStep()` — check / apply pattern with typed results on both the skipped and applied branches. |
|
|
5549
5667
|
| [Wait-for helpers](https://docs.kici.dev/user/sdk/wait-for/) | `waitFor()` and `waitForStep()` — poll a condition on an interval, run an optional success action, recover gracefully on timeout. |
|
|
5668
|
+
| [Parallel steps](https://docs.kici.dev/user/sdk/parallel/) | `parallel()` — run independent steps concurrently within one job behind a join barrier, each as its own observable step, with `failFast` and `maxParallel` controls. |
|
|
5550
5669
|
|
|
5551
5670
|
The `@kici-dev/sdk` package re-exports the entire surface from a single entry point. Pick what you need:
|
|
5552
5671
|
|
|
@@ -5569,6 +5688,99 @@ For the complete list of every named export (factory functions, triggers, rules,
|
|
|
5569
5688
|
|
|
5570
5689
|
# CLI and authoring
|
|
5571
5690
|
|
|
5691
|
+
## Drive KiCI from your coding agent
|
|
5692
|
+
|
|
5693
|
+
Source: https://docs.kici.dev/user/ai-agents/
|
|
5694
|
+
|
|
5695
|
+
KiCI ships a hosted **MCP server** so a coding agent (Claude Code, or any MCP
|
|
5696
|
+
client) can drive your CI directly: trigger runs, read a structured result,
|
|
5697
|
+
fetch the failing step's logs, cancel, and re-run — all under your own identity,
|
|
5698
|
+
org-scoped, and audited. There are no per-tool tokens to configure: point the
|
|
5699
|
+
agent at one URL with one credential and it's done.
|
|
5700
|
+
|
|
5701
|
+
The MCP exposes only what you can already do yourself through the `kici` CLI and
|
|
5702
|
+
the dashboard. It is not a new privileged surface — every tool maps to an
|
|
5703
|
+
existing user-facing operation and is gated by the same permissions your role
|
|
5704
|
+
grants.
|
|
5705
|
+
|
|
5706
|
+
## 1. Mint an agent token
|
|
5707
|
+
|
|
5708
|
+
The MCP accepts **only** an agent-kind personal access token (PAT). Mint one with
|
|
5709
|
+
the `kici` CLI (log in first with `kici login`):
|
|
5710
|
+
|
|
5711
|
+
```bash
|
|
5712
|
+
kici pat create --agent --name "claude-code"
|
|
5713
|
+
```
|
|
5714
|
+
|
|
5715
|
+
The `--name` value is the **agent label**. It is recorded on every action the
|
|
5716
|
+
agent takes, so your audit log shows exactly which agent did what (and on whose
|
|
5717
|
+
behalf). The token is printed once — save it now; it cannot be retrieved later.
|
|
5718
|
+
|
|
5719
|
+
An agent PAT inherits your permissions unchanged — it carries provenance, not
|
|
5720
|
+
extra authority. Powerful operator capabilities (secret rotation, agent and peer
|
|
5721
|
+
management, draining) are intentionally **not** exposed here.
|
|
5722
|
+
|
|
5723
|
+
## 2. Point your coding agent at the MCP server
|
|
5724
|
+
|
|
5725
|
+
Configure your MCP client with the KiCI MCP endpoint and the agent PAT as a
|
|
5726
|
+
Bearer credential. The endpoint is the hosted Platform URL plus `/api/v1/mcp`.
|
|
5727
|
+
|
|
5728
|
+
For Claude Code, add a remote MCP server whose URL is your KiCI Platform's
|
|
5729
|
+
`/api/v1/mcp` and whose `Authorization` header is `Bearer <your-agent-pat>`.
|
|
5730
|
+
|
|
5731
|
+
That's the entire setup. The agent can now call the tools below.
|
|
5732
|
+
|
|
5733
|
+
## 3. What the agent can do
|
|
5734
|
+
|
|
5735
|
+
**Read**
|
|
5736
|
+
|
|
5737
|
+
- `list_runs` — recent runs in your organization.
|
|
5738
|
+
- `get_run` — the structured, provenance-tagged result of a run: the typed job
|
|
5739
|
+
graph, per-step statuses and exit codes, durations, and a derived failure
|
|
5740
|
+
category.
|
|
5741
|
+
- `get_step_logs` — the log lines for a specific step.
|
|
5742
|
+
- `list_workflows` — your registered workflows.
|
|
5743
|
+
|
|
5744
|
+
**Drive**
|
|
5745
|
+
|
|
5746
|
+
- `trigger_run` — run a registered workflow ("run now").
|
|
5747
|
+
- `rerun_run` — re-run a completed run.
|
|
5748
|
+
- `cancel_run` — cancel an in-progress run.
|
|
5749
|
+
|
|
5750
|
+
If you belong to a single organization, the org is resolved automatically. If
|
|
5751
|
+
you belong to several, pass an `orgId` argument to any tool.
|
|
5752
|
+
|
|
5753
|
+
## 4. Why the structured result is agent-safe
|
|
5754
|
+
|
|
5755
|
+
`get_run` and `get_step_logs` return a machine-first shape designed for an agent
|
|
5756
|
+
to reason over without being misled by repository content. Every field that
|
|
5757
|
+
comes from your repo, a contributor, or a process's output — workflow and job
|
|
5758
|
+
names, refs, error messages, log lines, job outputs — is wrapped in an
|
|
5759
|
+
`{ untrusted: true, value: … }` envelope. KiCI-generated values (ids, statuses,
|
|
5760
|
+
exit codes, durations, the derived failure category) are left plain. An agent can
|
|
5761
|
+
keep user-controlled content out of its instruction channel by refusing to act
|
|
5762
|
+
on anything tagged `untrusted`.
|
|
5763
|
+
|
|
5764
|
+
Secret values are never returned — only the names of the secret keys a step
|
|
5765
|
+
accessed.
|
|
5766
|
+
|
|
5767
|
+
## 5. The audit guarantee
|
|
5768
|
+
|
|
5769
|
+
Because the MCP accepts only an agent-kind PAT, **every action that flows through
|
|
5770
|
+
it is agent-attributed by construction** — there is no path that produces an
|
|
5771
|
+
untagged, human-looking action. Each read and each drive operation is recorded in
|
|
5772
|
+
your orchestrator's access log under your identity plus the agent label, so you
|
|
5773
|
+
always have a complete trail of what your agent did.
|
|
5774
|
+
|
|
5775
|
+
Inspect that trail with `kici-admin access-log list --json` (or
|
|
5776
|
+
`kici-admin access-log show <id>` for one entry). An agent-attributed row keeps
|
|
5777
|
+
`actor_type` as `user` and `actor_id` as your own identity — the agent provenance
|
|
5778
|
+
rides in the row's actor metadata as `agentLabel` (the `--name` you minted the
|
|
5779
|
+
PAT with) and `agentPatId` (the token that acted). The label is also stored in a
|
|
5780
|
+
dedicated `agent_label` column on every such row.
|
|
5781
|
+
|
|
5782
|
+
---
|
|
5783
|
+
|
|
5572
5784
|
## CLI authentication
|
|
5573
5785
|
|
|
5574
5786
|
Source: https://docs.kici.dev/user/cli-auth/
|
|
@@ -5851,7 +6063,7 @@ Run commands with `npx kici` or add scripts to your `package.json`:
|
|
|
5851
6063
|
{
|
|
5852
6064
|
"scripts": {
|
|
5853
6065
|
"kici:compile": "kici compile",
|
|
5854
|
-
"kici:
|
|
6066
|
+
"kici:preview": "kici preview"
|
|
5855
6067
|
}
|
|
5856
6068
|
}
|
|
5857
6069
|
```
|
|
@@ -5946,6 +6158,8 @@ kici run local [event] [options]
|
|
|
5946
6158
|
| `--kici-dir <path>` | `.kici` | Path to .kici directory |
|
|
5947
6159
|
| `--in-place` | `false` | Run against the real working directory instead of an isolated tmp checkout (see "Execution isolation" below) |
|
|
5948
6160
|
| `--keep` | `false` | Always retain the isolated tmp checkout (default: keep only on failure) |
|
|
6161
|
+
| `--check` | `false` | Run in [check mode](https://docs.kici.dev/user/idempotent-steps/): each step reports drift instead of applying; the run still exits 0 |
|
|
6162
|
+
| `--fail-on-drift` | `false` | In check mode, exit non-zero if any step reports drift (no effect without `--check`) |
|
|
5949
6163
|
|
|
5950
6164
|
**Interactive workflow selection (`--pick` / `-p`):**
|
|
5951
6165
|
|
|
@@ -6087,6 +6301,10 @@ kici run remote [fixture] [options]
|
|
|
6087
6301
|
| `--target-allow-empty` | `false` | A `--target` that narrows a `runsOnAll` job to zero hosts skips it instead of failing |
|
|
6088
6302
|
| `--debug` | `false` | Verbose internals |
|
|
6089
6303
|
| `--kici-dir <path>` | `.kici` | Path to .kici directory |
|
|
6304
|
+
| `--routing-key <key>` | none | Override the routing key for this run (advanced; selecting the org normally suffices — see [How the run is routed](https://docs.kici.dev/user/cli-reference/#how-the-run-is-routed)) |
|
|
6305
|
+
| `--check` | `false` | Run in [check mode](https://docs.kici.dev/user/idempotent-steps/): each step reports drift instead of applying |
|
|
6306
|
+
| `--fail-on-drift` | `false` | In check mode, fail the run if any step reports drift (no effect without `--check`) |
|
|
6307
|
+
| `--approve-all, --yes` | `false` | Auto-approve every [approval gate](https://docs.kici.dev/user/approvals/) this run holds on (run-scoped; eligibility still enforced) |
|
|
6090
6308
|
|
|
6091
6309
|
**Examples:**
|
|
6092
6310
|
|
|
@@ -6252,12 +6470,12 @@ kici orchestrators use us-east
|
|
|
6252
6470
|
kici orchestrators use us-east --org xyz789ghi012
|
|
6253
6471
|
```
|
|
6254
6472
|
|
|
6255
|
-
### kici
|
|
6473
|
+
### kici preview
|
|
6256
6474
|
|
|
6257
6475
|
Preview which workflows match a trigger event (dry-run, no execution). Useful for verifying trigger configurations during development.
|
|
6258
6476
|
|
|
6259
6477
|
```bash
|
|
6260
|
-
kici
|
|
6478
|
+
kici preview [event] [options]
|
|
6261
6479
|
```
|
|
6262
6480
|
|
|
6263
6481
|
**Arguments:**
|
|
@@ -6284,19 +6502,19 @@ kici test [event] [options]
|
|
|
6284
6502
|
|
|
6285
6503
|
```bash
|
|
6286
6504
|
# Preview which workflows match a push event
|
|
6287
|
-
kici
|
|
6505
|
+
kici preview push
|
|
6288
6506
|
|
|
6289
6507
|
# Preview PR trigger matching
|
|
6290
|
-
kici
|
|
6508
|
+
kici preview pr:open
|
|
6291
6509
|
|
|
6292
6510
|
# Preview with branch override
|
|
6293
|
-
kici
|
|
6511
|
+
kici preview push --branch develop
|
|
6294
6512
|
|
|
6295
6513
|
# Filter to specific workflow
|
|
6296
|
-
kici
|
|
6514
|
+
kici preview push --workflow ci
|
|
6297
6515
|
|
|
6298
6516
|
# Simulate changed files for path-filtered triggers
|
|
6299
|
-
kici
|
|
6517
|
+
kici preview push --files src/index.ts --files README.md
|
|
6300
6518
|
```
|
|
6301
6519
|
|
|
6302
6520
|
**Exit codes:**
|
|
@@ -6306,7 +6524,7 @@ kici test push --files src/index.ts --files README.md
|
|
|
6306
6524
|
| 0 | Preview completed (including zero matches) |
|
|
6307
6525
|
| 1 | Error |
|
|
6308
6526
|
|
|
6309
|
-
**Migration from old `
|
|
6527
|
+
**Migration from the old `test` command:** The dry-run preview command was renamed from `test` to `preview`. If you were using the old `test` command with a fixture name for remote fixture execution, use `kici run remote <fixture-name>` instead. For local workflow execution, use `kici run local <event>`.
|
|
6310
6528
|
|
|
6311
6529
|
### kici login
|
|
6312
6530
|
|
|
@@ -6683,6 +6901,27 @@ Only key names are shown — secret values are never returned over this endpoint
|
|
|
6683
6901
|
|
|
6684
6902
|
**Prerequisites:** authenticate via `kici login` and select an active organization with `kici org use <name>`.
|
|
6685
6903
|
|
|
6904
|
+
### kici pat create
|
|
6905
|
+
|
|
6906
|
+
Mint a personal access token under your own identity. Pass `--agent` to mint an
|
|
6907
|
+
**agent-kind** PAT — the credential a coding agent points the KiCI MCP server at.
|
|
6908
|
+
|
|
6909
|
+
```bash
|
|
6910
|
+
kici pat create --agent --name "claude-code"
|
|
6911
|
+
```
|
|
6912
|
+
|
|
6913
|
+
- `--agent` marks the token as agent-kind. An agent PAT inherits your
|
|
6914
|
+
permissions unchanged (it carries provenance, not extra authority) and is the
|
|
6915
|
+
**only** credential the MCP server accepts.
|
|
6916
|
+
- `--name <label>` sets the token name. For an agent PAT this is the **agent
|
|
6917
|
+
label** recorded on every action the agent takes — required with `--agent`.
|
|
6918
|
+
- `--expires-in-days <n>` overrides the default expiry.
|
|
6919
|
+
|
|
6920
|
+
The token is printed once — save it immediately; it cannot be retrieved later.
|
|
6921
|
+
See [Drive KiCI from your coding agent](https://docs.kici.dev/user/ai-agents/) for the full setup.
|
|
6922
|
+
|
|
6923
|
+
**Prerequisites:** authenticate via `kici login` first.
|
|
6924
|
+
|
|
6686
6925
|
### kici types
|
|
6687
6926
|
|
|
6688
6927
|
Generate TypeScript declaration files from orchestrator environment metadata. The generated `.d.ts` file augments the SDK's `KnownSecretKeys` and `EnvironmentSecrets` interfaces, providing compile-time autocomplete and type checking for secret key names.
|
|
@@ -7001,7 +7240,7 @@ kici admin drain-worker --url http://worker-2.internal:10143
|
|
|
7001
7240
|
Verify a KiCI build-provenance attestation bundle offline. A bundle is the signed package a workflow step produces via `ctx.attestProvenance(...)`: a DSSE-wrapped SLSA in-toto statement, the ephemeral public key that signed it, and the KiCI identity token that anchors the build context. For the end-to-end attest → verify → view journey, see the [build provenance guide](https://docs.kici.dev/user/provenance/). Verification establishes the full chain — the identity token verifies against the trusted issuer's JWKS, the DSSE signature verifies against the bundled key, and the statement's build context must match the token's claims (a mismatch is a hard failure). When an `[artifact]` is given, its SHA-256 digest is also matched against the attestation subject.
|
|
7002
7241
|
|
|
7003
7242
|
```bash
|
|
7004
|
-
kici verify-attestation [artifact] --bundle <path-or-url> --trust-root <url-or-file> [options]
|
|
7243
|
+
kici verify-attestation [artifact] --bundle <path-or-url> [--trust-root <url-or-file>] [options]
|
|
7005
7244
|
```
|
|
7006
7245
|
|
|
7007
7246
|
**Arguments:**
|
|
@@ -7012,14 +7251,14 @@ kici verify-attestation [artifact] --bundle <path-or-url> --trust-root <url-or-f
|
|
|
7012
7251
|
|
|
7013
7252
|
**Options:**
|
|
7014
7253
|
|
|
7015
|
-
| Option | Required | Description
|
|
7016
|
-
| ---------------------------- | -------- |
|
|
7017
|
-
| `--bundle <path-or-url>` | yes | Path or `http(s)` URL to the attestation bundle JSON.
|
|
7018
|
-
| `--trust-root <url-or-file>` |
|
|
7019
|
-
| `--audience <aud>` | no | Expected token audience (defaults to the KiCI provenance audience).
|
|
7020
|
-
| `--json` | no | Print the structured verification result as JSON instead of human-readable output.
|
|
7254
|
+
| Option | Required | Description |
|
|
7255
|
+
| ---------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
7256
|
+
| `--bundle <path-or-url>` | yes | Path or `http(s)` URL to the attestation bundle JSON. |
|
|
7257
|
+
| `--trust-root <url-or-file>` | no | Trusted issuer (see below). Defaults to the hosted KiCI platform. The token issuer is pinned to it, never taken from the token. |
|
|
7258
|
+
| `--audience <aud>` | no | Expected token audience (defaults to the KiCI provenance audience). |
|
|
7259
|
+
| `--json` | no | Print the structured verification result as JSON instead of human-readable output. |
|
|
7021
7260
|
|
|
7022
|
-
**Trust root:** the verifier never trusts the issuer named inside the token
|
|
7261
|
+
**Trust root:** `--trust-root` defaults to the hosted KiCI platform's provenance issuer — the same platform you `kici login` against (see [Which trust root do I use?](https://docs.kici.dev/user/provenance/#which-trust-root-do-i-use)), so the common case needs no flag. The verifier never trusts the issuer named inside the token; supplying it out-of-band is what prevents a forged bundle from self-attesting. To override the default, pass `--trust-root` in one of two forms:
|
|
7023
7262
|
|
|
7024
7263
|
- **Online — an HTTPS issuer URL.** The verifier fetches `<url>/.well-known/openid-configuration`, reads its `issuer` and `jwks_uri`, and fetches the JWKS. The token's `iss` is pinned to the discovery document's `issuer`.
|
|
7025
7264
|
- **Offline — a self-contained trust-root file.** A local JSON file with the issuer and JWKS inlined, so no network access is needed (air-gapped verification):
|
|
@@ -7038,7 +7277,10 @@ kici verify-attestation [artifact] --bundle <path-or-url> --trust-root <url-or-f
|
|
|
7038
7277
|
**Examples:**
|
|
7039
7278
|
|
|
7040
7279
|
```bash
|
|
7041
|
-
#
|
|
7280
|
+
# Default: verify against the hosted KiCI platform (no --trust-root needed)
|
|
7281
|
+
kici verify-attestation ./dist/app.tgz --bundle ./app.tgz.kici.json
|
|
7282
|
+
|
|
7283
|
+
# Override: verify a bundle against a specific issuer, digest-checking the artifact
|
|
7042
7284
|
kici verify-attestation ./dist/app.tgz \
|
|
7043
7285
|
--bundle ./app.tgz.kici.json \
|
|
7044
7286
|
--trust-root https://platform.example/issuer
|
|
@@ -7055,10 +7297,10 @@ kici verify-attestation --bundle ./app.tgz.kici.json \
|
|
|
7055
7297
|
|
|
7056
7298
|
**Exit codes:**
|
|
7057
7299
|
|
|
7058
|
-
| Code | Meaning
|
|
7059
|
-
| ---- |
|
|
7060
|
-
| 0 | Verified — signature, identity, build context (and digest, if checked) all pass
|
|
7061
|
-
| 1 | Not verified, or an error (missing
|
|
7300
|
+
| Code | Meaning |
|
|
7301
|
+
| ---- | ----------------------------------------------------------------------------------------- |
|
|
7302
|
+
| 0 | Verified — signature, identity, build context (and digest, if checked) all pass |
|
|
7303
|
+
| 1 | Not verified, or an error (missing `--bundle`, unreadable bundle, unreachable trust root) |
|
|
7062
7304
|
|
|
7063
7305
|
## Workflow discovery
|
|
7064
7306
|
|
|
@@ -7100,7 +7342,7 @@ All commands follow a consistent exit code convention:
|
|
|
7100
7342
|
|
|
7101
7343
|
## Debug output
|
|
7102
7344
|
|
|
7103
|
-
Use `--debug` (on `kici run local`, `kici run remote`, `kici
|
|
7345
|
+
Use `--debug` (on `kici run local`, `kici run remote`, `kici preview`) or `--verbose` (on `kici compile`) for detailed output:
|
|
7104
7346
|
|
|
7105
7347
|
```bash
|
|
7106
7348
|
# Shows trigger matching, rule evaluation, decision traces
|
|
@@ -7110,7 +7352,7 @@ kici run local push --debug
|
|
|
7110
7352
|
kici compile --verbose
|
|
7111
7353
|
|
|
7112
7354
|
# Shows trigger matching preview
|
|
7113
|
-
kici
|
|
7355
|
+
kici preview pr:open --debug
|
|
7114
7356
|
```
|
|
7115
7357
|
|
|
7116
7358
|
Set `KICI_DEBUG=true` for additional internal debug output across all commands.
|
|
@@ -7391,7 +7633,7 @@ The lock file (`kici.lock.json`) is a JSON file with the following top-level fie
|
|
|
7391
7633
|
|
|
7392
7634
|
| Field | Description |
|
|
7393
7635
|
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
7394
|
-
| `schemaVersion` | Lock file schema version (currently
|
|
7636
|
+
| `schemaVersion` | Lock file schema version (currently 29). Incremented on breaking format changes. |
|
|
7395
7637
|
| `source` | Reference to the source file and export (e.g., `{ file: “.kici/workflows/ci.ts”, export: “#default” }`). |
|
|
7396
7638
|
| `contentHash` | SHA-256 of the serialized lock file content (excluding itself). Changes when any workflow, trigger, or job changes. |
|
|
7397
7639
|
| `lockfileHash` | SHA-256 of the detected package manager's lockfile, used as the dependency cache key. The lockfile is `.kici/package-lock.json` for npm, or the repo-root `pnpm-lock.yaml` / `yarn.lock` for a pnpm/yarn workspace; the hash input is prefixed with the manager name so a manager change is a guaranteed cache miss. Omitted when no lockfile exists. |
|
|
@@ -7514,7 +7756,7 @@ Test your workflows remotely against the full CI pipeline from your local machin
|
|
|
7514
7756
|
- Give test runs test-scoped secrets — your local secret files and `--env` values (uploaded encrypted) plus any environment flagged `allowLocalExecution: true` — while production environments stay unreachable
|
|
7515
7757
|
- Detect test mode in workflow code via `ctx.isTestRun`
|
|
7516
7758
|
|
|
7517
|
-
The command is remote-only -- all execution happens on the orchestrator and agent. For local-only trigger matching previews, use `kici
|
|
7759
|
+
The command is remote-only -- all execution happens on the orchestrator and agent. For local-only trigger matching previews, use `kici preview <event>`.
|
|
7518
7760
|
|
|
7519
7761
|
:::note[Orchestrator prerequisite: cache storage]
|
|
7520
7762
|
`kici run remote` uploads your working-tree overlay to the orchestrator's **cache storage** via a pre-signed URL, and the agent fetches it from there (see [Repo state transfer](https://docs.kici.dev/user/testing-guide/#repo-state-transfer)). The target orchestrator must therefore have cache storage enabled (`KICI_STORAGE_TYPE` = `s3` or `filesystem`).
|
|
@@ -8754,6 +8996,36 @@ job('deploy-review', {
|
|
|
8754
8996
|
|
|
8755
8997
|
A pure function like the one above (see [Dynamic values](https://docs.kici.dev/user/dynamic-values/)) is evaluated inline at dispatch with no init-job overhead. Dynamic environments that match a glob pattern (e.g., `review/*`) inherit the pattern's configuration, variables, and protection rules.
|
|
8756
8998
|
|
|
8999
|
+
### Multiple environments per job
|
|
9000
|
+
|
|
9001
|
+
A job can bind more than one environment with `environments`, an ordered array. This lets a single job draw secrets and variables from several environments at once — for example a shared `staging` environment plus a `my-testing` environment that carries test-only variables:
|
|
9002
|
+
|
|
9003
|
+
```typescript
|
|
9004
|
+
job('deploy', {
|
|
9005
|
+
runsOn: 'default',
|
|
9006
|
+
environments: ['staging', 'my-testing'],
|
|
9007
|
+
steps: [
|
|
9008
|
+
step('deploy', async (ctx) => {
|
|
9009
|
+
// ctx.secrets and ctx.env carry the merged set from both environments
|
|
9010
|
+
const dbUrl = await ctx.secrets.get('DB_URL');
|
|
9011
|
+
}),
|
|
9012
|
+
],
|
|
9013
|
+
});
|
|
9014
|
+
```
|
|
9015
|
+
|
|
9016
|
+
- `environment` (singular) and `environments` (array) are mutually exclusive — setting both is a compile error. `environment: 'staging'` is exactly equivalent to `environments: ['staging']`.
|
|
9017
|
+
- Each array entry is a static name or a function of the event, resolved per element exactly like a single dynamic environment.
|
|
9018
|
+
|
|
9019
|
+
**Merge order — last wins.** All bound environments are resolved on every dispatch (webhook, scheduled, and test runs alike) and merged in array order. When the same secret or variable key is defined in more than one environment, the later entry in the array wins. With `environments: ['staging', 'my-testing']`, a key defined in both resolves to `my-testing`'s value; keys defined in only one are preserved. The longest-scope-path-wins rule still applies _within_ each environment.
|
|
9020
|
+
|
|
9021
|
+
**Protection rules combine all-must-pass.** A job must satisfy **every** bound environment's gates — adding an environment can never loosen access. Branch restrictions, trigger-type filters, and repo patterns must pass for all environments; the minimum trust tier is the most restrictive across them; required reviewers are the union of all environments' reviewers; the wait timer is the longest; and the hold expiry is the shortest. If a run is gated out, the rejection names which environment and which rule rejected it (visible via `kici status` and the run's rejection reason), so a mutually-exclusive set of rules surfaces as a clear failure rather than a silent perpetual rejection.
|
|
9022
|
+
|
|
9023
|
+
**Skip-on-test.** On a test or local run (`kici run remote`, `kici run local`), any bound environment that disallows local execution is skipped — its variables and secrets are omitted from the merge and its gates are not evaluated. This makes the test-only-variables pattern work: with `environments: ['staging', 'my-testing']` where only `my-testing` allows local execution, a test run resolves just `my-testing`'s variables. If every bound environment disallows test runs, the job runs with no environment variables and a clear warning.
|
|
9024
|
+
|
|
9025
|
+
**Unconfigured environments contribute nothing at dispatch.** At dispatch time a bound environment name with no matching configured environment (and no matching glob environment) simply adds no variables, secrets, or protection rules — the job still runs, exactly as a single dynamic environment resolving to an as-yet-unconfigured name does today.
|
|
9026
|
+
|
|
9027
|
+
**Registration rejects a provably-unsatisfiable binding.** When a workflow is registered, KiCI statically checks every multi-environment binding: a bound environment that does not exist, a disabled one, or two environments with mutually-exclusive fixed branch / trigger-type / repository restrictions (no value can satisfy both) makes the binding provably unsatisfiable, and the registration is rejected with a precise message naming the job, the environments, and the rule — for example `unsatisfiable environment binding: job 'deploy' binds environments [staging, my-testing] with mutually exclusive branch restrictions (no value satisfies all bound environments)`. Bindings whose restrictions use globs are undecidable at registration and fall through to the dispatch-time gate check instead.
|
|
9028
|
+
|
|
8757
9029
|
### Job-level environment variables
|
|
8758
9030
|
|
|
8759
9031
|
The `env` property on a job provides static or dynamic environment variables:
|
|
@@ -8793,7 +9065,7 @@ job('deploy', {
|
|
|
8793
9065
|
});
|
|
8794
9066
|
```
|
|
8795
9067
|
|
|
8796
|
-
If no `concurrencyGroup` is specified, the environment name is used as the default concurrency group.
|
|
9068
|
+
If no `concurrencyGroup` is specified, the environment name is used as the default concurrency group. For a job bound to multiple environments, the default is the **first** bound environment's name.
|
|
8797
9069
|
|
|
8798
9070
|
### Step context
|
|
8799
9071
|
|
|
@@ -8934,6 +9206,12 @@ Each environment has four tabs:
|
|
|
8934
9206
|
|
|
8935
9207
|
4. **History** -- view filtered runs targeting this environment.
|
|
8936
9208
|
|
|
9209
|
+
### Bound environments on runs
|
|
9210
|
+
|
|
9211
|
+
A job's bound deployment environments are shown as chips on the run detail page (in the job metadata panel) in the order the job declared them, and the distinct set across a run's jobs appears as compact chips on the run list. For a multi-environment job the chips read left-to-right in merge order — later environments override earlier ones on key collisions. A `(dynamic)` chip marks an environment whose name is computed at runtime; it resolves to the real name once the run starts. A job that binds a single environment shows one chip; a job that binds none shows no chip.
|
|
9212
|
+
|
|
9213
|
+
If a multi-environment binding is gated out, the run's failure banner names which environment and which rule rejected it (the same all-must-pass detail surfaced by `kici status`).
|
|
9214
|
+
|
|
8937
9215
|
### Secrets management
|
|
8938
9216
|
|
|
8939
9217
|
Secrets are individual encrypted values organized by scope paths (e.g., `aws/prod`, `databases/postgres`). Scopes are bound to environments via bindings:
|
|
@@ -9957,11 +10235,34 @@ statement's build context must match the token's identity claims (a mismatch is
|
|
|
9957
10235
|
a hard failure).
|
|
9958
10236
|
|
|
9959
10237
|
```bash
|
|
9960
|
-
kici verify-attestation [artifact] --bundle <path-or-url> --trust-root <url-or-file>
|
|
10238
|
+
kici verify-attestation [artifact] --bundle <path-or-url> [--trust-root <url-or-file>]
|
|
9961
10239
|
```
|
|
9962
10240
|
|
|
9963
|
-
|
|
9964
|
-
|
|
10241
|
+
### Which trust root do I use?
|
|
10242
|
+
|
|
10243
|
+
The trust root is the **KiCI platform's provenance issuer** — the same hosted
|
|
10244
|
+
KiCI platform you `kici login` against. KiCI attestations are issued by, and
|
|
10245
|
+
verified against, that one issuer; there are no competing "roots" to choose
|
|
10246
|
+
between. So the answer to "shouldn't I just use KiCI as the trust root?" is yes
|
|
10247
|
+
— and that's the **default**: omit `--trust-root` and the verifier checks the
|
|
10248
|
+
bundle against the hosted KiCI platform automatically. You only pass
|
|
10249
|
+
`--trust-root` to verify against a different environment or, more commonly, an
|
|
10250
|
+
offline `{ issuer, jwks }` file for air-gapped checks.
|
|
10251
|
+
|
|
10252
|
+
### Why you supply it out-of-band
|
|
10253
|
+
|
|
10254
|
+
Given there's a single issuer, why pass it at all instead of letting the
|
|
10255
|
+
verifier read it from the token? Because the issuer named **inside** a token
|
|
10256
|
+
cannot be trusted: a forged bundle could carry a token that names
|
|
10257
|
+
`iss: https://attacker.example` _and_ bundle a key set that "verifies" it,
|
|
10258
|
+
making the whole signature chain circular and self-attesting. The verifier
|
|
10259
|
+
therefore pins to an issuer you supply out-of-band and checks the token against
|
|
10260
|
+
_that_ — the bundle is verified against a key set you trust, not one it shipped
|
|
10261
|
+
with. Naming the trust root is a security requirement, not a multiple-choice
|
|
10262
|
+
question.
|
|
10263
|
+
|
|
10264
|
+
To override the default, supply the trusted issuer via `--trust-root`, in one of
|
|
10265
|
+
two forms:
|
|
9965
10266
|
|
|
9966
10267
|
- **Online — an HTTPS issuer URL.** The verifier fetches
|
|
9967
10268
|
`<url>/.well-known/openid-configuration`, reads its `issuer` and `jwks_uri`,
|
|
@@ -9989,7 +10290,10 @@ when it does not (or on an error such as a missing flag or unreachable trust
|
|
|
9989
10290
|
root).
|
|
9990
10291
|
|
|
9991
10292
|
```bash
|
|
9992
|
-
#
|
|
10293
|
+
# Default: verify against the hosted KiCI platform (no --trust-root needed):
|
|
10294
|
+
kici verify-attestation ./dist/app.tgz --bundle ./app.tgz.kici.json
|
|
10295
|
+
|
|
10296
|
+
# Override the trust root to verify against a specific issuer:
|
|
9993
10297
|
kici verify-attestation ./dist/app.tgz \
|
|
9994
10298
|
--bundle ./app.tgz.kici.json \
|
|
9995
10299
|
--trust-root https://platform.example/issuer
|
|
@@ -10028,6 +10332,44 @@ attestations shows an empty state.
|
|
|
10028
10332
|
|
|
10029
10333
|
<!-- /help:run-attestations -->
|
|
10030
10334
|
|
|
10335
|
+
## Browsing attestations across runs
|
|
10336
|
+
|
|
10337
|
+
The **Attestations** page (in the org sidebar) lists every build-provenance
|
|
10338
|
+
attestation your organization has produced — not just one run's. It is the
|
|
10339
|
+
supply-chain audit surface: look up "who built `sha256:…`?" by digest, or browse
|
|
10340
|
+
and filter every attestation across all runs.
|
|
10341
|
+
|
|
10342
|
+
<!-- help:attestations-list#browsing-attestations-across-runs -->
|
|
10343
|
+
|
|
10344
|
+
The **Attestations** page lists every build-provenance attestation your organization has produced.
|
|
10345
|
+
|
|
10346
|
+
- **Search** by artifact digest (exact `sha256:…`) or name to trace a specific artifact.
|
|
10347
|
+
- **Filter** by verification status, repository, workflow, job, or date.
|
|
10348
|
+
- Each row's **status badge** is the verdict KiCI recorded when the attestation was produced (`verified`, `failed`, `unverifiable`, or `pending`).
|
|
10349
|
+
|
|
10350
|
+
Open a row for the parsed provenance statement and a live re-verification.
|
|
10351
|
+
|
|
10352
|
+
<!-- /help:attestations-list -->
|
|
10353
|
+
|
|
10354
|
+
The status badge here is the **server-side verdict**, computed once when the
|
|
10355
|
+
attestation was recorded (verify-at-ingest) — so the list stays fast at any
|
|
10356
|
+
size. `verified` means the signature, build identity, and build context all
|
|
10357
|
+
checked out against the provenance issuer; `failed` means verification ran and
|
|
10358
|
+
the bundle did not pass; `unverifiable` means no verdict could be computed (no
|
|
10359
|
+
provenance issuer configured, or its keys could not be read — not a forgery
|
|
10360
|
+
signal); `pending` means the verdict has not been computed yet.
|
|
10361
|
+
|
|
10362
|
+
Opening a row leads to the **attestation detail page**:
|
|
10363
|
+
|
|
10364
|
+
<!-- help:attestation-detail#browsing-attestations-across-runs -->
|
|
10365
|
+
|
|
10366
|
+
This page shows the parsed provenance for one attestation.
|
|
10367
|
+
|
|
10368
|
+
- **Builder identity, source, and build type** come from the signed SLSA statement.
|
|
10369
|
+
- The **stored badge** is the verdict recorded at build time; **Re-verify** runs the check live in your browser against the current signing keys.
|
|
10370
|
+
- **Download** exports the signed bundle for offline verification with `kici verify-attestation`.
|
|
10371
|
+
<!-- /help:attestation-detail -->
|
|
10372
|
+
|
|
10031
10373
|
## See also
|
|
10032
10374
|
|
|
10033
10375
|
- [SDK runtime reference](https://docs.kici.dev/user/sdk/runtime/) — the `ctx.attestProvenance` and
|
|
@@ -10049,6 +10391,8 @@ Secrets are managed per-environment in the orchestrator (see [operator docs](htt
|
|
|
10049
10391
|
|
|
10050
10392
|
This design prevents accidental secret leakage through child processes, log output, or error messages. Only secrets you explicitly request are loaded into memory.
|
|
10051
10393
|
|
|
10394
|
+
A job can bind several environments with `environments: ['staging', 'my-testing']`; the secret keys from all bound environments are merged in array order, with a later environment's value winning on a key collision. See [Multiple environments per job](https://docs.kici.dev/user/environments/#multiple-environments-per-job).
|
|
10395
|
+
|
|
10052
10396
|
## Where secret values come from
|
|
10053
10397
|
|
|
10054
10398
|
Secret values are written either through the dashboard or through `kici-admin` running against the orchestrator. The orchestrator operator decides — per organization — which surface accepts secret writes. From the workflow author's perspective, the resolution path at run time is identical either way; the difference is where you (or your ops team) **enter** the value.
|
|
@@ -11520,7 +11864,7 @@ Source: https://docs.kici.dev/architecture/data-flows/
|
|
|
11520
11864
|
|
|
11521
11865
|
This document describes the key data flows through the KiCI architecture: webhook delivery, job execution, developer-initiated remote runs, dependency caching, re-run and cancel, trace ID propagation, internal event routing, and generic webhook ingestion.
|
|
11522
11866
|
|
|
11523
|
-
> **Lock file schema version:** The lock file uses schema version
|
|
11867
|
+
> **Lock file schema version:** The lock file uses schema version 29. The orchestrator rejects any fetched lock whose `schemaVersion` does not exactly match the engine version it was built against, so a stale lock must be recompiled with `kici compile` and pushed again after any SDK upgrade that bumps the schema.
|
|
11524
11868
|
|
|
11525
11869
|
## Webhook delivery flow
|
|
11526
11870
|
|
|
@@ -11726,7 +12070,7 @@ Dep cache misses alone do **not** trigger a build job. Deps are platform-specifi
|
|
|
11726
12070
|
|
|
11727
12071
|
### Cross-source / no-contentHash workflows
|
|
11728
12072
|
|
|
11729
|
-
- **Lock files without `contentHash`** (schema v1) skip the source cache entirely; agents compile from source. Regenerate lock files with `kici compile` to enable caching. The current lock file schema version is
|
|
12073
|
+
- **Lock files without `contentHash`** (schema v1) skip the source cache entirely; agents compile from source. Regenerate lock files with `kici compile` to enable caching. The current lock file schema version is 29.
|
|
11730
12074
|
- **Cross-source / global-workflow dispatch** (a workflow registered against source A fired by a webhook on source B) bypasses both caches. The registration's lock file entry still carries `contentHash`, but the cross-source path always clone-and-installs — the eval temp dir doesn't ship `@kici-dev/sdk`. The execution agent still verifies `contentHash` against the cloned source for drift detection.
|
|
11731
12075
|
|
|
11732
12076
|
### Build deduplication
|
|
@@ -12294,7 +12638,7 @@ The compiler processes the workflow definition:
|
|
|
12294
12638
|
|
|
12295
12639
|
### Execution time (local test runner)
|
|
12296
12640
|
|
|
12297
|
-
When `kici
|
|
12641
|
+
When `kici run local` runs a workflow:
|
|
12298
12642
|
|
|
12299
12643
|
1. **SDK module resolution:** The runner resolves `setStepOutputsMap` / `setJobOutputsMap` from the same `@kici-dev/sdk` module instance that the workflow uses (ensures the proxy reads from the same map)
|
|
12300
12644
|
2. **Map injection:** Fresh `OutputsMap` and `StepRefMap` are created and injected via `setStepOutputsMap()` / `setStepRefMap()` before each job
|