@namzu/sandbox 13.0.0 → 14.0.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 (67) hide show
  1. package/CHANGELOG.md +309 -0
  2. package/README.md +151 -0
  3. package/dist/backends/firecracker/protocol.d.ts +22 -0
  4. package/dist/backends/firecracker/protocol.d.ts.map +1 -1
  5. package/dist/backends/firecracker/protocol.js.map +1 -1
  6. package/dist/backends/firecracker/transport.d.ts +104 -9
  7. package/dist/backends/firecracker/transport.d.ts.map +1 -1
  8. package/dist/backends/firecracker/transport.js +139 -13
  9. package/dist/backends/firecracker/transport.js.map +1 -1
  10. package/dist/backends/kubernetes/egress-policy.d.ts +219 -0
  11. package/dist/backends/kubernetes/egress-policy.d.ts.map +1 -0
  12. package/dist/backends/kubernetes/egress-policy.js +314 -0
  13. package/dist/backends/kubernetes/egress-policy.js.map +1 -0
  14. package/dist/backends/kubernetes/index.d.ts +374 -0
  15. package/dist/backends/kubernetes/index.d.ts.map +1 -0
  16. package/dist/backends/kubernetes/index.js +671 -0
  17. package/dist/backends/kubernetes/index.js.map +1 -0
  18. package/dist/backends/kubernetes/k8s-client.d.ts +125 -0
  19. package/dist/backends/kubernetes/k8s-client.d.ts.map +1 -0
  20. package/dist/backends/kubernetes/k8s-client.js +246 -0
  21. package/dist/backends/kubernetes/k8s-client.js.map +1 -0
  22. package/dist/backends/kubernetes/lease.d.ts +119 -0
  23. package/dist/backends/kubernetes/lease.d.ts.map +1 -0
  24. package/dist/backends/kubernetes/lease.js +151 -0
  25. package/dist/backends/kubernetes/lease.js.map +1 -0
  26. package/dist/backends/kubernetes/objects.d.ts +282 -0
  27. package/dist/backends/kubernetes/objects.d.ts.map +1 -0
  28. package/dist/backends/kubernetes/objects.js +156 -0
  29. package/dist/backends/kubernetes/objects.js.map +1 -0
  30. package/dist/backends/kubernetes/privilege-probe.d.ts +136 -0
  31. package/dist/backends/kubernetes/privilege-probe.d.ts.map +1 -0
  32. package/dist/backends/kubernetes/privilege-probe.js +185 -0
  33. package/dist/backends/kubernetes/privilege-probe.js.map +1 -0
  34. package/dist/backends/kubernetes/sandbox.d.ts +123 -0
  35. package/dist/backends/kubernetes/sandbox.d.ts.map +1 -0
  36. package/dist/backends/kubernetes/sandbox.js +299 -0
  37. package/dist/backends/kubernetes/sandbox.js.map +1 -0
  38. package/dist/backends/kubernetes/transport.d.ts +122 -0
  39. package/dist/backends/kubernetes/transport.d.ts.map +1 -0
  40. package/dist/backends/kubernetes/transport.js +197 -0
  41. package/dist/backends/kubernetes/transport.js.map +1 -0
  42. package/dist/backends/kubernetes/workspace.d.ts +381 -0
  43. package/dist/backends/kubernetes/workspace.d.ts.map +1 -0
  44. package/dist/backends/kubernetes/workspace.js +1064 -0
  45. package/dist/backends/kubernetes/workspace.js.map +1 -0
  46. package/dist/index.d.ts +132 -2
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +102 -34
  49. package/dist/index.js.map +1 -1
  50. package/dist/testing/sandbox-conformance.d.ts +193 -0
  51. package/dist/testing/sandbox-conformance.d.ts.map +1 -0
  52. package/dist/testing/sandbox-conformance.js +465 -0
  53. package/dist/testing/sandbox-conformance.js.map +1 -0
  54. package/package.json +5 -4
  55. package/src/backends/firecracker/protocol.ts +27 -0
  56. package/src/backends/firecracker/transport.ts +199 -28
  57. package/src/backends/kubernetes/egress-policy.ts +437 -0
  58. package/src/backends/kubernetes/index.ts +1012 -0
  59. package/src/backends/kubernetes/k8s-client.ts +352 -0
  60. package/src/backends/kubernetes/lease.ts +198 -0
  61. package/src/backends/kubernetes/objects.ts +363 -0
  62. package/src/backends/kubernetes/privilege-probe.ts +261 -0
  63. package/src/backends/kubernetes/sandbox.ts +395 -0
  64. package/src/backends/kubernetes/transport.ts +286 -0
  65. package/src/backends/kubernetes/workspace.ts +1386 -0
  66. package/src/index.ts +257 -35
  67. package/src/testing/sandbox-conformance.ts +667 -0
