@knowttl/kubernetes-axi 0.0.0-stage → 0.1.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.
Files changed (48) hide show
  1. package/README.md +306 -2
  2. package/THIRD_PARTY_NOTICES.md +13 -0
  3. package/axi-credential.schema.json +31 -0
  4. package/bin/kubernetes-axi.js +10 -0
  5. package/command-metadata.json +36947 -0
  6. package/dist/byte-process.d.ts +9 -0
  7. package/dist/byte-process.js +56 -0
  8. package/dist/cli.d.ts +1 -0
  9. package/dist/cli.js +68 -0
  10. package/dist/credentials.d.ts +28 -0
  11. package/dist/credentials.js +113 -0
  12. package/dist/errors.d.ts +12 -0
  13. package/dist/errors.js +11 -0
  14. package/dist/exec-shim.d.ts +1 -0
  15. package/dist/exec-shim.js +16 -0
  16. package/dist/grammar.d.ts +50 -0
  17. package/dist/grammar.js +248 -0
  18. package/dist/hosted-session.d.ts +1 -0
  19. package/dist/hosted-session.js +201 -0
  20. package/dist/metadata-pin.d.ts +3 -0
  21. package/dist/metadata-pin.js +4 -0
  22. package/dist/mutations.d.ts +11 -0
  23. package/dist/mutations.js +526 -0
  24. package/dist/native.d.ts +26 -0
  25. package/dist/native.js +143 -0
  26. package/dist/private-files.d.ts +9 -0
  27. package/dist/private-files.js +137 -0
  28. package/dist/protobuf-schema.d.ts +2 -0
  29. package/dist/protobuf-schema.js +1 -0
  30. package/dist/protobuf.d.ts +1 -0
  31. package/dist/protobuf.js +67 -0
  32. package/dist/redaction.d.ts +10 -0
  33. package/dist/redaction.js +50 -0
  34. package/dist/remote-session.d.ts +22 -0
  35. package/dist/remote-session.js +90 -0
  36. package/dist/route-policy.d.ts +1 -0
  37. package/dist/route-policy.js +19 -0
  38. package/dist/runner.d.ts +11 -0
  39. package/dist/runner.js +367 -0
  40. package/dist/workspace-tar.d.ts +6 -0
  41. package/dist/workspace-tar.js +109 -0
  42. package/docs/hooks.md +35 -0
  43. package/kubectl-pins.json +18 -0
  44. package/package.json +21 -4
  45. package/skills/kubernetes-axi/SKILL.md +32 -0
  46. package/third-party/kubectl-LICENSE.txt +202 -0
  47. package/vendor/kubectl-linux-amd64 +4 -0
  48. package/vendor/kubectl-windows-amd64.exe +4 -0
