@compforge/harness-toolbox 0.5.5 → 0.6.1

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 (37) hide show
  1. package/README.md +50 -14
  2. package/dist/{chunk-226wxr2s.js → chunk-7mc2jevr.js} +6 -6
  3. package/dist/{chunk-0d8vs5q8.js → chunk-91xh8tsr.js} +1 -1
  4. package/dist/{chunk-0zcq74ep.js → chunk-dfpqr0r9.js} +73 -46
  5. package/dist/{chunk-rq5fc007.js → chunk-evb5tj13.js} +11 -8
  6. package/dist/{chunk-9d0ph5km.js → chunk-s7a3fqzc.js} +2 -2
  7. package/dist/{chunk-mvkxs8d0.js → chunk-v9rcxg0e.js} +1 -1
  8. package/dist/{chunk-47x0r2kr.js → chunk-xv3nn2vd.js} +2 -2
  9. package/dist/http/client.js +5 -5
  10. package/dist/http/index.js +5 -5
  11. package/dist/kubernetes/apparmor.d.ts +24 -0
  12. package/dist/kubernetes/apparmor.js +60 -0
  13. package/dist/kubernetes/client.js +6 -6
  14. package/dist/kubernetes/environment-inspection.d.ts +36 -0
  15. package/dist/kubernetes/environment-inspection.js +107 -0
  16. package/dist/kubernetes/environment.js +6 -6
  17. package/dist/kubernetes/exec-transport.d.ts +3 -2
  18. package/dist/kubernetes/exec-transport.js +3 -1
  19. package/dist/kubernetes/executor.js +1 -1
  20. package/dist/kubernetes/pod-log-client.js +2 -2
  21. package/dist/kubernetes/pod-log-datasource.js +2 -2
  22. package/dist/kubernetes/port-forward.js +2 -2
  23. package/dist/kubernetes/service-port-forward.js +3 -3
  24. package/dist/mysql/client.js +5 -5
  25. package/dist/mysql/index.js +5 -5
  26. package/dist/opensearch/client.js +5 -5
  27. package/dist/opensearch/index.js +5 -5
  28. package/dist/redis/client.js +5 -5
  29. package/dist/redis/index.js +5 -5
  30. package/dist/s3/client.js +5 -5
  31. package/dist/s3/datasource.js +5 -5
  32. package/dist/s3/index.js +5 -5
  33. package/dist/transport/index.js +5 -5
  34. package/dist/transport/pod-relay.js +3 -3
  35. package/dist/transport/service-port-forward.js +4 -4
  36. package/package.json +2 -2
  37. package/dist/{chunk-mnad4zkp.js → chunk-010339ga.js} +3 -3
package/README.md CHANGED
@@ -152,23 +152,27 @@ selectorless Services and failed access raise KubernetesError.
152
152
 
153
153
  The resource path uses client-node kubeconfig authentication/TLS and bounded native JSON reads,
154
154
  not kubectl error text. Configure request timeout, concurrency and response bytes with the
155
- client's ResourceLimits constructor argument. Native exec uses the same root capacity/byte policy
155
+ client's ResourceLimits constructor argument. Exec uses the same root capacity/byte policy
156
156
  with a separate slot pool; its per-call timeout defaults to that policy and covers queueing,
157
157
  authentication, upgrade and execution. Explicit per-call timeouts support longer commands.
158
158
 
159
- Exec requires `get pods/exec` permission for the WebSocket upgrade (kubectl/SPDY paths may use
160
- `create pods/exec`). It connects directly to the Pod exec WebSocket endpoint without a preliminary Pod GET or
161
- kubectl subprocess. Each command owns a stream session; failures are never retried or replayed.
162
- Kubeconfig controls authentication, TLS and proxy access. stdout/stderr and remote exit status
163
- remain separate; retained output and individual messages are bounded. Streaming callers may
164
- set `collectStdout: false` and enforce their own total byte budget. Root disposal cancels active
165
- and queued sessions. Protocol v4 is accepted for output-only commands; stdin requires v5 to
166
- close input without losing remaining output/status. Bun does not expose HTTP upgrade rejection
167
- status, so those failures retain an unknown connection error. Native exec with a kubeconfig
168
- proxy requires Node: Bun cannot reliably release proxy sockets or preserve TLS name overrides.
169
- It fails before opening a session on Bun; use Node or explicitly provide an Executor adapter.
170
- The transport never bypasses the proxy or TLS checks.
171
- Port-forward still uses kubectl.
159
+ Output-only exec connects directly to the Pod exec WebSocket endpoint without a preliminary
160
+ Pod GET and requires `get pods/exec`. Commands with explicit stdin (including empty input) use
161
+ `kubectl exec -i`, which handles input EOF through SPDY/v5 on older and newer clusters. This
162
+ path requires a compatible kubectl on the Host, Pod read permission and `create pods/exec`
163
+ for SPDY (`get pods/exec` for WebSocket). The channel is selected before execution; failures
164
+ are never retried or replayed by Toolbox. The result's `command` records the actual channel.
165
+ Kubeconfig controls authentication, TLS and proxy access. Both paths share the root exec slot
166
+ pool, deadline, retained-output byte limit and cancellation. stdout/stderr remain separate;
167
+ native exec uses remote status and kubectl uses process exit status, retaining raw CLI stderr
168
+ without guessing structured HTTP error kinds. Streaming callers may set `collectStdout: false`
169
+ and enforce their own total byte budget; individual output chunks remain bounded. Root disposal
170
+ cancels active and queued sessions and waits for the local kubectl process to exit.
171
+ Output-only sessions accept v4/v5. Bun does not expose HTTP upgrade rejection status, so those
172
+ failures retain an unknown connection error. Native exec with a kubeconfig proxy requires Node:
173
+ Bun cannot reliably release proxy sockets or preserve TLS name overrides. This restriction does
174
+ not apply to the kubectl stdin path. Neither path bypasses proxy or TLS checks.
175
+ Port-forward also uses kubectl.
172
176
  See [the shared Workload model](../../../docs/workload.md).
173
177
 
