@crvouga/dev-fleet 0.0.0-stage → 0.2.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 (363) hide show
  1. package/.mise/locks/aws-cdk/2.1146.1/aube-lock.yaml +24 -0
  2. package/.mise/locks/aws-cdk/2.1146.1/package.json +7 -0
  3. package/.mise/locks/azure-cli/2.91.0~a837e014/pyproject.toml +5 -0
  4. package/.mise/locks/azure-cli/2.91.0~a837e014/uv.lock +2794 -0
  5. package/.mise/locks/gemini/0.66.0~84aac8e6/aube-lock.yaml +123 -0
  6. package/.mise/locks/gemini/0.66.0~84aac8e6/package.json +12 -0
  7. package/.mise/locks/npm-devcontainers-cli/0.90.0/aube-lock.yaml +24 -0
  8. package/.mise/locks/npm-devcontainers-cli/0.90.0/package.json +7 -0
  9. package/.mise/locks/npm-modelcontextprotocol-inspector/2.13.0~4c109bea/aube-lock.yaml +1432 -0
  10. package/.mise/locks/npm-modelcontextprotocol-inspector/2.13.0~4c109bea/package.json +7 -0
  11. package/.mise/locks/npm-vercel/65.8.0/aube-lock.yaml +3595 -0
  12. package/.mise/locks/npm-vercel/65.8.0/package.json +7 -0
  13. package/.mise/locks/npm-wrangler/4.156.0/aube-lock.yaml +895 -0
  14. package/.mise/locks/npm-wrangler/4.156.0/package.json +7 -0
  15. package/.mise/locks/npm-yarnpkg-cli-dist/4.18.1/aube-lock.yaml +24 -0
  16. package/.mise/locks/npm-yarnpkg-cli-dist/4.18.1/package.json +7 -0
  17. package/LICENSE +21 -0
  18. package/README.md +357 -2
  19. package/agents/antigravity-proxy.ts +3 -0
  20. package/agents/audit.md +89 -0
  21. package/agents/claude-proxy +5 -0
  22. package/agents/claude-proxy.ts +3 -0
  23. package/agents/codex-proxy.ts +3 -0
  24. package/agents/grok-proxy.ts +3 -0
  25. package/agents/managed-proxy.ts +55 -0
  26. package/agents/opencode-proxy.ts +3 -0
  27. package/agents/registry.json +209 -0
  28. package/agents/registry.schema.json +149 -0
  29. package/agents/setup.md +158 -0
  30. package/agents/t3.json +40 -0
  31. package/ansible/macos/manager.yml +30 -0
  32. package/ansible/macos/policy.json +9 -0
  33. package/ansible/monitoring/README.md +215 -0
  34. package/ansible/monitoring/agent-darwin.yml +198 -0
  35. package/ansible/monitoring/agent.yml +172 -0
  36. package/ansible/monitoring/beszel-agent.service +42 -0
  37. package/ansible/monitoring/compose.yml +74 -0
  38. package/ansible/monitoring/hub-darwin.yml +102 -0
  39. package/ansible/monitoring/hub-route-darwin.yml +51 -0
  40. package/ansible/monitoring/lock.json +16 -0
  41. package/ansible/net/remote-probe.sh +13 -0
  42. package/ansible/pyproject.toml +12 -0
  43. package/ansible/ubuntu/authorize-sudo.sh +51 -0
  44. package/ansible/ubuntu/baseline.yml +89 -0
  45. package/ansible/ubuntu/disk-gc.py +336 -0
  46. package/ansible/ubuntu/disk-guard.py +104 -0
  47. package/ansible/ubuntu/policy.json +52 -0
  48. package/ansible/ubuntu/recovery.yml +15 -0
  49. package/ansible/ubuntu/t3/policy.json +7 -0
  50. package/ansible/ubuntu/t3-desktop.yml +220 -0
  51. package/ansible/ubuntu/t3-health.sh +33 -0
  52. package/ansible/ubuntu/t3-policy.yml +76 -0
  53. package/ansible/ubuntu/t3-route.yml +28 -0
  54. package/ansible/ubuntu/tailscale.yml +78 -0
  55. package/ansible/ubuntu/tasks/credentials.yml +47 -0
  56. package/ansible/ubuntu/tasks/docker.yml +31 -0
  57. package/ansible/ubuntu/tasks/packages.yml +56 -0
  58. package/ansible/ubuntu/tasks/power.yml +51 -0
  59. package/ansible/ubuntu/tasks/recovery.yml +39 -0
  60. package/ansible/ubuntu/tasks/resources.yml +312 -0
  61. package/ansible/ubuntu/tasks/services.yml +31 -0
  62. package/ansible/ubuntu/tasks/ssh.yml +71 -0
  63. package/ansible/ubuntu/tasks/user.yml +120 -0
  64. package/ansible/uv.lock +190 -0
  65. package/bin/devfleet.mjs +36 -0
  66. package/bootstrap/bootstrap.ps1 +50 -0
  67. package/bootstrap/bootstrap.sh +80 -0
  68. package/bootstrap/devfleet +7 -0
  69. package/bootstrap/docker-desktop.sh +33 -0
  70. package/bootstrap/doctor.ts +234 -0
  71. package/bootstrap/fleet-manager-run.sh +103 -0
  72. package/bootstrap/fleet-remote-bootstrap.sh +258 -0
  73. package/bootstrap/global-config.ts +171 -0
  74. package/bootstrap/install-launcher.sh +10 -0
  75. package/bootstrap/native-aws.ts +86 -0
  76. package/bootstrap/native-t3.ts +154 -0
  77. package/bootstrap/npm.ts +358 -0
  78. package/bootstrap/release-version.ts +157 -0
  79. package/bootstrap/setup-status.ts +51 -0
  80. package/bootstrap/setup.ts +88 -0
  81. package/bootstrap/shell-path.ts +105 -0
  82. package/bootstrap/verify-t3-archive.py +49 -0
  83. package/bootstrap/worker-auth.ts +65 -0
  84. package/bootstrap/worker-github.ts +47 -0
  85. package/bootstrap/worker-tools.ts +24 -0
  86. package/cliproxy/AGENTS.md +11 -0
  87. package/cliproxy/README.md +269 -0
  88. package/cliproxy/clients/bootstrap.py +143 -0
  89. package/cliproxy/clients/launcher.py +57 -0
  90. package/cliproxy/compose.yaml +90 -0
  91. package/cliproxy/config.template.yaml +70 -0
  92. package/cliproxy/docs/cloud-adoption.md +16 -0
  93. package/cliproxy/docs/deployment.png +0 -0
  94. package/cliproxy/docs/deployment.svg +109 -0
  95. package/cliproxy/docs/health-workflow.example.yml +185 -0
  96. package/cliproxy/docs/migration.md +131 -0
  97. package/cliproxy/docs/model-health-report.schema.json +364 -0
  98. package/cliproxy/docs/model-health.md +393 -0
  99. package/cliproxy/image.lock.json +5 -0
  100. package/cliproxy/launchd/dev.devfleet.cliproxy-backup-check.plist +38 -0
  101. package/cliproxy/launchd/dev.devfleet.cliproxy-backup.plist +48 -0
  102. package/cliproxy/launchd/dev.devfleet.cliproxy-fleet.plist +32 -0
  103. package/cliproxy/launchd/dev.devfleet.cliproxy-gc.plist +38 -0
  104. package/cliproxy/launchd/dev.devfleet.cliproxy-monitor.plist +29 -0
  105. package/cliproxy/launchd/dev.devfleet.cliproxy-vault-renew.plist +31 -0
  106. package/cliproxy/models.json +1618 -0
  107. package/cliproxy/requirements.lock +78 -0
  108. package/cliproxy/scripts/accounts.py +38 -0
  109. package/cliproxy/scripts/audit.py +123 -0
  110. package/cliproxy/scripts/backup +234 -0
  111. package/cliproxy/scripts/check.py +34 -0
  112. package/cliproxy/scripts/checkpoint.py +226 -0
  113. package/cliproxy/scripts/cli.py +64 -0
  114. package/cliproxy/scripts/cliproxy_host.py +257 -0
  115. package/cliproxy/scripts/cloud_state.py +150 -0
  116. package/cliproxy/scripts/container-health +6 -0
  117. package/cliproxy/scripts/docker +24 -0
  118. package/cliproxy/scripts/external-health.py +79 -0
  119. package/cliproxy/scripts/fleet_config.py +43 -0
  120. package/cliproxy/scripts/fleet_sync.py +274 -0
  121. package/cliproxy/scripts/initialize +84 -0
  122. package/cliproxy/scripts/install-dependencies +48 -0
  123. package/cliproxy/scripts/install.py +406 -0
  124. package/cliproxy/scripts/model_health.py +16 -0
  125. package/cliproxy/scripts/modelhealth/__init__.py +5 -0
  126. package/cliproxy/scripts/modelhealth/checks.py +429 -0
  127. package/cliproxy/scripts/modelhealth/cli.py +117 -0
  128. package/cliproxy/scripts/modelhealth/config.py +186 -0
  129. package/cliproxy/scripts/modelhealth/emulator.py +536 -0
  130. package/cliproxy/scripts/modelhealth/expect.py +88 -0
  131. package/cliproxy/scripts/modelhealth/findings.py +183 -0
  132. package/cliproxy/scripts/modelhealth/protocol.py +330 -0
  133. package/cliproxy/scripts/modelhealth/redact.py +28 -0
  134. package/cliproxy/scripts/modelhealth/report.py +150 -0
  135. package/cliproxy/scripts/modelhealth/runner.py +390 -0
  136. package/cliproxy/scripts/modelhealth/scenario.py +131 -0
  137. package/cliproxy/scripts/modelhealth/schema.py +63 -0
  138. package/cliproxy/scripts/modelhealth/simulate.py +111 -0
  139. package/cliproxy/scripts/modelhealth/transport.py +213 -0
  140. package/cliproxy/scripts/monitor +68 -0
  141. package/cliproxy/scripts/ops +527 -0
  142. package/cliproxy/scripts/public-endpoint +127 -0
  143. package/cliproxy/scripts/recover_node.py +177 -0
  144. package/cliproxy/scripts/restore-verify +60 -0
  145. package/cliproxy/scripts/retention.py +144 -0
  146. package/cliproxy/scripts/service-start +7 -0
  147. package/cliproxy/scripts/validate-config +56 -0
  148. package/cliproxy/scripts/vault-access.py +57 -0
  149. package/cliproxy/scripts/vault-backup-login +55 -0
  150. package/cliproxy/scripts/vault-recovery +56 -0
  151. package/cliproxy/scripts/vault-renew +30 -0
  152. package/cliproxy/systemd/cliproxy-backup-check.service +10 -0
  153. package/cliproxy/systemd/cliproxy-backup-check.timer +8 -0
  154. package/cliproxy/systemd/cliproxy-backup.service +13 -0
  155. package/cliproxy/systemd/cliproxy-backup.timer +8 -0
  156. package/cliproxy/systemd/cliproxy-fleet.service +17 -0
  157. package/cliproxy/systemd/cliproxy-gc.service +13 -0
  158. package/cliproxy/systemd/cliproxy-gc.timer +8 -0
  159. package/cliproxy/systemd/cliproxy-monitor.service +8 -0
  160. package/cliproxy/systemd/cliproxy-monitor.timer +7 -0
  161. package/cliproxy/systemd/cliproxy-vault-renew.service +8 -0
  162. package/cliproxy/systemd/cliproxy-vault-renew.timer +7 -0
  163. package/cliproxy/vendor/LICENSE +22 -0
  164. package/cliproxy/vendor/config.upstream.yaml +1349 -0
  165. package/docs/consumer-setup.md +408 -0
  166. package/docs/declared.md +89 -0
  167. package/docs/machine-setup.md +399 -0
  168. package/docs/operations.md +276 -0
  169. package/docs/releasing.md +103 -0
  170. package/docs/state.md +254 -0
  171. package/docs/topology.md +67 -0
  172. package/docs/ubuntu-sync.md +351 -0
  173. package/docs/worker-contract.md +67 -0
  174. package/examples/fleet.json +100 -0
  175. package/examples/roster.json +13 -0
  176. package/llms.txt +35 -0
  177. package/mise.lock +1521 -0
  178. package/mise.toml +110 -0
  179. package/package.json +74 -4
  180. package/schema/fleet.schema.json +420 -0
  181. package/schema/roster.schema.json +77 -0
  182. package/src/agents/account-relay.ts +111 -0
  183. package/src/agents/accounts.ts +85 -0
  184. package/src/agents/audit.ts +77 -0
  185. package/src/agents/cli.ts +13 -0
  186. package/src/agents/command.ts +204 -0
  187. package/src/agents/converge.ts +123 -0
  188. package/src/agents/doctor.ts +107 -0
  189. package/src/agents/errors.ts +2 -0
  190. package/src/agents/files.ts +73 -0
  191. package/src/agents/fleet-verify.ts +165 -0
  192. package/src/agents/launch.ts +290 -0
  193. package/src/agents/native-verify.ts +371 -0
  194. package/src/agents/provider-errors.ts +57 -0
  195. package/src/agents/registry.ts +61 -0
  196. package/src/agents/render.ts +110 -0
  197. package/src/agents/round-trip.ts +192 -0
  198. package/src/agents/secrets.ts +13 -0
  199. package/src/agents/toolchain.ts +34 -0
  200. package/src/agents/verify-cache.ts +103 -0
  201. package/src/agents/verify.ts +127 -0
  202. package/src/auth-checks.ts +163 -0
  203. package/src/cli/agent-guide.ts +129 -0
  204. package/src/cli/app.ts +122 -0
  205. package/src/cli/cli.ts +28 -0
  206. package/src/cli/command-index.ts +57 -0
  207. package/src/cli/contracts.ts +25 -0
  208. package/src/cli/fleet-reference.ts +17 -0
  209. package/src/cli/fleet-state.ts +499 -0
  210. package/src/cli/fleet-sync-checkout.ts +130 -0
  211. package/src/cli/fleet-sync-enrollment.ts +140 -0
  212. package/src/cli/fleet-sync-forward.ts +134 -0
  213. package/src/cli/fleet-sync-manager.ts +249 -0
  214. package/src/cli/fleet-sync-monitoring.ts +185 -0
  215. package/src/cli/fleet-sync-output.ts +317 -0
  216. package/src/cli/fleet-sync-privilege.ts +27 -0
  217. package/src/cli/fleet-sync-progress.ts +109 -0
  218. package/src/cli/fleet-sync-remote.ts +242 -0
  219. package/src/cli/fleet-sync-report.ts +26 -0
  220. package/src/cli/fleet-sync-schedule.ts +138 -0
  221. package/src/cli/fleet-sync-state.ts +86 -0
  222. package/src/cli/fleet-sync-vault.ts +166 -0
  223. package/src/cli/fleet-sync.ts +375 -0
  224. package/src/cli/fleet.ts +165 -0
  225. package/src/cli/managed-health.ts +219 -0
  226. package/src/cli/node-deployment.ts +34 -0
  227. package/src/cli/node-sync.ts +121 -0
  228. package/src/cli/node-t3.ts +31 -0
  229. package/src/cli/options.ts +141 -0
  230. package/src/cli/probe-source.ts +7 -0
  231. package/src/cli/program.ts +185 -0
  232. package/src/cli/project.ts +51 -0
  233. package/src/cli/register-fleet.ts +296 -0
  234. package/src/cli/registry.ts +185 -0
  235. package/src/cli/repair-apply.ts +67 -0
  236. package/src/cli/repair-guard.ts +11 -0
  237. package/src/cli/repair-inspect.ts +150 -0
  238. package/src/cli/repair-script.ts +76 -0
  239. package/src/cli/repair.ts +209 -0
  240. package/src/cli/roster.ts +105 -0
  241. package/src/cli/search.ts +35 -0
  242. package/src/cli/settings.ts +67 -0
  243. package/src/cli/source-operations.ts +102 -0
  244. package/src/cli/t3/command.ts +90 -0
  245. package/src/cli/t3/register.ts +55 -0
  246. package/src/cli/tailnet.ts +127 -0
  247. package/src/cli/ui-actions.ts +133 -0
  248. package/src/cli/ui-controller.ts +113 -0
  249. package/src/cli/ui-data.ts +106 -0
  250. package/src/cli/ui-execute.ts +163 -0
  251. package/src/cli/ui-repairs.ts +34 -0
  252. package/src/cli/ui-reports.ts +211 -0
  253. package/src/cli/ui-targets.ts +100 -0
  254. package/src/cli/ui-terminal.ts +109 -0
  255. package/src/cli/ui-types.ts +49 -0
  256. package/src/cli/ui-wizard.ts +101 -0
  257. package/src/cli/ui.ts +9 -0
  258. package/src/cli/worker-health-output.ts +37 -0
  259. package/src/config.ts +186 -0
  260. package/src/configure.ts +255 -0
  261. package/src/definition.ts +290 -0
  262. package/src/diagnostics.ts +92 -0
  263. package/src/doctor-check.ts +10 -0
  264. package/src/errors.ts +1 -0
  265. package/src/fingerprint.ts +120 -0
  266. package/src/fleet-config.ts +174 -0
  267. package/src/input-hashes.ts +73 -0
  268. package/src/machine/local-source.ts +52 -0
  269. package/src/machine/lock-error.ts +2 -0
  270. package/src/machine/platform.ts +44 -0
  271. package/src/machine/source.ts +68 -0
  272. package/src/machine/state.ts +173 -0
  273. package/src/machine-health.ts +95 -0
  274. package/src/managed-source.ts +47 -0
  275. package/src/manager-failure.ts +48 -0
  276. package/src/manager-sync.ts +405 -0
  277. package/src/manager.ts +62 -0
  278. package/src/monitoring/agent-evidence.ts +146 -0
  279. package/src/monitoring/apply.ts +183 -0
  280. package/src/monitoring/beszel.ts +198 -0
  281. package/src/monitoring/enroll.ts +111 -0
  282. package/src/monitoring/hub-access.ts +114 -0
  283. package/src/monitoring/hub-backup.ts +121 -0
  284. package/src/monitoring/hub-viewer.ts +142 -0
  285. package/src/monitoring/hub.ts +93 -0
  286. package/src/monitoring/manager-agent.ts +73 -0
  287. package/src/monitoring/manager-hub.ts +248 -0
  288. package/src/monitoring/remote.ts +65 -0
  289. package/src/network-definition.ts +83 -0
  290. package/src/node-converge-linux.ts +374 -0
  291. package/src/node-converge-shared.ts +83 -0
  292. package/src/node-converge.ts +40 -0
  293. package/src/onboard.ts +35 -0
  294. package/src/package-info.ts +45 -0
  295. package/src/platform/ansible-receipt.ts +128 -0
  296. package/src/platform/ansible.ts +66 -0
  297. package/src/platform/darwin.ts +203 -0
  298. package/src/platform/detect.ts +11 -0
  299. package/src/platform/fallback.ts +110 -0
  300. package/src/platform/index.ts +38 -0
  301. package/src/platform/launchd.ts +98 -0
  302. package/src/platform/linux.ts +139 -0
  303. package/src/platform/ps.ts +45 -0
  304. package/src/platform/resource-verify.ts +132 -0
  305. package/src/platform/systemd-user.ts +95 -0
  306. package/src/platform/t3-policy.ts +137 -0
  307. package/src/platform/t3-route.ts +68 -0
  308. package/src/platform/t3-service.ts +75 -0
  309. package/src/platform/types.ts +123 -0
  310. package/src/platform/ubuntu-audit.ts +66 -0
  311. package/src/platform/ubuntu-verify.ts +105 -0
  312. package/src/platform/windows.ts +148 -0
  313. package/src/power-recovery.ts +55 -0
  314. package/src/probe.ts +51 -0
  315. package/src/protocol.ts +119 -0
  316. package/src/proxy-converge.ts +85 -0
  317. package/src/remote-bootstrap.ts +210 -0
  318. package/src/remote-entry.ts +89 -0
  319. package/src/remote-lock.ts +12 -0
  320. package/src/repair-catalog.ts +206 -0
  321. package/src/repair-plan.ts +78 -0
  322. package/src/repair-runner.ts +84 -0
  323. package/src/report.ts +71 -0
  324. package/src/runner.ts +104 -0
  325. package/src/secrets.ts +169 -0
  326. package/src/service-auth.ts +115 -0
  327. package/src/ssh.ts +135 -0
  328. package/src/state/bucket.ts +208 -0
  329. package/src/state/check.ts +74 -0
  330. package/src/state/connection.ts +92 -0
  331. package/src/state/enrollment.ts +45 -0
  332. package/src/state/legacy.ts +89 -0
  333. package/src/state/litestream.ts +143 -0
  334. package/src/state/operator.ts +20 -0
  335. package/src/state/paths.ts +40 -0
  336. package/src/state/roster.ts +62 -0
  337. package/src/state/store.ts +169 -0
  338. package/src/state/sync.ts +352 -0
  339. package/src/sync.ts +104 -0
  340. package/src/t3/accounts.ts +81 -0
  341. package/src/t3/desired.ts +165 -0
  342. package/src/t3/files.ts +81 -0
  343. package/src/t3/names-check.ts +53 -0
  344. package/src/t3/names.ts +155 -0
  345. package/src/t3/plan.ts +82 -0
  346. package/src/t3/providers.ts +74 -0
  347. package/src/t3/reconcile.ts +123 -0
  348. package/src/t3-endpoint.ts +104 -0
  349. package/src/t3-linked-check.ts +123 -0
  350. package/src/tailnet-health.ts +231 -0
  351. package/src/tailnet-matching.ts +37 -0
  352. package/src/tailscale.ts +141 -0
  353. package/src/toolchain-checks.ts +108 -0
  354. package/src/topology.ts +24 -0
  355. package/src/transport.ts +122 -0
  356. package/src/types.ts +99 -0
  357. package/src/vault-config.ts +38 -0
  358. package/src/worker-access-checks.ts +168 -0
  359. package/src/worker-capacity.ts +34 -0
  360. package/src/worker-host-checks.ts +181 -0
  361. package/src/worker-policy.ts +64 -0
  362. package/src/worker-readiness.ts +64 -0
  363. package/src/workstation-checks.ts +29 -0