package/README.md CHANGED
@@ -1,3 +1,307 @@
1
- # Temporary Holding Version
1
+ # kubernetes-axi
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Agent-facing Kubernetes CLI that runs a pinned kubectl with an isolated identity, read-only by default.
4
+
5
+ [Why](#why-this-exists) | [Quickstart](#quickstart) | [Use with your agent](#use-with-your-agent) | [Commands](#commands) | [Safety](#safety) | [Configuration](#configuration) | [Output](#output-and-exit-codes) | [Limitations](#limitations) | [Development](#development) | [Security](#security) | [License](#license)
6
+
7
+ ## Why this exists
8
+
9
+ Raw kubectl output is unbounded, mixes credentials from the developer's kubeconfig into every call and can change a cluster in one step.
10
+ kubernetes-axi returns bounded, token-efficient TOON with provenance fields (`complete`, `truncated`, `continue`) so an agent knows when a result is partial.
11
+ Each call runs the pinned kubectl v1.32.2 with a private kubeconfig built from a selected profile, never from ambient developer settings.
12
+ Cluster writes are off by default and need an explicit switch plus a prepare, preview and confirm workflow.
13
+
14
+ ## Quickstart
15
+
16
+ Requires Node 24.14.0 and npm 11.9.0, as pinned in [package.json](package.json).
17
+
18
+ ```text
19
+ npm install --global @knowttl/kubernetes-axi
20
+ kubernetes-axi --version
21
+ kubernetes-axi --help
22
+ ```
23
+
24
+ Without a usable credential configuration, cluster commands fail with a structured error such as:
25
+
26
+ ```text
27
+ error:
28
+ code: AUTH_REQUIRED
29
+ message: Supply a complete environment profile or select a configured profile.
30
+ ```
31
+
32
+ First authenticated read, using a configured profile:
33
+
34
+ ```text
35
+ kubernetes-axi version --profile <name>
36
+ kubernetes-axi get pods --profile <name> --namespace <namespace>
37
+ ```
38
+
39
+ Running `kubernetes-axi` with no arguments shows the selected source, isolated context, namespace, compatible binary and a bounded live pod summary.
40
+
41
+ ## Use with your agent
42
+
43
+ - Optional session hooks for Claude Code, Codex and OpenCode are described in [docs/hooks.md](docs/hooks.md).
44
+ A hook is installed only after explicit opt-in; package installation, CLI reads and tests never install one.
45
+ - An installable skill is an alternative when hooks are unavailable: `npx skills add knowttl/kubernetes-axi --skill kubernetes-axi`.
46
+ Its source is [skills/kubernetes-axi/SKILL.md](skills/kubernetes-axi/SKILL.md).
47
+
48
+ ## Commands
49
+
50
+ `kubernetes-axi --help` lists the compact read surface.
51
+ `--version` prints the package version without loading the command graph.
52
+
53
+ ```text
54
+ kubernetes-axi version
55
+ kubernetes-axi get <resource> [name]
56
+ kubernetes-axi api-versions
57
+ kubernetes-axi api-resources
58
+ kubernetes-axi logs <pod> -n <namespace>
59
+ kubernetes-axi top node
60
+ kubernetes-axi top pod -n <namespace>
61
+ kubernetes-axi describe <resource> <name>
62
+ kubernetes-axi explain <resource>
63
+ kubernetes-axi native -- <kubectl arguments>
64
+ ```
65
+
66
+ Global flags: `--config <absolute-path>`, `--profile <name>`, `--namespace <name>` (`-n`), `--help`.
67
+ Inspection commands that need no cluster request: `auth status`, `profile list`, `config path` and `doctor`.
68
+
69
+ Reads:
70
+
71
+ - Compact reads discover resource names, aliases, scope and kinds dynamically, including custom resources.
72
+ - Pods report name, namespace and phase, nodes report readiness, deployments report desired and available replicas, and `top` aggregates CPU and memory.
73
+ - Use `get <resource> [name] -o json` for compact JSON.
74
+ It serializes the same bounded summary as TOON, not the upstream object.
75
+ - `describe`, `explain`, `rollout history` and `rollout status` wrap upstream text with provenance and `complete: false`.
76
+ - `logs` preserves text and defaults to 100 trailing lines and 65,536 bytes.
77
+ - `native -- <kubectl arguments>` returns upstream presentation and preserves ordered and repeated flags.
78
+ Its stdout, stderr and exit status are kept after redaction, with the same time and byte bounds.
79
+ - `--profile` before `native --` selects an AXI identity; upstream `--profile` after the delimiter is refused as profiling output.
80
+
81
+ Writes and operations (all require `KUBERNETES_AXI_READ_ONLY=false`):
82
+
83
+ ```text
84
+ kubernetes-axi --profile <name> prepare -- <mutation>
85
+ kubernetes-axi --profile <name> preview <request-key>
86
+ kubernetes-axi --profile <name> confirm <request-key> --digest <preview-digest>
87
+ kubernetes-axi --profile <name> server-dry-run -- <mutation>
88
+ ```
89
+
90
+ - Supported mutations: create, replace, client and server apply, merge, strategic and JSON patch, delete, rollout changes, scale, autoscale, node cordon, uncordon, taint and drain, certificate approval and denial, labels, annotations, `set`, `run`, `expose` and disruption budgets.
91
+ - Resource names must be explicit; generated names cannot be bound to a stable preview.
92
+ - Non-interactive `exec` and `attach` and `debug --attach=false` use the same workflow.
93
+ - Authorization and identity reviews use their own non-persistent POST APIs and work in read-only mode.
94
+
95
+ Generated grammar:
96
+
97
+ - [command-metadata.json](command-metadata.json) is extracted from the pinned `k8s.io/kubectl@v0.32.2` command tree, with inherited flags, aliases, pflag types and an effect classification.
98
+ - [effect-policy.json](effect-policy.json) classifies every exact command path and flag name.
99
+ - Run `kubernetes-axi native -- <command> --help` for generated upstream flags.
100
+ - Regenerate with `npm run generate:metadata`, which needs Go and the pinned public module dependencies.
101
+ `npm run check:metadata` verifies freshness offline.
102
+
103
+ ## Safety
104
+
105
+ - Reads are bounded: one page of at most 100 objects, no automatic continuation, a 15-second budget per read, at most 64 child invocations, a 5-second request timeout, a 10-second child limit and 4 MiB of retained output.
106
+ - Writes default off.
107
+ `KUBERNETES_AXI_READ_ONLY` accepts only `true`, `false`, `1` or `0` and also gates native configuration writes.
108
+ - `prepare` runs the pinned kubectl through a guarded channel, captures the exact operation sequence, freezes UIDs and resourceVersions, and never forwards mutations.
109
+ The child gets a temporary loopback capability, not the upstream credentials.
110
+ - `preview` reads only the saved snapshot and makes no API request.
111
+ Its digest covers the cluster and identity binding, namespace, selected objects and the exact bytes to be forwarded.
112
+ Secret payloads, last-applied configuration and configured credential values are redacted from the public preview.
113
+ The private saved request under `requests/<request-key>` beside the config file retains the original payloads, including Secret data, so protect that directory.
114
+ - `confirm` needs the exact digest and original identity, rechecks every target, uses UID and resourceVersion preconditions and claims the request atomically.
115
+ A repeated confirmation never replays a mutation.
116
+ - Conflicts and transport failures return a failure with the method, route, upstream status where available and a reconciliation read of the target.
117
+ Partial operations stay failures and keep results for completed requests; prepare a fresh request for the rest.
118
+ - Bulk deletion also needs `KUBERNETES_AXI_COLLECTION_DELETE=true`, at most 100 frozen objects and the API's `deletecollection` permission.
119
+ - `server-dry-run` is an explicit `dryRun=All` API operation that never issues a confirmation.
120
+ - Token issuance (`create token`) additionally needs `KUBERNETES_AXI_ACQUIRE_CREDENTIAL=true`, a duration of at most one hour and a private inherited pipe passed as `--credential-fd <fd>` to `confirm`.
121
+ The token is delivered once and never stored.
122
+ - Credential overrides, server overrides, impersonation, TLS bypass and generic proxy listeners are refused.
123
+ Unknown flags are rejected before any effect.
124
+ - In 0.1.x, execution of editors, plugins and external render/diff helpers is refused before effects, including when writes are enabled.
125
+ Run those tools outside the CLI, then submit their manifest or patch through preparation, preview and confirmation.
126
+ An opt-in two-stage local execution design is tracked in [issue 30](https://github.com/knowttl/kubernetes-axi/issues/30).
127
+ - Raw reads are classified by their API route, including nested proxy routes and query-based watches.
128
+ Raw execution, token issuance and proxy connections cannot bypass their explicit capability boundaries.
129
+ Raw resource mutations still require preparation and confirmation.
130
+ - Secrets in output are redacted, including literal, escaped, URI, form and base64 forms.
131
+ Public native Secret reads are refused; `get secrets` returns metadata only.
132
+ - Runtime digest checks refuse stale generated metadata before credential resolution or API calls.
133
+
134
+ ### Bounded execution and the 0.1.x capability boundary
135
+
136
+ Non-interactive `exec` and `attach` use the prepare, preview and confirm workflow.
137
+ Preparation freezes the named pod, container and exact command argument sequence without opening a stream.
138
+ Confirmation checks the selected identity, cluster and pod snapshot before invoking pinned kubectl.
139
+ The private gateway supports WebSocket GET and kubectl's SPDY fallback, preserves separate stdout/stderr, and returns the remote exit code.
140
+ Both operations require `KUBERNETES_AXI_READ_ONLY=false`.
141
+
142
+ In 0.1.x, managed interactive `exec`, `attach` and debugging are refused before effects, even in a real terminal.
143
+ Standalone watches, followed logs and port forwarding are also refused before effects.
144
+ Credentials come only from existing config/profile and secure credential references.
145
+ Tool-managed sessions never read credential secrets from terminal prompts.
146
+ Canonical streaming redaction is tracked in [issue #34](https://github.com/knowttl/kubernetes-axi/issues/34), and redesigned interactive exec/attach in [issue #35](https://github.com/knowttl/kubernetes-axi/issues/35).
147
+ Existing hosted bounded/noninteractive byte sessions, watches, followed logs and forwarding retain their established behavior.
148
+
149
+ `debug --attach=false` still prepares named create or ephemeral-container patches through the mutation policy.
150
+ Helper-backed mutations and execution remain refused.
151
+ Native Windows support remains pending.
152
+
153
+ Native `completion`, `options`, `plugin list` and `version --client=true` run offline without credentials.
154
+ `plugin list` discovers programs on PATH without executing them.
155
+
156
+ ```sh
157
+ kubernetes-axi --profile <name> prepare -- exec <pod> -n <namespace> -- true
158
+ kubernetes-axi --profile <name> preview <request-key>
159
+ kubernetes-axi --profile <name> confirm <request-key> --digest <preview-digest>
160
+ kubernetes-axi native -- completion bash
161
+ ```
162
+
163
+ ### Native identity
164
+
165
+ ```text
166
+ kubernetes-axi --native-config /absolute/kubeconfig get pods
167
+ kubernetes-axi --native-config ambient native -- --context=<context> get pods -o json
168
+ kubernetes-axi --native-config /absolute/kubeconfig --trust-exec get pods
169
+ ```
170
+
171
+ - `ambient` uses native KUBECONFIG precedence, or `~/.kube/config` when unset.
172
+ Native selection is refused when a standard profile is selected.
173
+ - The adapter resolves the context in memory and runs with an isolated temporary kubeconfig; ordinary reads leave native files unchanged.
174
+ - Credential helpers need explicit `--trust-exec`.
175
+ Helper identities can read but cannot use `prepare`, `confirm` or `server-dry-run`; they fail with `AUTH_HELPER_MUTATION_UNAVAILABLE`.
176
+ Use a static token or client certificate for mutations.
177
+ Tracked in [issue #19](https://github.com/knowttl/kubernetes-axi/issues/19).
178
+ - Native configuration edits need a single explicit source path.
179
+ Generic `config set`, credential argv writes and raw credential inspection are refused.
180
+
181
+ ### Hosted sessions
182
+
183
+ Used with an Artium host that has the Kubernetes session integration (a frozen local fixture is the only verified integration).
184
+
185
+ - Caller-owned file trees can be uploaded; host file arguments use `workspace:<relative-path>` and copy downloads use `artifact:<relative-path>`.
186
+ Copy needs `tar` in the container.
187
+ - The session API at `/v1/tools/kubernetes-axi/sessions` provides start, status, output and cancel, with bounded stdin, followed logs and pod watches.
188
+ Every operation checks the caller, login family, current operation grant and credential revision.
189
+ - Port-forward sessions freeze a named pod and up to eight numeric remote ports.
190
+ Continued client input after a remote-initiated half-close is not supported; see [issue 26](https://github.com/knowttl/kubernetes-axi/issues/26).
191
+
192
+ ```text
193
+ artium-axi kubernetes-axi tunnel <session-id> --port 8080 --port 9090
194
+ ```
195
+
196
+ ## Configuration
197
+
198
+ Profiles follow [axi-credential.schema.json](axi-credential.schema.json) and take tokens and private keys only as SecretRefs, never in argv or inline.
199
+ There is no persistent login or token store.
200
+ Each invocation creates a private kubeconfig and discovery cache below `TMPDIR` and removes them afterwards.
201
+
202
+ ```json
203
+ {
204
+ "version": 1,
205
+ "defaultProfile": "selected",
206
+ "profiles": {
207
+ "selected": {
208
+ "origin": "https://127.0.0.1:6443",
209
+ "auth": "token",
210
+ "namespace": "default",
211
+ "certificateAuthority": "<trusted PEM CA certificate>",
212
+ "token": { "env": "SELECTED_TOKEN" }
213
+ }
214
+ }
215
+ }
216
+ ```
217
+
218
+ Config file location, in order:
219
+
220
+ - `--config <absolute-path>` or `KUBERNETES_AXI_CONFIG`.
221
+ - Linux: an absolute `XDG_CONFIG_HOME` plus `kubernetes-axi/config.json`, else `~/.config/kubernetes-axi/config.json`.
222
+ - Windows: `APPDATA` plus `kubernetes-axi/config.json`.
223
+
224
+ Linux config files must belong to the current uid and not be writable by group or other.
225
+ Secret files must have no group or other permissions (0600 or 0400).
226
+
227
+ Environment variables:
228
+
229
+ | Variable | Purpose |
230
+ | --- | --- |
231
+ | `KUBERNETES_AXI_PROFILE` | Select a file profile, same as `--profile`. |
232
+ | `KUBERNETES_AXI_ORIGIN`, `KUBERNETES_AXI_AUTH`, `KUBERNETES_AXI_CERTIFICATE_AUTHORITY`, `KUBERNETES_AXI_TOKEN` | Token environment profile. |
233
+ | `KUBERNETES_AXI_CLIENT_CERTIFICATE`, `KUBERNETES_AXI_PRIVATE_KEY` | Certificate profile, used instead of the token. |
234
+ | `KUBERNETES_AXI_NAMESPACE` | Optional default namespace. |
235
+ | `KUBERNETES_AXI_READ_ONLY` | `false` enables writes. |
236
+ | `KUBERNETES_AXI_COLLECTION_DELETE` | `true` allows bulk deletion. |
237
+ | `KUBERNETES_AXI_ACQUIRE_CREDENTIAL` | `true` allows token issuance. |
238
+
239
+ A partial environment profile fails rather than borrowing fields from the file.
240
+ With no environment fields or selection, the file's `defaultProfile` is used, or its sole profile.
241
+ A file profile that omits its token or private key reference reads `KUBERNETES_AXI_TOKEN` or `KUBERNETES_AXI_PRIVATE_KEY`.
242
+ Insecure or redirected paths fail before credentials are read.
243
+
244
+ ## Output and exit codes
245
+
246
+ - Output is TOON by default; failures print `error:` with a `code` and `message`, and keep the upstream status where available.
247
+ - Distinct codes cover NotFound, denied access, expired continuation, authentication, unavailable APIs, malformed bodies, timeouts and byte limits.
248
+ - Check `complete`, `truncated` and `continue` before treating a list as complete.
249
+ An oversized server page is truncated with `complete: false`, and a bounded log snapshot never claims completeness.
250
+ - Empty event lists are successful.
251
+ - A failed command exits 1.
252
+ `native` preserves the upstream exit status.
253
+ - The verification entry points exit 0 on pass, 1 on failure and 2 when a prerequisite is pending.
254
+
255
+ ## Limitations
256
+
257
+ - Native Windows execution, ACL conformance and helper channels are pending; Linux is the verified platform.
258
+ - Live cluster commissioning and complete command coverage are pending.
259
+ - For local editor, plugin and external helper restrictions, see [Safety](#safety).
260
+ - Standalone mode has no direct file transfer or generic proxy listener; execution and streaming restrictions are described in the [0.1.x capability boundary](#bounded-execution-and-the-01x-capability-boundary).
261
+ - Hosted transfers, byte sessions and port forwarding are verified only against a frozen local Artium fixture, not a released Artium.
262
+ - Terminal-bound helpers and legacy auth-provider plugins fail explicitly.
263
+ - Supported server minors are listed in [kubectl-pins.json](kubectl-pins.json).
264
+ - The `release` verification entry point is pending.
265
+
266
+ ## Development
267
+
268
+ Node and npm are pinned in [package.json](package.json), with exact dependencies in package-lock.json.
269
+ Verification also uses Python 3.12.3 and OpenSSL 3.0.13, plus `unshare`, `ip` and `prlimit` with permission to create a user and network namespace.
270
+
271
+ ```text
272
+ npm ci
273
+ npm run check
274
+ python3 scripts/verify.py task B1.1 --mode offline --pack evidence
275
+ python3 scripts/verify.py task B5.1 --mode offline --pack evidence
276
+ python3 scripts/verify.py task B5.2 --mode offline --pack evidence
277
+ ```
278
+
279
+ The verifier uses Python 3; use `python3` on Linux hosts without a `python` alias.
280
+ B5.1 verifies the reduced 0.1.x boundary: interactive and standalone-streaming requests refuse before effects, while bounded execution and offline native client/config commands remain available.
281
+ B5.2 runs cumulative package journeys, strict types and generated-contract checks.
282
+ Artium hosted proof is optional for the 0.1.x package gate.
283
+ Add `--artium <frozen-checkout>` to either B5 command to opt in to hosted verification.
284
+ B5.2 additionally runs the selected frozen Artium aggregate.
285
+ For B5.2 with `--artium`, private hygiene runs when `ARTIUM_AXI_HYGIENE_DENY_LIST_FILE` supplies the owner's external deny list; otherwise it reports pending.
286
+ Container acceptance requires separate owner evidence and remains pending in the verifier.
287
+
288
+ - For offline builds, place the official kubectl binaries named in [kubectl-pins.json](kubectl-pins.json) in `vendor/` before installing; the build checks their SHA256 digests and otherwise downloads only from the pinned official URL.
289
+ - `npm test` runs inside a loopback-only Linux namespace, so outbound network access is denied.
290
+ Only the external Kubernetes API is faked, through a verified TLS loopback server with synthetic identities.
291
+ - The package-contract check packs and installs the package offline in a temporary directory, checks the published file contract and admission module exports, and runs the installed bin with `--help` and `--version`.
292
+ - Hosted journeys need a frozen Artium checkout: `python3 scripts/verify.py task B1.2 --mode offline --pack evidence --artium <frozen-checkout>`.
293
+ Without `--artium` they are skipped with an explicit reason.
294
+ - B3.4 also needs a verified `strace` in `KUBERNETES_AXI_TEST_WRITE_OBSERVER` with its digest in `KUBERNETES_AXI_TEST_WRITE_OBSERVER_SHA256`; without it the task reports pending and exits 2.
295
+ - Retained fixture provenance is in [evidence/README.md](evidence/README.md).
296
+ - Release Please opens release PRs on `main`; merging one publishes to npm with provenance through the `release-please.yml` workflow.
297
+
298
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for test-quality rules.
299
+
300
+ ## Security
301
+
302
+ No `SECURITY.md` exists yet; a reporting policy is pending.
303
+
304
+ ## License
305
+
306
+ No `LICENSE` file exists yet; the license is pending.
307
+ The bundled kubectl license is in [third-party/kubectl-LICENSE.txt](third-party/kubectl-LICENSE.txt), and notices are in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
@@ -0,0 +1,13 @@
1
+ # Third-party notices
2
+
3
+ The local package contains official kubectl v1.32.2 binaries from the Kubernetes project.
4
+ Copyright The Kubernetes Authors.
5
+ Kubectl is licensed under the Apache License, Version 2.0, reproduced in third-party/kubectl-LICENSE.txt.
6
+ Source: https://github.com/kubernetes/kubernetes/tree/v1.32.2.
7
+ The binary URLs and SHA-256 values are recorded in kubectl-pins.json.
8
+ These binaries are unmodified.
9
+
10
+ The generated protobuf schema and JSON field mappings derive from the official k8s.io/api and k8s.io/apimachinery v0.32.2 .proto and Go files, also under the Kubernetes Apache 2.0 license.
11
+ Source file SHA-256 pins and generation are recorded in scripts/generate-protobuf.ts.
12
+ The runtime npm dependencies @toon-format/toon, ajv and protobufjs are distributed by npm with their own license files.
13
+ No code was copied from the kubernetes-axi reference implementation.
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "urn:kubernetes-axi:credential-profile",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": ["origin", "auth", "certificateAuthority"],
7
+ "properties": {
8
+ "origin": { "type": "string", "minLength": 1 },
9
+ "auth": { "enum": ["token", "certificate"] },
10
+ "namespace": { "type": "string", "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$", "maxLength": 63 },
11
+ "certificateAuthority": { "type": "string", "minLength": 1 },
12
+ "token": { "$ref": "#/definitions/secretRef", "x-secret": true },
13
+ "clientCertificate": { "type": "string", "minLength": 1 },
14
+ "privateKey": { "$ref": "#/definitions/secretRef", "x-secret": true }
15
+ },
16
+ "allOf": [
17
+ {
18
+ "if": { "properties": { "auth": { "const": "token" } } },
19
+ "then": { "not": { "anyOf": [{ "required": ["privateKey"] }, { "required": ["clientCertificate"] }] } },
20
+ "else": { "required": ["clientCertificate"], "not": { "required": ["token"] } }
21
+ }
22
+ ],
23
+ "definitions": {
24
+ "secretRef": {
25
+ "oneOf": [
26
+ { "type": "object", "additionalProperties": false, "required": ["env"], "properties": { "env": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" } } },
27
+ { "type": "object", "additionalProperties": false, "required": ["file"], "properties": { "file": { "type": "string", "minLength": 1 } } }
28
+ ]
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from 'node:fs';
3
+
4
+ const args = process.argv.slice(2);
5
+ if (args.length === 1 && ['-v', '-V', '--version'].includes(args[0])) {
6
+ console.log(JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version);
7
+ } else {
8
+ const { main } = await import('../dist/cli.js');
9
+ await main(args);
10
+ }