174
178
  ```ts
@@ -465,3 +469,35 @@ IP literals and Kubernetes `service.namespace` names use the same API. There is
465
469
  implicit execution on the caller host or ICMP requirement. Network failure returns
466
470
  evidence; missing Python, execution failure and incomplete output throw. TLS success
467
471
  does not establish HTTP authorization, object access or application download policy.
472
+
473
+
474
+ ## Kubernetes environment and AppArmor admission
475
+
476
+ `@compforge/harness-toolbox/kubernetes/environment-inspection` exports
477
+ `inspectKubernetesEnvironment(access, instance, {timeoutMs, signal?})`. Pass an existing Common
478
+ `WorkloadInstance`; the caller discovers and selects it (for example with `KubernetesClient.resolveWorkload`).
479
+ The function reads that Pod, verifies its UID, reads `ip_forward` in the selected running container,
480
+ and gets only its associated Node's `operatingSystem`, `osImage`, `kernelVersion` and `architecture`.
481
+ It does not enumerate Nodes, select workloads or infer a host forwarding setting from the Pod namespace.
482
+
483
+ ```ts
484
+ const result = await inspectKubernetesEnvironment({
485
+ resources: client.clusterResources(),
486
+ exec: client.exec.bind(client),
487
+ }, selectedInstance, { timeoutMs: 5_000, signal });
488
+ ```
489
+
490
+ Use a cluster-scoped resource view: Pod GET supplies its namespace explicitly; Node GET has none.
491
+ The positive timeout is a shared request budget. Resource/exec adapters must honor the supplied timeout
492
+ and cancellation signal. Node and forwarding reads retain independent successes and sanitized issues;
493
+ `complete`, `partial` and `unavailable` describe coverage, not Service health. Cancellation throws.
494
+ A missing or changed Pod UID prevents exec and Node attribution. A same-name replacement during the later
495
+ name-addressed exec cannot be excluded atomically by Kubernetes; results describe a best-effort sample.
496
+
497
+ `@compforge/harness-toolbox/kubernetes/apparmor` exports
498
+ `probeAppArmorUnconfinedAdmission(executor, {namespace, serviceAccountName, image}, {timeoutMs, signal?})`.
499
+ The caller supplies an authorized `Executor.run` channel. The function uses an explicit namespace and
500
+ ServiceAccount impersonation with `create --dry-run=server`; it never persists a Pod. Results are
501
+ `allowed`, `denied` (explicit AppArmor Unconfined admission rejection), or `unknown` (including generic
502
+ RBAC, impersonation, timeout and transport failures). Acceptance does not verify Node runtime support.
503
+ The caller owns permissions, Service semantics, scheduling and borrowed client/executor cleanup.
@@ -1,18 +1,18 @@
1
- import {
2
- resolveWorkload
3
- } from "./chunk-d2y5ewbb.js";
4
1
  import {
5
2
  KubernetesResourceTransport
6
3
  } from "./chunk-361x998p.js";
4
+ import {
5
+ resolveWorkload
6
+ } from "./chunk-d2y5ewbb.js";
7
7
  import {
8
8
  KubernetesExecTransport
9
- } from "./chunk-0zcq74ep.js";
9
+ } from "./chunk-dfpqr0r9.js";
10
10
  import {
11
11
  ServicePortForwarder
12
- } from "./chunk-0d8vs5q8.js";
12
+ } from "./chunk-91xh8tsr.js";
13
13
  import {
14
14
  KubectlExecutor
15
- } from "./chunk-rq5fc007.js";
15
+ } from "./chunk-evb5tj13.js";
16
16
  import {
17
17
  KubernetesError
18
18
  } from "./chunk-68zz17hs.js";
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-6fnhzhdb.js";
9
9
  import {
10
10
  PortForwardScope
11
- } from "./chunk-mvkxs8d0.js";
11
+ } from "./chunk-v9rcxg0e.js";
12
12
 
13
13
  // src/kubernetes/service-port-forward.ts
14
14
  class ServicePortForwarder {
@@ -1,6 +1,10 @@
1
1
  import {
2
2
  ConcurrencyPool
3
3
  } from "./chunk-v3hxvnrc.js";
4
+ import {
5
+ KubectlExecutor,
6
+ buildExecArgs
7
+ } from "./chunk-evb5tj13.js";
4
8
  import {
5
9
  KubernetesError,
6
10
  kubernetesHttpError
@@ -10,29 +14,28 @@ import {
10
14
  import { KubeConfig } from "@kubernetes/client-node";
11
15
  import WebSocket from "ws";
12
16
  class KubernetesExecTransport {
17
+ connection;
13
18
  signal;
14
19
  limits;
15
20
  #config = new KubeConfig;
16
21
  #capacity;
17
22
  #server;
18
- constructor(options, signal, limits) {
23
+ constructor(connection, signal, limits) {
24
+ this.connection = connection;
19
25
  this.signal = signal;
20
26
  this.limits = limits;
21
27
  if (!Object.values(limits).every((value) => Number.isSafeInteger(value) && value > 0)) {
22
28
  throw new KubernetesError("Exec limits must be positive integers", { kind: "invalid_argument" });
23
29
  }
24
- if (options.kubeconfig)
25
- this.#config.loadFromFile(options.kubeconfig);
30
+ if (connection.kubeconfig)
31
+ this.#config.loadFromFile(connection.kubeconfig);
26
32
  else
27
33
  this.#config.loadFromDefault();
28
- if (options.context)
29
- this.#config.setCurrentContext(options.context);
34
+ if (connection.context)
35
+ this.#config.setCurrentContext(connection.context);
30
36
  const cluster = this.#config.getCurrentCluster();
31
37
  if (!cluster)
32
38
  throw new KubernetesError("Kubernetes context has no cluster", { kind: "invalid_argument" });
33
- if (process.versions.bun && cluster.proxyUrl) {
34
- throw new KubernetesError("Native exec through a kubeconfig proxy requires a Node host", { kind: "unsupported_operation" });
35
- }
36
39
  this.#server = cluster.server.replace(/\/$/, "");
37
40
  if (new URL(cluster.server).protocol === "http:")
38
41
  this.#config.clusters = this.#config.clusters.map((item) => item === cluster ? { ...item, skipTLSVerify: true } : item);
@@ -49,17 +52,71 @@ class KubernetesExecTransport {
49
52
  const signal = AbortSignal.any([caller, deadline.signal]);
50
53
  const timer = setTimeout(() => deadline.abort(), timeoutMs);
51
54
  try {
52
- return await this.#capacity.run(() => this.#session(namespace, target, command, options, signal, started, deadline.signal), signal);
55
+ return await this.#capacity.run(() => options.stdin === undefined ? this.#session(namespace, target, command, options, signal, started, deadline.signal) : this.#stdinSession(namespace, target, command, options, signal, started), signal);
53
56
  } catch (error) {
54
57
  if (caller.aborted)
55
58
  throw caller.reason;
56
- if (deadline.signal.aborted)
57
- return this.#result(namespace, target, command, started, null, "", "Exec deadline exceeded", true);
59
+ if (deadline.signal.aborted) {
60
+ const result = this.#result(namespace, target, command, started, null, "", "Exec deadline exceeded", true);
61
+ if (options.stdin !== undefined)
62
+ result.command = buildExecArgs({ ...this.connection, namespace }, target, command, true);
63
+ return result;
64
+ }
58
65
  throw error;
59
66
  } finally {
60
67
  clearTimeout(timer);
61
68
  }
62
69
  }
70
+ async#stdinSession(namespace, target, command, options, signal, started) {
71
+ const controller = new AbortController;
72
+ const combined = AbortSignal.any([signal, controller.signal]);
73
+ let retained = 0;
74
+ let stdout = "";
75
+ let failure;
76
+ const guard = (action) => {
77
+ if (combined.aborted)
78
+ return;
79
+ try {
80
+ action();
81
+ } catch (cause) {
82
+ failure = cause;
83
+ controller.abort(cause);
84
+ throw cause;
85
+ }
86
+ };
87
+ const count = (size, retain) => {
88
+ if (retain)
89
+ retained += size;
90
+ if (size > this.limits.maxBytes || retained > this.limits.maxBytes) {
91
+ throw new KubernetesError(`Kubernetes exec ${namespace}/${target.pod} output exceeds ${this.limits.maxBytes} bytes`, { kind: "limit_exceeded" });
92
+ }
93
+ };
94
+ const executor = new KubectlExecutor({ ...this.connection, namespace });
95
+ const result = await executor.exec(target, command, {
96
+ ...options,
97
+ signal: combined,
98
+ timeoutMs: Math.max(1, (options.timeoutMs ?? this.limits.timeoutMs) - (performance.now() - started)),
99
+ collectStdout: false,
100
+ onStdoutBytes: (bytes) => guard(() => {
101
+ count(bytes.length, options.collectStdout !== false);
102
+ options.onStdoutBytes?.(bytes);
103
+ }),
104
+ onStdout: (text) => guard(() => {
105
+ if (options.collectStdout !== false)
106
+ stdout += text;
107
+ options.onStdout?.(text);
108
+ }),
109
+ onStderr: (text) => guard(() => {
110
+ count(Buffer.byteLength(text), true);
111
+ options.onStderr?.(text);
112
+ })
113
+ });
114
+ if (controller.signal.aborted)
115
+ throw failure;
116
+ if (signal.aborted)
117
+ throw signal.reason;
118
+ return { ...result, stdout, durationMs: performance.now() - started };
119
+ }
63
120
  #result(namespace, target, command, started, exitCode, stdout, stderr, timedOut = false) {
64
121
  return {
65
122
  ok: exitCode === 0 && !timedOut,
@@ -81,10 +138,12 @@ class KubernetesExecTransport {
81
138
  };
82
139
  }
83
140
  #session(namespace, target, command, options, signal, started, deadline) {
141
+ if (process.versions.bun && this.#config.getCurrentCluster()?.proxyUrl) {
142
+ throw new KubernetesError("Native exec through a kubeconfig proxy requires a Node host", { kind: "unsupported_operation" });
143
+ }
84
144
  return new Promise((resolve, reject) => {
85
145
  let socket;
86
146
  let agent;
87
- let input;
88
147
  let settled = false;
89
148
  let stdout = "", stderr = "", retained = 0;
90
149
  const outDecoder = new TextDecoder, errDecoder = new TextDecoder;
@@ -95,7 +154,6 @@ class KubernetesExecTransport {
95
154
  signal.removeEventListener("abort", abort);
96
155
  socket?.terminate();
97
156
  agent?.destroy();
98
- input?.cancel().catch(() => {});
99
157
  const tail = outDecoder.decode(), errTail = errDecoder.decode();
100
158
  if (options.collectStdout !== false)
101
159
  stdout += tail;
@@ -140,11 +198,11 @@ Exec deadline exceeded`;
140
198
  url.searchParams.append("command", arg);