@@ -0,0 +1,374 @@
1
+ /**
2
+ * Kubernetes / agent-sandbox backend — acquire, readiness and teardown.
3
+ *
4
+ * Sibling of `firecracker/` and `aci-standby-pool/`: same
5
+ * {@link SandboxBackend} surface, same "the host supplies the credential
6
+ * callback and this package carries no cloud SDK" boundary, a different
7
+ * control plane. Here the control plane is the Kubernetes API server and the
8
+ * warm pool is a `SandboxWarmPool` reconciled by the agent-sandbox controller
9
+ * (kubernetes-sigs/agent-sandbox v1.0.2).
10
+ *
11
+ * Registered as `microvm` because {@link SandboxTier} names the strength of
12
+ * the boundary, not the orchestrator that starts it: a pod scheduled onto a
13
+ * Kata RuntimeClass runs in a hardware-virtualized guest. The tier also keeps
14
+ * the backend out of the container tier's mandatory
15
+ * `ContainerSandboxLayout`, which a remote-copy backend has no use for —
16
+ * Firecracker took the same exemption.
17
+ *
18
+ * ## Two acquire paths, and why they create different kinds
19
+ *
20
+ * - `warmPoolName` set → POST a `SandboxClaim` at the named pool. The
21
+ * controller binds an already-running Sandbox out of the pool, which is
22
+ * what makes a sub-second acquire possible at all.
23
+ * - `warmPoolName` unset → POST a `Sandbox` directly. This is necessitated
24
+ * rather than chosen: `SandboxClaimSpec.warmPoolRef` is a REQUIRED field,
25
+ * so a pool-less claim does not exist in the API.
26
+ *
27
+ * The claim this backend POSTs is PRISTINE: `warmPoolRef` and a lifecycle
28
+ * bound, nothing else. `spec.env` and `spec.volumeClaimTemplates` are
29
+ * available on the claim and are never set, because a claim carrying either
30
+ * is forced to cold-start instead of adopting a pool sandbox — the single
31
+ * most expensive mistake available on this path, and a silent one, since such
32
+ * a claim still works and only the latency shows it. Per-sandbox controls
33
+ * that would need those fields are refused by {@link assertEnforceable}
34
+ * rather than accepted and dropped.
35
+ *
36
+ * ## The bound sandbox is not named after the claim
37
+ *
38
+ * A pool sandbox keeps the generated name the pool gave it when the claim
39
+ * adopts it. The backend therefore reads the bound identity back out of
40
+ * `status.sandbox` and never derives it from the claim's own name. A test
41
+ * covers exactly that asymmetry.
42
+ *
43
+ * ## Credential
44
+ *
45
+ * The per-instance agent bind token is the backing pod's own
46
+ * `metadata.uid`: the host learns it from the API server after readiness, the
47
+ * guest learns it through the downward API (`NAMZU_AGENT_BIND_TOKEN`), and
48
+ * nothing has to be minted, stored or injected at claim time. One GET, no
49
+ * claim mutation, so the warm path stays pristine. A resumed pod is a new pod
50
+ * with a new uid, which is correct: it is a new instance.
51
+ *
52
+ * ## The lease
53
+ *
54
+ * The `shutdownTime` acquire stamps is the leak guard AND, unrenewed, a
55
+ * deadline on the run. The Sandbox handle owns a renewal loop that PATCHes
56
+ * it forward every half-TTL for as long as the handle is alive, and
57
+ * `destroy()` stops it — so a live run keeps its pod and a dead host still
58
+ * costs the cluster exactly one expiry. See `lease.ts`.
59
+ *
60
+ * ## The privilege probe
61
+ *
62
+ * `create()` does not resolve until the guest has reported — and this
63
+ * backend has checked — that it is deprivileged: all four capability masks
64
+ * zero, `NoNewPrivs: 1`, read out of `/proc/self/status` over the agent's
65
+ * `execute` op, on a clock of its own so a guest that goes quiet is refused
66
+ * rather than waited on. A refusal destroys the instance and rejects, so no
67
+ * handle to an under-hardened sandbox escapes. There is no off switch. See
68
+ * `privilege-probe.ts`.
69
+ *
70
+ * ## Not watch
71
+ *
72
+ * Readiness is polled against the shared {@link OperationDeadline}, exactly as
73
+ * ACI polls `provisioningState`. A watch would buy nothing on a path whose
74
+ * whole budget is under a second, and would cost resourceVersion tracking,
75
+ * bookmarks, 410-relist and reconnect backoff.
76
+ *
77
+ * ## Egress
78
+ *
79
+ * `config.egress` is optional and, when set, translated and VERIFIED — never
80
+ * created — by `egress-policy.ts`. Verification happens once, lazily, on the
81
+ * first `create()`, so `buildKubernetesBackend` itself still contacts
82
+ * nothing. Every Sandbox this file creates directly (`buildSandboxBody`)
83
+ * carries {@link sandboxTemplateLabel} on its podTemplate specifically so
84
+ * that translated policy's `podSelector` has something stable to match —
85
+ * see `objects.ts`'s doc comment on that label for why agent-sandbox's own
86
+ * controller-owned label does not cover this path.
87
+ */
88
+ import type { Sandbox } from '@namzu/sdk';
89
+ import type { SandboxBackend, SandboxBackendOptions } from '../../index.js';
90
+ import { OperationDeadline } from '../readiness.js';
91
+ import { type KubernetesEgressConfig } from './egress-policy.js';
92
+ import { type KubernetesAccess, type KubernetesClient } from './k8s-client.js';
93
+ import { type SandboxPodTemplate, type SandboxResource, type SandboxVolumeClaimTemplate } from './objects.js';
94
+ export type { KubernetesEgressConfig, KubernetesEgressEngine } from './egress-policy.js';
95
+ /**
96
+ * How the backend reaches the API server. Two sources, neither needing a YAML
97
+ * parser — see `k8s-client.ts` for the reasoning.
98
+ */
99
+ export type KubernetesClusterAccess = {
100
+ readonly inCluster: true;
101
+ } | {
102
+ readonly inCluster?: false;
103
+ readonly server: string;
104
+ readonly ca?: string | Buffer;
105
+ readonly getToken: () => Promise<string>;
106
+ };
107
+ export interface KubernetesBackendInternalConfig {
108
+ readonly access: KubernetesClusterAccess;
109
+ /** Namespace the claims, sandboxes and pods live in. */
110
+ readonly namespace: string;
111
+ /**
112
+ * SandboxTemplate whose `podTemplate` a POOL-LESS create copies into the
113
+ * Sandbox it posts. The warm path never reads it — the pool's own
114
+ * `sandboxTemplateRef` decides there — but an operator reading this config
115
+ * still learns which template these sandboxes are built from.
116
+ */
117
+ readonly sandboxTemplateName: string;
118
+ /** Named `SandboxWarmPool`. Absent → every create is a direct Sandbox. */
119
+ readonly warmPoolName?: string;
120
+ /** TCP port the guest agent listens on. Default {@link DEFAULT_AGENT_PORT}. */
121
+ readonly agentPort?: number;
122
+ readonly readyPollIntervalMs?: number;
123
+ readonly readyTimeoutMs?: number;
124
+ /**
125
+ * Lifetime bound written into every created object, and the amount each
126
+ * lease renewal pushes the expiry forward. Default 1 hour.
127
+ */
128
+ readonly claimTtlSeconds?: number;
129
+ /**
130
+ * Every lease-renewal failure that is not "the object is already gone".
131
+ * `@namzu/sandbox` owns no logger and reads none from module scope, so a
132
+ * diagnostic it cannot print is handed to the host that can. Renewal
133
+ * retries on the next tick either way; nothing here changes behaviour.
134
+ */
135
+ readonly onLeaseRenewalError?: (error: unknown) => void;
136
+ /**
137
+ * RuntimeClass for a POOL-LESS create. Refused together with
138
+ * `warmPoolName`: a pooled sandbox's runtime class is fixed by the pool's
139
+ * SandboxTemplate and cannot be chosen per claim.
140
+ */
141
+ readonly runtimeClassName?: string;
142
+ /**
143
+ * Egress policy this backend's `NetworkPolicy` (or `CiliumNetworkPolicy`,
144
+ * under `engine: 'cilium'`) is expected to carry. Unset means this backend
145
+ * neither computes nor verifies one — the cluster's default posture (the
146
+ * SandboxTemplate's own managed NetworkPolicy) is all that applies. See
147
+ * `egress-policy.ts`.
148
+ */
149
+ readonly egress?: KubernetesEgressConfig;
150
+ }
151
+ /**
152
+ * The address the guest agent answers on, plus the token to present.
153
+ *
154
+ * Structurally the `tcp` arm of the transport's `SandboxAgentHandle`. It is
155
+ * declared here rather than imported so acquire does not depend on the
156
+ * transport landing first; the two are asserted equal where they meet.
157
+ */
158
+ export interface KubernetesAgentAddress {
159
+ readonly kind: 'tcp';
160
+ readonly host: string;
161
+ readonly port: number;
162
+ readonly token: string;
163
+ }
164
+ /** What the controller bound, read back off the object's own status. */
165
+ export interface KubernetesSandboxBinding {
166
+ /** The Sandbox's own name — NOT the claim's. */
167
+ readonly name: string;
168
+ readonly podIPs?: readonly string[];
169
+ readonly serviceFQDN?: string;
170
+ /** `Sandbox.status.selector`, when the path that read it had it for free. */
171
+ readonly podSelector?: string;
172
+ }
173
+ /** One acquired sandbox: what it is, where it answers, how to give it back. */
174
+ export interface KubernetesAcquisition {
175
+ readonly binding: KubernetesSandboxBinding;
176
+ readonly agent: KubernetesAgentAddress;
177
+ /** API path of the object THIS backend created — the claim, or the Sandbox. */
178
+ readonly ownedPath: string;
179
+ /** The TTL acquire stamped, which every renewal re-stamps. */
180
+ readonly ttlSeconds: number;
181
+ /** DELETE that object. An already-gone object counts as released. */
182
+ release(signal?: AbortSignal): Promise<void>;
183
+ /**
184
+ * Merge-PATCH the created object's expiry forward to `shutdownTime`.
185
+ *
186
+ * On the acquisition rather than in `lease.ts` because only this path
187
+ * knows WHICH object it created and therefore where the field lives: a
188
+ * `SandboxClaim` carries it at `spec.lifecycle.shutdownTime`, a directly
189
+ * created `Sandbox` at `spec.shutdownTime` (v1beta1 as served keeps it at
190
+ * the top of `spec`). A merge patch of the nested object leaves
191
+ * `shutdownPolicy` alone.
192
+ */
193
+ renew(shutdownTime: string, signal?: AbortSignal): Promise<void>;
194
+ }
195
+ /**
196
+ * The same number the Firecracker guest agent listens on over vsock
197
+ * (`DEFAULT_AGENT_VSOCK_PORT`), so one agent has one port across both tiers
198
+ * and a manifest, a NetworkPolicy and a transport can all name it from
199
+ * memory. Unprivileged, and the sandbox pod is not sharing it with anything.
200
+ */
201
+ export declare const DEFAULT_AGENT_PORT = 1024;
202
+ /**
203
+ * How long the privilege probe may take, given the caller's readiness budget.
204
+ *
205
+ * `readyTimeoutMs` bounds the CONTROL plane and has usually expired by the
206
+ * time the probe starts, so the probe cannot share it — but it is still the
207
+ * number the caller chose to describe how long an acquire may take, so the
208
+ * probe is allowed exactly that much again and no more, capped. A caller who
209
+ * asked for a 500 ms acquire gets a 500 ms probe; one who asked for two
210
+ * minutes of cold start still gets {@link PRIVILEGE_PROBE_TIMEOUT_CAP_MS}.
211
+ * Deliberately not a separate config key: a knob whose only correct value is
212
+ * "long enough for one `cat`" is a knob that only ever gets set wrong.
213
+ */
214
+ export declare function resolveProbeTimeoutMs(readyTimeoutMs: number): number;
215
+ /**
216
+ * The readiness bounds every path in this backend polls against — acquire,
217
+ * and `workspace.ts`'s create/suspend/resume. One function so the two cannot
218
+ * drift apart on defaults.
219
+ */
220
+ export declare function resolveKubernetesReadiness(config: {
221
+ readonly readyTimeoutMs?: number;
222
+ readonly readyPollIntervalMs?: number;
223
+ }): {
224
+ readonly timeoutMs: number;
225
+ readonly pollIntervalMs: number;
226
+ };
227
+ export declare function assertEnforceable(options: SandboxBackendOptions): void;
228
+ /**
229
+ * Refuse a runtime class the pool path cannot honour.
230
+ *
231
+ * A pooled sandbox is already running by the time a claim reaches it, under
232
+ * whatever RuntimeClass its SandboxTemplate named. `runtimeClassName` in this
233
+ * config would therefore be read, accepted and ignored — and the thing it
234
+ * selects is the VM boundary, which is the last control to lose quietly.
235
+ */
236
+ export declare function assertRuntimeClassIsApplicable(config: {
237
+ warmPoolName?: string;
238
+ runtimeClassName?: string;
239
+ }): void;
240
+ /**
241
+ * Build a {@link SandboxBackend} against a cluster running the agent-sandbox
242
+ * controller. Construction is synchronous and contacts nothing: readiness
243
+ * bounds and the config refusals are validated here so a misconfiguration
244
+ * surfaces during host wiring rather than mid-run, and the first API call
245
+ * happens on the first `create()`.
246
+ */
247
+ export declare function buildKubernetesBackend(config: KubernetesBackendInternalConfig): SandboxBackend;
248
+ /**
249
+ * Translate `egress.policy` and confirm an operator applied a matching
250
+ * object — the whole verify-not-trust step, isolated so `create()` above
251
+ * stays about ONE thing (memoize-once-per-backend) rather than two.
252
+ *
253
+ * Exported because `workspace.ts` runs the identical step: a workspace does
254
+ * not go through `buildKubernetesBackend`, and a config `egress` honoured on
255
+ * one entry point and ignored on the other would be a silent downgrade of the
256
+ * boundary this backend calls primary. `sandboxTemplateName` is the template
257
+ * the caller is actually building from — it decides both the default policy
258
+ * name and the pod label the policy's selector has to match, and a workspace
259
+ * may be built from a different template than the task path's.
260
+ */
261
+ export declare function verifyEgressPolicyConfigured(client: KubernetesClient, namespace: string, sandboxTemplateName: string, egress: KubernetesEgressConfig, signal?: AbortSignal): Promise<void>;
262
+ /** Config → the client's own access shape. Shared with `workspace.ts`. */
263
+ export declare function clientAccess(config: KubernetesBackendInternalConfig): KubernetesAccess;
264
+ /**
265
+ * Claim or create, wait for Ready, read the bound identity back, resolve the
266
+ * address and learn the pod's uid — or leave nothing behind trying.
267
+ *
268
+ * Exported because the sandbox surface is built on top of this record rather
269
+ * than beside it: one acquire path, one cleanup path, whatever ends up
270
+ * wrapping them.
271
+ */
272
+ export declare function acquireKubernetesSandbox(client: KubernetesClient, config: KubernetesBackendInternalConfig, options: SandboxBackendOptions, readiness: {
273
+ readonly timeoutMs: number;
274
+ readonly pollIntervalMs: number;
275
+ }): Promise<KubernetesAcquisition>;
276
+ /**
277
+ * What a directly created Sandbox copies out of a `SandboxTemplate`, and the
278
+ * two things it decides for itself.
279
+ */
280
+ export interface SandboxBodyOptions {
281
+ readonly namespace: string;
282
+ readonly name: string;
283
+ readonly template: SandboxTemplateCopy;
284
+ /** The template the copy came from — the value of {@link sandboxTemplateLabel}. */
285
+ readonly sandboxTemplateName: string;
286
+ readonly runtimeClassName?: string;
287
+ /**
288
+ * RFC 3339 expiry, paired with `shutdownPolicy: Delete`. ABSENT means the
289
+ * object carries no expiry at all and nothing reaps it on the wall clock:
290
+ * that is the persistent workspace (`workspace.ts`), which is explicitly
291
+ * managed and must survive a host that stops renewing. Every task sandbox
292
+ * sets it, because an unbounded task sandbox is a leak.
293
+ */
294
+ readonly shutdownTime?: string;
295
+ }
296
+ /**
297
+ * The pool-less body. `Sandbox.spec` has no `templateRef` — only a
298
+ * SandboxWarmPool consumes a SandboxTemplate — so the template's podTemplate
299
+ * is copied in here by the client.
300
+ *
301
+ * `service: true` is forced rather than inherited: a Sandbox without a Service
302
+ * has no `status.serviceFQDN`, and then the only address left is a pod IP that
303
+ * changes on every resume.
304
+ *
305
+ * `volumeClaimTemplates` is copied VERBATIM when the template declares any.
306
+ * Dropping it would be silent: the Sandbox would come up healthy with no disk,
307
+ * the container's `volumeDevices`/`volumeMounts` entry would fail to resolve
308
+ * (or, worse, resolve to an empty emptyDir on some paths), and the only
309
+ * symptom of a workspace that lost its disk would be that yesterday's files
310
+ * are gone. The controller wires the mount by the entry's own NAME,
311
+ * StatefulSet style, so the copy needs no matching `volumes:` entry and this
312
+ * function adds none.
313
+ *
314
+ * The podTemplate's metadata gains {@link sandboxTemplateLabel}: this Sandbox
315
+ * is created DIRECTLY, never adopted out of a pool, so it never gets
316
+ * agent-sandbox's own controller-owned
317
+ * `agents.x-k8s.io/sandbox-template-ref-hash` label (that is written only on
318
+ * bind). Without a label of its own a direct Sandbox's pod would carry
319
+ * nothing `egress-policy.ts`'s translated `NetworkPolicy` could select it
320
+ * by. Existing labels on the copied template are preserved — this ADDS to
321
+ * them rather than replacing the object outright — but this backend's own
322
+ * key always wins if the template happened to set it too, since this is the
323
+ * label the translated policy is built to match.
324
+ */
325
+ export declare function buildSandboxBody(options: SandboxBodyOptions): Record<string, unknown>;
326
+ /** The two halves of a `SandboxTemplate` a directly created Sandbox copies. */
327
+ export interface SandboxTemplateCopy {
328
+ readonly podTemplate: SandboxPodTemplate;
329
+ /** Absent when the template declares no disk, which is every task template. */
330
+ readonly volumeClaimTemplates?: readonly SandboxVolumeClaimTemplate[];
331
+ }
332
+ export declare function readSandboxTemplate(client: KubernetesClient, namespace: string, sandboxTemplateName: string, signal?: AbortSignal): Promise<SandboxTemplateCopy>;
333
+ /**
334
+ * Where the agent answers.
335
+ *
336
+ * Its own function, and the Service FQDN wins over a pod IP, because the
337
+ * address outlives the pod: a suspended-then-resumed workspace comes back as a
338
+ * new pod with a new IP behind the same name, and the transport re-resolves
339
+ * the name on every dial. A literal IP baked into a long-lived handle is the
340
+ * bug that would produce.
341
+ */
342
+ export declare function resolveAgentAddress(binding: KubernetesSandboxBinding, agentPort: number, token: string): KubernetesAgentAddress;
343
+ /** Ready-or-not-yet, read off a `Sandbox`'s own status. Shared with `workspace.ts`. */
344
+ export declare function bindingFromSandbox(sandbox: SandboxResource | undefined): KubernetesSandboxBinding | undefined;
345
+ /**
346
+ * Poll until `read` reports a binding. `read` returns `undefined` for "not
347
+ * yet" and throws for a failure worth surfacing; the deadline owns every wait,
348
+ * including the sleep between attempts, so an expired clock cannot be extended
349
+ * by one more round trip. Shaped after ACI's `pollForRunningIp`.
350
+ */
351
+ export declare function pollForBinding(read: (signal: AbortSignal) => Promise<KubernetesSandboxBinding | undefined>, deadline: OperationDeadline, readiness: {
352
+ readonly timeoutMs: number;
353
+ readonly pollIntervalMs: number;
354
+ }, label: string): Promise<KubernetesSandboxBinding>;
355
+ /**
356
+ * The per-instance bind token: the backing pod's `metadata.uid`.
357
+ *
358
+ * The pod is named after its Sandbox in agent-sandbox v1.0.2 — verified
359
+ * against a running cluster — but that is an observation, not a documented
360
+ * guarantee, and `Sandbox.status` exposes no pod name to fall back on. So the
361
+ * fast path is one GET by that name, and the only cost of the name convention
362
+ * changing upstream is a second round trip through `status.selector`, which is
363
+ * exactly what the controller publishes the selector for.
364
+ */
365
+ export declare function readPodBindToken(client: KubernetesClient, namespace: string, binding: KubernetesSandboxBinding, signal?: AbortSignal): Promise<string>;
366
+ /**
367
+ * Run the probe against a built Sandbox, on its own clock, and throw if it
368
+ * refuses. Cleanup is the CALLER's, and the two callers want opposite things:
369
+ * a task acquire destroys the instance, while `workspace.ts` suspends it,
370
+ * because deleting a workspace deletes its disk and a probe refusal is not a
371
+ * reason to lose a caller's files.
372
+ */
373
+ export declare function probeSandboxPrivileges(sandbox: Sandbox, sandboxName: string, probeTimeoutMs: number, signal?: AbortSignal): Promise<void>;
374
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/backends/kubernetes/index.ts"],"names":[],"mappings":"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"}