@paperclipai/plugin-kubernetes 0.1.0 → 2026.620.0-canary.4

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 (90) hide show
  1. package/LICENSE +21 -0
  2. package/dist/adapter-defaults.d.ts +29 -0
  3. package/dist/adapter-defaults.d.ts.map +1 -0
  4. package/dist/adapter-defaults.js +104 -0
  5. package/dist/adapter-defaults.js.map +1 -0
  6. package/dist/adapter-registry.d.ts +64 -0
  7. package/dist/adapter-registry.d.ts.map +1 -0
  8. package/dist/adapter-registry.js +25 -0
  9. package/dist/adapter-registry.js.map +1 -0
  10. package/dist/cilium-network-policy.d.ts +8 -0
  11. package/dist/cilium-network-policy.d.ts.map +1 -0
  12. package/dist/cilium-network-policy.js +57 -0
  13. package/dist/cilium-network-policy.js.map +1 -0
  14. package/dist/image-allowlist.d.ts +18 -0
  15. package/dist/image-allowlist.d.ts.map +1 -0
  16. package/dist/image-allowlist.js +39 -0
  17. package/dist/image-allowlist.js.map +1 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +3 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/job-orchestrator.d.ts +24 -0
  23. package/dist/job-orchestrator.d.ts.map +1 -0
  24. package/dist/job-orchestrator.js +90 -0
  25. package/dist/job-orchestrator.js.map +1 -0
  26. package/dist/kube-client.d.ts +15 -0
  27. package/dist/kube-client.d.ts.map +1 -0
  28. package/dist/kube-client.js +23 -0
  29. package/dist/kube-client.js.map +1 -0
  30. package/dist/lease-lifecycle.d.ts +62 -0
  31. package/dist/lease-lifecycle.d.ts.map +1 -0
  32. package/dist/lease-lifecycle.js +155 -0
  33. package/dist/lease-lifecycle.js.map +1 -0
  34. package/dist/manifest.d.ts +4 -0
  35. package/dist/manifest.d.ts.map +1 -0
  36. package/dist/manifest.js +108 -0
  37. package/dist/manifest.js.map +1 -0
  38. package/dist/network-policy.d.ts +18 -0
  39. package/dist/network-policy.d.ts.map +1 -0
  40. package/dist/network-policy.js +113 -0
  41. package/dist/network-policy.js.map +1 -0
  42. package/dist/plugin.d.ts +3 -0
  43. package/dist/plugin.d.ts.map +1 -0
  44. package/dist/plugin.js +687 -0
  45. package/dist/plugin.js.map +1 -0
  46. package/dist/pod-exec.d.ts +28 -0
  47. package/dist/pod-exec.d.ts.map +1 -0
  48. package/dist/pod-exec.js +164 -0
  49. package/dist/pod-exec.js.map +1 -0
  50. package/dist/pod-spec-builder.d.ts +25 -0
  51. package/dist/pod-spec-builder.d.ts.map +1 -0
  52. package/dist/pod-spec-builder.js +82 -0
  53. package/dist/pod-spec-builder.js.map +1 -0
  54. package/dist/sandbox-cr-builder.d.ts +40 -0
  55. package/dist/sandbox-cr-builder.d.ts.map +1 -0
  56. package/dist/sandbox-cr-builder.js +123 -0
  57. package/dist/sandbox-cr-builder.js.map +1 -0
  58. package/dist/sandbox-cr-orchestrator.d.ts +62 -0
  59. package/dist/sandbox-cr-orchestrator.d.ts.map +1 -0
  60. package/dist/sandbox-cr-orchestrator.js +248 -0
  61. package/dist/sandbox-cr-orchestrator.js.map +1 -0
  62. package/dist/sandbox-orchestrator.d.ts +39 -0
  63. package/dist/sandbox-orchestrator.d.ts.map +1 -0
  64. package/dist/sandbox-orchestrator.js +2 -0
  65. package/dist/sandbox-orchestrator.js.map +1 -0
  66. package/dist/secret-manager.d.ts +14 -0
  67. package/dist/secret-manager.d.ts.map +1 -0
  68. package/dist/secret-manager.js +39 -0
  69. package/dist/secret-manager.js.map +1 -0
  70. package/dist/tenant-orchestrator.d.ts +35 -0
  71. package/dist/tenant-orchestrator.d.ts.map +1 -0
  72. package/dist/tenant-orchestrator.js +263 -0
  73. package/dist/tenant-orchestrator.js.map +1 -0
  74. package/dist/types.d.ts +264 -0
  75. package/dist/types.d.ts.map +1 -0
  76. package/dist/types.js +65 -0
  77. package/dist/types.js.map +1 -0
  78. package/dist/upload-interceptor.d.ts +44 -0
  79. package/dist/upload-interceptor.d.ts.map +1 -0
  80. package/dist/upload-interceptor.js +114 -0
  81. package/dist/upload-interceptor.js.map +1 -0
  82. package/dist/utils.d.ts +11 -0
  83. package/dist/utils.d.ts.map +1 -0
  84. package/dist/utils.js +51 -0
  85. package/dist/utils.js.map +1 -0
  86. package/dist/worker.d.ts +3 -0
  87. package/dist/worker.d.ts.map +1 -0
  88. package/dist/worker.js +5 -0
  89. package/dist/worker.js.map +1 -0
  90. package/package.json +4 -12