141
199
  url.searchParams.set("stdout", "true");
142
200
  url.searchParams.set("stderr", "true");
143
- url.searchParams.set("stdin", String(options.stdin !== undefined));
201
+ url.searchParams.set("stdin", "false");
144
202
  url.searchParams.set("tty", "false");
145
203
  if (target.container)
146
204
  url.searchParams.set("container", target.container);
147
- socket = new WebSocket(url, options.stdin === undefined ? ["v5.channel.k8s.io", "v4.channel.k8s.io"] : ["v5.channel.k8s.io"], { ...request, ...process.versions.bun ? { tls: {
205
+ socket = new WebSocket(url, ["v5.channel.k8s.io", "v4.channel.k8s.io"], { ...request, ...process.versions.bun ? { tls: {
148
206
  ca: request.ca,
149
207
  cert: request.cert,
150
208
  key: request.key,
@@ -225,37 +283,6 @@ Exec deadline exceeded`;
225
283
  fail("invalid_response", error);
226
284
  }
227
285
  });
228
- socket.on("open", () => {
229
- if (options.stdin === undefined || settled)
230
- return;
231
- const send = (bytes) => new Promise((done, failed) => {
232
- if (settled) {
233
- failed(new Error("Exec closed"));
234
- return;
235
- }
236
- socket.send(Buffer.concat([Buffer.from([0]), bytes]), (error) => error ? failed(error) : done());
237
- });
238
- (async () => {
239
- const stdin = options.stdin;
240
- if (typeof stdin === "string" || stdin instanceof Uint8Array)
241
- await send(typeof stdin === "string" ? new TextEncoder().encode(stdin) : stdin);
242
- else {
243
- const reader = stdin.getReader();
244
- input = reader;
245
- while (!settled) {
246
- const chunk = await reader.read();
247
- if (chunk.done)
248
- break;
249
- await send(chunk.value);
250
- }
251
- }
252
- if (!settled)
253
- socket.send(Buffer.from([255, 0]));
254
- })().catch((error) => {
255
- if (!settled)
256
- fail("connection_failed", error);
257
- });
258
- });
259
286
  }).catch((error) => {
260
287
  if (!settled)
261
288
  fail("connection_failed", error);
@@ -68,24 +68,25 @@ async function runArgv(argv, opts) {
68
68
  let aborted = false;
69
69
  const abort = () => {
70
70
  aborted = true;
71
- proc.kill();
71
+ proc.kill("SIGKILL");
72
72
  };
73
73
  const timer = setTimeout(() => {
74
74
  timedOut = true;
75
- proc.kill();
75
+ proc.kill("SIGKILL");
76
76
  }, timeoutMs);
77
77
  if (opts?.signal?.aborted)
78
78
  abort();
79
79
  else
80
80
  opts?.signal?.addEventListener("abort", abort, { once: true });
81
+ const outputs = [
82
+ readOutput(proc.stdout, opts?.onStdout, opts?.onStdoutBytes, opts?.collectStdout ?? true),
83
+ readOutput(proc.stderr, opts?.onStderr),
84
+ proc.exited
85
+ ];
81
86
  try {
82
- const [stdout, stderr, exitCode] = await Promise.all([
83
- readOutput(proc.stdout, opts?.onStdout, opts?.onStdoutBytes, opts?.collectStdout ?? true),
84
- readOutput(proc.stderr, opts?.onStderr),
85
- proc.exited
86
- ]);
87
+ const [stdout, stderr, exitCode] = await Promise.all(outputs);
87
88
  return {
88
- ok: exitCode === 0 && !timedOut,
89
+ ok: exitCode === 0 && !timedOut && !aborted,
89
90
  exitCode,
90
91
  stdout,
91
92
  stderr: timedOut ? `${stderr}
@@ -96,6 +97,8 @@ async function runArgv(argv, opts) {
96
97
  command: argv
97
98
  };
98
99
  } catch (err) {
100
+ proc.kill("SIGKILL");
101
+ await Promise.allSettled(outputs);
99
102
  return {
100
103
  ok: false,
101
104
  exitCode: null,
@@ -3,10 +3,10 @@ import {
3
3
  } from "./chunk-ssj93brx.js";
4
4
  import {
5
5
  startPortForward
6
- } from "./chunk-mvkxs8d0.js";
6
+ } from "./chunk-v9rcxg0e.js";
7
7
  import {
8
8
  KubectlExecutor
9
- } from "./chunk-rq5fc007.js";
9
+ } from "./chunk-evb5tj13.js";
10
10
  import {
11
11
  Transport
12
12
  } from "./chunk-6rcyw5ek.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildKubectlArgs
3
- } from "./chunk-rq5fc007.js";
3
+ } from "./chunk-evb5tj13.js";
4
4
  import {
5
5
  spawnProcess
6
6
  } from "./chunk-9shz0bw1.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  ServicePortForwarder
3
- } from "./chunk-0d8vs5q8.js";
3
+ } from "./chunk-91xh8tsr.js";
4
4
  import {
5
5
  KubectlExecutor
6
- } from "./chunk-rq5fc007.js";
6
+ } from "./chunk-evb5tj13.js";
7
7
  import {
8
8
  Transport
9
9
  } from "./chunk-6rcyw5ek.js";
@@ -2,16 +2,16 @@ import {
2
2
  HttpClient
3
3
  } from "../chunk-81agmerq.js";
4
4
  import"../chunk-ps7f1x05.js";
5
- import"../chunk-9d0ph5km.js";
5
+ import"../chunk-s7a3fqzc.js";
6
6
  import"../chunk-v3hxvnrc.js";
7
7
  import"../chunk-c2b2jwm4.js";
8
8
  import"../chunk-ssj93brx.js";
9
- import"../chunk-47x0r2kr.js";
10
- import"../chunk-0d8vs5q8.js";
9
+ import"../chunk-xv3nn2vd.js";
10
+ import"../chunk-91xh8tsr.js";
11
11
  import"../chunk-xgnz10sr.js";
12
12
  import"../chunk-6fnhzhdb.js";
13
- import"../chunk-mvkxs8d0.js";
14
- import"../chunk-rq5fc007.js";
13
+ import"../chunk-v9rcxg0e.js";
14
+ import"../chunk-evb5tj13.js";
15
15
  import"../chunk-9shz0bw1.js";
16
16
  import"../chunk-6rcyw5ek.js";
17
17
  import"../chunk-9f9dsjnr.js";
@@ -2,16 +2,16 @@ import {
2
2
  HttpClient
3
3
  } from "../chunk-81agmerq.js";
4
4
  import"../chunk-ps7f1x05.js";
5
- import"../chunk-9d0ph5km.js";
5
+ import"../chunk-s7a3fqzc.js";
6
6
  import"../chunk-v3hxvnrc.js";
7
7
  import"../chunk-c2b2jwm4.js";
8
8
  import"../chunk-ssj93brx.js";
9
- import"../chunk-47x0r2kr.js";
10
- import"../chunk-0d8vs5q8.js";
9
+ import"../chunk-xv3nn2vd.js";
10
+ import"../chunk-91xh8tsr.js";
11
11
  import"../chunk-xgnz10sr.js";
12
12
  import"../chunk-6fnhzhdb.js";
13
- import"../chunk-mvkxs8d0.js";
14
- import"../chunk-rq5fc007.js";
13
+ import"../chunk-v9rcxg0e.js";
14
+ import"../chunk-evb5tj13.js";
15
15
  import"../chunk-9shz0bw1.js";
16
16
  import"../chunk-6rcyw5ek.js";
17
17
  import"../chunk-9f9dsjnr.js";
@@ -0,0 +1,24 @@
1
+ import { type ErrorKind } from "../errors";
2
+ import type { Executor } from "./executor";
3
+ export interface AppArmorUnconfinedAdmissionInput {
4
+ namespace: string;
5
+ serviceAccountName: string;
6
+ image: string;
7
+ }
8
+ export interface AppArmorUnconfinedAdmissionResult {
9
+ target: AppArmorUnconfinedAdmissionInput;
10
+ observedAt: string;
11
+ status: "allowed" | "denied" | "unknown";
12
+ reason?: string;
13
+ errorKind?: ErrorKind;
14
+ }
15
+ /**
16
+ * @spec Probe AppArmor Unconfined admission as the supplied ServiceAccount using server-side dry-run only.
17
+ * @rule Admission acceptance does not prove Node support. Generic RBAC/auth/transport failures remain unknown.
18
+ * @rule Caller owns target selection, authorization and executor lifecycle; no workload or Service discovery occurs.
19
+ * @link docs/toolbox.md
20
+ */
21
+ export declare function probeAppArmorUnconfinedAdmission(executor: Pick<Executor, "run">, input: AppArmorUnconfinedAdmissionInput, options: {
22
+ timeoutMs: number;
23
+ signal?: AbortSignal;
24
+ }): Promise<AppArmorUnconfinedAdmissionResult>;
@@ -0,0 +1,60 @@
1
+ import {
2
+ KubernetesError,
3
+ kubernetesCommandError
4
+ } from "../chunk-68zz17hs.js";
5
+
6
+ // src/kubernetes/apparmor.ts
7
+ async function probeAppArmorUnconfinedAdmission(executor, input, options) {
8
+ if (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0 || !input.image.trim() || !/^[a-z0-9][a-z0-9-]*$/.test(input.namespace) || !/^[a-z0-9][a-z0-9.-]*$/.test(input.serviceAccountName)) {
9
+ throw new KubernetesError("AppArmor admission requires namespace, ServiceAccount, image and positive timeout", { kind: "invalid_argument" });
10
+ }
11
+ options.signal?.throwIfAborted();
12
+ const result = { target: { ...input }, observedAt: new Date().toISOString(), status: "unknown" };
13
+ const manifest = {
14
+ apiVersion: "v1",
15
+ kind: "Pod",
16
+ metadata: { generateName: "apparmor-unconfined-probe-", namespace: input.namespace },
17
+ spec: { serviceAccountName: input.serviceAccountName, restartPolicy: "Never", containers: [{
18
+ name: "probe",
19
+ image: input.image,
20
+ securityContext: {
21
+ appArmorProfile: { type: "Unconfined" },
22
+ allowPrivilegeEscalation: false,
23
+ capabilities: { drop: ["ALL"] },
24
+ runAsNonRoot: true,
25
+ runAsUser: 65532,
26
+ seccompProfile: { type: "RuntimeDefault" }
27
+ }
28
+ }] }
29
+ };
30
+ try {
31
+ const execution = await executor.run([
32
+ "create",
33
+ "-f",
34
+ "-",
35
+ "--dry-run=server",
36
+ "-o",
37
+ "json",
38
+ "--namespace",
39
+ input.namespace,
40
+ "--as",
41
+ `system:serviceaccount:${input.namespace}:${input.serviceAccountName}`
42
+ ], { ...options, stdin: JSON.stringify(manifest) });
43
+ options.signal?.throwIfAborted();
44
+ if (execution.ok)
45
+ return { ...result, status: "allowed" };
46
+ const output = `${execution.stderr}
47
+ ${execution.stdout}`;
48
+ if (!execution.timedOut && /apparmor/i.test(output) && /unconfined/i.test(output) && /(?:admission|violates\s+podsecurity)/i.test(output) && /(denied|forbidden|violates\s+podsecurity)/i.test(output)) {
49
+ return { ...result, status: "denied", reason: "Admission rejected AppArmor Unconfined" };
50
+ }
51
+ throw kubernetesCommandError(execution);
52
+ } catch (error) {
53
+ options.signal?.throwIfAborted();
54
+ const kind = error instanceof KubernetesError ? error.kind : "operation_failed";
55
+ return { ...result, errorKind: kind, reason: `AppArmor admission could not be determined: ${kind}` };
56
+ }
57
+ }
58
+ export {
59
+ probeAppArmorUnconfinedAdmission
60
+ };
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  KubernetesClient
3
- } from "../chunk-226wxr2s.js";
4
- import"../chunk-d2y5ewbb.js";
3
+ } from "../chunk-7mc2jevr.js";
5
4
  import"../chunk-361x998p.js";
