@kici-dev/compiler 0.1.23 → 0.1.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/headless-detect.js +1 -1
- package/dist/cli-banner.js +1 -1
- package/dist/cli.d.ts +18 -0
- package/dist/cli.js +71 -10
- package/dist/commands/approve.js +2 -2
- package/dist/commands/check-mode.js +1 -1
- package/dist/commands/compile.js +1 -1
- package/dist/commands/diagnostics.js +1 -1
- package/dist/commands/docs.js +1 -1
- package/dist/commands/drain-worker.js +1 -1
- package/dist/commands/endpoints.js +1 -1
- package/dist/commands/fixture.js +2 -2
- package/dist/commands/held-run-client.d.ts +1 -1
- package/dist/commands/held-run-client.js +1 -1
- package/dist/commands/hook.js +1 -1
- package/dist/commands/index.d.ts +5 -3
- package/dist/commands/index.js +5 -4
- package/dist/commands/init.js +3 -3
- package/dist/commands/login.js +1 -1
- package/dist/commands/logout.js +1 -1
- package/dist/commands/orchestrators.js +1 -1
- package/dist/commands/org.js +1 -1
- 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} +16 -15
- package/dist/commands/reject.js +2 -2
- package/dist/commands/run-hold-watch.d.ts +10 -1
- package/dist/commands/run-hold-watch.js +13 -12
- package/dist/commands/run.d.ts +20 -1
- package/dist/commands/run.js +62 -12
- package/dist/commands/runs/cancel.js +1 -1
- package/dist/commands/runs/list.js +1 -1
- package/dist/commands/runs/logs.js +1 -1
- package/dist/commands/runs/rerun.js +1 -1
- package/dist/commands/runs/show.js +1 -1
- package/dist/commands/secrets-list.js +1 -1
- package/dist/commands/types.js +1 -1
- package/dist/commands/verify-attestation.d.ts +4 -1
- package/dist/commands/verify-attestation.js +34 -12
- package/dist/commands/watch.js +1 -1
- package/dist/commands/workflows.js +1 -1
- package/dist/errors/capability-gap.js +1 -1
- package/dist/errors/formatter.js +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/execution/executor.d.ts +5 -6
- package/dist/execution/executor.js +6 -7
- package/dist/execution/index.js +1 -1
- package/dist/execution/sdk-alias.d.ts +4 -14
- package/dist/execution/sdk-alias.js +6 -45
- package/dist/execution/ts-loader.js +1 -1
- package/dist/fixtures/compiler.js +1 -1
- package/dist/fixtures/defaults/index.js +1 -1
- package/dist/fixtures/describe-event.d.ts +0 -4
- package/dist/fixtures/describe-event.js +35 -5
- package/dist/fixtures/picker.js +1 -1
- package/dist/format.js +1 -1
- package/dist/generators/secrets-dts.js +3 -1
- package/dist/hooks/detector.js +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/installer.js +1 -1
- package/dist/hooks/templates.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/llm-context/llms-architecture.txt +4 -4
- package/dist/llm-context/llms-cli.txt +346 -33
- package/dist/llm-context/llms-features.txt +128 -21
- package/dist/llm-context/llms-full.txt +610 -71
- package/dist/llm-context/llms-getting-started.txt +7 -7
- package/dist/llm-context/llms-sdk.txt +125 -6
- package/dist/llm-context/llms.txt +7 -5
- package/dist/local-executor/dag-scheduler.js +1 -1
- package/dist/local-executor/index.js +3 -2
- package/dist/local-executor/job-runner.js +4 -4
- package/dist/local-executor/materializer.js +1 -1
- package/dist/local-executor/output-streamer.js +1 -1
- package/dist/local-executor/payload-generator.js +1 -1
- package/dist/local-executor/picker.js +1 -1
- package/dist/local-executor/runs-on-display.js +1 -1
- package/dist/local-executor/secret-loader.js +1 -1
- package/dist/local-executor/to-event-payload.js +1 -1
- package/dist/local-executor/types.js +1 -1
- package/dist/local-executor/workflow-lock.js +0 -0
- package/dist/lockfile/generator.d.ts +10 -2
- package/dist/lockfile/generator.js +107 -53
- package/dist/lockfile/hash-files.js +1 -1
- package/dist/lockfile/hasher.js +1 -1
- package/dist/lockfile/index.js +1 -1
- package/dist/lockfile/purity-analyzer.js +3 -3
- package/dist/postinstall.js +1 -1
- package/dist/provenance-trust-root.js +1 -1
- package/dist/remote/config.js +1 -1
- package/dist/remote/dashboard-client.js +1 -1
- package/dist/remote/encryption.js +1 -1
- package/dist/remote/history.d.ts +1 -1
- package/dist/remote/history.js +2 -2
- package/dist/remote/local-repo-identity.d.ts +32 -0
- package/dist/remote/local-repo-identity.js +74 -0
- package/dist/remote/oauth.js +1 -1
- package/dist/remote/oidc-discovery.js +1 -1
- package/dist/remote/output/json.js +1 -1
- package/dist/remote/output/junit.js +1 -1
- package/dist/remote/output/streaming.js +1 -1
- package/dist/remote/output/summary.js +1 -1
- package/dist/remote/platform-client.d.ts +2 -0
- package/dist/remote/platform-client.js +1 -1
- package/dist/remote/prod-defaults.d.ts +9 -1
- package/dist/remote/prod-defaults.js +11 -3
- package/dist/remote/render.js +1 -1
- package/dist/remote/secret-upload.js +1 -1
- package/dist/remote/uploader.js +4 -4
- package/dist/{chunk-BTugEXQM.js → rolldown-runtime-ClRpJifh.js} +0 -1
- package/dist/templates/agents-md.d.ts +1 -1
- package/dist/templates/agents-md.js +3 -3
- package/dist/templates/index.js +1 -1
- package/dist/templates/package-json.js +2 -2
- package/dist/templates/tsconfig-json.js +1 -1
- package/dist/templates/workflows/hello-world.js +1 -1
- package/dist/templates/workflows/pr-checks.js +1 -1
- package/dist/test-runner/dry-run.js +1 -1
- package/dist/test-runner/event-types.js +1 -1
- package/dist/test-runner/git-detector.js +1 -1
- package/dist/test-runner/index.js +1 -1
- package/dist/test-runner/job-executor.js +1 -1
- package/dist/test-runner/output-formatter.js +1 -1
- package/dist/test-runner/payload-builder.js +1 -1
- package/dist/test-runner/rule-evaluator.js +1 -1
- package/dist/test-runner/secrets-file.js +1 -1
- package/dist/test-runner/step-context.d.ts +1 -1
- package/dist/test-runner/step-context.js +3 -2
- package/dist/types.d.ts +33 -6
- package/dist/types.js +6 -2
- package/dist/validation/index.js +1 -1
- package/dist/validation/validator.js +1 -1
- package/package.json +4 -7
- package/sbom.spdx.json +35 -35
- package/dist/commands/held-run-resolve.js +0 -53
|
@@ -641,7 +641,7 @@ env: async (event) => {
|
|
|
641
641
|
|
|
642
642
|
Source: https://docs.kici.dev/user/env-vars/
|
|
643
643
|
|
|
644
|
-
The KiCI CLI reads the following environment variables to customize its behavior. OAuth login (`kici login` without `--token`) defaults `KICI_PLATFORM_URL`, `KICI_OIDC_ISSUER`, and `KICI_OIDC_CLIENT_ID` to the hosted KiCI Platform, so `kici login` works with no configuration. Set them only to target a
|
|
644
|
+
The KiCI CLI reads the following environment variables to customize its behavior. OAuth login (`kici login` without `--token`) defaults `KICI_PLATFORM_URL`, `KICI_OIDC_ISSUER`, and `KICI_OIDC_CLIENT_ID` to the hosted KiCI Platform, so `kici login` works with no configuration. Set them only to target another KiCI environment (e.g. a testing instance) or a custom OIDC provider.
|
|
645
645
|
|
|
646
646
|
## Authentication
|
|
647
647
|
|
|
@@ -676,9 +676,9 @@ Authenticate with a pre-existing API key (no browser needed):
|
|
|
676
676
|
kici login --token <<< "$KICI_API_KEY"
|
|
677
677
|
```
|
|
678
678
|
|
|
679
|
-
###
|
|
679
|
+
### Targeting another environment or custom OIDC provider
|
|
680
680
|
|
|
681
|
-
`kici login` targets the hosted KiCI Platform by default. To point the CLI at a
|
|
681
|
+
`kici login` targets the hosted KiCI Platform by default. To point the CLI at another KiCI environment (e.g. a testing instance) or a custom OIDC provider, override the defaults:
|
|
682
682
|
|
|
683
683
|
```bash
|
|
684
684
|
export KICI_OIDC_ISSUER=https://your-idp.example.com
|
|
@@ -802,6 +802,36 @@ job('deploy-review', {
|
|
|
802
802
|
|
|
803
803
|
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.
|
|
804
804
|
|
|
805
|
+
### Multiple environments per job
|
|
806
|
+
|
|
807
|
+
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:
|
|
808
|
+
|
|
809
|
+
```typescript
|
|
810
|
+
job('deploy', {
|
|
811
|
+
runsOn: 'default',
|
|
812
|
+
environments: ['staging', 'my-testing'],
|
|
813
|
+
steps: [
|
|
814
|
+
step('deploy', async (ctx) => {
|
|
815
|
+
// ctx.secrets and ctx.env carry the merged set from both environments
|
|
816
|
+
const dbUrl = await ctx.secrets.get('DB_URL');
|
|
817
|
+
}),
|
|
818
|
+
],
|
|
819
|
+
});
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
- `environment` (singular) and `environments` (array) are mutually exclusive — setting both is a compile error. `environment: 'staging'` is exactly equivalent to `environments: ['staging']`.
|
|
823
|
+
- Each array entry is a static name or a function of the event, resolved per element exactly like a single dynamic environment.
|
|
824
|
+
|
|
825
|
+
**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.
|
|
826
|
+
|
|
827
|
+
**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 runs show <run-id>` and the run's rejection reason), so a mutually-exclusive set of rules surfaces as a clear failure rather than a silent perpetual rejection.
|
|
828
|
+
|
|
829
|
+
**Skip-on-test (allow-and-warn).** On a test or local run (`kici run remote`, `kici run local`), a bound environment never rejects the run. Any bound environment that disallows local execution (`allowLocalExecution: false`) — or that is not configured — is **skipped**: its variables and secrets are omitted from the merge and its gates are not evaluated. The run proceeds, and a user-visible warning naming the skipped environment(s) is shown both on the `kici run remote` CLI output and on the dashboard run view. 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 and warns that `staging` was skipped. If every bound environment is skipped, the job runs with no environment variables. This is intentionally different from a fixture `secrets:` mapping, which is fail-closed — see the [testing guide](https://docs.kici.dev/user/testing-guide/).
|
|
830
|
+
|
|
831
|
+
**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.
|
|
832
|
+
|
|
833
|
+
**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.
|
|
834
|
+
|
|
805
835
|
### Job-level environment variables
|
|
806
836
|
|
|
807
837
|
The `env` property on a job provides static or dynamic environment variables:
|
|
@@ -841,25 +871,30 @@ job('deploy', {
|
|
|
841
871
|
});
|
|
842
872
|
```
|
|
843
873
|
|
|
844
|
-
If no `concurrencyGroup` is specified, the environment name is used as the default concurrency group.
|
|
874
|
+
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.
|
|
845
875
|
|
|
846
876
|
### Step context
|
|
847
877
|
|
|
848
878
|
Inside a step, the `ctx` object provides:
|
|
849
879
|
|
|
850
|
-
| Property | Type | Description
|
|
851
|
-
| ----------------- | ------------------------------------- |
|
|
852
|
-
| `ctx.environment` | `string \| undefined` | Resolved environment name (undefined for jobs without environment)
|
|
853
|
-
| `ctx.env` | `Record<string, string \| undefined>` | Environment variables (merged from system, org, source, and job-level `env`)
|
|
854
|
-
| `ctx.secrets` | `StepSecretsTyped` | Async accessor for bound secrets (get, expose, has, getMeta)
|
|
855
|
-
|
|
856
|
-
| Method
|
|
857
|
-
|
|
|
858
|
-
| `await ctx.secrets.get(key)`
|
|
859
|
-
| `await ctx.secrets.expose(key)`
|
|
860
|
-
| `ctx.secrets.has(key)`
|
|
861
|
-
| `ctx.secrets.getMeta(key)`
|
|
862
|
-
| `ctx.
|
|
880
|
+
| Property | Type | Description |
|
|
881
|
+
| ----------------- | ------------------------------------- | ----------------------------------------------------------------------------------------- |
|
|
882
|
+
| `ctx.environment` | `string \| undefined` | Resolved environment name (undefined for jobs without environment) |
|
|
883
|
+
| `ctx.env` | `Record<string, string \| undefined>` | Environment variables (merged from system, org, source, and job-level `env`) |
|
|
884
|
+
| `ctx.secrets` | `StepSecretsTyped` | Async accessor for bound secrets (get, expose, has, getMeta, list, mountFile, exposeFile) |
|
|
885
|
+
|
|
886
|
+
| Method | Returns | Description |
|
|
887
|
+
| -------------------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
888
|
+
| `await ctx.secrets.get(key)` | `string` | Retrieve a secret value. Throws `SecretNotFoundError` if not found. |
|
|
889
|
+
| `await ctx.secrets.expose(key)` | `void` | Set the secret as an environment variable for this step — visible via `ctx.env` and to child processes (`process.env`). Throws `SecretNotFoundError` if not found. |
|
|
890
|
+
| `ctx.secrets.has(key)` | `boolean` | Check if a secret key exists. Synchronous, never throws. |
|
|
891
|
+
| `ctx.secrets.getMeta(key)` | `SecretMeta \| undefined` | Retrieve metadata (value, backend name, scope path) for a resolved secret. Returns `undefined` if not found. |
|
|
892
|
+
| `ctx.secrets.list()` | `string[]` | Every secret key available to the step, sorted alphabetically. Synchronous, never throws. |
|
|
893
|
+
| `await ctx.secrets.mountFile(opts)` | `{ path }` | Materialise one or more secrets to a per-step tmpfile (auto-removed at step end). See [Secrets → Mounting secrets as files](https://docs.kici.dev/user/secrets/#mounting-secrets-as-files). |
|
|
894
|
+
| `await ctx.secrets.exposeFile(envVar, opts)` | `{ path }` | `mountFile` plus `process.env[envVar] = path`; the env var is unset at step end. |
|
|
895
|
+
| `ctx.setSecretOutput(key, val)` | `void` | Publish an encrypted secret output from this job, consumable by downstream jobs via `needs`. Never logged or stored in plaintext. |
|
|
896
|
+
|
|
897
|
+
The full secrets API — including `SecretFileOptions`, log masking, and the canonical `sops` example — is documented in [Secrets](https://docs.kici.dev/user/secrets/).
|
|
863
898
|
|
|
864
899
|
## Environment variable merge precedence
|
|
865
900
|
|
|
@@ -982,6 +1017,12 @@ Each environment has four tabs:
|
|
|
982
1017
|
|
|
983
1018
|
4. **History** -- view filtered runs targeting this environment.
|
|
984
1019
|
|
|
1020
|
+
### Bound environments on runs
|
|
1021
|
+
|
|
1022
|
+
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.
|
|
1023
|
+
|
|
1024
|
+
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 runs show <run-id>`).
|
|
1025
|
+
|
|
985
1026
|
### Secrets management
|
|
986
1027
|
|
|
987
1028
|
Secrets are individual encrypted values organized by scope paths (e.g., `aws/prod`, `databases/postgres`). Scopes are bound to environments via bindings:
|
|
@@ -2005,11 +2046,34 @@ statement's build context must match the token's identity claims (a mismatch is
|
|
|
2005
2046
|
a hard failure).
|
|
2006
2047
|
|
|
2007
2048
|
```bash
|
|
2008
|
-
kici verify-attestation [artifact] --bundle <path-or-url> --trust-root <url-or-file>
|
|
2049
|
+
kici verify-attestation [artifact] --bundle <path-or-url> [--trust-root <url-or-file>]
|
|
2009
2050
|
```
|
|
2010
2051
|
|
|
2011
|
-
|
|
2012
|
-
|
|
2052
|
+
### Which trust root do I use?
|
|
2053
|
+
|
|
2054
|
+
The trust root is the **KiCI platform's provenance issuer** — the same hosted
|
|
2055
|
+
KiCI platform you `kici login` against. KiCI attestations are issued by, and
|
|
2056
|
+
verified against, that one issuer; there are no competing "roots" to choose
|
|
2057
|
+
between. So the answer to "shouldn't I just use KiCI as the trust root?" is yes
|
|
2058
|
+
— and that's the **default**: omit `--trust-root` and the verifier checks the
|
|
2059
|
+
bundle against the hosted KiCI platform automatically. You only pass
|
|
2060
|
+
`--trust-root` to verify against a different environment or, more commonly, an
|
|
2061
|
+
offline `{ issuer, jwks }` file for air-gapped checks.
|
|
2062
|
+
|
|
2063
|
+
### Why you supply it out-of-band
|
|
2064
|
+
|
|
2065
|
+
Given there's a single issuer, why pass it at all instead of letting the
|
|
2066
|
+
verifier read it from the token? Because the issuer named **inside** a token
|
|
2067
|
+
cannot be trusted: a forged bundle could carry a token that names
|
|
2068
|
+
`iss: https://attacker.example` _and_ bundle a key set that "verifies" it,
|
|
2069
|
+
making the whole signature chain circular and self-attesting. The verifier
|
|
2070
|
+
therefore pins to an issuer you supply out-of-band and checks the token against
|
|
2071
|
+
_that_ — the bundle is verified against a key set you trust, not one it shipped
|
|
2072
|
+
with. Naming the trust root is a security requirement, not a multiple-choice
|
|
2073
|
+
question.
|
|
2074
|
+
|
|
2075
|
+
To override the default, supply the trusted issuer via `--trust-root`, in one of
|
|
2076
|
+
two forms:
|
|
2013
2077
|
|
|
2014
2078
|
- **Online — an HTTPS issuer URL.** The verifier fetches
|
|
2015
2079
|
`<url>/.well-known/openid-configuration`, reads its `issuer` and `jwks_uri`,
|
|
@@ -2037,7 +2101,10 @@ when it does not (or on an error such as a missing flag or unreachable trust
|
|
|
2037
2101
|
root).
|
|
2038
2102
|
|
|
2039
2103
|
```bash
|
|
2040
|
-
#
|
|
2104
|
+
# Default: verify against the hosted KiCI platform (no --trust-root needed):
|
|
2105
|
+
kici verify-attestation ./dist/app.tgz --bundle ./app.tgz.kici.json
|
|
2106
|
+
|
|
2107
|
+
# Override the trust root to verify against a specific issuer:
|
|
2041
2108
|
kici verify-attestation ./dist/app.tgz \
|
|
2042
2109
|
--bundle ./app.tgz.kici.json \
|
|
2043
2110
|
--trust-root https://platform.example/issuer
|
|
@@ -2076,6 +2143,44 @@ attestations shows an empty state.
|
|
|
2076
2143
|
|
|
2077
2144
|
<!-- /help:run-attestations -->
|
|
2078
2145
|
|
|
2146
|
+
## Browsing attestations across runs
|
|
2147
|
+
|
|
2148
|
+
The **Attestations** page (in the org sidebar) lists every build-provenance
|
|
2149
|
+
attestation your organization has produced — not just one run's. It is the
|
|
2150
|
+
supply-chain audit surface: look up "who built `sha256:…`?" by digest, or browse
|
|
2151
|
+
and filter every attestation across all runs.
|
|
2152
|
+
|
|
2153
|
+
<!-- help:attestations-list#browsing-attestations-across-runs -->
|
|
2154
|
+
|
|
2155
|
+
The **Attestations** page lists every build-provenance attestation your organization has produced.
|
|
2156
|
+
|
|
2157
|
+
- **Search** by artifact digest (exact `sha256:…`) or name to trace a specific artifact.
|
|
2158
|
+
- **Filter** by verification status, repository, workflow, job, or date.
|
|
2159
|
+
- Each row's **status badge** is the verdict KiCI recorded when the attestation was produced (`verified`, `failed`, `unverifiable`, or `pending`).
|
|
2160
|
+
|
|
2161
|
+
Open a row for the parsed provenance statement and a live re-verification.
|
|
2162
|
+
|
|
2163
|
+
<!-- /help:attestations-list -->
|
|
2164
|
+
|
|
2165
|
+
The status badge here is the **server-side verdict**, computed once when the
|
|
2166
|
+
attestation was recorded (verify-at-ingest) — so the list stays fast at any
|
|
2167
|
+
size. `verified` means the signature, build identity, and build context all
|
|
2168
|
+
checked out against the provenance issuer; `failed` means verification ran and
|
|
2169
|
+
the bundle did not pass; `unverifiable` means no verdict could be computed (no
|
|
2170
|
+
provenance issuer configured, or its keys could not be read — not a forgery
|
|
2171
|
+
signal); `pending` means the verdict has not been computed yet.
|
|
2172
|
+
|
|
2173
|
+
Opening a row leads to the **attestation detail page**:
|
|
2174
|
+
|
|
2175
|
+
<!-- help:attestation-detail#browsing-attestations-across-runs -->
|
|
2176
|
+
|
|
2177
|
+
This page shows the parsed provenance for one attestation.
|
|
2178
|
+
|
|
2179
|
+
- **Builder identity, source, and build type** come from the signed SLSA statement.
|
|
2180
|
+
- The **stored badge** is the verdict recorded at build time; **Re-verify** runs the check live in your browser against the current signing keys.
|
|
2181
|
+
- **Download** exports the signed bundle for offline verification with `kici verify-attestation`.
|
|
2182
|
+
<!-- /help:attestation-detail -->
|
|
2183
|
+
|
|
2079
2184
|
## See also
|
|
2080
2185
|
|
|
2081
2186
|
- [SDK runtime reference](https://docs.kici.dev/user/sdk/runtime/) — the `ctx.attestProvenance` and
|
|
@@ -2097,6 +2202,8 @@ Secrets are managed per-environment in the orchestrator (see [operator docs](htt
|
|
|
2097
2202
|
|
|
2098
2203
|
This design prevents accidental secret leakage through child processes, log output, or error messages. Only secrets you explicitly request are loaded into memory.
|
|
2099
2204
|
|
|
2205
|
+
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).
|
|
2206
|
+
|
|
2100
2207
|
## Where secret values come from
|
|
2101
2208
|
|
|
2102
2209
|
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.
|