@namzu/sandbox 26.0.0 → 27.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.
- package/CHANGELOG.md +47 -0
- package/README.md +20 -7
- package/dist/backends/firecracker/protocol.d.ts +46 -0
- package/dist/backends/firecracker/protocol.d.ts.map +1 -1
- package/dist/backends/firecracker/protocol.js +31 -0
- package/dist/backends/firecracker/protocol.js.map +1 -1
- package/dist/backends/firecracker/transport.d.ts +15 -1
- package/dist/backends/firecracker/transport.d.ts.map +1 -1
- package/dist/backends/firecracker/transport.js +16 -0
- package/dist/backends/firecracker/transport.js.map +1 -1
- package/dist/backends/kubernetes/allocation.d.ts +115 -0
- package/dist/backends/kubernetes/allocation.d.ts.map +1 -0
- package/dist/backends/kubernetes/allocation.js +130 -0
- package/dist/backends/kubernetes/allocation.js.map +1 -0
- package/dist/backends/kubernetes/egress-policy.d.ts +111 -35
- package/dist/backends/kubernetes/egress-policy.d.ts.map +1 -1
- package/dist/backends/kubernetes/egress-policy.js +81 -41
- package/dist/backends/kubernetes/egress-policy.js.map +1 -1
- package/dist/backends/kubernetes/identity.d.ts +129 -0
- package/dist/backends/kubernetes/identity.d.ts.map +1 -1
- package/dist/backends/kubernetes/identity.js +150 -0
- package/dist/backends/kubernetes/identity.js.map +1 -1
- package/dist/backends/kubernetes/index.d.ts +23 -1
- package/dist/backends/kubernetes/index.d.ts.map +1 -1
- package/dist/backends/kubernetes/index.js +22 -3
- package/dist/backends/kubernetes/index.js.map +1 -1
- package/dist/backends/kubernetes/objects.d.ts +76 -0
- package/dist/backends/kubernetes/objects.d.ts.map +1 -1
- package/dist/backends/kubernetes/objects.js +61 -0
- package/dist/backends/kubernetes/objects.js.map +1 -1
- package/dist/backends/kubernetes/per-sandbox-fence.d.ts +194 -0
- package/dist/backends/kubernetes/per-sandbox-fence.d.ts.map +1 -0
- package/dist/backends/kubernetes/per-sandbox-fence.js +522 -0
- package/dist/backends/kubernetes/per-sandbox-fence.js.map +1 -0
- package/dist/backends/kubernetes/per-sandbox-policy.d.ts +45 -3
- package/dist/backends/kubernetes/per-sandbox-policy.d.ts.map +1 -1
- package/dist/backends/kubernetes/per-sandbox-policy.js +98 -8
- package/dist/backends/kubernetes/per-sandbox-policy.js.map +1 -1
- package/dist/backends/kubernetes/sandbox.d.ts +4 -9
- package/dist/backends/kubernetes/sandbox.d.ts.map +1 -1
- package/dist/backends/kubernetes/sandbox.js +4 -9
- package/dist/backends/kubernetes/sandbox.js.map +1 -1
- package/dist/backends/kubernetes/transport.d.ts +108 -1
- package/dist/backends/kubernetes/transport.d.ts.map +1 -1
- package/dist/backends/kubernetes/transport.js +150 -6
- package/dist/backends/kubernetes/transport.js.map +1 -1
- package/dist/backends/kubernetes/workspace-allocate.d.ts +206 -0
- package/dist/backends/kubernetes/workspace-allocate.d.ts.map +1 -0
- package/dist/backends/kubernetes/workspace-allocate.js +332 -0
- package/dist/backends/kubernetes/workspace-allocate.js.map +1 -0
- package/dist/backends/kubernetes/workspace-observe.d.ts +187 -0
- package/dist/backends/kubernetes/workspace-observe.d.ts.map +1 -0
- package/dist/backends/kubernetes/workspace-observe.js +343 -0
- package/dist/backends/kubernetes/workspace-observe.js.map +1 -0
- package/dist/backends/kubernetes/workspace-per-sandbox.d.ts +94 -0
- package/dist/backends/kubernetes/workspace-per-sandbox.d.ts.map +1 -0
- package/dist/backends/kubernetes/workspace-per-sandbox.js +119 -0
- package/dist/backends/kubernetes/workspace-per-sandbox.js.map +1 -0
- package/dist/backends/kubernetes/workspace.d.ts +139 -5
- package/dist/backends/kubernetes/workspace.d.ts.map +1 -1
- package/dist/backends/kubernetes/workspace.js +434 -36
- package/dist/backends/kubernetes/workspace.js.map +1 -1
- package/dist/index.d.ts +83 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +100 -6
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/backends/firecracker/protocol.ts +47 -0
- package/src/backends/firecracker/transport.ts +31 -0
- package/src/backends/kubernetes/allocation.ts +199 -0
- package/src/backends/kubernetes/egress-policy.ts +165 -42
- package/src/backends/kubernetes/identity.ts +210 -0
- package/src/backends/kubernetes/index.ts +61 -2
- package/src/backends/kubernetes/objects.ts +98 -0
- package/src/backends/kubernetes/per-sandbox-fence.ts +800 -0
- package/src/backends/kubernetes/per-sandbox-policy.ts +152 -17
- package/src/backends/kubernetes/sandbox.ts +4 -9
- package/src/backends/kubernetes/transport.ts +203 -4
- package/src/backends/kubernetes/workspace-allocate.ts +607 -0
- package/src/backends/kubernetes/workspace-observe.ts +590 -0
- package/src/backends/kubernetes/workspace-per-sandbox.ts +179 -0
- package/src/backends/kubernetes/workspace.ts +655 -34
- package/src/index.ts +193 -3
|
@@ -68,6 +68,19 @@ export interface KubernetesObjectMeta {
|
|
|
68
68
|
* `k8s-client.ts` states still holds. See {@link buildHolderEpochPatch}.
|
|
69
69
|
*/
|
|
70
70
|
readonly resourceVersion?: string
|
|
71
|
+
/**
|
|
72
|
+
* `metadata.generation`: bumped by the API server on every change to
|
|
73
|
+
* `spec`. Read only by the readiness observation, which compares it with a
|
|
74
|
+
* condition's `observedGeneration` so that a `Ready: True` the controller
|
|
75
|
+
* wrote for an EARLIER spec is not mistaken for the outcome of the latest
|
|
76
|
+
* one.
|
|
77
|
+
*/
|
|
78
|
+
readonly generation?: number
|
|
79
|
+
/** Who owns this object. Read off a PVC, to tell the Sandbox's disk from a stranger's. */
|
|
80
|
+
readonly ownerReferences?: readonly {
|
|
81
|
+
readonly uid?: string
|
|
82
|
+
readonly controller?: boolean
|
|
83
|
+
}[]
|
|
71
84
|
/**
|
|
72
85
|
* Set the moment a DELETE is accepted, long before the object goes away.
|
|
73
86
|
* A pod that carries one is on its way out and must never be bound to —
|
|
@@ -85,6 +98,12 @@ export interface KubernetesCondition {
|
|
|
85
98
|
readonly reason?: string
|
|
86
99
|
readonly message?: string
|
|
87
100
|
readonly lastTransitionTime?: string
|
|
101
|
+
/**
|
|
102
|
+
* The `metadata.generation` the controller had seen when it wrote this
|
|
103
|
+
* condition. A condition whose value is below the object's current
|
|
104
|
+
* generation describes an earlier spec.
|
|
105
|
+
*/
|
|
106
|
+
readonly observedGeneration?: number
|
|
88
107
|
}
|
|
89
108
|
|
|
90
109
|
/**
|
|
@@ -561,6 +580,70 @@ export function podTemplateHash(podTemplate: SandboxPodTemplate): string {
|
|
|
561
580
|
return `sha256:${digest}`
|
|
562
581
|
}
|
|
563
582
|
|
|
583
|
+
/**
|
|
584
|
+
* `sha256:<hex>` over any JSON-serialisable value, taken over its CANONICAL
|
|
585
|
+
* form: object keys sorted by code unit at every depth, `undefined` members
|
|
586
|
+
* dropped, arrays kept in order, then `JSON.stringify` with no whitespace.
|
|
587
|
+
*
|
|
588
|
+
* {@link podTemplateHash} and the execution-profile fingerprint both go
|
|
589
|
+
* through it, so two hosts on the same release computing it over the same
|
|
590
|
+
* content get the same string whatever order their objects were built in.
|
|
591
|
+
*/
|
|
592
|
+
export function canonicalFingerprint(value: unknown): string {
|
|
593
|
+
const digest = createHash('sha256')
|
|
594
|
+
.update(JSON.stringify(canonicalJson(value)))
|
|
595
|
+
.digest('hex')
|
|
596
|
+
return `sha256:${digest}`
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Backend-owned annotation carrying the ALLOCATION ID a workspace was created
|
|
601
|
+
* for by `allocateKubernetesWorkspace`: the host's own immutable identifier
|
|
602
|
+
* for "this allocation", chosen and persisted by the host BEFORE the create.
|
|
603
|
+
*
|
|
604
|
+
* Public contract. Written once, in the create POST, and never patched by
|
|
605
|
+
* this backend afterwards — a refresh, a resume, a suspend or an epoch write
|
|
606
|
+
* merges other annotations and leaves it alone. Absent on a workspace made
|
|
607
|
+
* by `createKubernetesWorkspace`.
|
|
608
|
+
*
|
|
609
|
+
* Same prefix as {@link HOLDER_EPOCH_ANNOTATION_KEY}.
|
|
610
|
+
*/
|
|
611
|
+
export const ALLOCATION_ID_ANNOTATION_KEY = 'sandbox.namzu.ai/allocation-id'
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Backend-owned annotation carrying the host's SCOPE FINGERPRINT for the
|
|
615
|
+
* allocation: an opaque string naming what the workspace is for (tenant,
|
|
616
|
+
* project, session — the host decides). The backend never interprets it; it
|
|
617
|
+
* only stores it and compares it for equality. Written with, and under the
|
|
618
|
+
* same rules as, {@link ALLOCATION_ID_ANNOTATION_KEY}.
|
|
619
|
+
*/
|
|
620
|
+
export const ALLOCATION_SCOPE_ANNOTATION_KEY = 'sandbox.namzu.ai/allocation-scope'
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Backend-owned annotation carrying the EXECUTION PROFILE FINGERPRINT the
|
|
624
|
+
* workspace was allocated under: the `sha256:<hex>` that
|
|
625
|
+
* `resolveKubernetesExecutionProfile` returns. Written with, and under the
|
|
626
|
+
* same rules as, {@link ALLOCATION_ID_ANNOTATION_KEY}.
|
|
627
|
+
*/
|
|
628
|
+
export const EXECUTION_PROFILE_ANNOTATION_KEY = 'sandbox.namzu.ai/execution-profile'
|
|
629
|
+
|
|
630
|
+
/** What a Sandbox's allocation annotations say; each `undefined` when absent. */
|
|
631
|
+
export interface AllocationReading {
|
|
632
|
+
readonly id: string | undefined
|
|
633
|
+
readonly scopeFingerprint: string | undefined
|
|
634
|
+
readonly executionProfile: string | undefined
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/** Read the three allocation annotations off an object's metadata. */
|
|
638
|
+
export function readAllocation(meta: KubernetesObjectMeta | undefined): AllocationReading {
|
|
639
|
+
const annotations = meta?.annotations
|
|
640
|
+
return {
|
|
641
|
+
id: annotations?.[ALLOCATION_ID_ANNOTATION_KEY],
|
|
642
|
+
scopeFingerprint: annotations?.[ALLOCATION_SCOPE_ANNOTATION_KEY],
|
|
643
|
+
executionProfile: annotations?.[EXECUTION_PROFILE_ANNOTATION_KEY],
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
564
647
|
/**
|
|
565
648
|
* One RFC 6902 operation, in the only three shapes this backend sends.
|
|
566
649
|
*
|
|
@@ -621,6 +704,11 @@ export interface HolderEpochReading {
|
|
|
621
704
|
readonly hasAnnotations: boolean
|
|
622
705
|
/** `metadata.resourceVersion`, for the fallback `test` and a fenced DELETE. */
|
|
623
706
|
readonly resourceVersion?: string
|
|
707
|
+
/**
|
|
708
|
+
* `metadata.uid` of the object this reading came from, so a write can
|
|
709
|
+
* refuse a same-name replacement off the very read it is conditioned on.
|
|
710
|
+
*/
|
|
711
|
+
readonly sandboxUid?: string
|
|
624
712
|
}
|
|
625
713
|
|
|
626
714
|
/** Decimal, no sign, no padding, no exponent — what this backend writes. */
|
|
@@ -637,6 +725,7 @@ export function readHolderEpoch(meta: KubernetesObjectMeta | undefined): HolderE
|
|
|
637
725
|
const base = {
|
|
638
726
|
hasAnnotations: annotations !== undefined,
|
|
639
727
|
...(resourceVersion !== undefined ? { resourceVersion } : {}),
|
|
728
|
+
...(typeof meta?.uid === 'string' && meta.uid !== '' ? { sandboxUid: meta.uid } : {}),
|
|
640
729
|
}
|
|
641
730
|
if (typeof stored !== 'string') return { ...base, epoch: 0 }
|
|
642
731
|
if (!HOLDER_EPOCH_PATTERN.test(stored)) return { ...base, annotation: stored }
|
|
@@ -963,6 +1052,15 @@ export function validatingAdmissionPolicyBindingPath(name: string): string {
|
|
|
963
1052
|
return `/apis/${ADMISSION_REGISTRATION_API_GROUP}/${ADMISSION_REGISTRATION_API_VERSION}/validatingadmissionpolicybindings/${segment(name)}`
|
|
964
1053
|
}
|
|
965
1054
|
|
|
1055
|
+
/**
|
|
1056
|
+
* One core `ConfigMap`. Read by exactly one caller: the per-sandbox fence's
|
|
1057
|
+
* operator-pinned host set (`per-sandbox-fence.ts`), which the backend only
|
|
1058
|
+
* ever GETs.
|
|
1059
|
+
*/
|
|
1060
|
+
export function configMapPath(namespace: string, name: string): string {
|
|
1061
|
+
return `/api/v1/namespaces/${segment(namespace)}/configmaps/${segment(name)}`
|
|
1062
|
+
}
|
|
1063
|
+
|
|
966
1064
|
/**
|
|
967
1065
|
* An `ownerReferences` entry, as this backend writes it.
|
|
968
1066
|
*
|