5
+ import"../chunk-d2y5ewbb.js";
6
6
  import"../chunk-jt8fn3wg.js";
7
- import"../chunk-0zcq74ep.js";
7
+ import"../chunk-dfpqr0r9.js";
8
8
  import"../chunk-a9htb6cr.js";
9
9
  import"../chunk-v3hxvnrc.js";
10
- import"../chunk-0d8vs5q8.js";
10
+ import"../chunk-91xh8tsr.js";
11
11
  import"../chunk-xgnz10sr.js";
12
12
  import"../chunk-6fnhzhdb.js";
13
- import"../chunk-mvkxs8d0.js";
14
- import"../chunk-rq5fc007.js";
13
+ import"../chunk-v9rcxg0e.js";
14
+ import"../chunk-evb5tj13.js";
15
15
  import"../chunk-9shz0bw1.js";
16
16
  import"../chunk-68zz17hs.js";
17
17
  export {
@@ -0,0 +1,36 @@
1
+ import type { WorkloadInstance } from "@compforge/harness-common";
2
+ import { type ErrorKind } from "../errors";
3
+ import type { KubernetesClient } from "./client";
4
+ import type { ResourceAccess } from "./resources";
5
+ export interface KubernetesEnvironmentAccess {
6
+ /** Explicit cluster-scoped resource view; Pod requests supply their namespace, Node requests do not. */
7
+ resources: Pick<ResourceAccess, "get">;
8
+ /** Borrow the caller's authorized exec channel; this function never creates or disposes a client. */
9
+ exec: KubernetesClient["exec"];
10
+ }
11
+ export interface KubernetesEnvironmentIssue {
12
+ source: "pod" | "pod.ip_forward" | "node" | `node.${string}`;
13
+ kind: ErrorKind;
14
+ message: string;
15
+ }
16
+ export interface KubernetesEnvironmentInspection {
17
+ instance: WorkloadInstance;
18
+ observedAt: string;
19
+ status: "complete" | "partial" | "unavailable";
20
+ /** Value in the sampled Pod's network namespace, not proof of the host setting. */
21
+ podIpForward?: 0 | 1;
22
+ container?: string;
23
+ nodeName?: string;
24
+ nodeInfo: Partial<Record<"operatingSystem" | "osImage" | "kernelVersion" | "architecture", string>>;
25
+ issues: KubernetesEnvironmentIssue[];
26
+ }
27
+ /**
28
+ * @spec Inspect only the supplied WorkloadInstance and its Node. Discovery and sampling belong to the caller.
29
+ * @rule Reject a Pod already replaced at the identity read; later name-addressed exec is not atomic with that read.
30
+ * @rule ip_forward is Pod-netns scoped; OS metadata comes from Node status.nodeInfo, never the container image.
31
+ * @link docs/toolbox.md
32
+ */
33
+ export declare function inspectKubernetesEnvironment(access: KubernetesEnvironmentAccess, instance: WorkloadInstance, options: {
34
+ timeoutMs: number;
35
+ signal?: AbortSignal;
36
+ }): Promise<KubernetesEnvironmentInspection>;
@@ -0,0 +1,107 @@
1
+ import {
2
+ KubernetesError
3
+ } from "../chunk-68zz17hs.js";
4
+
5
+ // src/kubernetes/environment-inspection.ts
6
+ function object(value) {
7
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
8
+ }
9
+ function text(value) {
10
+ return typeof value === "string" && value.trim() ? value : undefined;
11
+ }
12
+ function issue(source, error) {
13
+ const kind = error instanceof KubernetesError ? error.kind : "operation_failed";
14
+ return { source, kind, message: `Kubernetes environment read failed: ${kind}` };
15
+ }
16
+ async function inspectKubernetesEnvironment(access, instance, options) {
17
+ if (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0 || instance.platform !== "kubernetes" || [instance.environment, instance.workload, instance.namespace, instance.pod, instance.uid].some((value) => !value?.trim())) {
18
+ throw new KubernetesError("Environment inspection requires a WorkloadInstance and positive timeout", { kind: "invalid_argument" });
19
+ }
20
+ const deadline = performance.now() + options.timeoutMs;
21
+ const request = () => {
22
+ options.signal?.throwIfAborted();
23
+ const timeoutMs = Math.ceil(deadline - performance.now());
24
+ if (timeoutMs <= 0)
25
+ throw new KubernetesError("Environment inspection budget exhausted", { kind: "timeout" });
26
+ return { timeoutMs, signal: options.signal };
27
+ };
28
+ const result = {
29
+ instance: { ...instance },
30
+ observedAt: new Date().toISOString(),
31
+ status: "unavailable",
32
+ nodeInfo: {},
33
+ issues: []
34
+ };
35
+ let pod;
36
+ try {
37
+ pod = await access.resources.get({ apiVersion: "v1", resource: "pods", namespace: instance.namespace, name: instance.pod }, request());
38
+ options.signal?.throwIfAborted();
39
+ const meta = object(pod.metadata);
40
+ if (meta.uid !== instance.uid || meta.name !== instance.pod || meta.namespace !== instance.namespace) {
41
+ throw new KubernetesError("Pod identity changed or is missing", { kind: "invalid_response" });
42
+ }
43
+ } catch (error) {
44
+ options.signal?.throwIfAborted();
45
+ result.issues.push(issue("pod", error));
46
+ return result;
47
+ }
48
+ const spec = object(pod.spec), status = object(pod.status);
49
+ const containers = Array.isArray(spec.containers) ? spec.containers.map(object) : [];
50
+ const container = instance.container ? containers.find((item) => item.name === instance.container) : containers.length === 1 ? containers[0] : undefined;
51
+ result.container = text(container?.name);
52
+ result.nodeName = text(spec.nodeName);
53
+ const [forwardingIssues, nodeIssues] = await Promise.all([
54
+ (async () => {
55
+ try {
56
+ if (!result.container)
57
+ throw new KubernetesError("Target container is absent or ambiguous", { kind: "invalid_argument" });
58
+ const states = Array.isArray(status.containerStatuses) ? status.containerStatuses.map(object) : [];
59
+ if (status.phase !== "Running" || !object(states.find((item) => item.name === result.container)?.state).running) {
60
+ throw new KubernetesError("Target container is not running", { kind: "unsupported_operation" });
61
+ }
62
+ const execution = await access.exec(instance.namespace, { pod: instance.pod, container: result.container }, ["cat", "/proc/sys/net/ipv4/ip_forward"], request());
63
+ options.signal?.throwIfAborted();
64
+ if (!execution.ok)
65
+ throw new KubernetesError("Could not read ip_forward", { kind: execution.timedOut ? "timeout" : "operation_failed" });
66
+ const value = execution.stdout.trim();
67
+ if (value !== "0" && value !== "1")
68
+ throw new KubernetesError("Invalid ip_forward response", { kind: "invalid_response" });
69
+ result.podIpForward = value === "1" ? 1 : 0;
70
+ return [];
71
+ } catch (error) {
72
+ options.signal?.throwIfAborted();
73
+ return [issue("pod.ip_forward", error)];
74
+ }
75
+ })(),
76
+ (async () => {
77
+ try {
78
+ if (!result.nodeName)
79
+ throw new KubernetesError("Pod nodeName is absent", { kind: "resource_not_found" });
80
+ const node = await access.resources.get({ apiVersion: "v1", resource: "nodes", name: result.nodeName }, request());
81
+ options.signal?.throwIfAborted();
82
+ if (node.metadata?.name !== result.nodeName)
83
+ throw new KubernetesError("Node identity is missing or mismatched", { kind: "invalid_response" });
84
+ const info = object(object(node.status).nodeInfo);
85
+ const issues = [];
86
+ for (const field of ["operatingSystem", "osImage", "kernelVersion", "architecture"]) {
87
+ const value = text(info[field]);
88
+ if (value)
89
+ result.nodeInfo[field] = value;
90
+ else
91
+ issues.push({ source: `node.${field}`, kind: "invalid_response", message: `Node status.nodeInfo.${field} is missing` });
92
+ }
93
+ return issues;
94
+ } catch (error) {
95
+ options.signal?.throwIfAborted();
96
+ return [issue("node", error)];
97
+ }
98
+ })()
99
+ ]);
100
+ options.signal?.throwIfAborted();
101
+ result.issues.push(...forwardingIssues, ...nodeIssues);
102
+ result.status = !result.issues.length ? "complete" : result.podIpForward !== undefined || Object.keys(result.nodeInfo).length ? "partial" : "unavailable";
103
+ return result;
104
+ }
105
+ export {
106
+ inspectKubernetesEnvironment
107
+ };
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  KubernetesClient
3
- } from "../chunk-226wxr2s.js";
4
- import"../chunk-d2y5ewbb.js";
3
+ } from "../chunk-7mc2jevr.js";
5
4
  import"../chunk-361x998p.js";