@@ -0,0 +1,248 @@
1
+ /**
2
+ * SandboxOrchestrator implementation backed by the kubernetes-sigs/agent-sandbox
3
+ * Sandbox CRD (agents.x-k8s.io/v1alpha1).
4
+ *
5
+ * The Sandbox CR creates a long-lived pod that paperclip-server can exec into
6
+ * for multi-command adapter-install workflows — the key architectural win over
7
+ * the batch/v1 Job backend.
8
+ *
9
+ * Key semantic differences from jobOrchestrator:
10
+ * - claim() creates a Sandbox CR via CustomObjectsApi instead of a batch Job
11
+ * - getStatus() maps Sandbox phase (Pending|Ready|Terminating|Failed) to SandboxStatus
12
+ * - findPod() reads status.podName from the Sandbox CR (falls back to label query)
13
+ * - waitForCompletion() means "wait until pod is Ready to exec" NOT "wait until
14
+ * workload finishes". The Sandbox pod runs sleep infinity; execution completion
15
+ * is tracked by the individual execInPod() calls.
16
+ * - release() deletes the Sandbox CR with Foreground propagation (controller
17
+ * tears down the underlying pod).
18
+ *
19
+ * NOTE: streamLogs() is provided for interface conformance but is limited —
20
+ * the sleep-infinity pod has no meaningful stdout. Callers in execute mode
21
+ * should use execInPod() and capture its stdout/stderr directly.
22
+ */
23
+ const SANDBOX_GROUP = "agents.x-k8s.io";
24
+ const SANDBOX_VERSION = "v1alpha1";
25
+ const SANDBOX_PLURAL = "sandboxes";
26
+ export class SandboxCrTimeoutError extends Error {
27
+ constructor(namespace, name, timeoutMs) {
28
+ super(`Sandbox ${namespace}/${name} did not reach Ready phase within ${timeoutMs}ms`);
29
+ this.name = "SandboxCrTimeoutError";
30
+ }
31
+ }
32
+ function sleep(ms) {
33
+ return new Promise((resolve) => setTimeout(resolve, ms));
34
+ }
35
+ /**
36
+ * Map a Sandbox CR status.phase value to our SandboxStatus shape.
37
+ * Sandbox phases: Pending | Ready | Terminating | Failed
38
+ */
39
+ function mapSandboxPhase(cr) {
40
+ const status = cr.status ?? {};
41
+ const phase = status.phase ?? "Pending";
42
+ switch (phase) {
43
+ case "Ready":
44
+ return {
45
+ phase: "Running", // SandboxStatus.phase uses Job semantics; "Running" = active pod
46
+ complete: false,
47
+ active: 1,
48
+ succeeded: 0,
49
+ failed: 0,
50
+ };
51
+ case "Terminating":
52
+ return {
53
+ phase: "Running",
54
+ complete: false,
55
+ active: 0,
56
+ succeeded: 0,
57
+ failed: 0,
58
+ reason: "Terminating",
59
+ };
60
+ case "Failed": {
61
+ const conditions = status.conditions ?? [];
62
+ const failedCond = conditions.find((c) => c.type === "Failed");
63
+ return {
64
+ phase: "Failed",
65
+ complete: false,
66
+ active: 0,
67
+ succeeded: 0,
68
+ failed: 1,
69
+ reason: failedCond?.reason,
70
+ message: failedCond?.message,
71
+ };
72
+ }
73
+ default:
74
+ // "Pending" or unknown
75
+ return {
76
+ phase: "Pending",
77
+ complete: false,
78
+ active: 0,
79
+ succeeded: 0,
80
+ failed: 0,
81
+ };
82
+ }
83
+ }
84
+ export async function createSandboxCr(clients, namespace, manifest) {
85
+ const result = await clients.custom.createNamespacedCustomObject({
86
+ group: SANDBOX_GROUP,
87
+ version: SANDBOX_VERSION,
88
+ namespace,
89
+ plural: SANDBOX_PLURAL,
90
+ body: manifest,
91
+ });
92
+ const uid = result.metadata?.uid;
93
+ if (!uid)
94
+ throw new Error("Sandbox CR created without a UID");
95
+ return { uid };
96
+ }
97
+ export async function getSandboxCrStatus(clients, namespace, name) {
98
+ const result = await clients.custom.getNamespacedCustomObject({
99
+ group: SANDBOX_GROUP,
100
+ version: SANDBOX_VERSION,
101
+ namespace,
102
+ plural: SANDBOX_PLURAL,
103
+ name,
104
+ });
105
+ return mapSandboxPhase(result);
106
+ }
107
+ /**
108
+ * Returns the pod name backing a Sandbox CR.
109
+ * Primary: read status.podName from the CR (set by the controller once ready).
110
+ * Fallback: list pods in the namespace filtered by the paperclip.io/managed-by
111
+ * label and the sandbox name label set on the pod template.
112
+ */
113
+ export async function findPodForSandbox(clients, namespace, name) {
114
+ // Primary: read status.podName from the Sandbox CR
115
+ const cr = await clients.custom.getNamespacedCustomObject({
116
+ group: SANDBOX_GROUP,
117
+ version: SANDBOX_VERSION,
118
+ namespace,
119
+ plural: SANDBOX_PLURAL,
120
+ name,
121
+ });
122
+ const status = cr.status ?? {};
123
+ const podName = status.podName;
124
+ if (podName && podName.trim().length > 0) {
125
+ return podName;
126
+ }
127
+ // Secondary: the agent-sandbox controller (v0.4.x) names the backing pod
128
+ // EXACTLY after the Sandbox CR and labels it only with
129
+ // agents.x-k8s.io/sandbox-name-hash (a hash, not the full name), so the
130
+ // full-name label selector below matches nothing on that controller. An
131
+ // exact-name GET is collision-free (unlike name-prefix matching, which
132
+ // could hit a concurrent sandbox sharing a prefix) and resolves the pod on
133
+ // every controller version that keeps pod name == sandbox name.
134
+ try {
135
+ const pod = (await clients.core.readNamespacedPod({ namespace, name }));
136
+ if (pod?.metadata?.name) {
137
+ return pod.metadata.name;
138
+ }
139
+ }
140
+ catch (err) {
141
+ const code = err.code ??
142
+ err.statusCode;
143
+ if (code !== 404)
144
+ throw err;
145
+ }
146
+ // Fallback: list pods by a full-name sandbox label, for controller versions
147
+ // that label pods with the sandbox name. A broader managed-by selector plus
148
+ // name-prefix narrowing could match a concurrent sandbox whose generated
149
+ // name shares a prefix, and exec would target the wrong lease's pod.
150
+ const result = await clients.core.listNamespacedPod({
151
+ namespace,
152
+ labelSelector: `agents.x-k8s.io/sandbox-name=${name}`,
153
+ });
154
+ const items = (result.items) ?? [];
155
+ // The label selector already scopes to exactly this sandbox's pod(s); keep a
156
+ // defensive re-check on the label value only (no name-prefix matching).
157
+ const matching = items.filter((p) => (p.metadata?.labels ?? {})["agents.x-k8s.io/sandbox-name"] === name);
158
+ const running = matching.find((p) => p.status?.phase === "Running");
159
+ return (running ?? matching[0])?.metadata?.name ?? null;
160
+ }
161
+ export async function streamSandboxLogs(clients, namespace, podName, onChunk) {
162
+ // V1 limitation: readNamespacedPodLog returns combined stdout. The
163
+ // sleep-infinity pod will have minimal output; this is provided for interface
164
+ // conformance. For actual command output, use execInPod() directly.
165
+ const result = await clients.core.readNamespacedPodLog({
166
+ namespace,
167
+ name: podName,
168
+ });
169
+ const text = result ?? "";
170
+ if (text.length > 0)
171
+ await onChunk("stdout", text);
172
+ }
173
+ export async function deleteSandboxCr(clients, namespace, name) {
174
+ await clients.custom.deleteNamespacedCustomObject({
175
+ group: SANDBOX_GROUP,
176
+ version: SANDBOX_VERSION,
177
+ namespace,
178
+ plural: SANDBOX_PLURAL,
179
+ name,
180
+ propagationPolicy: "Foreground",
181
+ });
182
+ }
183
+ /**
184
+ * Wait until the Sandbox CR's pod reaches Ready phase (i.e., the pod is up and
185
+ * exec-able). This is NOT waiting for a workload to finish — the Sandbox pod
186
+ * runs sleep infinity indefinitely. Execution completion is tracked by the
187
+ * individual execInPod() calls.
188
+ *
189
+ * Throws SandboxCrTimeoutError if Ready is not reached within timeoutMs.
190
+ * Throws if the Sandbox transitions to Failed.
191
+ */
192
+ export async function waitForSandboxReady(clients, namespace, name, opts = {
193
+ timeoutMs: 120_000,
194
+ pollMs: 2000,
195
+ }) {
196
+ const deadline = Date.now() + opts.timeoutMs;
197
+ const pollMs = opts.pollMs ?? 2000;
198
+ while (Date.now() < deadline) {
199
+ const cr = await clients.custom.getNamespacedCustomObject({
200
+ group: SANDBOX_GROUP,
201
+ version: SANDBOX_VERSION,
202
+ namespace,
203
+ plural: SANDBOX_PLURAL,
204
+ name,
205
+ });
206
+ const status = cr.status ?? {};
207
+ // agent-sandbox v1alpha1 uses status.conditions[type=Ready,status=True],
208
+ // not status.phase. Fall back to phase for forward-compat.
209
+ const conditions = Array.isArray(status.conditions) ? status.conditions : [];
210
+ const readyCondition = conditions.find((c) => c.type === "Ready");
211
+ const failedCondition = conditions.find((c) => c.type === "Failed" || (c.type === "Ready" && c.status === "False" && typeof c.reason === "string" && /failed/i.test(c.reason)));
212
+ const phase = status.phase ?? "";
213
+ if (readyCondition?.status === "True" || phase === "Ready") {
214
+ return mapSandboxPhase(cr);
215
+ }
216
+ if (failedCondition?.status === "True" || phase === "Failed") {
217
+ const mapped = mapSandboxPhase(cr);
218
+ throw new Error(`Sandbox ${namespace}/${name} failed: ${mapped.reason ?? failedCondition?.reason ?? "unknown reason"} — ${mapped.message ?? failedCondition?.message ?? ""}`);
219
+ }
220
+ if (phase === "Terminating") {
221
+ // A Sandbox being torn down will never transition to Ready. Polling
222
+ // until the deadline would burn the full timeoutMs (potentially
223
+ // 30+ minutes) before throwing a generic timeout. Fail fast instead
224
+ // so the caller can surface a clear "the lease is being released"
225
+ // error and decide whether to retry against a fresh Sandbox.
226
+ throw new Error(`Sandbox ${namespace}/${name} is Terminating — cannot wait for Ready`);
227
+ }
228
+ // Pending — keep polling
229
+ await sleep(pollMs);
230
+ }
231
+ throw new SandboxCrTimeoutError(namespace, name, opts.timeoutMs);
232
+ }
233
+ /**
234
+ * Sandbox CR-backed conformance to SandboxOrchestrator.
235
+ *
236
+ * waitForCompletion semantics change: for this backend, "completion" means
237
+ * "pod is up and Ready to exec into" — NOT "workload finished". The actual
238
+ * command execution and its completion is handled by execInPod().
239
+ */
240
+ export const sandboxCrOrchestrator = {
241
+ claim: createSandboxCr,
242
+ getStatus: getSandboxCrStatus,
243
+ findPod: findPodForSandbox,
244
+ streamLogs: streamSandboxLogs,
245
+ release: deleteSandboxCr,
246
+ waitForCompletion: waitForSandboxReady,
247
+ };
248
+ //# sourceMappingURL=sandbox-cr-orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-cr-orchestrator.js","sourceRoot":"","sources":["../src/sandbox-cr-orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { KubeClients } from "./kube-client.js";
2
+ export interface SandboxStatus {
3
+ phase: "Pending" | "Running" | "Succeeded" | "Failed";
4
+ complete: boolean;
5
+ active: number;
6
+ succeeded: number;
7
+ failed: number;
8
+ reason?: string;
9
+ message?: string;
10
+ }
11
+ /**
12
+ * Abstract interface over a sandbox runtime backend. The current implementation
13
+ * is Job-backed (job-orchestrator.ts). Future backends slot in by exporting an
14
+ * object conforming to this shape — e.g. a Kata-FC warm-pool backend that
15
+ * additionally implements the optional pause/resume slots, or a CRD-backed
16
+ * backend on kubernetes-sigs/agent-sandbox once it reaches Beta.
17
+ */
18
+ export interface SandboxOrchestrator {
19
+ /** Provision the sandbox. Returns the runtime's stable UID. */
20
+ claim(clients: KubeClients, namespace: string, manifest: Record<string, unknown>): Promise<{
21
+ uid: string;
22
+ }>;
23
+ /** Read current lifecycle phase. */
24
+ getStatus(clients: KubeClients, namespace: string, name: string): Promise<SandboxStatus>;
25
+ /** Locate the pod backing this sandbox (or null if none exists yet). */
26
+ findPod(clients: KubeClients, namespace: string, name: string): Promise<string | null>;
27
+ /** Read logs from the sandbox's pod. V1: post-completion read. */
28
+ streamLogs(clients: KubeClients, namespace: string, podName: string, onChunk: (stream: "stdout" | "stderr", text: string) => Promise<void>): Promise<void>;
29
+ /** Tear down the sandbox. Implementations MUST cascade-delete child resources. */
30
+ release(clients: KubeClients, namespace: string, name: string): Promise<void>;
31
+ /** Block until phase is Succeeded or Failed, or throw on timeout. */
32
+ waitForCompletion(clients: KubeClients, namespace: string, name: string, opts: {
33
+ timeoutMs: number;
34
+ pollMs?: number;
35
+ }): Promise<SandboxStatus>;
36
+ pause?(clients: KubeClients, namespace: string, name: string): Promise<void>;
37
+ resume?(clients: KubeClients, namespace: string, name: string): Promise<void>;
38
+ }
39
+ //# sourceMappingURL=sandbox-orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-orchestrator.d.ts","sourceRoot":"","sources":["../src/sandbox-orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtD,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,+DAA+D;IAC/D,KAAK,CACH,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE5B,oCAAoC;IACpC,SAAS,CACP,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,aAAa,CAAC,CAAC;IAE1B,wEAAwE;IACxE,OAAO,CACL,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE1B,kEAAkE;IAClE,UAAU,CACR,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACpE,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB,kFAAkF;IAClF,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9E,qEAAqE;IACrE,iBAAiB,CACf,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3C,OAAO,CAAC,aAAa,CAAC,CAAC;IAO1B,KAAK,CAAC,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,MAAM,CAAC,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/E"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sandbox-orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-orchestrator.js","sourceRoot":"","sources":["../src/sandbox-orchestrator.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ import type { KubeClients } from "./kube-client.js";
2
+ export interface CreatePerRunSecretInput {
3
+ namespace: string;
4
+ secretName: string;
5
+ runId: string;
6
+ ownerKind: string;
7
+ ownerApiVersion: string;
8
+ ownerName: string;
9
+ ownerUid: string;
10
+ bootstrapToken: string;
11
+ adapterEnv: Record<string, string>;
12
+ }
13
+ export declare function createPerRunSecret(clients: KubeClients, input: CreatePerRunSecretInput): Promise<void>;
14
+ //# sourceMappingURL=secret-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-manager.d.ts","sourceRoot":"","sources":["../src/secret-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC5G"}
@@ -0,0 +1,39 @@
1
+ export async function createPerRunSecret(clients, input) {
2
+ if (!input.ownerUid) {
3
+ throw new Error("createPerRunSecret requires a non-empty ownerUid");
4
+ }
5
+ if ("BOOTSTRAP_TOKEN" in input.adapterEnv) {
6
+ throw new Error("adapterEnv must not contain BOOTSTRAP_TOKEN (reserved key)");
7
+ }
8
+ await clients.core.createNamespacedSecret({
9
+ namespace: input.namespace,
10
+ body: {
11
+ apiVersion: "v1",
12
+ kind: "Secret",
13
+ type: "Opaque",
14
+ metadata: {
15
+ name: input.secretName,
16
+ namespace: input.namespace,
17
+ labels: {
18
+ "paperclip.io/run-id": input.runId,
19
+ "paperclip.io/managed-by": "paperclip-k8s-plugin",
20
+ },
21
+ ownerReferences: [
22
+ {
23
+ apiVersion: input.ownerApiVersion,
24
+ kind: input.ownerKind,
25
+ name: input.ownerName,
26
+ uid: input.ownerUid,
27
+ controller: true,
28
+ blockOwnerDeletion: true,
29
+ },
30
+ ],
31
+ },
32
+ stringData: {
33
+ BOOTSTRAP_TOKEN: input.bootstrapToken,
34
+ ...input.adapterEnv,
35
+ },
36
+ },
37
+ });
38
+ }
39
+ //# sourceMappingURL=secret-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-manager.js","sourceRoot":"","sources":["../src/secret-manager.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAoB,EAAE,KAA8B;IAC3F,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,iBAAiB,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC;QACxC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,IAAI,EAAE;YACJ,UAAU,EAAE,IAAI;YAChB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE;gBACR,IAAI,EAAE,KAAK,CAAC,UAAU;gBACtB,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,MAAM,EAAE;oBACN,qBAAqB,EAAE,KAAK,CAAC,KAAK;oBAClC,yBAAyB,EAAE,sBAAsB;iBAClD;gBACD,eAAe,EAAE;oBACf;wBACE,UAAU,EAAE,KAAK,CAAC,eAAe;wBACjC,IAAI,EAAE,KAAK,CAAC,SAAS;wBACrB,IAAI,EAAE,KAAK,CAAC,SAAS;wBACrB,GAAG,EAAE,KAAK,CAAC,QAAQ;wBACnB,UAAU,EAAE,IAAI;wBAChB,kBAAkB,EAAE,IAAI;qBACzB;iBACF;aACF;YACD,UAAU,EAAE;gBACV,eAAe,EAAE,KAAK,CAAC,cAAc;gBACrC,GAAG,KAAK,CAAC,UAAU;aACpB;SACF;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,35 @@
1
+ import type { KubeClients } from "./kube-client.js";
2
+ export interface EnsureTenantInput {
3
+ namespace: string;
4
+ companyId: string;
5
+ paperclipServerNamespace: string;
6
+ serviceAccountAnnotations: Record<string, string>;
7
+ egressMode: "standard" | "cilium";
8
+ egressAllowFqdns: string[];
9
+ egressAllowCidrs: string[];
10
+ resourceQuota: {
11
+ pods: string;
12
+ requestsCpu: string;
13
+ requestsMemory: string;
14
+ limitsCpu: string;
15
+ limitsMemory: string;
16
+ };
17
+ }
18
+ /**
19
+ * Lazy, first-write-wins tenant provisioning. Each helper checks if the named
20
+ * resource exists and creates it only on 404; if it already exists, it is
21
+ * left as-is — config-driven values (quota limits, RBAC permissions, network
22
+ * policies, egress allow-list) are FROZEN at first provisioning time.
23
+ *
24
+ * V1 limitation: changing KubernetesProviderConfig after a tenant namespace
25
+ * is provisioned does NOT update the in-cluster resources. To apply config
26
+ * changes, an operator must delete the per-tenant resources manually (or
27
+ * the namespace itself). A future iteration should add strategic-merge
28
+ * reconciliation here.
29
+ *
30
+ * Particular gotcha: switching egressMode "standard" → "cilium" leaves the
31
+ * old paperclip-egress-allow NetworkPolicy in place alongside the new
32
+ * CiliumNetworkPolicy. Both apply; the effective egress is the intersection.
33
+ */
34
+ export declare function ensureTenant(clients: KubeClients, input: EnsureTenantInput): Promise<void>;
35
+ //# sourceMappingURL=tenant-orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-orchestrator.d.ts","sourceRoot":"","sources":["../src/tenant-orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,wBAAwB,EAAE,MAAM,CAAC;IACjC,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,UAAU,EAAE,UAAU,GAAG,QAAQ,CAAC;IAClC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,EAAE,MAAM,CAAC;QACvB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAQD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQhG"}