@usine/executor 0.2.1 → 0.4.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 (250) hide show
  1. package/LICENSE +661 -21
  2. package/README.md +212 -37
  3. package/dist/child-command.d.ts +5 -8
  4. package/dist/child-command.d.ts.map +1 -1
  5. package/dist/child-command.js +10 -14
  6. package/dist/child-command.js.map +1 -1
  7. package/dist/child-environment.d.ts +19 -0
  8. package/dist/child-environment.d.ts.map +1 -0
  9. package/dist/child-environment.js +18 -0
  10. package/dist/child-environment.js.map +1 -0
  11. package/dist/claude-login-lock.d.ts +9 -0
  12. package/dist/claude-login-lock.d.ts.map +1 -0
  13. package/dist/claude-login-lock.js +15 -0
  14. package/dist/claude-login-lock.js.map +1 -0
  15. package/dist/cloudflare/client.d.ts +50 -0
  16. package/dist/cloudflare/client.d.ts.map +1 -0
  17. package/dist/cloudflare/client.js +108 -0
  18. package/dist/cloudflare/client.js.map +1 -0
  19. package/dist/cloudflare/cloudflare.d.ts +17 -0
  20. package/dist/cloudflare/cloudflare.d.ts.map +1 -0
  21. package/dist/cloudflare/cloudflare.js +704 -0
  22. package/dist/cloudflare/cloudflare.js.map +1 -0
  23. package/dist/cloudflare/model.d.ts +42 -0
  24. package/dist/cloudflare/model.d.ts.map +1 -0
  25. package/dist/cloudflare/model.js +2 -0
  26. package/dist/cloudflare/model.js.map +1 -0
  27. package/dist/cloudflare/shell/environment.d.ts +12 -0
  28. package/dist/cloudflare/shell/environment.d.ts.map +1 -0
  29. package/dist/cloudflare/shell/environment.js +12 -0
  30. package/dist/cloudflare/shell/environment.js.map +1 -0
  31. package/dist/cloudflare/shell/shell.d.ts +2 -0
  32. package/dist/cloudflare/shell/shell.d.ts.map +1 -0
  33. package/dist/cloudflare/shell/shell.js +155 -0
  34. package/dist/cloudflare/shell/shell.js.map +1 -0
  35. package/dist/credential-environment.d.ts +20 -0
  36. package/dist/credential-environment.d.ts.map +1 -0
  37. package/dist/credential-environment.js +20 -0
  38. package/dist/credential-environment.js.map +1 -0
  39. package/dist/durable-session.d.ts +81 -0
  40. package/dist/durable-session.d.ts.map +1 -0
  41. package/dist/durable-session.js +550 -0
  42. package/dist/durable-session.js.map +1 -0
  43. package/dist/exe-dev/commands.d.ts +23 -13
  44. package/dist/exe-dev/commands.d.ts.map +1 -1
  45. package/dist/exe-dev/commands.js +11 -57
  46. package/dist/exe-dev/commands.js.map +1 -1
  47. package/dist/exe-dev/exe-dev.d.ts +9 -3
  48. package/dist/exe-dev/exe-dev.d.ts.map +1 -1
  49. package/dist/exe-dev/exe-dev.js +61 -128
  50. package/dist/exe-dev/exe-dev.js.map +1 -1
  51. package/dist/exe-dev/grants.d.ts.map +1 -1
  52. package/dist/exe-dev/grants.js +35 -15
  53. package/dist/exe-dev/grants.js.map +1 -1
  54. package/dist/exe-dev/model.d.ts +15 -19
  55. package/dist/exe-dev/model.d.ts.map +1 -1
  56. package/dist/exe-dev/model.js +9 -12
  57. package/dist/exe-dev/model.js.map +1 -1
  58. package/dist/exe-dev/preflight.d.ts +8 -4
  59. package/dist/exe-dev/preflight.d.ts.map +1 -1
  60. package/dist/exe-dev/preflight.js +26 -35
  61. package/dist/exe-dev/preflight.js.map +1 -1
  62. package/dist/executor.d.ts +292 -44
  63. package/dist/executor.d.ts.map +1 -1
  64. package/dist/executor.js +187 -19
  65. package/dist/executor.js.map +1 -1
  66. package/dist/guard.d.ts +57 -7
  67. package/dist/guard.d.ts.map +1 -1
  68. package/dist/guard.js +274 -59
  69. package/dist/guard.js.map +1 -1
  70. package/dist/harness-preflight.d.ts +27 -5
  71. package/dist/harness-preflight.d.ts.map +1 -1
  72. package/dist/harness-preflight.js +32 -31
  73. package/dist/harness-preflight.js.map +1 -1
  74. package/dist/keyed-lock.d.ts +2 -3
  75. package/dist/keyed-lock.d.ts.map +1 -1
  76. package/dist/keyed-lock.js +2 -3
  77. package/dist/keyed-lock.js.map +1 -1
  78. package/dist/leftovers.d.ts +9 -0
  79. package/dist/leftovers.d.ts.map +1 -0
  80. package/dist/leftovers.js +14 -0
  81. package/dist/leftovers.js.map +1 -0
  82. package/dist/local/credentials.d.ts +21 -0
  83. package/dist/local/credentials.d.ts.map +1 -0
  84. package/dist/local/credentials.js +39 -0
  85. package/dist/local/credentials.js.map +1 -0
  86. package/dist/local/leftovers.d.ts +8 -0
  87. package/dist/local/leftovers.d.ts.map +1 -0
  88. package/dist/local/leftovers.js +23 -0
  89. package/dist/local/leftovers.js.map +1 -0
  90. package/dist/local/local.d.ts +17 -11
  91. package/dist/local/local.d.ts.map +1 -1
  92. package/dist/local/local.js +205 -132
  93. package/dist/local/local.js.map +1 -1
  94. package/dist/memory-preflight.d.ts +27 -0
  95. package/dist/memory-preflight.d.ts.map +1 -0
  96. package/dist/memory-preflight.js +83 -0
  97. package/dist/memory-preflight.js.map +1 -0
  98. package/dist/pre-push-hook.d.ts +20 -0
  99. package/dist/pre-push-hook.d.ts.map +1 -0
  100. package/dist/pre-push-hook.js +33 -0
  101. package/dist/pre-push-hook.js.map +1 -0
  102. package/dist/prepared-attempt.d.ts +41 -3
  103. package/dist/prepared-attempt.d.ts.map +1 -1
  104. package/dist/prepared-attempt.js +109 -31
  105. package/dist/prepared-attempt.js.map +1 -1
  106. package/dist/provision.d.ts +129 -15
  107. package/dist/provision.d.ts.map +1 -1
  108. package/dist/provision.js +428 -69
  109. package/dist/provision.js.map +1 -1
  110. package/dist/remote/commands.d.ts +51 -0
  111. package/dist/remote/commands.d.ts.map +1 -0
  112. package/dist/remote/commands.js +94 -0
  113. package/dist/remote/commands.js.map +1 -0
  114. package/dist/remote/container.d.ts +90 -0
  115. package/dist/remote/container.d.ts.map +1 -0
  116. package/dist/remote/container.js +480 -0
  117. package/dist/remote/container.js.map +1 -0
  118. package/dist/remote/leftovers.d.ts +14 -0
  119. package/dist/remote/leftovers.d.ts.map +1 -0
  120. package/dist/remote/leftovers.js +22 -0
  121. package/dist/remote/leftovers.js.map +1 -0
  122. package/dist/remote/liveness.d.ts +33 -0
  123. package/dist/remote/liveness.d.ts.map +1 -0
  124. package/dist/remote/liveness.js +196 -0
  125. package/dist/remote/liveness.js.map +1 -0
  126. package/dist/remote/machine.d.ts +110 -0
  127. package/dist/remote/machine.d.ts.map +1 -0
  128. package/dist/remote/machine.js +2 -0
  129. package/dist/remote/machine.js.map +1 -0
  130. package/dist/remote/remote.d.ts +28 -0
  131. package/dist/remote/remote.d.ts.map +1 -0
  132. package/dist/remote/remote.js +556 -0
  133. package/dist/remote/remote.js.map +1 -0
  134. package/dist/remote/sweep.d.ts +17 -0
  135. package/dist/remote/sweep.d.ts.map +1 -0
  136. package/dist/remote/sweep.js +117 -0
  137. package/dist/remote/sweep.js.map +1 -0
  138. package/dist/renewable-credential.d.ts +17 -0
  139. package/dist/renewable-credential.d.ts.map +1 -0
  140. package/dist/renewable-credential.js +58 -0
  141. package/dist/renewable-credential.js.map +1 -0
  142. package/dist/salvage.d.ts +38 -0
  143. package/dist/salvage.d.ts.map +1 -0
  144. package/dist/salvage.js +198 -0
  145. package/dist/salvage.js.map +1 -0
  146. package/dist/ssh/api-keys.d.ts +36 -0
  147. package/dist/ssh/api-keys.d.ts.map +1 -0
  148. package/dist/ssh/api-keys.js +72 -0
  149. package/dist/ssh/api-keys.js.map +1 -0
  150. package/dist/ssh/codex-homes.d.ts +21 -0
  151. package/dist/ssh/codex-homes.d.ts.map +1 -0
  152. package/dist/ssh/codex-homes.js +78 -0
  153. package/dist/ssh/codex-homes.js.map +1 -0
  154. package/dist/ssh/container.d.ts +32 -0
  155. package/dist/ssh/container.d.ts.map +1 -0
  156. package/dist/ssh/container.js +282 -0
  157. package/dist/ssh/container.js.map +1 -0
  158. package/dist/ssh/credentials.d.ts +43 -0
  159. package/dist/ssh/credentials.d.ts.map +1 -0
  160. package/dist/ssh/credentials.js +86 -0
  161. package/dist/ssh/credentials.js.map +1 -0
  162. package/dist/ssh/gateway/admin.d.ts +45 -0
  163. package/dist/ssh/gateway/admin.d.ts.map +1 -0
  164. package/dist/ssh/gateway/admin.js +129 -0
  165. package/dist/ssh/gateway/admin.js.map +1 -0
  166. package/dist/ssh/gateway/attachments.d.ts +31 -0
  167. package/dist/ssh/gateway/attachments.d.ts.map +1 -0
  168. package/dist/ssh/gateway/attachments.js +168 -0
  169. package/dist/ssh/gateway/attachments.js.map +1 -0
  170. package/dist/ssh/gateway/environment.d.ts +71 -0
  171. package/dist/ssh/gateway/environment.d.ts.map +1 -0
  172. package/dist/ssh/gateway/environment.js +148 -0
  173. package/dist/ssh/gateway/environment.js.map +1 -0
  174. package/dist/ssh/gateway/forward.d.ts +74 -0
  175. package/dist/ssh/gateway/forward.d.ts.map +1 -0
  176. package/dist/ssh/gateway/forward.js +247 -0
  177. package/dist/ssh/gateway/forward.js.map +1 -0
  178. package/dist/ssh/gateway/preflight.d.ts +67 -0
  179. package/dist/ssh/gateway/preflight.d.ts.map +1 -0
  180. package/dist/ssh/gateway/preflight.js +320 -0
  181. package/dist/ssh/gateway/preflight.js.map +1 -0
  182. package/dist/ssh/limits.d.ts +60 -0
  183. package/dist/ssh/limits.d.ts.map +1 -0
  184. package/dist/ssh/limits.js +84 -0
  185. package/dist/ssh/limits.js.map +1 -0
  186. package/dist/ssh/model.d.ts +153 -0
  187. package/dist/ssh/model.d.ts.map +1 -0
  188. package/dist/ssh/model.js +2 -0
  189. package/dist/ssh/model.js.map +1 -0
  190. package/dist/ssh/preflight.d.ts +35 -0
  191. package/dist/ssh/preflight.d.ts.map +1 -0
  192. package/dist/ssh/preflight.js +87 -0
  193. package/dist/ssh/preflight.js.map +1 -0
  194. package/dist/ssh/provisioner/boat.d.ts +33 -0
  195. package/dist/ssh/provisioner/boat.d.ts.map +1 -0
  196. package/dist/ssh/provisioner/boat.js +247 -0
  197. package/dist/ssh/provisioner/boat.js.map +1 -0
  198. package/dist/ssh/provisioner/hetzner.d.ts +32 -0
  199. package/dist/ssh/provisioner/hetzner.d.ts.map +1 -0
  200. package/dist/ssh/provisioner/hetzner.js +337 -0
  201. package/dist/ssh/provisioner/hetzner.js.map +1 -0
  202. package/dist/ssh/provisioner/host-key.d.ts +11 -0
  203. package/dist/ssh/provisioner/host-key.d.ts.map +1 -0
  204. package/dist/ssh/provisioner/host-key.js +57 -0
  205. package/dist/ssh/provisioner/host-key.js.map +1 -0
  206. package/dist/ssh/provisioner/http.d.ts +45 -0
  207. package/dist/ssh/provisioner/http.d.ts.map +1 -0
  208. package/dist/ssh/provisioner/http.js +72 -0
  209. package/dist/ssh/provisioner/http.js.map +1 -0
  210. package/dist/ssh/provisioner/machines.d.ts +48 -0
  211. package/dist/ssh/provisioner/machines.d.ts.map +1 -0
  212. package/dist/ssh/provisioner/machines.js +686 -0
  213. package/dist/ssh/provisioner/machines.js.map +1 -0
  214. package/dist/ssh/provisioner/model.d.ts +92 -0
  215. package/dist/ssh/provisioner/model.d.ts.map +1 -0
  216. package/dist/ssh/provisioner/model.js +37 -0
  217. package/dist/ssh/provisioner/model.js.map +1 -0
  218. package/dist/ssh/ssh.d.ts +23 -0
  219. package/dist/ssh/ssh.d.ts.map +1 -0
  220. package/dist/ssh/ssh.js +145 -0
  221. package/dist/ssh/ssh.js.map +1 -0
  222. package/dist/ssh/worker-records.d.ts +18 -0
  223. package/dist/ssh/worker-records.d.ts.map +1 -0
  224. package/dist/ssh/worker-records.js +100 -0
  225. package/dist/ssh/worker-records.js.map +1 -0
  226. package/dist/ssh/workers.d.ts +80 -0
  227. package/dist/ssh/workers.d.ts.map +1 -0
  228. package/dist/ssh/workers.js +247 -0
  229. package/dist/ssh/workers.js.map +1 -0
  230. package/package.json +25 -9
  231. package/dist/exe-dev/channel.d.ts +0 -12
  232. package/dist/exe-dev/channel.d.ts.map +0 -1
  233. package/dist/exe-dev/channel.js +0 -42
  234. package/dist/exe-dev/channel.js.map +0 -1
  235. package/dist/exe-dev/shell.d.ts +0 -12
  236. package/dist/exe-dev/shell.d.ts.map +0 -1
  237. package/dist/exe-dev/shell.js +0 -31
  238. package/dist/exe-dev/shell.js.map +0 -1
  239. package/dist/exe-dev/sweep.d.ts +0 -10
  240. package/dist/exe-dev/sweep.d.ts.map +0 -1
  241. package/dist/exe-dev/sweep.js +0 -117
  242. package/dist/exe-dev/sweep.js.map +0 -1
  243. package/dist/invalid-frame.d.ts +0 -17
  244. package/dist/invalid-frame.d.ts.map +0 -1
  245. package/dist/invalid-frame.js +0 -111
  246. package/dist/invalid-frame.js.map +0 -1
  247. package/dist/run-host-session.d.ts +0 -27
  248. package/dist/run-host-session.d.ts.map +0 -1
  249. package/dist/run-host-session.js +0 -303
  250. package/dist/run-host-session.js.map +0 -1