5
+ import"../chunk-d2y5ewbb.js";
6
6
  import"../chunk-jt8fn3wg.js";
7
- import"../chunk-0zcq74ep.js";
7
+ import"../chunk-dfpqr0r9.js";
8
8
  import {
9
9
  clientKey
10
10
  } from "../chunk-a9htb6cr.js";
11
11
  import"../chunk-v3hxvnrc.js";
12
- import"../chunk-0d8vs5q8.js";
12
+ import"../chunk-91xh8tsr.js";
13
13
  import"../chunk-xgnz10sr.js";
14
14
  import"../chunk-6fnhzhdb.js";
15
- import"../chunk-mvkxs8d0.js";
16
- import"../chunk-rq5fc007.js";
15
+ import"../chunk-v9rcxg0e.js";
16
+ import"../chunk-evb5tj13.js";
17
17
  import"../chunk-9shz0bw1.js";
18
18
  import"../chunk-68zz17hs.js";
19
19
 
@@ -1,4 +1,4 @@
1
- import type { ExecTarget, ExecResult, RunOptions } from "./executor";
1
+ import { type ExecTarget, type ExecResult, type RunOptions } from "./executor";
2
2
  import type { KubernetesConnectionOptions } from "./resource-transport";
3
3
  export interface KubernetesExecLimits {
4
4
  timeoutMs: number;
@@ -12,8 +12,9 @@ export interface KubernetesExecLimits {
12
12
  */
13
13
  export declare class KubernetesExecTransport {
14
14
  #private;
15
+ private readonly connection;
15
16
  private readonly signal;
16
17
  private readonly limits;
17
- constructor(options: KubernetesConnectionOptions, signal: AbortSignal, limits: KubernetesExecLimits);
18
+ constructor(connection: KubernetesConnectionOptions, signal: AbortSignal, limits: KubernetesExecLimits);
18
19
  exec(namespace: string, target: ExecTarget, command: string[], options?: RunOptions): Promise<ExecResult>;
19
20
  }
@@ -1,7 +1,9 @@
1
1
  import {
2
2
  KubernetesExecTransport
3
- } from "../chunk-0zcq74ep.js";
3
+ } from "../chunk-dfpqr0r9.js";
4
4
  import"../chunk-v3hxvnrc.js";
5
+ import"../chunk-evb5tj13.js";
6
+ import"../chunk-9shz0bw1.js";
5
7
  import"../chunk-68zz17hs.js";
6
8
  export {
7
9
  KubernetesExecTransport
@@ -3,7 +3,7 @@ import {
3
3
  buildExecArgs,
4
4
  buildKubectlArgs,
5
5
  runArgv
6
- } from "../chunk-rq5fc007.js";
6
+ } from "../chunk-evb5tj13.js";
7
7
  import"../chunk-9shz0bw1.js";
8
8
  export {
9
9
  runArgv,
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  PodLogClient
3
- } from "../chunk-mnad4zkp.js";
3
+ } from "../chunk-010339ga.js";
4
4
  import"../chunk-8nm9f0hh.js";
5
- import"../chunk-mp88s7r7.js";
6
5
  import"../chunk-1vfwvgkj.js";
6
+ import"../chunk-mp88s7r7.js";
7
7
  import"../chunk-a9htb6cr.js";
8
8
  import"../chunk-v3hxvnrc.js";
9
9
  export {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  PodLogClient
3
- } from "../chunk-mnad4zkp.js";
3
+ } from "../chunk-010339ga.js";
4
4
  import"../chunk-8nm9f0hh.js";
5
- import"../chunk-mp88s7r7.js";
6
5
  import"../chunk-1vfwvgkj.js";
6
+ import"../chunk-mp88s7r7.js";
7
7
  import"../chunk-a9htb6cr.js";
8
8
  import {
9
9
  clientKey
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  PortForwardScope,
3
3
  startPortForward
4
- } from "../chunk-mvkxs8d0.js";
5
- import"../chunk-rq5fc007.js";
4
+ } from "../chunk-v9rcxg0e.js";
5
+ import"../chunk-evb5tj13.js";
6
6
  import"../chunk-9shz0bw1.js";
7
7
  export {
8
8
  startPortForward,
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  ServicePortForwarder
3
- } from "../chunk-0d8vs5q8.js";
3
+ } from "../chunk-91xh8tsr.js";
4
4
  import"../chunk-xgnz10sr.js";
5
5
  import"../chunk-6fnhzhdb.js";
6
- import"../chunk-mvkxs8d0.js";
7
- import"../chunk-rq5fc007.js";
6
+ import"../chunk-v9rcxg0e.js";
7
+ import"../chunk-evb5tj13.js";
8
8
  import"../chunk-9shz0bw1.js";
9
9
  export {
10
10
  ServicePortForwarder
@@ -7,15 +7,15 @@ import"../chunk-m91t44jh.js";
7
7
  import"../chunk-db4an9td.js";
8
8
  import"../chunk-835fssgz.js";
9
9
  import"../chunk-ps7f1x05.js";
10
- import"../chunk-9d0ph5km.js";
10
+ import"../chunk-s7a3fqzc.js";
11
11
  import"../chunk-v3hxvnrc.js";
12
12
  import"../chunk-ssj93brx.js";
13
- import"../chunk-47x0r2kr.js";
14
- import"../chunk-0d8vs5q8.js";
13
+ import"../chunk-xv3nn2vd.js";
14
+ import"../chunk-91xh8tsr.js";
15
15
  import"../chunk-xgnz10sr.js";
16
16
  import"../chunk-6fnhzhdb.js";
17
- import"../chunk-mvkxs8d0.js";
18
- import"../chunk-rq5fc007.js";
17
+ import"../chunk-v9rcxg0e.js";
18
+ import"../chunk-evb5tj13.js";
19
19
  import"../chunk-9shz0bw1.js";
20
20
  import"../chunk-6rcyw5ek.js";
21
21
  import"../chunk-9f9dsjnr.js";
@@ -19,15 +19,15 @@ import {
19
19
  } from "../chunk-1gyshqd9.js";
20
20
  import"../chunk-835fssgz.js";
21
21
  import"../chunk-ps7f1x05.js";
22
- import"../chunk-9d0ph5km.js";
22
+ import"../chunk-s7a3fqzc.js";
23
23
  import"../chunk-v3hxvnrc.js";
24
24
  import"../chunk-ssj93brx.js";
25
- import"../chunk-47x0r2kr.js";
26
- import"../chunk-0d8vs5q8.js";
25
+ import"../chunk-xv3nn2vd.js";
26
+ import"../chunk-91xh8tsr.js";
27
27
  import"../chunk-xgnz10sr.js";
28
28
  import"../chunk-6fnhzhdb.js";
29
- import"../chunk-mvkxs8d0.js";
30
- import"../chunk-rq5fc007.js";
29
+ import"../chunk-v9rcxg0e.js";
30
+ import"../chunk-evb5tj13.js";
31
31
  import"../chunk-9shz0bw1.js";
32
32
  import"../chunk-6rcyw5ek.js";
33
33
  import"../chunk-9f9dsjnr.js";
@@ -7,14 +7,14 @@ import {
7
7
  openSearchServername
8
8
  } from "../chunk-6dfcndra.js";
9
9
  import"../chunk-ps7f1x05.js";
10
- import"../chunk-9d0ph5km.js";
10
+ import"../chunk-s7a3fqzc.js";
11
11
  import"../chunk-ssj93brx.js";
12
- import"../chunk-47x0r2kr.js";
13
- import"../chunk-0d8vs5q8.js";
12
+ import"../chunk-xv3nn2vd.js";
13
+ import"../chunk-91xh8tsr.js";
14
14
  import"../chunk-xgnz10sr.js";
15
15
  import"../chunk-6fnhzhdb.js";
16
- import"../chunk-mvkxs8d0.js";
17
- import"../chunk-rq5fc007.js";
16
+ import"../chunk-v9rcxg0e.js";
17
+ import"../chunk-evb5tj13.js";
18
18
  import"../chunk-9shz0bw1.js";
19
19
  import"../chunk-6rcyw5ek.js";
20
20
  import"../chunk-9f9dsjnr.js";
@@ -14,14 +14,14 @@ import {
14
14
  openSearchServername
15
15
  } from "../chunk-6dfcndra.js";
16
16
  import"../chunk-ps7f1x05.js";
17
- import"../chunk-9d0ph5km.js";
17
+ import"../chunk-s7a3fqzc.js";
18
18
  import"../chunk-ssj93brx.js";
19
- import"../chunk-47x0r2kr.js";
20
- import"../chunk-0d8vs5q8.js";
19
+ import"../chunk-xv3nn2vd.js";
20
+ import"../chunk-91xh8tsr.js";
21
21
  import"../chunk-xgnz10sr.js";
22
22
  import"../chunk-6fnhzhdb.js";
23
- import"../chunk-mvkxs8d0.js";
24
- import"../chunk-rq5fc007.js";
23
+ import"../chunk-v9rcxg0e.js";
24
+ import"../chunk-evb5tj13.js";
25
25
  import"../chunk-9shz0bw1.js";
26
26
  import"../chunk-6rcyw5ek.js";
27
27
  import"../chunk-9f9dsjnr.js";
@@ -7,14 +7,14 @@ import {
7
7
  } from "../chunk-ywk81p8a.js";
8
8
  import"../chunk-5tbzf9wd.js";
9
9
  import"../chunk-ps7f1x05.js";
10
- import"../chunk-9d0ph5km.js";
10
+ import"../chunk-s7a3fqzc.js";
11
11
  import"../chunk-ssj93brx.js";
12
- import"../chunk-47x0r2kr.js";
13
- import"../chunk-0d8vs5q8.js";
12
+ import"../chunk-xv3nn2vd.js";
13
+ import"../chunk-91xh8tsr.js";
14
14
  import"../chunk-xgnz10sr.js";
15
15
  import"../chunk-6fnhzhdb.js";
16
- import"../chunk-mvkxs8d0.js";
17
- import"../chunk-rq5fc007.js";
16
+ import"../chunk-v9rcxg0e.js";
17
+ import"../chunk-evb5tj13.js";
18
18
  import"../chunk-9shz0bw1.js";
19
19
  import"../chunk-6rcyw5ek.js";
20
20
  import"../chunk-9f9dsjnr.js";
@@ -13,14 +13,14 @@ import {
13
13
  discoverRedisTopology
14
14
  } from "../chunk-5tbzf9wd.js";
15
15
  import"../chunk-ps7f1x05.js";
16
- import"../chunk-9d0ph5km.js";
16
+ import"../chunk-s7a3fqzc.js";
17
17
  import"../chunk-ssj93brx.js";
18
- import"../chunk-47x0r2kr.js";
19
- import"../chunk-0d8vs5q8.js";
18
+ import"../chunk-xv3nn2vd.js";
19
+ import"../chunk-91xh8tsr.js";
20
20
  import"../chunk-xgnz10sr.js";
21
21
  import"../chunk-6fnhzhdb.js";
22
- import"../chunk-mvkxs8d0.js";
23
- import"../chunk-rq5fc007.js";
22
+ import"../chunk-v9rcxg0e.js";
23
+ import"../chunk-evb5tj13.js";
24
24
  import"../chunk-9shz0bw1.js";
25
25
  import"../chunk-6rcyw5ek.js";
26
26
  import"../chunk-9f9dsjnr.js";
package/dist/s3/client.js CHANGED
@@ -2,17 +2,17 @@ import {
2
2
  S3Client
3
3
  } from "../chunk-mj6ckk1g.js";
4
4
  import"../chunk-ps7f1x05.js";
5
- import"../chunk-9d0ph5km.js";
5
+ import"../chunk-s7a3fqzc.js";
6
6
  import"../chunk-v3hxvnrc.js";
7
7
  import"../chunk-z8e1ckkq.js";
8
8
  import"../chunk-c2b2jwm4.js";
9
9
  import"../chunk-ssj93brx.js";
10
- import"../chunk-47x0r2kr.js";
11
- import"../chunk-0d8vs5q8.js";
10
+ import"../chunk-xv3nn2vd.js";
11
+ import"../chunk-91xh8tsr.js";
12
12
  import"../chunk-xgnz10sr.js";
13
13
  import"../chunk-6fnhzhdb.js";
14
- import"../chunk-mvkxs8d0.js";
15
- import"../chunk-rq5fc007.js";
14
+ import"../chunk-v9rcxg0e.js";
15
+ import"../chunk-evb5tj13.js";
16
16
  import"../chunk-9shz0bw1.js";
17
17
  import"../chunk-6rcyw5ek.js";
18
18
  import"../chunk-9f9dsjnr.js";
@@ -4,17 +4,17 @@ import {
4
4
  import"../chunk-z5pm2emz.js";
5
5
  import"../chunk-mj6ckk1g.js";
6
6
  import"../chunk-ps7f1x05.js";
7
- import"../chunk-9d0ph5km.js";
7
+ import"../chunk-s7a3fqzc.js";
8
8
  import"../chunk-v3hxvnrc.js";
9
9
  import"../chunk-z8e1ckkq.js";
10
10
  import"../chunk-c2b2jwm4.js";
11
11
  import"../chunk-ssj93brx.js";
12
- import"../chunk-47x0r2kr.js";
13
- import"../chunk-0d8vs5q8.js";
12
+ import"../chunk-xv3nn2vd.js";
13
+ import"../chunk-91xh8tsr.js";
14
14
  import"../chunk-xgnz10sr.js";
15
15
  import"../chunk-6fnhzhdb.js";
16
- import"../chunk-mvkxs8d0.js";
17
- import"../chunk-rq5fc007.js";
16
+ import"../chunk-v9rcxg0e.js";
17
+ import"../chunk-evb5tj13.js";
18
18
  import"../chunk-9shz0bw1.js";
19
19
  import"../chunk-6rcyw5ek.js";
20
20
  import"../chunk-9f9dsjnr.js";
package/dist/s3/index.js CHANGED
@@ -6,17 +6,17 @@ import {
6
6
  S3Client
7
7
  } from "../chunk-mj6ckk1g.js";
8
8
  import"../chunk-ps7f1x05.js";
9
- import"../chunk-9d0ph5km.js";
9
+ import"../chunk-s7a3fqzc.js";
10
10
  import"../chunk-v3hxvnrc.js";
11
11
  import"../chunk-z8e1ckkq.js";
12
12
  import"../chunk-c2b2jwm4.js";
13
13
  import"../chunk-ssj93brx.js";
14
- import"../chunk-47x0r2kr.js";
15
- import"../chunk-0d8vs5q8.js";
14
+ import"../chunk-xv3nn2vd.js";
15
+ import"../chunk-91xh8tsr.js";
16
16
  import"../chunk-xgnz10sr.js";
17
17
  import"../chunk-6fnhzhdb.js";
18
- import"../chunk-mvkxs8d0.js";
19
- import"../chunk-rq5fc007.js";
18
+ import"../chunk-v9rcxg0e.js";
19
+ import"../chunk-evb5tj13.js";
20
20
  import"../chunk-9shz0bw1.js";
21
21
  import"../chunk-6rcyw5ek.js";
22
22
  import"../chunk-9f9dsjnr.js";
@@ -6,16 +6,16 @@ import {
6
6
  } from "../chunk-ps7f1x05.js";
7
7
  import {
8
8
  PodRelayTransport
9
- } from "../chunk-9d0ph5km.js";
9
+ } from "../chunk-s7a3fqzc.js";
10
10
  import"../chunk-ssj93brx.js";
11
11
  import {
12
12
  ServicePortForwardTransport
13
- } from "../chunk-47x0r2kr.js";
14
- import"../chunk-0d8vs5q8.js";
13
+ } from "../chunk-xv3nn2vd.js";
14
+ import"../chunk-91xh8tsr.js";
15
15
  import"../chunk-xgnz10sr.js";