package/mise.toml ADDED
@@ -0,0 +1,110 @@
1
+ # Shared workstation toolchain. Bootstrap installs this globally; projects may override it.
2
+ # Commit mise.lock whenever changing these pins.
3
+ # min_version is also the exact mise bootstrap/bootstrap.sh installs; bump the
4
+ # mise_*_sha256 digests under [vars] with it.
5
+ min_version = "2026.10.24"
6
+
7
+ [settings]
8
+ lockfile = true
9
+ lockfile_platforms = ["linux-x64", "linux-arm64", "macos-x64", "macos-arm64", "windows-x64"]
10
+
11
+ [tools]
12
+ gh = "2.103.3"
13
+ shellcheck = "0.11.0"
14
+ actionlint = "1.7.12"
15
+ opentofu = "1.13.0"
16
+ bun = "1.4.4"
17
+ node = "26.13.0"
18
+ atlas = { version = "1.3.0", os = ["linux", "macos"], lazy = true }
19
+ azure-cli = { version = "2.91.0", lazy = true }
20
+ # CLI proxy backups on the manager (cliproxy/scripts/install-dependencies).
21
+ restic = { version = "0.19.1", os = ["linux", "macos"], lazy = true }
22
+ # Replicates the fleet state database to the storage bucket (src/state).
23
+ litestream = { version = "0.5.18", os = ["linux", "macos"], lazy = true }
24
+ pnpm = "12.16.1"
25
+ "npm:@yarnpkg/cli-dist" = "4.18.1"
26
+ deno = "2.9.8"
27
+ python = "3.15.2"
28
+ uv = "0.13.6"
29
+ go = "1.27.3"
30
+ jq = "1.8.2"
31
+ yq = "4.54.1"
32
+ ripgrep = "15.2.0"
33
+ fd = "10.5.0"
34
+ fzf = "0.74.5"
35
+ bat = "0.26.1"
36
+ delta = "0.18.2"
37
+ git-lfs = "3.8.1"
38
+ docker-cli = "29.9.2"
39
+ "npm:vercel" = "65.8.0"
40
+ "npm:wrangler" = "4.156.0"
41
+ railway = "5.71.0"
42
+ "aqua:anomalyco/opencode" = "1.19.5"
43
+ vault = "2.2.1"
44
+ claude = "2.1.314"
45
+ codex = "0.166.0"
46
+ gemini = { version = "0.66.0", allow_builds = ["@lydell/node-pty"] }
47
+ copilot = "1.0.105"
48
+ # Agent CLIs without a registry backend: exact vendor artifacts, checksums in mise.lock.
49
+ "http:grok" = { version = "1.0.77", os = ["linux", "macos"], bin = "grok", platforms = { linux-x64 = { url = "https://x.ai/cli/grok-{{version}}-linux-x86_64" }, linux-arm64 = { url = "https://x.ai/cli/grok-{{version}}-linux-aarch64" }, macos-x64 = { url = "https://x.ai/cli/grok-{{version}}-macos-x86_64" }, macos-arm64 = { url = "https://x.ai/cli/grok-{{version}}-macos-aarch64" } } }
50
+ "http:antigravity" = { version = "1.5.3", os = ["linux", "macos"], bin = "antigravity", platforms = { linux-x64 = { url = "https://storage.googleapis.com/antigravity-public/antigravity-cli/1.5.3-6604829099950080/linux-x64/cli_linux_x64.tar.gz" }, linux-arm64 = { url = "https://storage.googleapis.com/antigravity-public/antigravity-cli/1.5.3-6604829099950080/linux-arm/cli_linux_arm64.tar.gz" }, macos-x64 = { url = "https://storage.googleapis.com/antigravity-public/antigravity-cli/1.5.3-6604829099950080/darwin-x64/cli_mac_x64.tar.gz" }, macos-arm64 = { url = "https://storage.googleapis.com/antigravity-public/antigravity-cli/1.5.3-6604829099950080/darwin-arm/cli_mac_arm64.tar.gz" } } }
51
+
52
+ "aws" = { version = "2.39.2", os = ["linux", "macos"] }
53
+ "rust" = "1.99.1"
54
+ "cmake" = "4.4.5"
55
+ "ninja" = "1.13.2"
56
+ "just" = "1.59.0"
57
+ "gitleaks" = "8.30.1"
58
+ "shfmt" = "3.14.1"
59
+ "sops" = "3.13.3"
60
+ "age" = "1.3.2"
61
+ "kubectl" = "1.37.2"
62
+ "helm" = "4.3.1"
63
+ "xh" = "0.26.3"
64
+ "usql" = "0.21.6"
65
+ "java" = { version = "temurin-25.0.5+8.0.LTS", lazy = true }
66
+ "dotnet" = { version = "10.0.403", lazy = true, lazy_bins = ["dotnet"] }
67
+ "gcloud" = { version = "591.0.0", lazy = true }
68
+ "npm:@devcontainers/cli" = "0.90.0"
69
+ # pino's 9.x backport was manually published; integrity and all published JS
70
+ # were checked against pinojs/pino v9.14.0. Keep the exception version-specific.
71
+ "npm:@modelcontextprotocol/inspector" = { version = "2.13.0", lazy = true, lazy_bins = ["mcp-inspector", "inspector", "mcpdo"], trust_policy_excludes = ["pino@9.14.0"] }
72
+ "aws-cdk" = { version = "2.1146.1", lazy = true }
73
+ "aws-sam" = { version = "1.171.0", lazy = true, os = ["linux", "macos"] }
74
+
75
+ # Keep self-updaters from bypassing the reviewed toolchain lock.
76
+ [env]
77
+ DISABLE_AUTOUPDATER = "1"
78
+ COPILOT_AUTO_UPDATE = "false"
79
+ GROK_DISABLE_AUTOUPDATER = "1"
80
+ # Antigravity ignores "1"; only "true" stops its in-place self-updater.
81
+ AGY_CLI_DISABLE_AUTO_UPDATE = "true"
82
+
83
+ [vars]
84
+ # mise itself, installed by bootstrap/bootstrap.sh before mise can read this
85
+ # file: the version is min_version above, these are its release archives
86
+ # (SHASUMS256.txt of that release).
87
+ mise_linux_x64_sha256 = "9a6c9c55f5c6372d0af70a9979fe6d742aea3793267a929e1738022143c466cc"
88
+ mise_linux_arm64_sha256 = "8c8f5d7f748bf3aef431dc50f0ad776270f36025c788aa21c74e2fabdbbd6d3e"
89
+ mise_macos_x64_sha256 = "83a36355bf6ee7c1660300e12dd94464de5c672dab1b8cc33ec4d19356e7ddac"
90
+ mise_macos_arm64_sha256 = "aa2fc59242db108f97ea9fb2d2e2cb42ff1467fcafe3c91e48d51c841ba67a65"
91
+ # Official native Ubuntu server distribution; bootstrap/native-t3.ts owns installation.
92
+ t3_version = "0.1.8-nightly.20261106.4262"
93
+ t3_linux_x64_sha256 = "5df94ca15c4f68f749fa5540fbb9d5ca879ca8750ac43dd2704f6a18899ed6d5"
94
+ t3_linux_arm64_sha256 = "0649615c4a294eee40bc753c8668e4a83c5c3620794f2163758f8dc48a39b880"
95
+ # Official T3 Code desktop .deb (same release). Workers run this GUI app as their
96
+ # only T3 process; it embeds the server. Upstream SHA256SUMS omits .deb files,
97
+ # so these digests were computed from the release assets.
98
+ t3_desktop_amd64_sha256 = "952703bd48b87029a4f9a2b275aeeb79bc74eacf01867784ab6878adecaf03d7"
99
+ t3_desktop_arm64_sha256 = "ae8a32a71a32760831af40a16cae9aabe8683b7021df6b899b57e8d559a7e777"
100
+ # Official AWS v2 Windows MSI, same version as tools.aws; checked before execution.
101
+ aws_windows_msi_sha256 = "c7857d5981e68396852e8b7eca0b1772f1c99b34d4938075857d45ec9c232113"
102
+ # Docker Desktop supplies the macOS engine, Compose and Buildx as one vendor bundle.
103
+ # Official release/checksums: https://docs.docker.com/desktop/release-notes/#4980
104
+ docker_desktop_version = "4.98.0"
105
+ docker_desktop_build = "245422"
106
+ docker_desktop_arm64_sha256 = "9c6f13ce4edda2abf20d801552b6acb96acd3d64b3e91b50c4484353802758b5"
107
+ docker_desktop_amd64_sha256 = "96b53f9a4a807b6be6207d18f360b9778ff481e1d94b5027bdf1ae2a22d837cb"
108
+
109
+ # Minimal remote development baseline; versions are resolved exclusively by tools + mise.lock.
110
+ worker_tools = "bun,node,gh,python,uv,docker-cli,vault,jq,codex,claude,aqua:anomalyco/opencode,gemini,copilot,http:grok,http:antigravity"
package/package.json CHANGED
@@ -1,6 +1,76 @@
1
1
  {
2
2
  "name": "@crvouga/dev-fleet",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.0",
4
+ "description": "Keeps a set of development machines in sync: one manager and many workers",
5
+ "license": "MIT",
6
+ "repository": "github:crvouga/dev-fleet",
7
+ "homepage": "https://github.com/crvouga/dev-fleet#readme",
8
+ "bugs": {
9
+ "url": "https://github.com/crvouga/dev-fleet/issues"
10
+ },
11
+ "type": "module",
12
+ "bin": {
13
+ "devfleet": "./bin/devfleet.mjs"
14
+ },
15
+ "files": [
16
+ "bin",
17
+ "llms.txt",
18
+ "docs",
19
+ "src",
20
+ "agents",
21
+ "ansible",
22
+ "bootstrap",
23
+ "cliproxy",
24
+ "schema",
25
+ "examples",
26
+ ".mise",
27
+ "mise.toml",
28
+ "mise.lock",
29
+ "!**/*.test.ts",
30
+ "!**/test_*.py",
31
+ "!**/tests",
32
+ "!**/__pycache__"
33
+ ],
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "scripts": {
38
+ "devfleet": "bun src/cli/cli.ts",
39
+ "bootstrap": "bun bootstrap/npm.ts",
40
+ "tc": "tsc --noEmit",
41
+ "lint": "eslint . --max-warnings 0",
42
+ "format": "prettier --check .",
43
+ "test": "bun test",
44
+ "test:cliproxy": "DEVFLEET_CONFIG=$PWD/examples/fleet.json python3 -B -m unittest discover -s cliproxy/tests -p \"test_*.py\"",
45
+ "lint:cliproxy": "DEVFLEET_CONFIG=$PWD/examples/fleet.json python3 -B cliproxy/scripts/check.py",
46
+ "check": "bun run format && bun run tc && bun run lint && bun test && bun run lint:cliproxy && bun run test:cliproxy"
47
+ },
48
+ "dependencies": {
49
+ "@inquirer/prompts": "8.7.5",
50
+ "boxen": "9.0.0",
51
+ "bun": "1.4.4",
52
+ "chalk": "6.0.1",
53
+ "cli-table3": "0.6.5",
54
+ "commander": "15.0.0",
55
+ "fuse.js": "7.5.0",
56
+ "ora": "10.0.0",
57
+ "yaml": "^2.8.0"
58
+ },
59
+ "devDependencies": {
60
+ "@cucumber/cucumber-expressions": "20.1.0",
61
+ "@cucumber/gherkin": "42.0.1",
62
+ "@cucumber/messages": "34.2.1",
63
+ "@eslint/js": "^9.25.0",
64
+ "@types/bun": "^1.3.9",
65
+ "@types/node": "^22.15.29",
66
+ "eslint": "^9.25.0",
67
+ "prettier": "^3.8.1",
68
+ "typescript": "~5.9.2",
69
+ "typescript-eslint": "^8.58.0"
70
+ },
71
+ "packageManager": "bun@1.4.4",
72
+ "engines": {
73
+ "node": ">=22"
74
+ },
75
+ "gitHead": "6dee8455d48203125eb5c0546c3c4446034fca85"
76
+ }
@@ -0,0 +1,420 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "Fleet topology: one manager (the human's machine, which runs every singleton service) and stateless Linux workers. Local paths remain in roster overrides.",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": [
7
+ "version",
8
+ "manager",
9
+ "workers",
10
+ "services",
11
+ "ubuntu",
12
+ "source",
13
+ "secrets"
14
+ ],
15
+ "properties": {
16
+ "$schema": {
17
+ "type": "string"
18
+ },
19
+ "version": {
20
+ "const": 3
21
+ },
22
+ "manager": {
23
+ "type": "object",
24
+ "additionalProperties": false,
25
+ "description": "The singleton manager: the human's machine that runs fleet-sync and hosts every singleton service (CLI proxy, Beszel hub).",
26
+ "required": ["id", "os", "network", "neverSleepOnPower"],
27
+ "properties": {
28
+ "id": {
29
+ "type": "string",
30
+ "pattern": "^[a-z][a-z0-9-]{0,62}$",
31
+ "description": "A short stable id for the manager, used in reports."
32
+ },
33
+ "os": {
34
+ "const": "macOS"
35
+ },
36
+ "network": {
37
+ "type": "object",
38
+ "additionalProperties": false,
39
+ "required": ["tailscaleName", "user"],
40
+ "properties": {
41
+ "tailscaleName": {
42
+ "type": "string",
43
+ "pattern": "^[a-zA-Z0-9][a-zA-Z0-9._-]{0,252}$",
44
+ "description": "The manager's Tailscale MagicDNS name, without the trailing dot (tailscale status --json: .Self.DNSName)."
45
+ },
46
+ "user": {
47
+ "type": "string",
48
+ "pattern": "^[a-z_][a-z0-9_.-]{0,31}$",
49
+ "description": "The manager's login name (id -un)."
50
+ }
51
+ }
52
+ },
53
+ "neverSleepOnPower": {
54
+ "const": true,
55
+ "description": "Workers depend on the manager's singleton services, so it never sleeps on AC power."
56
+ }
57
+ }
58
+ },
59
+ "workers": {
60
+ "type": "array",
61
+ "minItems": 1,
62
+ "maxItems": 64,
63
+ "items": {
64
+ "type": "object",
65
+ "additionalProperties": false,
66
+ "required": ["id", "ssh", "os"],
67
+ "properties": {
68
+ "id": {
69
+ "type": "string",
70
+ "pattern": "^[a-z][a-z0-9-]{0,62}$",
71
+ "description": "A short stable id for the worker. The first worker listed is the canary: a revision new to the fleet must pass there before the others receive it."
72
+ },
73
+ "ssh": {
74
+ "type": "string",
75
+ "pattern": "^[a-zA-Z0-9][a-zA-Z0-9._-]{0,252}$",
76
+ "description": "The worker's Host alias in the manager's ~/.ssh/config. It must work with BatchMode=yes and a host key already in known_hosts."
77
+ },
78
+ "os": {
79
+ "const": "linux",
80
+ "description": "Workers are the Linux boxes: stateless, replaceable, never hosting a singleton service."
81
+ },
82
+ "network": {
83
+ "type": "object",
84
+ "additionalProperties": false,
85
+ "required": ["tailscaleName", "user", "sshPort", "t3Port"],
86
+ "properties": {
87
+ "tailscaleName": {
88
+ "type": "string",
89
+ "pattern": "^[a-zA-Z0-9][a-zA-Z0-9._-]{0,252}$",
90
+ "description": "The worker's Tailscale MagicDNS name, without the trailing dot."
91
+ },
92
+ "user": {
93
+ "type": "string",
94
+ "pattern": "^[a-z_][a-z0-9_-]{0,31}$",
95
+ "description": "The non-root worker account that can use sudo."
96
+ },
97
+ "sshPort": {
98
+ "type": "integer",
99
+ "minimum": 1,
100
+ "maximum": 65535,
101
+ "description": "The port sshd listens on, normally 22."
102
+ },
103
+ "t3Port": {
104
+ "type": "integer",
105
+ "minimum": 1,
106
+ "maximum": 65535,
107
+ "description": "The port the worker T3 server listens on, normally 3773."
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+ },
114
+ "services": {
115
+ "type": "object",
116
+ "additionalProperties": false,
117
+ "required": ["proxy", "monitoring"],
118
+ "description": "Singleton services. Every one runs on the manager; workers are clients only.",
119
+ "properties": {
120
+ "proxy": {
121
+ "type": "object",
122
+ "additionalProperties": false,
123
+ "required": ["endpoint"],
124
+ "properties": {
125
+ "endpoint": {
126
+ "type": "string",
127
+ "pattern": "^https://[A-Za-z0-9.-]+$",
128
+ "description": "Public HTTPS origin of the CLI proxy every node uses."
129
+ }
130
+ }
131
+ },
132
+ "monitoring": {
133
+ "type": "object",
134
+ "additionalProperties": false,
135
+ "required": [
136
+ "hubPort",
137
+ "publicUrl",
138
+ "managerAccount",
139
+ "viewerAccount"
140
+ ],
141
+ "properties": {
142
+ "hubPort": {
143
+ "const": 8443
144
+ },
145
+ "publicUrl": {
146
+ "type": "string",
147
+ "pattern": "^https://[A-Za-z0-9.-]+$",
148
+ "description": "Public dashboard origin."
149
+ },
150
+ "managerAccount": {
151
+ "type": "string",
152
+ "format": "email",
153
+ "description": "Beszel account the manager enrolls nodes with."
154
+ },
155
+ "viewerAccount": {
156
+ "type": "string",
157
+ "format": "email",
158
+ "description": "Read-only Beszel account visitors are signed in as."
159
+ }
160
+ }
161
+ }
162
+ }
163
+ },
164
+ "ubuntu": {
165
+ "type": "object",
166
+ "additionalProperties": false,
167
+ "required": ["release", "architectures"],
168
+ "properties": {
169
+ "release": {
170
+ "const": "26.04"
171
+ },
172
+ "architectures": {
173
+ "const": ["amd64", "arm64"]
174
+ }
175
+ },
176
+ "description": "The supported worker release and architectures (fixed)."
177
+ },
178
+ "worker": {
179
+ "type": "object",
180
+ "additionalProperties": false,
181
+ "required": [
182
+ "requiredCapabilities",
183
+ "githubLogin",
184
+ "vaultUser",
185
+ "toolchain",
186
+ "agentProfile",
187
+ "unattendedSudo",
188
+ "persistentT3",
189
+ "neverSleep"
190
+ ],
191
+ "properties": {
192
+ "requiredCapabilities": {
193
+ "type": "array",
194
+ "uniqueItems": true,
195
+ "items": {
196
+ "enum": [
197
+ "github",
198
+ "vault",
199
+ "t3",
200
+ "toolchain",
201
+ "workstation",
202
+ "worker"
203
+ ]
204
+ },
205
+ "description": "Readiness checks every worker must pass; normally all six."
206
+ },
207
+ "githubLogin": {
208
+ "type": "string",
209
+ "pattern": "^[a-zA-Z0-9-]{1,39}$",
210
+ "description": "The GitHub login every worker must be signed in as."
211
+ },
212
+ "vaultUser": {
213
+ "type": "string",
214
+ "pattern": "^[a-zA-Z0-9_.-]{1,64}$",
215
+ "description": "The Vault user each worker's own token is issued for."
216
+ },
217
+ "toolchain": {
218
+ "const": "mise.lock"
219
+ },
220
+ "agentProfile": {
221
+ "const": "proxy"
222
+ },
223
+ "unattendedSudo": {
224
+ "const": true
225
+ },
226
+ "persistentT3": {
227
+ "const": true
228
+ },
229
+ "neverSleep": {
230
+ "const": true
231
+ }
232
+ },
233
+ "description": "Policy every worker must meet. All but the two logins and the capabilities are fixed."
234
+ },
235
+ "source": {
236
+ "type": "object",
237
+ "additionalProperties": false,
238
+ "required": ["repository"],
239
+ "description": "The Git repository machines take dev-fleet's code from: the one the package you run was published from, or your fork. Nodes only accept source from it.",
240
+ "properties": {
241
+ "repository": {
242
+ "type": "string",
243
+ "pattern": "^https://[A-Za-z0-9.-]+/[A-Za-z0-9._/-]+\\.git$"
244
+ }
245
+ }
246
+ },
247
+ "state": {
248
+ "description": "The bucket that holds the fleet state (the roster, the approved revision and the configuration last applied). Any S3-compatible service, or a directory. Never credentials: a devfleet command reads those from DEVFLEET_BUCKET_ACCESS_KEY_ID and DEVFLEET_BUCKET_SECRET_ACCESS_KEY.",
249
+ "oneOf": [
250
+ {
251
+ "type": "object",
252
+ "additionalProperties": false,
253
+ "required": ["bucket"],
254
+ "properties": {
255
+ "bucket": {
256
+ "type": "string",
257
+ "pattern": "^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$"
258
+ },
259
+ "endpoint": {
260
+ "type": "string",
261
+ "description": "The https origin of the S3 service; omit for AWS S3.",
262
+ "pattern": "^https://[A-Za-z0-9.-]{1,253}(:[0-9]{1,5})?$"
263
+ },
264
+ "region": {
265
+ "type": "string",
266
+ "pattern": "^[a-z0-9-]{1,32}$"
267
+ },
268
+ "prefix": {
269
+ "type": "string",
270
+ "description": "Key prefix, so one bucket can hold several fleets. Default: dev-fleet.",
271
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._/-]{0,199}$"
272
+ }
273
+ }
274
+ },
275
+ {
276
+ "type": "object",
277
+ "additionalProperties": false,
278
+ "required": ["directory"],
279
+ "properties": {
280
+ "directory": {
281
+ "type": "string",
282
+ "description": "An absolute path on an attached disk or a mounted share.",
283
+ "pattern": "^/"
284
+ }
285
+ }
286
+ }
287
+ ]
288
+ },
289
+ "secrets": {
290
+ "description": "Where this fleet keeps its secrets. env: DEVFLEET_SECRET_<NAME>; file: one file per secret; sops: one encrypted document; vault: a KV v2 location per secret.",
291
+ "oneOf": [
292
+ {
293
+ "type": "object",
294
+ "additionalProperties": false,
295
+ "required": ["provider"],
296
+ "properties": {
297
+ "provider": {
298
+ "const": "env"
299
+ }
300
+ }
301
+ },
302
+ {
303
+ "type": "object",
304
+ "additionalProperties": false,
305
+ "required": ["provider"],
306
+ "properties": {
307
+ "provider": {
308
+ "const": "file"
309
+ },
310
+ "directory": {
311
+ "type": "string"
312
+ }
313
+ }
314
+ },
315
+ {
316
+ "type": "object",
317
+ "additionalProperties": false,
318
+ "required": ["provider", "file"],
319
+ "properties": {
320
+ "provider": {
321
+ "const": "sops"
322
+ },
323
+ "file": {
324
+ "type": "string"
325
+ }
326
+ }
327
+ },
328
+ {
329
+ "type": "object",
330
+ "additionalProperties": false,
331
+ "required": ["provider", "address", "mount", "locations"],
332
+ "properties": {
333
+ "provider": {
334
+ "const": "vault"
335
+ },
336
+ "address": {
337
+ "type": "string",
338
+ "pattern": "^https://[A-Za-z0-9.-]+$"
339
+ },
340
+ "mount": {
341
+ "type": "string"
342
+ },
343
+ "locations": {
344
+ "type": "object",
345
+ "additionalProperties": false,
346
+ "required": [
347
+ "proxy-client-key",
348
+ "monitoring-account-password",
349
+ "monitoring-tunnel-token",
350
+ "proxy-tunnel-token"
351
+ ],
352
+ "properties": {
353
+ "proxy-client-key": {
354
+ "type": "object",
355
+ "additionalProperties": false,
356
+ "required": ["path", "field"],
357
+ "properties": {
358
+ "path": {
359
+ "type": "string",
360
+ "pattern": "^[A-Za-z0-9._/-]+$"
361
+ },
362
+ "field": {
363
+ "type": "string",
364
+ "pattern": "^[A-Za-z0-9_]+$"
365
+ }
366
+ }
367
+ },
368
+ "monitoring-account-password": {
369
+ "type": "object",
370
+ "additionalProperties": false,
371
+ "required": ["path", "field"],
372
+ "properties": {
373
+ "path": {
374
+ "type": "string",
375
+ "pattern": "^[A-Za-z0-9._/-]+$"
376
+ },
377
+ "field": {
378
+ "type": "string",
379
+ "pattern": "^[A-Za-z0-9_]+$"
380
+ }
381
+ }
382
+ },
383
+ "monitoring-tunnel-token": {
384
+ "type": "object",
385
+ "additionalProperties": false,
386
+ "required": ["path", "field"],
387
+ "properties": {
388
+ "path": {
389
+ "type": "string",
390
+ "pattern": "^[A-Za-z0-9._/-]+$"
391
+ },
392
+ "field": {
393
+ "type": "string",
394
+ "pattern": "^[A-Za-z0-9_]+$"
395
+ }
396
+ }
397
+ },
398
+ "proxy-tunnel-token": {
399
+ "type": "object",
400
+ "additionalProperties": false,
401
+ "required": ["path", "field"],
402
+ "properties": {
403
+ "path": {
404
+ "type": "string",
405
+ "pattern": "^[A-Za-z0-9._/-]+$"
406
+ },
407
+ "field": {
408
+ "type": "string",
409
+ "pattern": "^[A-Za-z0-9_]+$"
410
+ }
411
+ }
412
+ }
413
+ }
414
+ }
415
+ }
416
+ }
417
+ ]
418
+ }
419
+ }
420
+ }
@@ -0,0 +1,77 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "Developer fleet roster (not infrastructure inventory)",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": ["version", "nodes"],
7
+ "properties": {
8
+ "$schema": {
9
+ "type": "string"
10
+ },
11
+ "version": {
12
+ "const": 1
13
+ },
14
+ "nodes": {
15
+ "type": "array",
16
+ "minItems": 1,
17
+ "maxItems": 64,
18
+ "items": {
19
+ "type": "object",
20
+ "additionalProperties": false,
21
+ "required": ["id", "ssh", "workspace"],
22
+ "properties": {
23
+ "id": {
24
+ "type": "string",
25
+ "pattern": "^[a-z][a-z0-9-]{0,62}$"
26
+ },
27
+ "ssh": {
28
+ "type": "string",
29
+ "pattern": "^[a-zA-Z0-9][a-zA-Z0-9._-]{0,252}$"
30
+ },
31
+ "workspace": {
32
+ "type": "string",
33
+ "maxLength": 4096,
34
+ "pattern": "^/[^\\u0000-\\u001f\\u007f]*$"
35
+ },
36
+ "runtime": {
37
+ "type": "string",
38
+ "maxLength": 4096,
39
+ "pattern": "^/[^\\u0000-\\u001f\\u007f]*$"
40
+ },
41
+ "required": {
42
+ "type": "array",
43
+ "uniqueItems": true,
44
+ "default": ["github", "vault", "t3", "toolchain"],
45
+ "items": {
46
+ "enum": [
47
+ "github",
48
+ "vault",
49
+ "t3",
50
+ "vscode",
51
+ "toolchain",
52
+ "codex",
53
+ "claude",
54
+ "services",
55
+ "workstation",
56
+ "worker"
57
+ ]
58
+ }
59
+ },
60
+ "tailscaleId": {
61
+ "type": "string",
62
+ "pattern": "^[a-zA-Z0-9:_-]{1,128}$",
63
+ "description": "Explicitly enrolled stable Tailscale device ID; replacements require reenrollment."
64
+ },
65
+ "bootstrapViaSsh": {
66
+ "type": "boolean",
67
+ "description": "Explicit permission to bootstrap an enrolled node over its trusted SSH route while Tailscale is unavailable; does not accept host keys or replace device identities."
68
+ },
69
+ "t3EnvironmentId": {
70
+ "type": "string",
71
+ "pattern": "^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$"
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }