@kici-dev/compiler 0.1.27 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/headless-detect.d.ts +14 -5
- package/dist/auth/headless-detect.js +50 -9
- package/dist/cli.js +120 -11
- package/dist/commands/compile.js +28 -4
- package/dist/commands/diagnostics.js +14 -2
- package/dist/commands/doctor.d.ts +64 -0
- package/dist/commands/doctor.js +413 -0
- package/dist/commands/endpoints.js +6 -0
- package/dist/commands/fixture.js +13 -0
- package/dist/commands/hook.js +3 -2
- package/dist/commands/index.d.ts +8 -0
- package/dist/commands/index.js +5 -1
- package/dist/commands/init-host-os.d.ts +34 -0
- package/dist/commands/init-host-os.js +44 -0
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.js +159 -36
- package/dist/commands/local.d.ts +28 -2
- package/dist/commands/local.js +74 -5
- package/dist/commands/login.js +1 -1
- package/dist/commands/notifications.d.ts +61 -0
- package/dist/commands/notifications.js +274 -0
- package/dist/commands/preview.js +8 -1
- package/dist/commands/run-routed.js +10 -1
- package/dist/commands/run.js +41 -12
- package/dist/commands/runs/artifacts/download.d.ts +24 -0
- package/dist/commands/runs/artifacts/download.js +154 -0
- package/dist/commands/runs/artifacts/list.d.ts +5 -0
- package/dist/commands/runs/artifacts/list.js +47 -0
- package/dist/commands/runs/cancel.js +2 -2
- package/dist/commands/runs/list.js +8 -2
- package/dist/commands/verify-attestation.d.ts +3 -1
- package/dist/commands/verify-attestation.js +18 -7
- package/dist/errors/formatter.d.ts +14 -1
- package/dist/errors/formatter.js +13 -3
- package/dist/errors/index.d.ts +2 -1
- package/dist/errors/index.js +3 -2
- package/dist/errors/source-location.d.ts +20 -0
- package/dist/errors/source-location.js +45 -0
- package/dist/execution/executor.js +25 -5
- package/dist/fixtures/defaults/index.js +2 -1
- package/dist/llm-context/llms-architecture.txt +51 -22
- package/dist/llm-context/llms-cli.txt +2461 -1582
- package/dist/llm-context/llms-features.txt +178 -106
- package/dist/llm-context/llms-full.txt +6127 -4426
- package/dist/llm-context/llms-getting-started.txt +306 -42
- package/dist/llm-context/llms-patterns.txt +13 -7
- package/dist/llm-context/llms-sdk-runtime.txt +2013 -0
- package/dist/llm-context/llms-sdk.txt +591 -2152
- package/dist/llm-context/llms.txt +30 -16
- package/dist/local-plane/orchestrator-process.d.ts +12 -7
- package/dist/local-plane/orchestrator-process.js +28 -14
- package/dist/local-plane/os-mismatch-hint.d.ts +16 -0
- package/dist/local-plane/os-mismatch-hint.js +34 -0
- package/dist/local-plane/plane-liveness.d.ts +68 -0
- package/dist/local-plane/plane-liveness.js +145 -0
- package/dist/local-plane/plane-manager.d.ts +60 -18
- package/dist/local-plane/plane-manager.js +210 -70
- package/dist/local-plane/plane-trigger.d.ts +13 -4
- package/dist/local-plane/plane-trigger.js +27 -14
- package/dist/local-plane/platform-attach.js +1 -5
- package/dist/local-plane/port-holder.d.ts +78 -0
- package/dist/local-plane/port-holder.js +227 -0
- package/dist/local-plane/postgres.d.ts +15 -3
- package/dist/local-plane/postgres.js +34 -12
- package/dist/local-plane/run-follow.d.ts +20 -0
- package/dist/local-plane/run-follow.js +51 -4
- package/dist/local-plane/scaler-config.d.ts +28 -14
- package/dist/local-plane/scaler-config.js +59 -41
- package/dist/local-plane/source-provider.js +4 -10
- package/dist/lockfile/generator.d.ts +14 -1
- package/dist/lockfile/generator.js +99 -33
- package/dist/lockfile/index.d.ts +3 -1
- package/dist/lockfile/index.js +3 -2
- package/dist/lockfile/purity-diagnostics.d.ts +31 -0
- package/dist/lockfile/purity-diagnostics.js +52 -0
- package/dist/postinstall.js +2 -1
- package/dist/remote/artifact-extract.d.ts +8 -0
- package/dist/remote/artifact-extract.js +58 -0
- package/dist/remote/config.d.ts +21 -3
- package/dist/remote/config.js +24 -5
- package/dist/remote/dashboard-client.d.ts +39 -2
- package/dist/remote/dashboard-client.js +47 -4
- package/dist/remote/fs-case.d.ts +21 -0
- package/dist/remote/fs-case.js +45 -0
- package/dist/remote/history.d.ts +9 -3
- package/dist/remote/history.js +79 -10
- package/dist/remote/local-repo-identity.d.ts +1 -1
- package/dist/remote/local-repo-identity.js +2 -1
- package/dist/remote/notifications-client.d.ts +149 -0
- package/dist/remote/notifications-client.js +103 -0
- package/dist/remote/oauth.d.ts +13 -0
- package/dist/remote/oauth.js +31 -5
- package/dist/remote/output/summary.js +76 -14
- package/dist/remote/render.js +30 -9
- package/dist/remote/uploader.js +5 -4
- package/dist/templates/agents-md.d.ts +1 -1
- package/dist/templates/agents-md.js +6 -6
- package/dist/templates/index.d.ts +1 -1
- package/dist/templates/index.js +2 -2
- package/dist/templates/package-json.d.ts +15 -0
- package/dist/templates/package-json.js +26 -5
- package/dist/test-runner/dry-run.d.ts +2 -1
- package/dist/test-runner/dry-run.js +18 -1
- package/dist/test-runner/event-types.d.ts +2 -0
- package/dist/test-runner/event-types.js +3 -0
- package/dist/test-runner/job-executor.d.ts +1 -0
- package/dist/test-runner/job-executor.js +81 -43
- package/dist/test-runner/output-formatter.d.ts +5 -2
- package/dist/test-runner/output-formatter.js +6 -4
- package/dist/test-runner/payload-builder.d.ts +7 -1
- package/dist/test-runner/payload-builder.js +11 -2
- package/dist/test-runner/rule-evaluator.d.ts +7 -3
- package/dist/test-runner/rule-evaluator.js +13 -12
- package/dist/test-runner/step-context.d.ts +23 -5
- package/dist/test-runner/step-context.js +28 -118
- package/dist/types.d.ts +21 -2
- package/dist/types.js +4 -2
- package/dist/validation/index.d.ts +2 -0
- package/dist/validation/index.js +2 -1
- package/dist/validation/typecheck.d.ts +28 -0
- package/dist/validation/typecheck.js +110 -0
- package/dist/validation/validator.d.ts +9 -4
- package/dist/validation/validator.js +38 -44
- package/package.json +12 -15
- package/sbom.spdx.json +1322 -1964
- package/dist/assets/api-TJJVHrjC.json +0 -118
- package/dist/assets/descriptor-BTtjzN9L.json +0 -1382
- package/dist/assets/package-BpQF9kR8.json +0 -74
- package/dist/assets/package-Ceo2h27X.json +0 -89
- package/dist/assets/source_context-D0atuL28.json +0 -20
- package/dist/assets/type-BFqO8SCZ.json +0 -202
- package/dist/commands/cancel.d.ts +0 -22
- package/dist/commands/detect-package-manager.d.ts +0 -42
- package/dist/commands/held-run-resolve.d.ts +0 -50
- package/dist/commands/status.d.ts +0 -34
- package/dist/commands/test.d.ts +0 -88
- package/dist/errors/codes.d.ts +0 -25
- package/dist/local-executor/dag-scheduler.d.ts +0 -44
- package/dist/local-executor/index.d.ts +0 -23
- package/dist/local-executor/job-runner.d.ts +0 -47
- package/dist/local-executor/materializer.d.ts +0 -44
- package/dist/local-executor/output-streamer.d.ts +0 -31
- package/dist/local-executor/payload-generator.d.ts +0 -16
- package/dist/local-executor/picker.d.ts +0 -33
- package/dist/local-executor/runs-on-display.d.ts +0 -9
- package/dist/local-executor/secret-loader.d.ts +0 -18
- package/dist/local-executor/to-event-payload.d.ts +0 -16
- package/dist/local-executor/types.d.ts +0 -93
- package/dist/local-executor/workflow-lock.d.ts +0 -82
- package/dist/package-F7UXSDHW.json +0 -74
- package/dist/remote/client.d.ts +0 -210
- package/dist/remote/observer.d.ts +0 -81
- package/dist/test-runner/summary.d.ts +0 -7
|
@@ -101,13 +101,13 @@ When the run reaches this job, it is held instead of dispatched. The held run ap
|
|
|
101
101
|
job('deploy', {
|
|
102
102
|
runsOn: 'default',
|
|
103
103
|
approval: true,
|
|
104
|
-
steps: [
|
|
105
|
-
/* ... */
|
|
106
|
-
],
|
|
104
|
+
steps: [/* ... */],
|
|
107
105
|
});
|
|
108
106
|
```
|
|
109
107
|
|
|
110
|
-
`approval: true` holds the element until **any** org member who can act on approvals signs off — anyone with
|
|
108
|
+
`approval: true` holds the element until **any** org member who can act on approvals signs off — anyone with `contexts:write`, since an `approval` gate always raises a reviewer hold. Use it when you want a manual gate without restricting who may release it.
|
|
109
|
+
|
|
110
|
+
A **security** hold is different: it is raised by the CI trust pipeline (an unknown contributor, a fork PR, a workflow-modifying PR), never by `approval`, and releasing one requires `ci_trust:write`. See [Approval gates (operator guide)](https://docs.kici.dev/operator/approvals/#who-may-approve).
|
|
111
111
|
|
|
112
112
|
### Approver list (AND)
|
|
113
113
|
|
|
@@ -135,15 +135,17 @@ approval: {
|
|
|
135
135
|
},
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
-
| Field | Type | Description
|
|
139
|
-
| ----------- | --------------------- |
|
|
140
|
-
| `when` | `'always' \| 'drift'` | When the gate fires. `'always'` (default) gates before the element; `'drift'` gates a check/apply step only when it finds drift. See [Drift gates](https://docs.kici.dev/user/approvals/#drift-gates-whendrift).
|
|
141
|
-
| `approvers` | `ApproverClause[]` | The AND list of `{ team }` / `{ user }` clauses. An empty list means "any approval-capable member".
|
|
142
|
-
| `reason` | `string` | A human-readable label shown in the dashboard queue and the held-for-approval status check.
|
|
143
|
-
| `timeout` | `number` | Per-gate expiry in **seconds**, overriding the org default. On expiry the element is rejected.
|
|
138
|
+
| Field | Type | Description |
|
|
139
|
+
| ----------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
140
|
+
| `when` | `'always' \| 'drift'` | When the gate fires. `'always'` (default) gates before the element; `'drift'` gates a check/apply step only when it finds drift. See [Drift gates](https://docs.kici.dev/user/approvals/#drift-gates-whendrift). |
|
|
141
|
+
| `approvers` | `ApproverClause[]` | The AND list of `{ team }` / `{ user }` clauses. An empty list means "any approval-capable member". |
|
|
142
|
+
| `reason` | `string` | A human-readable label shown in the dashboard queue and the held-for-approval status check. |
|
|
143
|
+
| `timeout` | `number` | Per-gate expiry in **seconds**, overriding the org default. Must be a **positive integer** number of seconds; a non-positive or non-finite value is rejected at compile time. On expiry the element is rejected. |
|
|
144
144
|
|
|
145
145
|
When `timeout` is omitted, the gate uses the org's default approval expiry (set by the operator). On expiry, the held element is rejected and the run fails — see [expiry](https://docs.kici.dev/operator/approvals/#expiry).
|
|
146
146
|
|
|
147
|
+
A `timeout` that is zero, negative, or non-finite (for example a computed `minutes * 60` where `minutes` is `0`) fails `kici compile` with a clear author-facing error, so a misconfigured gate can never silently expire the moment it is created. If an orchestrator ever receives such a value from a hand-edited lock file, the run fails fast with an **Approval gate misconfigured** init-failure rather than dispatching ungated.
|
|
148
|
+
|
|
147
149
|
## Granularity
|
|
148
150
|
|
|
149
151
|
The same `approval` field is accepted on a workflow, a job, and a step.
|
|
@@ -168,9 +170,7 @@ A job-level gate holds just that job; other jobs in the run proceed normally:
|
|
|
168
170
|
job('publish', {
|
|
169
171
|
runsOn: 'default',
|
|
170
172
|
approval: [{ team: 'leads' }],
|
|
171
|
-
steps: [
|
|
172
|
-
/* ... */
|
|
173
|
-
],
|
|
173
|
+
steps: [/* ... */],
|
|
174
174
|
});
|
|
175
175
|
```
|
|
176
176
|
|
|
@@ -241,14 +241,14 @@ kici approve <run-id>
|
|
|
241
241
|
# Approve a held job
|
|
242
242
|
kici approve <run-id> --job deploy-production
|
|
243
243
|
|
|
244
|
-
# Approve a held step
|
|
245
|
-
kici approve <run-id> --job migrate-and-deploy --step
|
|
244
|
+
# Approve a held step (--step takes the step's zero-based index within the job)
|
|
245
|
+
kici approve <run-id> --job migrate-and-deploy --step 1
|
|
246
246
|
|
|
247
247
|
# Reject (a reason is required)
|
|
248
248
|
kici reject <run-id> --job deploy-production --reason "Wrong release branch"
|
|
249
249
|
```
|
|
250
250
|
|
|
251
|
-
You must be eligible for at least one unsatisfied clause — being a member of a named team or being a named user. The orchestrator verifies eligibility against the operator-defined teams, so naming a team in your workflow can never let an ineligible person release the gate. The command reports whether the element was released, how many clauses remain, or that it was rejected. See [`kici approve`](https://docs.kici.dev/user/cli-
|
|
251
|
+
You must be eligible for at least one unsatisfied clause — being a member of a named team or being a named user. The orchestrator verifies eligibility against the operator-defined teams, so naming a team in your workflow can never let an ineligible person release the gate. The command reports whether the element was released, how many clauses remain, or that it was rejected. See [`kici approve`](https://docs.kici.dev/user/cli/runs-and-approvals/#kici-approve) for the full command reference.
|
|
252
252
|
|
|
253
253
|
### Inline approval and `--approve-all` in `kici run remote`
|
|
254
254
|
|
|
@@ -357,9 +357,7 @@ workflow('deploy', {
|
|
|
357
357
|
group: (ctx) => `deploy-${ctx.branch}`,
|
|
358
358
|
cancelInProgress: true,
|
|
359
359
|
},
|
|
360
|
-
jobs: [
|
|
361
|
-
/* ... */
|
|
362
|
-
],
|
|
360
|
+
jobs: [/* ... */],
|
|
363
361
|
});
|
|
364
362
|
```
|
|
365
363
|
|
|
@@ -383,9 +381,7 @@ workflow('migrate-db', {
|
|
|
383
381
|
cancelInProgress: false,
|
|
384
382
|
max: 1,
|
|
385
383
|
},
|
|
386
|
-
jobs: [
|
|
387
|
-
/* ... */
|
|
388
|
-
],
|
|
384
|
+
jobs: [/* ... */],
|
|
389
385
|
});
|
|
390
386
|
```
|
|
391
387
|
|
|
@@ -403,9 +399,7 @@ workflow('test', {
|
|
|
403
399
|
cancelInProgress: false,
|
|
404
400
|
max: 3,
|
|
405
401
|
},
|
|
406
|
-
jobs: [
|
|
407
|
-
/* ... */
|
|
408
|
-
],
|
|
402
|
+
jobs: [/* ... */],
|
|
409
403
|
});
|
|
410
404
|
```
|
|
411
405
|
|
|
@@ -425,9 +419,7 @@ workflow('deploy', {
|
|
|
425
419
|
job('deploy-staging', {
|
|
426
420
|
runsOn: 'linux',
|
|
427
421
|
context: 'staging',
|
|
428
|
-
steps: [
|
|
429
|
-
/* ... */
|
|
430
|
-
],
|
|
422
|
+
steps: [/* ... */],
|
|
431
423
|
}),
|
|
432
424
|
],
|
|
433
425
|
});
|
|
@@ -442,9 +434,7 @@ workflow('migrate', {
|
|
|
442
434
|
group: () => 'db-migration',
|
|
443
435
|
cancelInProgress: false,
|
|
444
436
|
},
|
|
445
|
-
jobs: [
|
|
446
|
-
/* ... */
|
|
447
|
-
],
|
|
437
|
+
jobs: [/* ... */],
|
|
448
438
|
});
|
|
449
439
|
```
|
|
450
440
|
|
|
@@ -460,9 +450,7 @@ workflow('deploy', {
|
|
|
460
450
|
},
|
|
461
451
|
cancelInProgress: true,
|
|
462
452
|
},
|
|
463
|
-
jobs: [
|
|
464
|
-
/* ... */
|
|
465
|
-
],
|
|
453
|
+
jobs: [/* ... */],
|
|
466
454
|
});
|
|
467
455
|
```
|
|
468
456
|
|
|
@@ -486,11 +474,11 @@ In addition to workflow-level concurrency, individual jobs can define their own
|
|
|
486
474
|
|
|
487
475
|
## Local execution
|
|
488
476
|
|
|
489
|
-
`kici run <event> --local`
|
|
477
|
+
`kici run <event> --local` is a real routed dispatch: your machine becomes an ephemeral agent behind the local dev plane, whose own orchestrator applies the same concurrency machinery described above. The `group` callback is evaluated agent-side against the simulated event, and `cancelInProgress` carries its usual semantics — `true` supersedes the older run in the group, `false` queues the newer one behind it.
|
|
490
478
|
|
|
491
|
-
Coordination is
|
|
479
|
+
Coordination is scoped to that plane. The plane's state (including its database) lives under `~/.kici/local/`, so enforcement is per-machine and per-user: running the same workflow on two different machines does not serialize across them. For cross-host enforcement (queueing across agents, dashboard visibility), use `kici run remote` against a deployed orchestrator.
|
|
492
480
|
|
|
493
|
-
|
|
481
|
+
See [`kici run <event> --local`](https://docs.kici.dev/user/cli/runs-and-approvals/#kici-run-event---local) for the rest of the local-run behavior, and [the local dev plane](https://docs.kici.dev/operator/orchestrator/local-dev-plane/) for the plane's state directory and lifecycle.
|
|
494
482
|
|
|
495
483
|
---
|
|
496
484
|
|
|
@@ -645,9 +633,7 @@ job('deploy', {
|
|
|
645
633
|
concurrencyGroup: 'production-api',
|
|
646
634
|
// Or dynamic:
|
|
647
635
|
// concurrencyGroup: (event) => `review-${event.payload.pull_request.number}`,
|
|
648
|
-
steps: [
|
|
649
|
-
/* ... */
|
|
650
|
-
],
|
|
636
|
+
steps: [/* ... */],
|
|
651
637
|
});
|
|
652
638
|
```
|
|
653
639
|
|
|
@@ -712,7 +698,7 @@ Require manual approval before a job can proceed:
|
|
|
712
698
|
Required reviewers: alice, bob
|
|
713
699
|
```
|
|
714
700
|
|
|
715
|
-
When reviewers are required, the job enters a "held" state. Reviewers can approve or reject via the dashboard, the [`kici approve`](https://docs.kici.dev/user/cli-
|
|
701
|
+
When reviewers are required, the job enters a "held" state. Reviewers can approve or reject via the dashboard, the [`kici approve`](https://docs.kici.dev/user/cli/runs-and-approvals/#kici-approve) command, or the API. Held runs expire after a configurable timeout.
|
|
716
702
|
|
|
717
703
|
This operator-set rule is the **mandatory** form of an approval gate. Workflow authors can also declare gates in code with `approval` at step, job, or workflow level — see [Approval gates](https://docs.kici.dev/user/approvals/). Both forms use the same held-element mechanism and the same queue.
|
|
718
704
|
|
|
@@ -753,14 +739,16 @@ See the [CI security architecture docs](https://docs.kici.dev/architecture/secur
|
|
|
753
739
|
|
|
754
740
|
### Security approval queue
|
|
755
741
|
|
|
756
|
-
When a PR is held for security review (
|
|
742
|
+
When a PR is held for security review — the org trust policy held it (a non-trusted contributor modified `.kici/` files, the PR came from a fork, or the contributor could not be resolved to a known identity), or a `minimumTrust` gate blocked the contributor — it enters the security approval queue. This is separate from the context approval queue: a security hold asks "is it safe to run this contributor's code at all?", while a context approval hold asks "should this job be promoted?". The two never cross — releasing a security hold needs `ci_trust:write` or higher, releasing a context approval hold needs `contexts:write` plus eligibility for one of the gate's clauses. See [Approval holds vs security holds](https://docs.kici.dev/architecture/approvals/#approval-holds-vs-security-holds) for the full comparison.
|
|
757
743
|
|
|
758
744
|
Held runs can be approved:
|
|
759
745
|
|
|
760
746
|
- Via the **dashboard** in Settings > CI trust > Approval queue
|
|
761
747
|
- Via a PR comment: `/kici approve` (commenter must have `ci_trust:write+`)
|
|
762
748
|
|
|
763
|
-
|
|
749
|
+
A hold raised by the org trust policy covers the whole PR and uses the org's approval expiry (default 72 hours). A `minimumTrust` hold is raised by a context rather than by the org policy, so it uses that context's own hold expiry (default one hour).
|
|
750
|
+
|
|
751
|
+
While the org trust policy is holding a pull request, your organization's global workflows do not run for it. Approving the hold releases that pull request's own workflows; it does not retroactively run the organization's global workflows for the event.
|
|
764
752
|
|
|
765
753
|
### Concurrency limits
|
|
766
754
|
|
|
@@ -771,6 +759,8 @@ Concurrency limit: 1
|
|
|
771
759
|
Strategy: queue (or cancel-pending)
|
|
772
760
|
```
|
|
773
761
|
|
|
762
|
+
The concurrency limit is a positive integer; leave it unset for unlimited concurrency.
|
|
763
|
+
|
|
774
764
|
- **queue** -- new jobs wait in a FIFO queue (with configurable timeout, default 1 hour)
|
|
775
765
|
- **cancel-pending** -- pending (queued) jobs are cancelled when the limit is reached
|
|
776
766
|
|
|
@@ -793,7 +783,7 @@ Each context has four tabs:
|
|
|
793
783
|
|
|
794
784
|
2. **Secrets** -- view bound secret scopes and their resolved secret count. Add bindings by specifying scope glob patterns (e.g., `aws/prod/**`).
|
|
795
785
|
|
|
796
|
-
3. **Protection** -- configure branch restrictions, required reviewers, wait timers, and concurrency limits with enable toggles for each section.
|
|
786
|
+
3. **Protection** -- configure branch restrictions, required reviewers, wait timers, and concurrency limits with enable toggles for each section. Turning a section's toggle off and saving clears that rule on the context, so the gate stops applying to new runs. Emptying the hold expiry field clears it too, and held runs fall back to the default one-hour hold window.
|
|
797
787
|
|
|
798
788
|
4. **History** -- view filtered runs targeting this context.
|
|
799
789
|
|
|
@@ -840,16 +830,17 @@ The KiCI dashboard is the browser interface for monitoring workflow runs, inspec
|
|
|
840
830
|
|
|
841
831
|
This guide is split across the following pages:
|
|
842
832
|
|
|
843
|
-
| Page | Covers
|
|
844
|
-
| ------------------------------------------------------------------------------------- |
|
|
845
|
-
| [Getting started](https://docs.kici.dev/user/dashboard/getting-started/) | Onboarding checklist and your organizations list
|
|
846
|
-
| [Navigation and layout](https://docs.kici.dev/user/dashboard/navigation/) | Sidebar, mobile nav, theme, time display, shortcuts, error pages
|
|
847
|
-
| [Runs and logs](https://docs.kici.dev/user/dashboard/runs/) | Run list, run detail, the log viewer
|
|
848
|
-
| [Settings](https://docs.kici.dev/user/dashboard/settings/) | Members, roles, teams, keys, sources, billing, security, support access
|
|
849
|
-
| [Workflows, diagnostics, and orchestrators](https://docs.kici.dev/user/dashboard/workflows-and-diagnostics/) | Registered workflows, infra health, per-cluster views
|
|
850
|
-
| [Contexts, secrets, and approvals](https://docs.kici.dev/user/dashboard/contexts-and-secrets/) | Contexts, secret scopes, approval queue
|
|
851
|
-
| [Activity and DLQ](https://docs.kici.dev/user/dashboard/activity-and-dlq/) | Forensic activity log and dead-letter queue
|
|
852
|
-
| [
|
|
833
|
+
| Page | Covers |
|
|
834
|
+
| ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
|
|
835
|
+
| [Getting started](https://docs.kici.dev/user/dashboard/getting-started/) | Onboarding checklist and your organizations list |
|
|
836
|
+
| [Navigation and layout](https://docs.kici.dev/user/dashboard/navigation/) | Sidebar, mobile nav, theme, time display, shortcuts, error pages |
|
|
837
|
+
| [Runs and logs](https://docs.kici.dev/user/dashboard/runs/) | Run list, run detail, the log viewer |
|
|
838
|
+
| [Settings](https://docs.kici.dev/user/dashboard/settings/) | Members, roles, teams, keys, sources, billing, security, support access |
|
|
839
|
+
| [Workflows, diagnostics, and orchestrators](https://docs.kici.dev/user/dashboard/workflows-and-diagnostics/) | Registered workflows, infra health, per-cluster views |
|
|
840
|
+
| [Contexts, secrets, and approvals](https://docs.kici.dev/user/dashboard/contexts-and-secrets/) | Contexts, secret scopes, approval queue |
|
|
841
|
+
| [Activity and DLQ](https://docs.kici.dev/user/dashboard/activity-and-dlq/) | Forensic activity log and dead-letter queue |
|
|
842
|
+
| [Notifications](https://docs.kici.dev/user/dashboard/notifications/) | Personal run notifications and org-wide channels, subscriptions, delivery log |
|
|
843
|
+
| [Account](https://docs.kici.dev/user/dashboard/account/) | Personal account settings |
|
|
853
844
|
|
|
854
845
|
---
|
|
855
846
|
|
|
@@ -865,9 +856,7 @@ job('deploy', {
|
|
|
865
856
|
context: (event) => event.targetBranch,
|
|
866
857
|
env: (event) => ({ BRANCH: event.targetBranch }),
|
|
867
858
|
concurrencyGroup: (event) => `deploy-${event.targetBranch}`,
|
|
868
|
-
steps: [
|
|
869
|
-
/* ... */
|
|
870
|
-
],
|
|
859
|
+
steps: [/* ... */],
|
|
871
860
|
});
|
|
872
861
|
```
|
|
873
862
|
|
|
@@ -876,9 +865,7 @@ job('deploy', {
|
|
|
876
865
|
runsOn: 'default',
|
|
877
866
|
// One shape everywhere: branch on the normalized event type.
|
|
878
867
|
context: (event) => (event.type === 'pull_request' ? 'preview' : 'production'),
|
|
879
|
-
steps: [
|
|
880
|
-
/* ... */
|
|
881
|
-
],
|
|
868
|
+
steps: [/* ... */],
|
|
882
869
|
});
|
|
883
870
|
```
|
|
884
871
|
|
|
@@ -923,7 +910,7 @@ context: (event) => {
|
|
|
923
910
|
|
|
924
911
|
### Impure functions (init-job evaluation)
|
|
925
912
|
|
|
926
|
-
If the compiler determines a function is impure, it
|
|
913
|
+
If the compiler determines a function is impure, it prints a `warning [W101]` naming the affected field (`context`, `env`, or `concurrencyGroup`), the reason the function was judged impure, and the ~5-10 second init-job cost — and compilation still succeeds. The function falls back to the two-phase init model. This means:
|
|
927
914
|
|
|
928
915
|
1. The orchestrator dispatches a special `__init__` job to a builder agent
|
|
929
916
|
2. The builder agent clones the repository and evaluates the function
|
|
@@ -932,6 +919,8 @@ If the compiler determines a function is impure, it emits a warning during compi
|
|
|
932
919
|
|
|
933
920
|
This adds approximately 5-10 seconds of overhead for cloning and evaluation.
|
|
934
921
|
|
|
922
|
+
`kici preview` lists the injected `__init__` job under each affected job, so you can spot the init-job cost before the first run.
|
|
923
|
+
|
|
935
924
|
**Examples of impure functions (will use init job):**
|
|
936
925
|
|
|
937
926
|
```typescript
|
|
@@ -965,8 +954,9 @@ env: async (event) => {
|
|
|
965
954
|
## Tips
|
|
966
955
|
|
|
967
956
|
- **Write pure functions whenever possible** to avoid the init-job delay. Most context and env computations only need the event payload data.
|
|
968
|
-
- **Check compiler warnings** -- the compiler
|
|
957
|
+
- **Check compiler warnings** -- the compiler prints a `warning [W101]` when a function is classified as impure, naming the reason and the ~5-10s init-job cost. Run `kici preview` to see the injected `__init__` job listed under each affected job before your first run.
|
|
969
958
|
- **Runtime errors in inline expressions cause immediate job failure.** There is no fallback to the init-job path. If your pure function throws at runtime (e.g., accessing a property on `undefined`), the job fails immediately.
|
|
959
|
+
- **See [how your workflow code executes](https://docs.kici.dev/user/execution-model/)** for the full picture of where pure vs. impure functions run relative to rules, hooks, and step bodies.
|
|
970
960
|
- **The event parameter is the normalized event envelope** — the same shape rules receive as `ctx.event`: `{ type, action, targetBranch, sourceBranch, changedFiles, payload, … }` (see the [event payload reference](https://docs.kici.dev/user/sdk/event-payloads/) for the complete schema). Narrow on `event.type` (`'push'`, `'pull_request'`, `'tag'`, …) to branch per trigger kind. The raw provider webhook body is nested at `event.payload` (for GitHub pushes: `payload.ref`, `payload.after`, `payload.repository`, …).
|
|
971
961
|
|
|
972
962
|
---
|
|
@@ -988,10 +978,10 @@ The KiCI CLI reads the following environment variables to customize its behavior
|
|
|
988
978
|
|
|
989
979
|
## Browser behavior
|
|
990
980
|
|
|
991
|
-
| Variable | Description | Default
|
|
992
|
-
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
993
|
-
| `KICI_BROWSER_CMD` | Custom browser command for OAuth login. Supports `{url}` placeholder. Set to `none` to suppress browser opening and print the URL to stdout instead. | Uses the system default browser
|
|
994
|
-
| `KICI_CALLBACK_PORT` | Fixed port for the OAuth PKCE callback server. Useful when firewall rules require a known port. | Random available port
|
|
981
|
+
| Variable | Description | Default |
|
|
982
|
+
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
|
|
983
|
+
| `KICI_BROWSER_CMD` | Custom browser command for OAuth login. Supports `{url}` placeholder. Set to `none` to suppress browser opening and print the URL to stdout instead. | Uses the system default browser |
|
|
984
|
+
| `KICI_CALLBACK_PORT` | Fixed port for the OAuth PKCE callback server. Useful when firewall rules require a known port. | Random available port |
|
|
995
985
|
|
|
996
986
|
## Development
|
|
997
987
|
|
|
@@ -1000,6 +990,35 @@ The KiCI CLI reads the following environment variables to customize its behavior
|
|
|
1000
990
|
| `KICI_DEV` | Enable development mode. When `true`, uses prerelease-compatible version ranges (`>=0.0.1-0`) for dev dependencies and skips npm version resolution. | unset |
|
|
1001
991
|
| `KICI_DEBUG` | Enable debug logging. When `true`, prints verbose diagnostics (SDK alias resolution, step-level debug logs, stack traces on errors). Equivalent to the `--debug` CLI flag. | unset |
|
|
1002
992
|
|
|
993
|
+
## Local dev plane
|
|
994
|
+
|
|
995
|
+
Read by the [local dev plane](https://docs.kici.dev/user/cli/authoring-and-local/#kici-local) that `kici run <event> --local` dispatches through.
|
|
996
|
+
|
|
997
|
+
| Variable | Description | Default |
|
|
998
|
+
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
|
999
|
+
| `KICI_LOCAL_ORCH_PORT` | Port the plane orchestrator listens on (HTTP + WebSocket). Change it when another process already holds the default. | `4319` |
|
|
1000
|
+
| `KICI_LOCAL_PG_PORT` | Port the plane's PostgreSQL listens on. | `45432` |
|
|
1001
|
+
| `KICI_LOCAL_PG_MODE` | Set to `podman` to force the container PostgreSQL fallback instead of the embedded binary. | Embedded PostgreSQL |
|
|
1002
|
+
| `KICI_LOCAL_ACCEPTANCE_TIMEOUT_MS` | How long a local run waits for an agent to claim its first job before failing fast. Raise it on a slow host; the run still fails quickly when no scaler label set matches `runsOn`. | `120000` (2 minutes) |
|
|
1003
|
+
|
|
1004
|
+
## CI detection
|
|
1005
|
+
|
|
1006
|
+
The CLI also reads the conventional CI markers your CI provider sets. They are not KiCI variables — KiCI only consumes them.
|
|
1007
|
+
|
|
1008
|
+
| Variable | Description | Default |
|
|
1009
|
+
| ---------------- | -------------------------------------------- | ------- |
|
|
1010
|
+
| `CI` | Generic CI marker. Set by most CI providers. | unset |
|
|
1011
|
+
| `GITHUB_ACTIONS` | Set to `true` by GitHub Actions. | unset |
|
|
1012
|
+
| `GITLAB_CI` | Set to `true` by GitLab CI/CD. | unset |
|
|
1013
|
+
|
|
1014
|
+
### How `CI` is interpreted
|
|
1015
|
+
|
|
1016
|
+
`kici` treats the environment as CI when `CI`, `GITHUB_ACTIONS`, or `GITLAB_CI` is set to any value other than an explicit opt-out. `0` and `false` are the opt-outs, compared case-insensitively, so `CI=0`, `CI=false`, and `CI=False` all mean "not CI". Surrounding whitespace is ignored, and a value that is empty or only whitespace (`CI=`) is treated as unset.
|
|
1017
|
+
|
|
1018
|
+
A vendor marker outranks the generic opt-out: `CI=false GITHUB_ACTIONS=true` is still CI, because an explicit vendor marker names a real runner rather than a preference.
|
|
1019
|
+
|
|
1020
|
+
This affects which login flow `kici login` chooses (browser vs device) and whether interactive commands such as `kici init` prompt.
|
|
1021
|
+
|
|
1003
1022
|
## Usage examples
|
|
1004
1023
|
|
|
1005
1024
|
### CI/CD environment
|
|
@@ -1007,7 +1026,7 @@ The KiCI CLI reads the following environment variables to customize its behavior
|
|
|
1007
1026
|
Authenticate with a pre-existing API key (no browser needed):
|
|
1008
1027
|
|
|
1009
1028
|
```bash
|
|
1010
|
-
kici login --token
|
|
1029
|
+
kici login --token "$KICI_API_KEY"
|
|
1011
1030
|
```
|
|
1012
1031
|
|
|
1013
1032
|
### Targeting another environment or custom OIDC provider
|
|
@@ -1383,11 +1402,11 @@ export const deployComplete = defineEvent(
|
|
|
1383
1402
|
);
|
|
1384
1403
|
```
|
|
1385
1404
|
|
|
1386
|
-
Then emit using the definition
|
|
1405
|
+
Then emit using the definition — the payload is checked against the schema:
|
|
1387
1406
|
|
|
1388
1407
|
```typescript
|
|
1389
1408
|
step('emit', async (ctx) => {
|
|
1390
|
-
await ctx.emit(deployComplete
|
|
1409
|
+
await ctx.emit(deployComplete, {
|
|
1391
1410
|
env: 'prod',
|
|
1392
1411
|
version: '1.2.3',
|
|
1393
1412
|
services: ['api', 'web'],
|
|
@@ -1442,7 +1461,7 @@ If you've only ever used per-repo workflows so far, start with the mental model
|
|
|
1442
1461
|
| Workflow repo | The repo whose `.kici/workflows/*.ts` file **declares** the global workflow. Holds the steps. Also known as the _authoring_ repo. |
|
|
1443
1462
|
| Source repo | The repo that **emits** the event (push / PR / tag / ...) that causes the global workflow to fire. The agent checks out this repo as the working copy. |
|
|
1444
1463
|
| Global | A workflow whose trigger carries one or more `repos:` glob patterns. The presence of `repos:` is what classifies a workflow as global. |
|
|
1445
|
-
| Authoring axis | Policy that answers "which repos may **author** global workflows?" Controlled by the allow-list in the dashboard's
|
|
1464
|
+
| Authoring axis | Policy that answers "which repos may **author** global workflows?" Controlled by the allow-list in the dashboard's _Allowed author repos_ setting. |
|
|
1446
1465
|
| Source axis | Policy that answers "which **source** repos' events are allowed to trigger global workflows?" Controlled by the deny-list in _Blocked source repos_. |
|
|
1447
1466
|
|
|
1448
1467
|
The two axes are independent. A global workflow fires only if it passes **both** — its authoring repo is allowed AND the source repo is not denied.
|
|
@@ -1497,7 +1516,7 @@ Global workflows are **opt-in per org**. In a fresh org, `repos:`-bearing workfl
|
|
|
1497
1516
|
|
|
1498
1517
|
| Setting | What it controls | Typical use |
|
|
1499
1518
|
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
|
1500
|
-
|
|
|
1519
|
+
| Allowed author repos | Restricts which repos can **author** (register) global workflows. Globs matched against the authoring repo identifier. When OFF, any repo in the org may author globals. | Lock authoring to `myorg/ci-*` so random product repos can't ship org-wide automation. |
|
|
1501
1520
|
| Blocked source repos | Blocks dispatch for events emitted from these **source** repos, regardless of authoring. Globs matched against the event source repo identifier. When OFF, events from any repo may trigger globals. | Protect against fork spam — e.g. `!myorg/*` via `myorg/fork-*`. |
|
|
1502
1521
|
| Elevated access | Authoring repos listed here get **read access to source-repo secrets** during execution. Globs matched against the authoring repo identifier. | A `myorg/ci-deploy` repo that needs to read a source repo's `NPM_TOKEN` to publish releases. |
|
|
1503
1522
|
|
|
@@ -1513,7 +1532,7 @@ The page is a two-state editor — changes are local until you click **Save chan
|
|
|
1513
1532
|
|
|
1514
1533
|
A global workflow fires only if:
|
|
1515
1534
|
|
|
1516
|
-
1. **The authoring repo is allowed.** If
|
|
1535
|
+
1. **The authoring repo is allowed.** If _Allowed author repos_ is ON, the workflow's authoring repo must match at least one allow-list glob. If OFF, any repo may author. Enforced at two points:
|
|
1517
1536
|
- At registration time (extraction from the lock file — non-matching globals are dropped with a warning).
|
|
1518
1537
|
- At dispatch time (defense-in-depth — policy changes after registration still take effect).
|
|
1519
1538
|
2. **The source repo is not denied.** If the event's source repo matches any glob in _Blocked source repos_, the global workflow is skipped. Enforced at dispatch time.
|
|
@@ -1615,7 +1634,7 @@ const configureNginx = step('configure-nginx', {
|
|
|
1615
1634
|
`summarize` is **required** whenever `check` is declared. `run` and `whenInSync`
|
|
1616
1635
|
both produce the same output type — one output shape per step, whichever path
|
|
1617
1636
|
runs. Every other step facet (`cache`, `rules`, `continueOnError`, `timeout`,
|
|
1618
|
-
`approval`, `onCancel`, `cleanup`, `outputs`) composes unchanged.
|
|
1637
|
+
`retry`, `approval`, `onCancel`, `cleanup`, `outputs`) composes unchanged.
|
|
1619
1638
|
|
|
1620
1639
|
A plain `step()` without `check` keeps its exact current behavior — the check
|
|
1621
1640
|
facet is fully optional.
|
|
@@ -1736,6 +1755,17 @@ The agent never writes the token bytes to your `.kici/.npmrc`. Each registry tok
|
|
|
1736
1755
|
|
|
1737
1756
|
After the install completes (success or failure), the agent restores the original `.kici/.npmrc` — your committed file is never permanently modified.
|
|
1738
1757
|
|
|
1758
|
+
### Package managers
|
|
1759
|
+
|
|
1760
|
+
The agent detects the package manager from the cloned repo — npm, pnpm, or yarn (classic and berry are both supported) — and applies the auth overlay the detected manager actually reads:
|
|
1761
|
+
|
|
1762
|
+
| Detected manager | Auth file the agent overlays | Notes |
|
|
1763
|
+
| ----------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1764
|
+
| npm, pnpm, yarn classic | `.kici/.npmrc` | Auth lines carry `${VAR}` references to the job-scoped token env vars. |
|
|
1765
|
+
| yarn berry (v2+) | `.kici/.yarnrc.yml` | Berry reads `.yarnrc.yml` instead of `.npmrc`, so the overlay uses berry's own registry/scope/auth keys with the same `${VAR}` indirection. |
|
|
1766
|
+
|
|
1767
|
+
Either file is restored on cleanup, exactly as described above.
|
|
1768
|
+
|
|
1739
1769
|
## Option C — committed `.kici/.npmrc` + `installEnv:`
|
|
1740
1770
|
|
|
1741
1771
|
If you'd rather hand-craft the `.npmrc`, commit it under `.kici/.npmrc` with `${VAR}` placeholders, then list each variable in the workflow's `installEnv:` block using the same qualified syntax as `tokenSecret`.
|
|
@@ -1891,8 +1921,8 @@ registries: [
|
|
|
1891
1921
|
## Security model
|
|
1892
1922
|
|
|
1893
1923
|
- **Per-context scoping.** Every `tokenSecret` and `installEnv` entry is qualified with a context name. The orchestrator runs the same protection-rule pipeline (branch / trust / concurrency / reviewer / wait-timer) against each named context **before** resolving any secret, so a workflow that wants a `production` token from a feature branch is rejected exactly like a job that tries to deploy to `production` from a feature branch. A reviewer-gated install context **pauses** the whole workflow dispatch as a workflow-scoped held run instead of resolving the token — see [Reviewer-gated installs](https://docs.kici.dev/user/private-registries/#reviewer-gated-installs) below.
|
|
1894
|
-
- **Untrusted contributors get no tokens.** When a fork PR is dispatched and the contributor-trust resolution returns anything other than `trusted`, the orchestrator strips both `npmRegistries` and `installEnvSecrets` out of the dispatch. The install runs without auth and fails naturally on the first private dep — fork PRs cannot ever observe a registry token, even if a misconfigured context lacks an explicit
|
|
1895
|
-
- **Lifecycle scripts disabled.** Whenever a private registry is in scope, the agent runs the install with `--ignore-scripts` (npm
|
|
1924
|
+
- **Untrusted contributors get no tokens.** When a fork PR is dispatched and the contributor-trust resolution returns anything other than `trusted`, the orchestrator strips both `npmRegistries` and `installEnvSecrets` out of the dispatch. The install runs without auth and fails naturally on the first private dep — fork PRs cannot ever observe a registry token, even if a misconfigured context lacks an explicit [minimum trust](https://docs.kici.dev/user/contexts/#minimum-trust) rule.
|
|
1925
|
+
- **Lifecycle scripts disabled.** Whenever a private registry is in scope, the agent runs the install with `--ignore-scripts` (npm, pnpm, and yarn classic alike; yarn berry gets the equivalent `enableScripts: false`). A malicious `preinstall` / `postinstall` hook in committed `package.json` cannot read the synthesized token env vars, even though they exist in the install subprocess. For a pnpm or yarn workspace, the agent builds your in-repo dependency closure as a separate step **after** the install's auth is torn down, so build scripts never see the tokens either.
|
|
1896
1926
|
- **Stderr is redacted.** If the install fails, the agent masks every token literal out of the surfaced stderr / stdout chunks before logging.
|
|
1897
1927
|
- **Job-scoped env-var names.** The synthesized auth env var is `KICI_NPM_TOKEN_<jobIdShort>_<i>` where `jobIdShort` is the first 8 chars of the dispatched job id. The name is unguessable from outside the install subprocess and not reused across jobs.
|
|
1898
1928
|
- **`.npmrc` restored.** Whatever the agent appended for one install is stripped (or the file unlinked) on cleanup, so the workspace is never permanently modified.
|
|
@@ -1956,13 +1986,20 @@ An attestation is a self-contained bundle holding three things:
|
|
|
1956
1986
|
commit, ref, workflow, run/job identifiers, timestamps).
|
|
1957
1987
|
- A **[DSSE](https://github.com/secure-systems-lab/dsse) signature** over that
|
|
1958
1988
|
statement, made with an ephemeral signing key generated for the run.
|
|
1959
|
-
- A short-lived **OIDC identity token** issued by
|
|
1960
|
-
the signature to the build identity. The token's identity claims
|
|
1961
|
-
(`repository`, `ref`, `sha`, run/job ids) are derived by the
|
|
1962
|
-
run itself — a step cannot forge them.
|
|
1989
|
+
- A short-lived **OIDC identity token** issued by your **orchestrator** that
|
|
1990
|
+
binds the signature to the build identity. The token's identity claims
|
|
1991
|
+
(`repository`, `ref`, `sha`, run/job ids) are derived by the orchestrator from
|
|
1992
|
+
the run itself — a step cannot forge them.
|
|
1993
|
+
|
|
1994
|
+
The orchestrator owns the provenance root of trust: it holds its own long-lived
|
|
1995
|
+
ES256 signing key, mints and signs the identity token **locally** from its own
|
|
1996
|
+
run records, and publishes its own OIDC discovery + public key set (JWKS). Builds
|
|
1997
|
+
therefore produce verifiable provenance with **no dependency on the hosted KiCI
|
|
1998
|
+
platform** — the availability, sovereignty, and air-gap story all follow from
|
|
1999
|
+
this.
|
|
1963
2000
|
|
|
1964
2001
|
Because the bundle carries the identity token and the public signing key, it is
|
|
1965
|
-
**offline-verifiable**: a verifier checks it against the
|
|
2002
|
+
**offline-verifiable**: a verifier checks it against the orchestrator's published
|
|
1966
2003
|
signing keys with no per-attestation online lookup.
|
|
1967
2004
|
|
|
1968
2005
|
## Attesting an artifact in a workflow
|
|
@@ -2011,8 +2048,11 @@ The identity token is fetched and masked in logs automatically — you never
|
|
|
2011
2048
|
handle it. The call returns `{ storageKey, subjectDigest, bundleMediaType }`
|
|
2012
2049
|
identifying the stored bundle.
|
|
2013
2050
|
|
|
2014
|
-
`ctx.attestProvenance` is only available inside a running job step
|
|
2015
|
-
|
|
2051
|
+
`ctx.attestProvenance` is only available inside a running job step; calling it
|
|
2052
|
+
outside one rejects with a clear error. `kici run --local` runs are supported:
|
|
2053
|
+
the offline local dev plane signs with a dev identity under the
|
|
2054
|
+
clearly-non-production issuer `kici-local`, and those bundles verify against a
|
|
2055
|
+
trust root exported with `kici local trust-root`.
|
|
2016
2056
|
|
|
2017
2057
|
### Requesting a raw identity token
|
|
2018
2058
|
|
|
@@ -2029,11 +2069,11 @@ step('mint', async (ctx) => {
|
|
|
2029
2069
|
|
|
2030
2070
|
The token is a short-lived (about 10 minutes) signed JWT scoped to the current
|
|
2031
2071
|
run and job. Its identity claims (`repository`, `ref`, `sha`, `kici_run_id`,
|
|
2032
|
-
`kici_job_id`) are derived by the
|
|
2033
|
-
spoof them. The returned token value is automatically masked in step logs,
|
|
2034
|
-
the step never holds
|
|
2035
|
-
|
|
2036
|
-
|
|
2072
|
+
`kici_job_id`) are derived by the orchestrator from the run context, so a step
|
|
2073
|
+
cannot spoof them. The returned token value is automatically masked in step logs,
|
|
2074
|
+
and the step never holds signing credentials — the orchestrator mints and signs
|
|
2075
|
+
the token on the step's behalf from its own run records. Like `attestProvenance`,
|
|
2076
|
+
it is only available inside a running job step.
|
|
2037
2077
|
|
|
2038
2078
|
## Verifying an attestation
|
|
2039
2079
|
|
|
@@ -2049,14 +2089,27 @@ kici verify-attestation [artifact] --bundle <path-or-url> [--trust-root <url-or-
|
|
|
2049
2089
|
|
|
2050
2090
|
### Which trust root do I use?
|
|
2051
2091
|
|
|
2052
|
-
The trust root is
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2092
|
+
The trust root is **your orchestrator's provenance issuer** — the orchestrator
|
|
2093
|
+
you `kici login` against, which owns the provenance signing key and publishes its
|
|
2094
|
+
own JWKS. That is the **default**: omit `--trust-root` and the verifier checks the
|
|
2095
|
+
bundle against your configured orchestrator automatically. There are three ways to
|
|
2096
|
+
verify, and offline is always the primary one:
|
|
2097
|
+
|
|
2098
|
+
1. **Offline against a JWKS / trust-root file (air-gap)** — export the
|
|
2099
|
+
`{ issuer, jwks }` file once with `kici-admin signing-key export --public` and
|
|
2100
|
+
verify against it with `--trust-root <file>`. No network needed at verify time.
|
|
2101
|
+
2. **Directly online against your orchestrator** — the default: the verifier
|
|
2102
|
+
resolves your orchestrator's discovery → JWKS. You can also POST a bundle to
|
|
2103
|
+
the orchestrator's native `POST /v1/verify-attestation` endpoint for a verdict
|
|
2104
|
+
against its live keys (fresh rotations / revocations included).
|
|
2105
|
+
3. **Against the hosted KiCI platform** — bundles produced before your
|
|
2106
|
+
orchestrator owned signing were signed by the hosted platform; those keep
|
|
2107
|
+
verifying forever. When no orchestrator is configured, the default falls back
|
|
2108
|
+
to the hosted platform's issuer so those historical bundles still verify with
|
|
2109
|
+
no flag.
|
|
2110
|
+
|
|
2111
|
+
You pass `--trust-root` to verify against a different environment or, most
|
|
2112
|
+
commonly, an offline `{ issuer, jwks }` file for air-gapped checks.
|
|
2060
2113
|
|
|
2061
2114
|
### Why you supply it out-of-band
|
|
2062
2115
|
|
|
@@ -2099,7 +2152,7 @@ when it does not (or on an error such as a missing flag or unreachable trust
|
|
|
2099
2152
|
root).
|
|
2100
2153
|
|
|
2101
2154
|
```bash
|
|
2102
|
-
# Default: verify against
|
|
2155
|
+
# Default: verify against your configured orchestrator (no --trust-root needed):
|
|
2103
2156
|
kici verify-attestation ./dist/app.tgz --bundle ./app.tgz.kici.json
|
|
2104
2157
|
|
|
2105
2158
|
# Override the trust root to verify against a specific issuer:
|
|
@@ -2113,7 +2166,7 @@ kici verify-attestation ./dist/app.tgz \
|
|
|
2113
2166
|
--trust-root ./kici-trust-root.json
|
|
2114
2167
|
```
|
|
2115
2168
|
|
|
2116
|
-
The full flag reference is in the [CLI reference](https://docs.kici.dev/user/cli-
|
|
2169
|
+
The full flag reference is in the [CLI reference](https://docs.kici.dev/user/cli/notifications-and-diagnostics/#kici-verify-attestation).
|
|
2117
2170
|
|
|
2118
2171
|
## Viewing attestations in the dashboard
|
|
2119
2172
|
|
|
@@ -2155,6 +2208,7 @@ The **Attestations** page lists every build-provenance attestation your organiza
|
|
|
2155
2208
|
- **Search** by artifact digest (exact `sha256:…`) or name to trace a specific artifact.
|
|
2156
2209
|
- **Filter** by verification status, repository, workflow, job, or date.
|
|
2157
2210
|
- Each row's **status badge** is the verdict KiCI recorded when the attestation was produced (`verified`, `failed`, `unverifiable`, or `pending`).
|
|
2211
|
+
- **Retry** on a `pending` row asks your orchestrator to mint that run's outstanding attestations now; **Retry pending** does the same for every pending run at once.
|
|
2158
2212
|
|
|
2159
2213
|
Open a row for the parsed provenance statement and a live re-verification.
|
|
2160
2214
|
|
|
@@ -2168,6 +2222,19 @@ the bundle did not pass; `unverifiable` means no verdict could be computed (no
|
|
|
2168
2222
|
provenance issuer configured, or its keys could not be read — not a forgery
|
|
2169
2223
|
signal); `pending` means the verdict has not been computed yet.
|
|
2170
2224
|
|
|
2225
|
+
A `pending` row is one still waiting to be minted — the attestation was signed
|
|
2226
|
+
at build time, but attaching its identity token has not completed yet. Those
|
|
2227
|
+
rows carry a **Retry** button that asks your orchestrator to mint that run's
|
|
2228
|
+
outstanding attestations immediately, and the page header offers **Retry
|
|
2229
|
+
pending** to do the same across every pending run. Only one retry runs at a
|
|
2230
|
+
time — the other retry buttons are unavailable until it finishes.
|
|
2231
|
+
|
|
2232
|
+
Retrying is safe to repeat while the mint is only temporarily unavailable: the
|
|
2233
|
+
row stays pending and the next retry tries again. A mint that is definitively
|
|
2234
|
+
rejected — for example the run's records are no longer there to bind the
|
|
2235
|
+
attestation to — is terminal: the row stops being retried, and re-arming it is
|
|
2236
|
+
an operator action (`kici-admin attestations retry --include-rejected`).
|
|
2237
|
+
|
|
2171
2238
|
Opening a row leads to the **attestation detail page**:
|
|
2172
2239
|
|
|
2173
2240
|
<!-- help:attestation-detail#browsing-attestations-across-runs -->
|
|
@@ -2177,13 +2244,14 @@ This page shows the parsed provenance for one attestation.
|
|
|
2177
2244
|
- **Builder identity, source, and build type** come from the signed SLSA statement.
|
|
2178
2245
|
- The **stored badge** is the verdict recorded at build time; **Re-verify** runs the check live in your browser against the current signing keys.
|
|
2179
2246
|
- **Download** exports the signed bundle for offline verification with `kici verify-attestation`.
|
|
2247
|
+
|
|
2180
2248
|
<!-- /help:attestation-detail -->
|
|
2181
2249
|
|
|
2182
2250
|
## See also
|
|
2183
2251
|
|
|
2184
2252
|
- [SDK runtime reference](https://docs.kici.dev/user/sdk/runtime/) — the `ctx.attestProvenance` and
|
|
2185
2253
|
`ctx.kici.oidc.token` step APIs in full.
|
|
2186
|
-
- [CLI reference](https://docs.kici.dev/user/cli-
|
|
2254
|
+
- [CLI reference](https://docs.kici.dev/user/cli/notifications-and-diagnostics/#kici-verify-attestation) — every
|
|
2187
2255
|
`kici verify-attestation` flag and exit code.
|
|
2188
2256
|
|
|
2189
2257
|
---
|
|
@@ -2211,7 +2279,7 @@ Secret values are written either through the dashboard or through `kici-admin` r
|
|
|
2211
2279
|
A fresh orchestrator starts in **permissive** mode: both surfaces are available.
|
|
2212
2280
|
|
|
2213
2281
|
- **Dashboard:** Settings → Secrets → pick a scope → enter the secret name and value.
|
|
2214
|
-
- **CLI:** `kici-admin secret set
|
|
2282
|
+
- **CLI:** `kici-admin secret set <orgId> <scope> <KEY>` against the orchestrator's HTTP admin API.
|
|
2215
2283
|
|
|
2216
2284
|
Use whichever fits the workflow — most small teams stay on the dashboard; ops engineers and CI scripts use the CLI.
|
|
2217
2285
|
|
|
@@ -2219,7 +2287,7 @@ Use whichever fits the workflow — most small teams stay on the dashboard; ops
|
|
|
2219
2287
|
|
|
2220
2288
|
The orchestrator operator can flip `secrets.set` (and `variables.set`) to **CLI-only** as part of the [dashboard-write policy](https://docs.kici.dev/operator/security/dashboard-write-policy). When that flip is on:
|
|
2221
2289
|
|
|
2222
|
-
- The dashboard's "Add secret" / "Edit value" controls render with a lock icon.
|
|
2290
|
+
- The dashboard's "Add secret" / "Edit value" controls render with a lock icon. Hovering or keyboard-focusing the lock shows a tooltip with the exact `kici-admin secret set` invocation needed. The control itself is inert, so there is nothing to click.
|
|
2223
2291
|
- The dashboard's secrets page still lists secret **names**, scopes, and bindings — only the value-entry path moves to the CLI.
|
|
2224
2292
|
- `kici-admin secret set` becomes the single entry point for new and updated secret values.
|
|
2225
2293
|
|
|
@@ -2227,26 +2295,30 @@ This configuration is common for SOC2-prep and regulated workloads, where the cu
|
|
|
2227
2295
|
|
|
2228
2296
|
### CLI input modes
|
|
2229
2297
|
|
|
2230
|
-
`kici-admin secret set` accepts five input modes
|
|
2298
|
+
`kici-admin secret set` takes the target as three positional arguments — `<orgId> <scope> <key>` — and accepts five input modes; pick the one that fits your workflow:
|
|
2231
2299
|
|
|
2232
2300
|
```bash
|
|
2233
2301
|
# Interactive prompt (default when stdin is a TTY). No echo, no shell history.
|
|
2234
|
-
kici-admin secret set
|
|
2302
|
+
kici-admin secret set my-org production DB_PASSWORD --prompt
|
|
2235
2303
|
|
|
2236
2304
|
# Pipe from another tool (default when stdin is not a TTY).
|
|
2237
|
-
pass show prod/db | kici-admin secret set
|
|
2305
|
+
pass show prod/db | kici-admin secret set my-org production DB_PASSWORD --from-stdin
|
|
2238
2306
|
|
|
2239
2307
|
# Read from a file (handy after `sops -d` to a tmpfile).
|
|
2240
|
-
kici-admin secret set
|
|
2308
|
+
kici-admin secret set my-org production DB_PASSWORD --from-file ./db.pass
|
|
2241
2309
|
|
|
2242
2310
|
# Read from a named environment variable (CI-friendly).
|
|
2243
2311
|
KICI_SECRET_VALUE=$(my-secrets-fetcher prod db) \
|
|
2244
|
-
kici-admin secret set
|
|
2312
|
+
kici-admin secret set my-org production DB_PASSWORD --from-env KICI_SECRET_VALUE
|
|
2245
2313
|
|
|
2246
2314
|
# Direct argv — discouraged. Prints a stderr warning ("visible in shell history").
|
|
2247
|
-
kici-admin secret set
|
|
2315
|
+
kici-admin secret set my-org production DB_PASSWORD --value "<plaintext>"
|
|
2248
2316
|
```
|
|
2249
2317
|
|
|
2318
|
+
When the scope is a deployment context, a flag-based sugar form is also accepted:
|
|
2319
|
+
`kici-admin secret set --org my-org --context production --key DB_PASSWORD --prompt`.
|
|
2320
|
+
The two forms are mutually exclusive — mixing them is refused.
|
|
2321
|
+
|
|
2250
2322
|
Two cross-cutting flags help every mode:
|
|
2251
2323
|
|
|
2252
2324
|
- `--confirm-fingerprint <hex>` — pre-compute SHA-256 of the value and pass it. The CLI rejects the call if the value's fingerprint doesn't match. Catches paste corruption.
|