16
16
  import"../chunk-6fnhzhdb.js";
17
- import"../chunk-mvkxs8d0.js";
18
- import"../chunk-rq5fc007.js";
17
+ import"../chunk-v9rcxg0e.js";
18
+ import"../chunk-evb5tj13.js";
19
19
  import"../chunk-9shz0bw1.js";
20
20
  import {
21
21
  Transport
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  PodRelayTransport
3
- } from "../chunk-9d0ph5km.js";
3
+ } from "../chunk-s7a3fqzc.js";
4
4
  import"../chunk-ssj93brx.js";
5
- import"../chunk-mvkxs8d0.js";
6
- import"../chunk-rq5fc007.js";
5
+ import"../chunk-v9rcxg0e.js";
6
+ import"../chunk-evb5tj13.js";
7
7
  import"../chunk-9shz0bw1.js";
8
8
  import"../chunk-6rcyw5ek.js";
9
9
  import"../chunk-9f9dsjnr.js";
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  ServicePortForwardTransport
3
- } from "../chunk-47x0r2kr.js";
4
- import"../chunk-0d8vs5q8.js";
3
+ } from "../chunk-xv3nn2vd.js";
4
+ import"../chunk-91xh8tsr.js";
5
5
  import"../chunk-xgnz10sr.js";
6
6
  import"../chunk-6fnhzhdb.js";
7
- import"../chunk-mvkxs8d0.js";
8
- import"../chunk-rq5fc007.js";
7
+ import"../chunk-v9rcxg0e.js";
8
+ import"../chunk-evb5tj13.js";
9
9
  import"../chunk-9shz0bw1.js";
10
10
  import"../chunk-6rcyw5ek.js";
11
11
  import"../chunk-9f9dsjnr.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compforge/harness-toolbox",
3
- "version": "0.5.5",
3
+ "version": "0.6.1",
4
4
  "description": "Shared infrastructure clients, transports and bounded data capture",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -112,7 +112,7 @@
112
112
  ],
113
113
  "dependencies": {
114
114
  "@aws-sdk/client-s3": "3.1133.0",
115
- "@compforge/harness-common": "0.5.13",
115
+ "@compforge/harness-common": "0.6.0",
116
116
  "@kubernetes/client-node": "1.4.0",
117
117
  "@opensearch-project/opensearch": "3.6.0",
118
118
  "@redis/client": "6.1.0",
@@ -2,12 +2,12 @@ import {
2
2
  PodLogByteBudget,
3
3
  runPodLogCapturePlan
4
4
  } from "./chunk-8nm9f0hh.js";
5
- import {
6
- logTimestampNanos
7
- } from "./chunk-mp88s7r7.js";
8
5
  import {
9
6
  LogCaptureFile
10
7
  } from "./chunk-1vfwvgkj.js";
8
+ import {
9
+ logTimestampNanos
10
+ } from "./chunk-mp88s7r7.js";
11
11
  import {
12
12
  clientKey
13
13
  } from "./chunk-a9htb6cr.js";