@@ -0,0 +1,78 @@
1
+ import { safeSegment } from "@usine/core/repository";
2
+ import { Effect, Ref } from "effect";
3
+ import { directChildren } from "../remote/sweep.js";
4
+ /**
5
+ * A script that prints each directory in the Codex homes directory `$1` whose Attempt has no
6
+ * checkout in the attempts directory `$2`, NUL-terminated. Prints nothing if `$1` is missing.
7
+ */
8
+ const HOMES_WITHOUT_CHECKOUT_SCRIPT = String.raw `
9
+ set -e
10
+ [ -d "$1" ] || exit 0
11
+ for home in "$1"/* "$1"/.[!.]* "$1"/..?*; do
12
+ [ -e "$home" ] || continue
13
+ [ -e "$2/$(basename "$home")" ] || printf '%s\0' "$home"
14
+ done
15
+ `.trim();
16
+ /** Returns the Codex home of `attemptId` in the Worker directory `workerDirectory`. */
17
+ export const codexHomeIn = (workerDirectory, attemptId) => `${workerDirectory}/codex/${safeSegment(attemptId)}`;
18
+ /** Returns the Attempt's Codex home on `machine`, which Codex also writes its sessions to. */
19
+ export const attemptCodexHome = (machine, attemptId) => codexHomeIn(machine.workerDirectory, attemptId);
20
+ /**
21
+ * Tracks the Codex homes that Attempts in this process use. `hold` gives an Attempt its Codex
22
+ * home and removes the directory when the caller's scope closes. `sweep` removes the Codex homes
23
+ * on a long-lived machine that no Attempt holds and whose Attempt has no checkout there, which
24
+ * a crash or a failed removal left.
25
+ */
26
+ export const codexHomesFor = Effect.fn("SshExecutor.codexHomesFor")(function* (commands) {
27
+ // The number of holds on each Codex home, by path.
28
+ const held = yield* Ref.make(new Map());
29
+ const count = (codexHome, change) => Ref.update(held, (current) => {
30
+ const next = new Map(current);
31
+ const holds = (current.get(codexHome) ?? 0) + change;
32
+ if (holds > 0)
33
+ next.set(codexHome, holds);
34
+ else
35
+ next.delete(codexHome);
36
+ return next;
37
+ });
38
+ const hold = Effect.fn("SshExecutor.holdCodexHome")(function* (machine, attemptId) {
39
+ const codexHome = attemptCodexHome(machine, attemptId);
40
+ const fields = { attemptId, worker: machine.address.name, codexHome };
41
+ yield* Effect.annotateCurrentSpan(fields);
42
+ // Held before the caller writes the directory, so a sweep that lists it finds the hold.
43
+ yield* Effect.acquireRelease(count(codexHome, 1), () => commands.run("cleanup", machine.shell, "rm", ["-rf", codexHome]).pipe(Effect.tap(() => Effect.logDebug("Removed the Attempt's Codex home", fields)), Effect.tapError((error) => Effect.logWarning("Could not remove the Attempt's Codex home; the next sweep removes it once the Attempt's checkout is gone", { ...fields, message: error.message })), Effect.ignore, Effect.ensuring(count(codexHome, -1))));
44
+ return codexHome;
45
+ });
46
+ const sweep = Effect.fn("SshExecutor.sweepCodexHomes")(function* (machine) {
47
+ const worker = machine.address.name;
48
+ const host = machine.shell.destination;
49
+ yield* Effect.annotateCurrentSpan({ worker, host });
50
+ const root = `${machine.workerDirectory}/codex`;
51
+ const output = yield* commands.run("cleanup", machine.shell, "sh", [
52
+ "-c",
53
+ HOMES_WITHOUT_CHECKOUT_SCRIPT,
54
+ "sh",
55
+ root,
56
+ `${machine.workerDirectory}/attempts`,
57
+ ]);
58
+ const listed = yield* directChildren("cleanup", root, output);
59
+ // Read after the listing, so a Codex home created since then can't be removed.
60
+ const holds = yield* Ref.get(held);
61
+ const leftovers = listed.filter((codexHome) => !holds.has(codexHome));
62
+ if (leftovers.length === 0)
63
+ return yield* Effect.logDebug("No Codex home to remove on the SSH Worker", {
64
+ worker,
65
+ host,
66
+ withoutCheckout: listed.length,
67
+ });
68
+ // Removes each Codex home separately, so one failure doesn't keep the others.
69
+ yield* Effect.forEach(leftovers, (codexHome) => commands.run("cleanup", machine.shell, "rm", ["-rf", codexHome]).pipe(Effect.tap(() => Effect.logInfo("Removed a Codex home that no Attempt holds and whose Attempt has no checkout", { worker, host, codexHome })), Effect.tapError((error) => Effect.logWarning("Could not remove a Codex home; the next sweep tries again", {
70
+ worker,
71
+ host,
72
+ codexHome,
73
+ message: error.message,
74
+ })), Effect.ignore), { discard: true });
75
+ });
76
+ return { hold, sweep };
77
+ });
78
+ //# sourceMappingURL=codex-homes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-homes.js","sourceRoot":"","sources":["../../src/ssh/codex-homes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { type WorkerName } from "@usine/core/worker";
2
+ import { Effect } from "effect";
3
+ import { type ExecutorError, WorkerCapabilityError } from "../executor.ts";
4
+ import type { RemoteCommands } from "../remote/commands.ts";
5
+ import { type AttemptIsolation, type ContainerSettings } from "../remote/container.ts";
6
+ import { type ResolvedLimits } from "./limits.ts";
7
+ import type { SshMachine } from "./model.ts";
8
+ /**
9
+ * The image of each Attempt container when `usine.yaml` names none, built from
10
+ * `infra/worker-image/Dockerfile` with this release's harness versions.
11
+ */
12
+ export declare const ATTEMPT_IMAGE: string & import("effect/Brand").Brand<"ContainerImage">;
13
+ /**
14
+ * Returns the container operations of the SSH executor: the preflight checks of a Worker's
15
+ * Docker and image, the isolation they found, a container for a preflight's harness probes, and
16
+ * the removal of containers an earlier process left.
17
+ */
18
+ export declare const sshContainersFor: (commands: RemoteCommands, machineFor: (worker: WorkerName) => Effect.Effect<SshMachine, ExecutorError>, instance: string, instanceId: string & import("effect/Brand").Brand<"InstanceId">) => Effect.Effect<{
19
+ verify: (machine: SshMachine, slots: number) => Effect.Effect<{
20
+ _tag: "Container";
21
+ settings: ContainerSettings;
22
+ limits: ResolvedLimits;
23
+ } | {
24
+ _tag: "SharedUser";
25
+ degraded: string;
26
+ }, import("../executor.ts").ExecutorOperationError | WorkerCapabilityError, never>;
27
+ isolation: (machine: SshMachine) => Effect.Effect<AttemptIsolation, import("../executor.ts").ExecutorOperationError | WorkerCapabilityError, never>;
28
+ preflightShell: (machine: SshMachine, settings: ContainerSettings, harnesses: readonly ("claude" | "codex" | "pi")[], environment: Readonly<Record<string, string>>) => Effect.Effect<import("@usine/agents/child-host").RemoteShell, import("../executor.ts").ExecutorOperationError, import("effect/Scope").Scope>;
29
+ reclaim: (worker: WorkerName) => Effect.Effect<void, never, never>;
30
+ }, never, never>;
31
+ export type SshContainers = Effect.Success<ReturnType<typeof sshContainersFor>>;
32
+ //# sourceMappingURL=container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/ssh/container.ts"],"names":[],"mappings":"AAIA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAS,MAAM,EAA+B,MAAM,QAAQ,CAAC;AACpE,OAAO,EAAE,KAAK,aAAa,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,iBAAiB,EAMvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAKL,KAAK,cAAc,EAEpB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;GAGG;AACH,eAAO,MAAM,aAAa,yDAEzB,CAAC;AA8CF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,kDAEN,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC;;;;;;;;;;;sBAkUxD,UAAU;gBAE9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,282 @@
1
+ import { SSH_FAILURE } from "@usine/agents/child-host";
2
+ import { safeSegment } from "@usine/core/repository";
3
+ import { ContainerImage } from "@usine/core/worker";
4
+ import { Cache, Effect, Option, Random, Ref, Schema } from "effect";
5
+ import { WorkerCapabilityError } from "../executor.js";
6
+ import { keyedLockFor } from "../keyed-lock.js";
7
+ import { CONTAINER_RUNTIME, containersFor, PNPM_STORE_MOUNT, PNPM_STORE_PATH, PNPM_STORE_VOLUME, sharedUser, } from "../remote/container.js";
8
+ import { configuredLimits, limitFields, RESOURCES_SCRIPT, resolveLimits, resourcesFromOutput, } from "./limits.js";
9
+ /**
10
+ * The image of each Attempt container when `usine.yaml` names none, built from
11
+ * `infra/worker-image/Dockerfile` with this release's harness versions.
12
+ */
13
+ export const ATTEMPT_IMAGE = ContainerImage.make("ghcr.io/basaltbytes/usine-worker:claude-2.1.308-codex-0.159.2");
14
+ /** The exit code of `DETECT_SCRIPT` when the machine has no Docker and the SSH user no access to one. */
15
+ const RUNTIME_ABSENT = 3;
16
+ /** The exit code of `DETECT_SCRIPT` when the SSH user can use Docker's socket but has no `docker` CLI. */
17
+ const SOCKET_WITHOUT_CLI = 4;
18
+ /**
19
+ * A script that prints the version of the container runtime `$1`'s server. Without the CLI, it
20
+ * exits 4 if the SSH user is in the `docker` group or can write Docker's socket, and 3 if not.
21
+ */
22
+ const DETECT_SCRIPT = String.raw `
23
+ if ! command -v "$1" >/dev/null 2>&1; then
24
+ for group in $(id -nG); do
25
+ if [ "$group" = docker ]; then exit 4; fi
26
+ done
27
+ if [ -w /var/run/docker.sock ]; then exit 4; fi
28
+ exit 3
29
+ fi
30
+ exec "$1" version -f '{{.Server.Version}}'
31
+ `.trim();
32
+ /** A script that prints the SSH user's ID and the ID of image `$2`'s user, separated by a space. */
33
+ const USER_IDS_SCRIPT = String.raw `
34
+ image_uid=$("$1" run --rm --network none --entrypoint id "$2" -u) || exit 1
35
+ printf '%s %s\n' "$(id -u)" "$image_uid"
36
+ `.trim();
37
+ const decodeStoreSize = Schema.decodeUnknownEffect(Schema.NumberFromString.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(0)));
38
+ const containerGap = (worker, message, cause) => new WorkerCapabilityError({ worker, capability: "container", message, cause });
39
+ /**
40
+ * Returns the container operations of the SSH executor: the preflight checks of a Worker's
41
+ * Docker and image, the isolation they found, a container for a preflight's harness probes, and
42
+ * the removal of containers an earlier process left.
43
+ */
44
+ export const sshContainersFor = Effect.fn("SshExecutor.containersFor")(function* (commands, machineFor, instance, instanceId) {
45
+ const containers = containersFor(commands);
46
+ const preparedStores = new WeakSet();
47
+ const storeLocks = yield* keyedLockFor();
48
+ const prepareStore = Effect.fn("SshExecutor.preparePnpmStore")(function* (machine, image) {
49
+ const fields = { worker: machine.address.name, host: machine.shell.destination, image };
50
+ yield* Effect.annotateCurrentSpan(fields);
51
+ if (preparedStores.has(machine)) {
52
+ yield* Effect.logDebug("Shared pnpm store already prepared on this machine", fields);
53
+ return;
54
+ }
55
+ yield* containers.prepareStore("prepare", machine.shell, image, machine.address.name);
56
+ preparedStores.add(machine);
57
+ }, (effect, machine) => effect.pipe(storeLocks.withLock(machine.address.name)));
58
+ const isolations = yield* Ref.make(new Map());
59
+ // Workers whose earlier containers this process removed. Their containers on a shared machine
60
+ // belong to this process, so another Worker's removal keeps them.
61
+ const reclaimed = yield* Ref.make(new Set());
62
+ const imageFor = (machine) => Option.getOrElse(machine.address.container.image, () => ATTEMPT_IMAGE);
63
+ /** Reads the CPUs, memory, and task limit of the machine's kernel. */
64
+ const readResources = Effect.fn("SshExecutor.readMachineResources")(function* (machine) {
65
+ const worker = machine.address.name;
66
+ const host = machine.shell.destination;
67
+ yield* Effect.annotateCurrentSpan({ worker, host });
68
+ const read = yield* commands.inspect("preflight", machine.shell, "sh", [
69
+ "-c",
70
+ RESOURCES_SCRIPT,
71
+ ]);
72
+ const resources = resourcesFromOutput(read.stdout);
73
+ if (read.exitCode === 0 && Option.isSome(resources))
74
+ return resources.value;
75
+ return yield* containerGap(worker, read.exitCode === SSH_FAILURE
76
+ ? `Can't reach SSH worker "${worker}" at ${host} to read its CPUs and memory`
77
+ : `Can't read the CPUs, memory, and task limit of SSH worker "${worker}" to derive the limits of its containers. Set cpus, memory_mib, and pids under the worker's container in usine.yaml.`, new Error(read.stderr.trim() || `exit code ${read.exitCode}`));
78
+ });
79
+ /**
80
+ * Returns the limits of each container on the machine when `slots` Attempts run on it at once:
81
+ * the ones `usine.yaml` sets, and the others derived from the machine. Reads the machine only
82
+ * if a limit is unset.
83
+ */
84
+ const limitsFor = Effect.fn("SshExecutor.containerLimits")(function* (machine, slots) {
85
+ yield* Effect.annotateCurrentSpan({ worker: machine.address.name, slots });
86
+ const configured = configuredLimits(machine.address.container);
87
+ if (Option.isSome(configured))
88
+ return configured.value;
89
+ return resolveLimits(machine.address.container, yield* readResources(machine), slots);
90
+ });
91
+ /**
92
+ * Returns the server version of the machine's Docker, or `None` if the machine has none and
93
+ * the SSH user no access to one. Fails if the SSH user can use Docker but Docker doesn't
94
+ * answer, because Attempts must then run in containers: as the SSH user, they could use
95
+ * Docker's socket to act as root.
96
+ */
97
+ const detect = Effect.fn("SshExecutor.detectContainerRuntime")(function* (machine) {
98
+ const worker = machine.address.name;
99
+ const host = machine.shell.destination;
100
+ yield* Effect.annotateCurrentSpan({ worker, host });
101
+ const detected = yield* commands.inspect("preflight", machine.shell, "sh", [
102
+ "-c",
103
+ DETECT_SCRIPT,
104
+ "sh",
105
+ CONTAINER_RUNTIME,
106
+ ]);
107
+ if (detected.exitCode === RUNTIME_ABSENT)
108
+ return Option.none();
109
+ const version = detected.stdout.trim();
110
+ if (detected.exitCode === 0 && version !== "")
111
+ return Option.some(version);
112
+ if (detected.exitCode === SSH_FAILURE)
113
+ return yield* containerGap(worker, `Can't reach SSH worker "${worker}" at ${host} to check Docker`, new Error(detected.stderr.trim() || `ssh exited with code ${SSH_FAILURE}`));
114
+ if (detected.exitCode === SOCKET_WITHOUT_CLI)
115
+ return yield* containerGap(worker, `The SSH user of worker "${worker}" can use Docker's socket, but the docker CLI isn't installed. Install it, so that each attempt runs in its own container, or take the user out of the docker group.`, new Error("docker group or writable socket without the docker CLI"));
116
+ return yield* containerGap(worker, `Docker on SSH worker "${worker}" doesn't respond to its SSH user. Start Docker, and add the user to the docker group.`, new Error(detected.stderr.trim() || `docker version exited with code ${detected.exitCode}`));
117
+ });
118
+ const record = (worker, isolation) => Ref.update(isolations, (current) => new Map(current).set(worker, isolation));
119
+ /**
120
+ * Records that the machine's Worker runs its Attempts as the SSH user, since the machine has no
121
+ * Docker, and logs it.
122
+ */
123
+ const recordSharedUser = (machine) => record(machine.address.name, sharedUser).pipe(Effect.andThen(Effect.logWarning("SSH Worker has no Docker; its Attempts run as the SSH user and can read each other's credentials", { worker: machine.address.name, host: machine.shell.destination })), Effect.as(sharedUser));
124
+ /**
125
+ * Records that each Attempt of the machine's Worker runs in its own container from the image,
126
+ * with the limits for `slots` Attempts on the machine at once, and logs them. `docker` is the
127
+ * server version of the machine's Docker.
128
+ */
129
+ const recordContainer = Effect.fn("SshExecutor.recordContainer")(function* (machine, docker, slots) {
130
+ const worker = machine.address.name;
131
+ const image = imageFor(machine);
132
+ yield* Effect.annotateCurrentSpan({ worker, image, slots });
133
+ const limits = yield* limitsFor(machine, slots);
134
+ const settings = { image, limits: limits.limits, instance, instanceId };
135
+ yield* record(worker, { _tag: "Container", settings });
136
+ yield* Effect.logInfo("SSH Worker runs each Attempt in its own container", {
137
+ worker,
138
+ host: machine.shell.destination,
139
+ docker,
140
+ image,
141
+ ...limitFields(limits),
142
+ });
143
+ return { _tag: "Container", settings, limits };
144
+ });
145
+ /**
146
+ * Checks the machine's Docker for preflight, pulls the Attempt image, checks that the image's
147
+ * user has the SSH user's ID, so the containers can write the checkouts, and finds the limits
148
+ * of each container when `slots` Attempts run on the machine at once. Only a machine without
149
+ * Docker runs Attempts as the SSH user, which the result reports as degraded; with Docker, any
150
+ * failure fails the preflight.
151
+ */
152
+ const verify = Effect.fn("SshExecutor.verifyContainers")(function* (machine, slots) {
153
+ const worker = machine.address.name;
154
+ const host = machine.shell.destination;
155
+ const image = imageFor(machine);
156
+ yield* Effect.annotateCurrentSpan({ worker, host, image, slots });
157
+ const version = yield* detect(machine);
158
+ if (Option.isNone(version)) {
159
+ yield* recordSharedUser(machine);
160
+ return {
161
+ _tag: "SharedUser",
162
+ degraded: "Docker isn't installed, so attempts run as the SSH user and can read each other's credentials. Install Docker to run each attempt in its own container.",
163
+ };
164
+ }
165
+ const pulled = yield* commands.inspect("preflight", machine.shell, CONTAINER_RUNTIME, [
166
+ "pull",
167
+ "--quiet",
168
+ image,
169
+ ]);
170
+ if (pulled.exitCode !== 0) {
171
+ const local = yield* commands.inspect("preflight", machine.shell, CONTAINER_RUNTIME, [
172
+ "image",
173
+ "inspect",
174
+ "--format",
175
+ "{{.Id}}",
176
+ image,
177
+ ]);
178
+ if (local.exitCode !== 0)
179
+ return yield* containerGap(worker, `SSH worker "${worker}" can't pull the attempt image ${image}`, new Error(pulled.stderr.trim() || `docker pull exited with code ${pulled.exitCode}`));
180
+ yield* Effect.logWarning("SSH Worker could not pull the Attempt image; its Attempts use the image already on the machine", { worker, host, image, message: pulled.stderr.trim() });
181
+ }
182
+ const ids = yield* commands.inspect("preflight", machine.shell, "sh", [
183
+ "-c",
184
+ USER_IDS_SCRIPT,
185
+ "sh",
186
+ CONTAINER_RUNTIME,
187
+ image,
188
+ ]);
189
+ const [hostId, imageId] = ids.stdout.trim().split(" ");
190
+ if (ids.exitCode !== 0 || hostId === undefined || imageId === undefined)
191
+ return yield* containerGap(worker, `SSH worker "${worker}" can't run the attempt image ${image}`, new Error(ids.stderr.trim() || `exit code ${ids.exitCode}`));
192
+ if (hostId !== imageId)
193
+ return yield* containerGap(worker, `The attempt image ${image} runs as user ID ${imageId}, and the SSH user of worker "${worker}" has ID ${hostId}, so its containers can't write the checkouts. Build the image with --build-arg USINE_UID=${hostId}.`, new Error(`user IDs ${hostId} and ${imageId}`));
194
+ yield* containers
195
+ .prepareStore("preflight", machine.shell, image, worker)
196
+ .pipe(Effect.mapError((error) => containerGap(worker, `Can't prepare the shared pnpm store: ${error.message}`, error)));
197
+ preparedStores.add(machine);
198
+ const size = yield* commands
199
+ .run("preflight", machine.shell, CONTAINER_RUNTIME, [
200
+ "run",
201
+ "--rm",
202
+ "--network",
203
+ "none",
204
+ "--mount",
205
+ PNPM_STORE_MOUNT,
206
+ "--entrypoint",
207
+ "du",
208
+ image,
209
+ "-sk",
210
+ PNPM_STORE_PATH,
211
+ ])
212
+ .pipe(Effect.flatMap((output) => decodeStoreSize(output.trim().split(/\s+/u)[0])), Effect.mapError((error) => containerGap(worker, `Can't measure the shared pnpm store on worker "${worker}"`, error)));
213
+ yield* Effect.logInfo("Shared pnpm store disk usage", {
214
+ worker,
215
+ host,
216
+ volume: PNPM_STORE_VOLUME,
217
+ sizeKiB: size,
218
+ });
219
+ return yield* recordContainer(machine, version.value, slots);
220
+ });
221
+ /**
222
+ * Returns how new Attempts on the machine run, as the Worker's last preflight found, or detects
223
+ * and logs it. Before any preflight on the Worker, as for the recovery of a provisioned Worker's
224
+ * machine, it derives the unset limits for one Attempt on the machine.
225
+ */
226
+ const isolationOf = Effect.fn("SshExecutor.isolation")(function* (machine) {
227
+ const recorded = (yield* Ref.get(isolations)).get(machine.address.name);
228
+ if (recorded !== undefined) {
229
+ if (recorded._tag === "Container")
230
+ yield* prepareStore(machine, recorded.settings.image);
231
+ return recorded;
232
+ }
233
+ const version = yield* detect(machine);
234
+ if (Option.isNone(version))
235
+ return yield* recordSharedUser(machine);
236
+ yield* prepareStore(machine, imageFor(machine));
237
+ const { settings } = yield* recordContainer(machine, version.value, 1);
238
+ return { _tag: "Container", settings };
239
+ });
240
+ /**
241
+ * Starts a container from `settings` for a preflight's harness probes, with the login files
242
+ * of `harnesses` and `environment`, until the caller's scope closes. It removes itself after
243
+ * 15 minutes if this process can't.
244
+ */
245
+ const preflightShell = Effect.fn("SshExecutor.preflightContainer")(function* (machine, settings, harnesses, environment) {
246
+ const suffix = yield* Random.nextIntBetween(0, 1_000_000_000);
247
+ return yield* containers.start("preflight", machine.shell, {
248
+ name: `usine-preflight-${safeSegment(machine.address.name)}-${suffix}`,
249
+ settings,
250
+ worker: machine.address.name,
251
+ attemptId: Option.none(),
252
+ checkout: Option.none(),
253
+ readOnly: [],
254
+ writable: [],
255
+ harnesses,
256
+ environment,
257
+ secrets: {},
258
+ });
259
+ });
260
+ const sweep = Effect.fn("SshExecutor.removeLeftContainers")(function* (worker) {
261
+ const machine = yield* machineFor(worker);
262
+ yield* Effect.annotateCurrentSpan({ worker, host: machine.shell.destination });
263
+ yield* Ref.update(reclaimed, (current) => new Set(current).add(worker));
264
+ yield* containers.sweep(machine.shell, instance, instanceId, worker, yield* Ref.get(reclaimed));
265
+ });
266
+ // Runs once per Worker in this process, before its first container starts. A failure is
267
+ // logged; the containers stay until the next process.
268
+ const swept = yield* Cache.make({
269
+ capacity: Number.POSITIVE_INFINITY,
270
+ lookup: (worker) => sweep(worker).pipe(Effect.tapError((error) => Effect.logWarning("Could not remove the containers an earlier process left", {
271
+ worker,
272
+ message: error.message,
273
+ })), Effect.ignore),
274
+ });
275
+ return {
276
+ verify,
277
+ isolation: isolationOf,
278
+ preflightShell,
279
+ reclaim: (worker) => Cache.get(swept, worker),
280
+ };
281
+ });
282
+ //# sourceMappingURL=container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/ssh/container.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { WorkerName } from "@usine/core/worker";
2
+ import { Effect } from "effect";
3
+ import { CredentialProvider, type ExecutorError } from "../executor.ts";
4
+ import type { RemoteCommands } from "../remote/commands.ts";
5
+ import type { SshMachine } from "./model.ts";
6
+ /**
7
+ * Writes each Attempt's token to a directory next to the Worker's checkouts that only the SSH
8
+ * user can read, renews it before expiry, and removes it when the Attempt's scope closes. All
9
+ * Attempts on the Worker can read each other's tokens (ADR 0026). `reclaim` removes credentials
10
+ * left by an earlier process, once per process.
11
+ */
12
+ export declare const sshCredentialsFor: (commands: RemoteCommands, machineFor: (worker: WorkerName) => Effect.Effect<SshMachine, ExecutorError>) => Effect.Effect<{
13
+ acquire: (attemptId: string & import("effect/Brand").Brand<"AttemptId">, worker: string & import("effect/Brand").Brand<"WorkerName">, repository: string & import("effect/Brand").Brand<"RepositoryName">, permissions: "read" | "write", machine: SshMachine, operation: "cancel" | "cleanup" | "launch" | "preflight" | "prepare") => Effect.Effect<{
14
+ environment: {
15
+ GH_CONFIG_DIR: string;
16
+ GH_PROMPT_DISABLED: string;
17
+ USINE_GITHUB_TOKEN_FILE: string;
18
+ GIT_CONFIG_COUNT: string;
19
+ GIT_CONFIG_KEY_0: string;
20
+ GIT_CONFIG_VALUE_0: string;
21
+ GIT_CONFIG_KEY_1: string;
22
+ GIT_CONFIG_VALUE_1: string;
23
+ };
24
+ gitEnvironment: {
25
+ GH_CONFIG_DIR: string;
26
+ GH_PROMPT_DISABLED: string;
27
+ USINE_GITHUB_TOKEN_FILE: string;
28
+ GIT_CONFIG_COUNT: string;
29
+ GIT_CONFIG_KEY_0: string;
30
+ GIT_CONFIG_VALUE_0: string;
31
+ GIT_CONFIG_KEY_1: string;
32
+ GIT_CONFIG_VALUE_1: string;
33
+ };
34
+ shell: import("@usine/agents/child-host").RemoteShell;
35
+ secrets: {};
36
+ readOnlyPaths: string[];
37
+ writablePaths: never[];
38
+ refresh: Effect.Effect<void, import("../executor.ts").CredentialUnavailableError | import("../executor.ts").ExecutorOperationError, never>;
39
+ scrub: (text: string) => string;
40
+ }, import("../executor.ts").CredentialUnavailableError | import("../executor.ts").ExecutorOperationError, import("effect/Scope").Scope>;
41
+ reclaim: (worker: WorkerName) => Effect.Effect<void, never, never>;
42
+ }, never, CredentialProvider>;
43
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/ssh/credentials.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAS,MAAM,EAAY,MAAM,QAAQ,CAAC;AAEjD,OAAO,EACL,kBAAkB,EAClB,KAAK,aAAa,EAGnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAuB7C;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,kDAEP,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBA+BnD,UAAU;6BA6EnC,CAAC"}
@@ -0,0 +1,86 @@
1
+ import { safeSegment } from "@usine/core/repository";
2
+ import { Cache, Effect, Redacted } from "effect";
3
+ import { credentialEnvironment, GH_CONFIG, ghHostsConfig } from "../credential-environment.js";
4
+ import { CredentialProvider, } from "../executor.js";
5
+ import { renewableCredential } from "../renewable-credential.js";
6
+ /**
7
+ * A script that writes the Attempt's credential directory `$3` inside the credentials root
8
+ * `$2`: the token from the first stdin line, gh's `hosts.yml` from the rest, and gh's
9
+ * `config.yml` from `$1`. Sets mode 700 on both directories. Reading the token from stdin keeps
10
+ * it out of arguments and the environment; each file is written then renamed.
11
+ */
12
+ const WRITE_CREDENTIAL_SCRIPT = String.raw `
13
+ set -e
14
+ umask 077
15
+ mkdir -p "$2" "$3"
16
+ chmod 700 "$2" "$3"
17
+ IFS= read -r token
18
+ printf '%s' "$token" > "$3/token.next"
19
+ cat > "$3/hosts.next"
20
+ test -f "$3/config.yml" || printf '%s' "$1" > "$3/config.yml"
21
+ mv "$3/token.next" "$3/token"
22
+ mv "$3/hosts.next" "$3/hosts.yml"
23
+ `.trim();
24
+ const credentialsRoot = (machine) => `${machine.workerDirectory}/credentials`;
25
+ /**
26
+ * Writes each Attempt's token to a directory next to the Worker's checkouts that only the SSH
27
+ * user can read, renews it before expiry, and removes it when the Attempt's scope closes. All
28
+ * Attempts on the Worker can read each other's tokens (ADR 0026). `reclaim` removes credentials
29
+ * left by an earlier process, once per process.
30
+ */
31
+ export const sshCredentialsFor = Effect.fn("SshExecutor.credentialsFor")(function* (commands, machineFor) {
32
+ const provider = yield* CredentialProvider;
33
+ const removeStale = Effect.fn("SshExecutor.removeStaleCredentials")(function* (worker) {
34
+ const machine = yield* machineFor(worker);
35
+ const host = machine.shell.destination;
36
+ yield* Effect.annotateCurrentSpan({ worker, host });
37
+ yield* commands.run("cleanup", machine.shell, "rm", ["-rf", credentialsRoot(machine)]);
38
+ yield* Effect.logInfo("Removed credentials an earlier process left on the SSH Worker", {
39
+ worker,
40
+ host,
41
+ });
42
+ });
43
+ // A failed removal is logged and cached, not retried: the remaining tokens expire within an
44
+ // hour and the next start removes them.
45
+ const reclaimed = yield* Cache.make({
46
+ capacity: Number.POSITIVE_INFINITY,
47
+ lookup: (worker) => removeStale(worker).pipe(Effect.tapError((error) => Effect.logWarning("Could not remove stale credentials from the SSH Worker", {
48
+ worker,
49
+ message: error.message,
50
+ })), Effect.ignore),
51
+ });
52
+ const reclaim = (worker) => Cache.get(reclaimed, worker);
53
+ const write = Effect.fn("SshExecutor.writeCredential")(function* (operation, machine, directory, { value }) {
54
+ yield* Effect.annotateCurrentSpan({ host: machine.shell.destination, directory });
55
+ const payload = Redacted.make(`${Redacted.value(value)}\n${ghHostsConfig(Redacted.value(value))}`);
56
+ yield* commands
57
+ .runWithInput(operation, machine.shell, "sh", ["-c", WRITE_CREDENTIAL_SCRIPT, "sh", GH_CONFIG, credentialsRoot(machine), directory], payload)
58
+ .pipe(Effect.ensuring(Effect.sync(() => Redacted.wipeUnsafe(payload))));
59
+ },
60
+ // Scope closure waits for an in-flight write, so a late renewal cannot run after the removal.
61
+ Effect.uninterruptible);
62
+ const acquire = Effect.fn("SshExecutor.acquireCredential")(function* (attemptId, worker, repository, permissions, machine, operation) {
63
+ const host = machine.shell.destination;
64
+ yield* Effect.annotateCurrentSpan({ attemptId, worker, repository, permissions, host });
65
+ const directory = `${credentialsRoot(machine)}/${safeSegment(attemptId)}`;
66
+ yield* Effect.addFinalizer(() => commands.run("cleanup", machine.shell, "rm", ["-rf", directory]).pipe(Effect.tap(() => Effect.logInfo("Removed the Attempt's credential from the SSH Worker", {
67
+ attemptId,
68
+ worker,
69
+ host,
70
+ })), Effect.tapError((error) => Effect.logError("Could not remove the Attempt's credential from the SSH Worker; it expires within the hour", { attemptId, worker, host, message: error.message })), Effect.ignore));
71
+ const credential = yield* renewableCredential(provider.issue, repository, attemptId, permissions, (issued) => write(operation, machine, directory, issued));
72
+ const environment = credentialEnvironment(directory);
73
+ return {
74
+ environment,
75
+ gitEnvironment: environment,
76
+ shell: machine.shell,
77
+ secrets: {},
78
+ readOnlyPaths: [directory],
79
+ writablePaths: [],
80
+ refresh: credential.refresh(),
81
+ scrub: credential.scrub,
82
+ };
83
+ });
84
+ return { acquire, reclaim };
85
+ });
86
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/ssh/credentials.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { type AttachRequest, type Attached, type AttachmentId, type AttachmentList, type Detached, type LlmProviderList } from "@usine/gateway/admin";
2
+ import { Effect, Option, Schema } from "effect";
3
+ import { HttpClient } from "effect/http";
4
+ import type { SshWorkerGateway } from "../model.ts";
5
+ import { type GatewayForward } from "./forward.ts";
6
+ declare const GatewayAdminError_base: Schema.Class<GatewayAdminError, Schema.TaggedStruct<"GatewayAdminError", {
7
+ readonly worker: Schema.brand<Schema.String, "WorkerName">;
8
+ readonly operation: Schema.Literals<readonly ["attach", "renew", "detach", "list", "providers"]>;
9
+ readonly message: Schema.NonEmptyString;
10
+ }>, import("effect/Cause").YieldableError>;
11
+ /**
12
+ * The error for a failed Gateway admin API request. `message` contains no token; the request
13
+ * and raw failure are discarded because an attach request contains the installation token.
14
+ */
15
+ export declare class GatewayAdminError extends GatewayAdminError_base {
16
+ }
17
+ export interface GatewayAdmin {
18
+ /** Attaches an Attempt's token for the Worker and a repository. Returns the attachment ID and its caller token. */
19
+ readonly attach: (request: AttachRequest) => Effect.Effect<Attached, GatewayAdminError>;
20
+ /** Replaces the token and expiry of attachment `id`, or re-creates it after a Gateway restart. The caller token doesn't change. */
21
+ readonly renew: (id: AttachmentId, request: AttachRequest) => Effect.Effect<Attached, GatewayAdminError>;
22
+ /** Removes attachment `id` and returns whether it existed. */
23
+ readonly detach: (id: AttachmentId) => Effect.Effect<Detached, GatewayAdminError>;
24
+ /** Returns the active attachments for all the Gateway's Workers. */
25
+ readonly list: Effect.Effect<AttachmentList, GatewayAdminError>;
26
+ /**
27
+ * Returns the LLM providers the Gateway has credentials for, with each credential kind. Returns
28
+ * `None` if the Gateway predates this endpoint.
29
+ */
30
+ readonly providers: Effect.Effect<Option.Option<LlmProviderList>, GatewayAdminError>;
31
+ }
32
+ /**
33
+ * Returns the admin API client for the Gateway in front of `worker`, connected through
34
+ * `forward` with the admin token as a bearer token. If the forward is closed or a request gets
35
+ * no response, reopens the forward and retries once.
36
+ */
37
+ export declare const gatewayAdminFor: (worker: string & import("effect/Brand").Brand<"WorkerName">, gateway: SshWorkerGateway, forward: GatewayForward) => Effect.Effect<{
38
+ attach: (request: AttachRequest) => Effect.Effect<Attached, GatewayAdminError, never>;
39
+ renew: (id: string & import("effect/Brand").Brand<"AttachmentId">, request: AttachRequest) => Effect.Effect<Attached, GatewayAdminError, never>;
40
+ detach: (id: string & import("effect/Brand").Brand<"AttachmentId">) => Effect.Effect<Detached, GatewayAdminError, never>;
41
+ list: Effect.Effect<AttachmentList, GatewayAdminError, never>;
42
+ providers: Effect.Effect<Option.Option<never> | Option.Option<LlmProviderList>, GatewayAdminError, never>;
43
+ }, never, HttpClient.HttpClient>;
44
+ export {};
45
+ //# sourceMappingURL=admin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../../src/ssh/gateway/admin.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,QAAQ,EAEb,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAkB,MAAM,EAAE,MAAM,EAAyB,MAAM,EAAE,MAAM,QAAQ,CAAC;AACvF,OAAO,EAAE,UAAU,EAAsC,MAAM,aAAa,CAAC;AAE7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,KAAK,cAAc,EAA0C,MAAM,cAAc,CAAC;;;;;;AAa3F;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,sBAMrC;CAAG;AAEL,MAAM,WAAW,YAAY;IAC3B,mHAAmH;IACnH,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IACxF,mIAAmI;IACnI,QAAQ,CAAC,KAAK,EAAE,CACd,EAAE,EAAE,YAAY,EAChB,OAAO,EAAE,aAAa,KACnB,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAChD,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,YAAY,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAClF,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC;IAChE;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,iBAAiB,CAAC,CAAC;CACtF;AAmED;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;;gCAgF1B,CAAC"}