charness 3.7.0 → 3.8.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 (359) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/DEVELOPMENT.md +6 -2
  3. package/README.md +5 -5
  4. package/SETUP.md +16 -5
  5. package/agent-plugin/skills/charness-manager/SKILL.md +3 -3
  6. package/dist/adapters/openCodeAdapter.d.ts.map +1 -1
  7. package/dist/adapters/openCodeAdapter.js +2 -1
  8. package/dist/adapters/openCodeAdapter.js.map +1 -1
  9. package/dist/bot.d.ts.map +1 -1
  10. package/dist/bot.js +50 -9
  11. package/dist/bot.js.map +1 -1
  12. package/dist/cli.js +44 -1
  13. package/dist/cli.js.map +1 -1
  14. package/dist/configDirFile.d.ts +7 -3
  15. package/dist/configDirFile.d.ts.map +1 -1
  16. package/dist/configDirFile.js +12 -5
  17. package/dist/configDirFile.js.map +1 -1
  18. package/dist/connectors/telegram/commands/botCore.d.ts +5 -1
  19. package/dist/connectors/telegram/commands/botCore.d.ts.map +1 -1
  20. package/dist/connectors/telegram/commands/runners.d.ts +52 -0
  21. package/dist/connectors/telegram/commands/runners.d.ts.map +1 -0
  22. package/dist/connectors/telegram/commands/runners.js +486 -0
  23. package/dist/connectors/telegram/commands/runners.js.map +1 -0
  24. package/dist/connectors/telegram/runnerPairingMessages.d.ts +27 -0
  25. package/dist/connectors/telegram/runnerPairingMessages.d.ts.map +1 -0
  26. package/dist/connectors/telegram/runnerPairingMessages.js +105 -0
  27. package/dist/connectors/telegram/runnerPairingMessages.js.map +1 -0
  28. package/dist/i18n/de.d.ts.map +1 -1
  29. package/dist/i18n/de.js +58 -0
  30. package/dist/i18n/de.js.map +1 -1
  31. package/dist/i18n/en.d.ts.map +1 -1
  32. package/dist/i18n/en.js +58 -0
  33. package/dist/i18n/en.js.map +1 -1
  34. package/dist/i18n/es.d.ts.map +1 -1
  35. package/dist/i18n/es.js +58 -0
  36. package/dist/i18n/es.js.map +1 -1
  37. package/dist/i18n/fr.d.ts.map +1 -1
  38. package/dist/i18n/fr.js +58 -0
  39. package/dist/i18n/fr.js.map +1 -1
  40. package/dist/i18n/hi.d.ts.map +1 -1
  41. package/dist/i18n/hi.js +58 -0
  42. package/dist/i18n/hi.js.map +1 -1
  43. package/dist/i18n/ja.d.ts.map +1 -1
  44. package/dist/i18n/ja.js +58 -0
  45. package/dist/i18n/ja.js.map +1 -1
  46. package/dist/i18n/ka.d.ts.map +1 -1
  47. package/dist/i18n/ka.js +58 -0
  48. package/dist/i18n/ka.js.map +1 -1
  49. package/dist/i18n/pt.d.ts.map +1 -1
  50. package/dist/i18n/pt.js +58 -0
  51. package/dist/i18n/pt.js.map +1 -1
  52. package/dist/i18n/ru.d.ts.map +1 -1
  53. package/dist/i18n/ru.js +58 -0
  54. package/dist/i18n/ru.js.map +1 -1
  55. package/dist/i18n/uk.d.ts.map +1 -1
  56. package/dist/i18n/uk.js +58 -0
  57. package/dist/i18n/uk.js.map +1 -1
  58. package/dist/i18n/uz.d.ts.map +1 -1
  59. package/dist/i18n/uz.js +58 -0
  60. package/dist/i18n/uz.js.map +1 -1
  61. package/dist/i18n/zh.d.ts.map +1 -1
  62. package/dist/i18n/zh.js +58 -0
  63. package/dist/i18n/zh.js.map +1 -1
  64. package/dist/installManager.d.ts +57 -1
  65. package/dist/installManager.d.ts.map +1 -1
  66. package/dist/installManager.js +88 -10
  67. package/dist/installManager.js.map +1 -1
  68. package/dist/instanceSettings.d.ts +12 -2
  69. package/dist/instanceSettings.d.ts.map +1 -1
  70. package/dist/instanceSettings.js +17 -3
  71. package/dist/instanceSettings.js.map +1 -1
  72. package/dist/outputTrace.d.ts +6 -0
  73. package/dist/outputTrace.d.ts.map +1 -1
  74. package/dist/outputTrace.js +24 -1
  75. package/dist/outputTrace.js.map +1 -1
  76. package/dist/remoteRun/cliArgs.d.ts +2 -0
  77. package/dist/remoteRun/cliArgs.d.ts.map +1 -1
  78. package/dist/remoteRun/cliArgs.js +11 -2
  79. package/dist/remoteRun/cliArgs.js.map +1 -1
  80. package/dist/remoteRun/commands.d.ts +21 -0
  81. package/dist/remoteRun/commands.d.ts.map +1 -1
  82. package/dist/remoteRun/commands.js +38 -17
  83. package/dist/remoteRun/commands.js.map +1 -1
  84. package/dist/remoteRun/interrupts.d.ts +10 -0
  85. package/dist/remoteRun/interrupts.d.ts.map +1 -1
  86. package/dist/remoteRun/interrupts.js +43 -6
  87. package/dist/remoteRun/interrupts.js.map +1 -1
  88. package/dist/remoteRun/output.d.ts +2 -0
  89. package/dist/remoteRun/output.d.ts.map +1 -1
  90. package/dist/remoteRun/output.js +45 -0
  91. package/dist/remoteRun/output.js.map +1 -1
  92. package/dist/remoteRun/pairedRunners.d.ts +51 -0
  93. package/dist/remoteRun/pairedRunners.d.ts.map +1 -0
  94. package/dist/remoteRun/pairedRunners.js +165 -0
  95. package/dist/remoteRun/pairedRunners.js.map +1 -0
  96. package/dist/remoteRun/probe.d.ts +23 -1
  97. package/dist/remoteRun/probe.d.ts.map +1 -1
  98. package/dist/remoteRun/probe.js +45 -11
  99. package/dist/remoteRun/probe.js.map +1 -1
  100. package/dist/remoteRun/remoteRunCli.d.ts +13 -6
  101. package/dist/remoteRun/remoteRunCli.d.ts.map +1 -1
  102. package/dist/remoteRun/remoteRunCli.js +34 -59
  103. package/dist/remoteRun/remoteRunCli.js.map +1 -1
  104. package/dist/remoteRun/runnerClient.d.ts +2 -0
  105. package/dist/remoteRun/runnerClient.d.ts.map +1 -1
  106. package/dist/remoteRun/runnerClient.js +5 -1
  107. package/dist/remoteRun/runnerClient.js.map +1 -1
  108. package/dist/remoteRun/runnerSummary.d.ts +24 -0
  109. package/dist/remoteRun/runnerSummary.d.ts.map +1 -0
  110. package/dist/remoteRun/runnerSummary.js +86 -0
  111. package/dist/remoteRun/runnerSummary.js.map +1 -0
  112. package/dist/remoteRun/runnerWait.d.ts +68 -0
  113. package/dist/remoteRun/runnerWait.d.ts.map +1 -0
  114. package/dist/remoteRun/runnerWait.js +137 -0
  115. package/dist/remoteRun/runnerWait.js.map +1 -0
  116. package/dist/remoteRun/runnerWaitTiming.d.ts +16 -0
  117. package/dist/remoteRun/runnerWaitTiming.d.ts.map +1 -0
  118. package/dist/remoteRun/runnerWaitTiming.js +37 -0
  119. package/dist/remoteRun/runnerWaitTiming.js.map +1 -0
  120. package/dist/remoteRun/runners.d.ts +7 -7
  121. package/dist/remoteRun/runners.d.ts.map +1 -1
  122. package/dist/remoteRun/runners.js +45 -17
  123. package/dist/remoteRun/runners.js.map +1 -1
  124. package/dist/remoteRun/runnersCatalog.d.ts +14 -0
  125. package/dist/remoteRun/runnersCatalog.d.ts.map +1 -0
  126. package/dist/remoteRun/runnersCatalog.js +68 -0
  127. package/dist/remoteRun/runnersCatalog.js.map +1 -0
  128. package/dist/remoteRun/runnersConfig.d.ts +29 -20
  129. package/dist/remoteRun/runnersConfig.d.ts.map +1 -1
  130. package/dist/remoteRun/runnersConfig.js +14 -12
  131. package/dist/remoteRun/runnersConfig.js.map +1 -1
  132. package/dist/remoteRun/ssh.d.ts +22 -2
  133. package/dist/remoteRun/ssh.d.ts.map +1 -1
  134. package/dist/remoteRun/ssh.js +41 -7
  135. package/dist/remoteRun/ssh.js.map +1 -1
  136. package/dist/runnerUtility/adminCheck.d.ts +11 -0
  137. package/dist/runnerUtility/adminCheck.d.ts.map +1 -0
  138. package/dist/runnerUtility/adminCheck.js +68 -0
  139. package/dist/runnerUtility/adminCheck.js.map +1 -0
  140. package/dist/runnerUtility/appInstall.d.ts +25 -0
  141. package/dist/runnerUtility/appInstall.d.ts.map +1 -0
  142. package/dist/runnerUtility/appInstall.js +147 -0
  143. package/dist/runnerUtility/appInstall.js.map +1 -0
  144. package/dist/runnerUtility/appUpdate.d.ts +39 -0
  145. package/dist/runnerUtility/appUpdate.d.ts.map +1 -0
  146. package/dist/runnerUtility/appUpdate.js +90 -0
  147. package/dist/runnerUtility/appUpdate.js.map +1 -0
  148. package/dist/runnerUtility/execEnv.d.ts +21 -0
  149. package/dist/runnerUtility/execEnv.d.ts.map +1 -0
  150. package/dist/runnerUtility/execEnv.js +109 -0
  151. package/dist/runnerUtility/execEnv.js.map +1 -0
  152. package/dist/runnerUtility/execSession.d.ts +13 -0
  153. package/dist/runnerUtility/execSession.d.ts.map +1 -0
  154. package/dist/runnerUtility/execSession.js +58 -0
  155. package/dist/runnerUtility/execSession.js.map +1 -0
  156. package/dist/runnerUtility/hubClient.d.ts +30 -0
  157. package/dist/runnerUtility/hubClient.d.ts.map +1 -0
  158. package/dist/runnerUtility/hubClient.js +127 -0
  159. package/dist/runnerUtility/hubClient.js.map +1 -0
  160. package/dist/runnerUtility/injectStream.d.ts +9 -0
  161. package/dist/runnerUtility/injectStream.d.ts.map +1 -0
  162. package/dist/runnerUtility/injectStream.js +12 -0
  163. package/dist/runnerUtility/injectStream.js.map +1 -0
  164. package/dist/runnerUtility/iosCheck.d.ts +62 -0
  165. package/dist/runnerUtility/iosCheck.d.ts.map +1 -0
  166. package/dist/runnerUtility/iosCheck.js +200 -0
  167. package/dist/runnerUtility/iosCheck.js.map +1 -0
  168. package/dist/runnerUtility/launcher.d.ts +5 -0
  169. package/dist/runnerUtility/launcher.d.ts.map +1 -0
  170. package/dist/runnerUtility/launcher.js +85 -0
  171. package/dist/runnerUtility/launcher.js.map +1 -0
  172. package/dist/runnerUtility/linkLoop.d.ts +47 -0
  173. package/dist/runnerUtility/linkLoop.d.ts.map +1 -0
  174. package/dist/runnerUtility/linkLoop.js +281 -0
  175. package/dist/runnerUtility/linkLoop.js.map +1 -0
  176. package/dist/runnerUtility/localLinkStop.d.ts +23 -0
  177. package/dist/runnerUtility/localLinkStop.d.ts.map +1 -0
  178. package/dist/runnerUtility/localLinkStop.js +79 -0
  179. package/dist/runnerUtility/localLinkStop.js.map +1 -0
  180. package/dist/runnerUtility/machineReport.d.ts +39 -0
  181. package/dist/runnerUtility/machineReport.d.ts.map +1 -0
  182. package/dist/runnerUtility/machineReport.js +161 -0
  183. package/dist/runnerUtility/machineReport.js.map +1 -0
  184. package/dist/runnerUtility/packageId.d.ts +5 -0
  185. package/dist/runnerUtility/packageId.d.ts.map +1 -0
  186. package/dist/runnerUtility/packageId.js +64 -0
  187. package/dist/runnerUtility/packageId.js.map +1 -0
  188. package/dist/runnerUtility/pairingRecovery.d.ts +31 -0
  189. package/dist/runnerUtility/pairingRecovery.d.ts.map +1 -0
  190. package/dist/runnerUtility/pairingRecovery.js +24 -0
  191. package/dist/runnerUtility/pairingRecovery.js.map +1 -0
  192. package/dist/runnerUtility/pueueDaemon.d.ts +36 -0
  193. package/dist/runnerUtility/pueueDaemon.d.ts.map +1 -0
  194. package/dist/runnerUtility/pueueDaemon.js +165 -0
  195. package/dist/runnerUtility/pueueDaemon.js.map +1 -0
  196. package/dist/runnerUtility/runnerCli.d.ts +18 -0
  197. package/dist/runnerUtility/runnerCli.d.ts.map +1 -0
  198. package/dist/runnerUtility/runnerCli.js +184 -0
  199. package/dist/runnerUtility/runnerCli.js.map +1 -0
  200. package/dist/runnerUtility/runnerCommands.d.ts +67 -0
  201. package/dist/runnerUtility/runnerCommands.d.ts.map +1 -0
  202. package/dist/runnerUtility/runnerCommands.js +418 -0
  203. package/dist/runnerUtility/runnerCommands.js.map +1 -0
  204. package/dist/runnerUtility/runnerConfig.d.ts +63 -0
  205. package/dist/runnerUtility/runnerConfig.d.ts.map +1 -0
  206. package/dist/runnerUtility/runnerConfig.js +153 -0
  207. package/dist/runnerUtility/runnerConfig.js.map +1 -0
  208. package/dist/runnerUtility/runnerFlags.d.ts +9 -0
  209. package/dist/runnerUtility/runnerFlags.d.ts.map +1 -0
  210. package/dist/runnerUtility/runnerFlags.js +53 -0
  211. package/dist/runnerUtility/runnerFlags.js.map +1 -0
  212. package/dist/runnerUtility/runnerHome.d.ts +30 -0
  213. package/dist/runnerUtility/runnerHome.d.ts.map +1 -0
  214. package/dist/runnerUtility/runnerHome.js +82 -0
  215. package/dist/runnerUtility/runnerHome.js.map +1 -0
  216. package/dist/runnerUtility/runnerKeys.d.ts +11 -0
  217. package/dist/runnerUtility/runnerKeys.d.ts.map +1 -0
  218. package/dist/runnerUtility/runnerKeys.js +80 -0
  219. package/dist/runnerUtility/runnerKeys.js.map +1 -0
  220. package/dist/runnerUtility/runnerServers.d.ts +40 -0
  221. package/dist/runnerUtility/runnerServers.d.ts.map +1 -0
  222. package/dist/runnerUtility/runnerServers.js +79 -0
  223. package/dist/runnerUtility/runnerServers.js.map +1 -0
  224. package/dist/runnerUtility/serviceManager.d.ts +54 -0
  225. package/dist/runnerUtility/serviceManager.d.ts.map +1 -0
  226. package/dist/runnerUtility/serviceManager.js +413 -0
  227. package/dist/runnerUtility/serviceManager.js.map +1 -0
  228. package/dist/runnerUtility/serviceUnits.d.ts +36 -0
  229. package/dist/runnerUtility/serviceUnits.d.ts.map +1 -0
  230. package/dist/runnerUtility/serviceUnits.js +169 -0
  231. package/dist/runnerUtility/serviceUnits.js.map +1 -0
  232. package/dist/runnerUtility/toolInstall.d.ts +95 -0
  233. package/dist/runnerUtility/toolInstall.d.ts.map +1 -0
  234. package/dist/runnerUtility/toolInstall.js +232 -0
  235. package/dist/runnerUtility/toolInstall.js.map +1 -0
  236. package/dist/runnerUtility/versionPollTiming.d.ts +16 -0
  237. package/dist/runnerUtility/versionPollTiming.d.ts.map +1 -0
  238. package/dist/runnerUtility/versionPollTiming.js +36 -0
  239. package/dist/runnerUtility/versionPollTiming.js.map +1 -0
  240. package/dist/runners/authorizedKeys.d.ts +52 -0
  241. package/dist/runners/authorizedKeys.d.ts.map +1 -0
  242. package/dist/runners/authorizedKeys.js +153 -0
  243. package/dist/runners/authorizedKeys.js.map +1 -0
  244. package/dist/runners/bootstrapLine.d.ts +4 -0
  245. package/dist/runners/bootstrapLine.d.ts.map +1 -0
  246. package/dist/runners/bootstrapLine.js +69 -0
  247. package/dist/runners/bootstrapLine.js.map +1 -0
  248. package/dist/runners/gate.d.ts +41 -0
  249. package/dist/runners/gate.d.ts.map +1 -0
  250. package/dist/runners/gate.js +216 -0
  251. package/dist/runners/gate.js.map +1 -0
  252. package/dist/runners/gateLink.d.ts +26 -0
  253. package/dist/runners/gateLink.d.ts.map +1 -0
  254. package/dist/runners/gateLink.js +240 -0
  255. package/dist/runners/gateLink.js.map +1 -0
  256. package/dist/runners/gateProtocol.d.ts +98 -0
  257. package/dist/runners/gateProtocol.d.ts.map +1 -0
  258. package/dist/runners/gateProtocol.js +149 -0
  259. package/dist/runners/gateProtocol.js.map +1 -0
  260. package/dist/runners/gateWrapper.d.ts +6 -0
  261. package/dist/runners/gateWrapper.d.ts.map +1 -0
  262. package/dist/runners/gateWrapper.js +70 -0
  263. package/dist/runners/gateWrapper.js.map +1 -0
  264. package/dist/runners/hubAddress.d.ts +33 -0
  265. package/dist/runners/hubAddress.d.ts.map +1 -0
  266. package/dist/runners/hubAddress.js +88 -0
  267. package/dist/runners/hubAddress.js.map +1 -0
  268. package/dist/runners/hubAddressCandidates.d.ts +16 -0
  269. package/dist/runners/hubAddressCandidates.d.ts.map +1 -0
  270. package/dist/runners/hubAddressCandidates.js +96 -0
  271. package/dist/runners/hubAddressCandidates.js.map +1 -0
  272. package/dist/runners/hubIds.d.ts +16 -0
  273. package/dist/runners/hubIds.d.ts.map +1 -0
  274. package/dist/runners/hubIds.js +25 -0
  275. package/dist/runners/hubIds.js.map +1 -0
  276. package/dist/runners/hubKey.d.ts +6 -0
  277. package/dist/runners/hubKey.d.ts.map +1 -0
  278. package/dist/runners/hubKey.js +78 -0
  279. package/dist/runners/hubKey.js.map +1 -0
  280. package/dist/runners/hubLock.d.ts +7 -0
  281. package/dist/runners/hubLock.d.ts.map +1 -0
  282. package/dist/runners/hubLock.js +230 -0
  283. package/dist/runners/hubLock.js.map +1 -0
  284. package/dist/runners/hubPackage.d.ts +23 -0
  285. package/dist/runners/hubPackage.d.ts.map +1 -0
  286. package/dist/runners/hubPackage.js +184 -0
  287. package/dist/runners/hubPackage.js.map +1 -0
  288. package/dist/runners/hubPairing.d.ts +63 -0
  289. package/dist/runners/hubPairing.d.ts.map +1 -0
  290. package/dist/runners/hubPairing.js +261 -0
  291. package/dist/runners/hubPairing.js.map +1 -0
  292. package/dist/runners/hubPaths.d.ts +38 -0
  293. package/dist/runners/hubPaths.d.ts.map +1 -0
  294. package/dist/runners/hubPaths.js +94 -0
  295. package/dist/runners/hubPaths.js.map +1 -0
  296. package/dist/runners/hubRegistry.d.ts +112 -0
  297. package/dist/runners/hubRegistry.d.ts.map +1 -0
  298. package/dist/runners/hubRegistry.js +210 -0
  299. package/dist/runners/hubRegistry.js.map +1 -0
  300. package/dist/runners/linkControl.d.ts +27 -0
  301. package/dist/runners/linkControl.d.ts.map +1 -0
  302. package/dist/runners/linkControl.js +124 -0
  303. package/dist/runners/linkControl.js.map +1 -0
  304. package/dist/runners/pairCode.d.ts +30 -0
  305. package/dist/runners/pairCode.d.ts.map +1 -0
  306. package/dist/runners/pairCode.js +46 -0
  307. package/dist/runners/pairCode.js.map +1 -0
  308. package/dist/runners/pairingTiming.d.ts +18 -0
  309. package/dist/runners/pairingTiming.d.ts.map +1 -0
  310. package/dist/runners/pairingTiming.js +42 -0
  311. package/dist/runners/pairingTiming.js.map +1 -0
  312. package/dist/runners/runnerProxy.d.ts +9 -0
  313. package/dist/runners/runnerProxy.d.ts.map +1 -0
  314. package/dist/runners/runnerProxy.js +67 -0
  315. package/dist/runners/runnerProxy.js.map +1 -0
  316. package/dist/runners/runnerRemoval.d.ts +21 -0
  317. package/dist/runners/runnerRemoval.d.ts.map +1 -0
  318. package/dist/runners/runnerRemoval.js +82 -0
  319. package/dist/runners/runnerRemoval.js.map +1 -0
  320. package/dist/runners/runnersCli.d.ts +16 -0
  321. package/dist/runners/runnersCli.d.ts.map +1 -0
  322. package/dist/runners/runnersCli.js +214 -0
  323. package/dist/runners/runnersCli.js.map +1 -0
  324. package/dist/runners/runnersList.d.ts +17 -0
  325. package/dist/runners/runnersList.d.ts.map +1 -0
  326. package/dist/runners/runnersList.js +49 -0
  327. package/dist/runners/runnersList.js.map +1 -0
  328. package/dist/runners/runnersOverview.d.ts +20 -0
  329. package/dist/runners/runnersOverview.d.ts.map +1 -0
  330. package/dist/runners/runnersOverview.js +55 -0
  331. package/dist/runners/runnersOverview.js.map +1 -0
  332. package/dist/runners/sshKeys.d.ts +26 -0
  333. package/dist/runners/sshKeys.d.ts.map +1 -0
  334. package/dist/runners/sshKeys.js +60 -0
  335. package/dist/runners/sshKeys.js.map +1 -0
  336. package/dist/runners/tarArchive.d.ts +20 -0
  337. package/dist/runners/tarArchive.d.ts.map +1 -0
  338. package/dist/runners/tarArchive.js +70 -0
  339. package/dist/runners/tarArchive.js.map +1 -0
  340. package/dist/scheduler/mcpSurface.d.ts +11 -5
  341. package/dist/scheduler/mcpSurface.d.ts.map +1 -1
  342. package/dist/scheduler/mcpSurface.js +59 -26
  343. package/dist/scheduler/mcpSurface.js.map +1 -1
  344. package/dist/selfUpdate/selfCheck.js +2 -2
  345. package/dist/selfUpdate/selfCheck.js.map +1 -1
  346. package/dist/testTimings.d.ts +5 -2
  347. package/dist/testTimings.d.ts.map +1 -1
  348. package/dist/testTimings.js +10 -1
  349. package/dist/testTimings.js.map +1 -1
  350. package/dist/utils/agentEnvironment.d.ts +6 -2
  351. package/dist/utils/agentEnvironment.d.ts.map +1 -1
  352. package/dist/utils/agentEnvironment.js +13 -2
  353. package/dist/utils/agentEnvironment.js.map +1 -1
  354. package/dist/utils/runnersScreenPlan.d.ts +130 -0
  355. package/dist/utils/runnersScreenPlan.d.ts.map +1 -0
  356. package/dist/utils/runnersScreenPlan.js +257 -0
  357. package/dist/utils/runnersScreenPlan.js.map +1 -0
  358. package/package.json +5 -2
  359. package/remoteRun/runner.sh +81 -6
@@ -0,0 +1,23 @@
1
+ import * as fsp from 'fs/promises';
2
+ import { type HubContext } from './hubPaths';
3
+ /** An archive that is no longer the current one is kept this long: a gate that was handed its path a moment ago must still find it. */
4
+ export declare const supersededArchiveGraceMs: number;
5
+ /** @description The packed package: where the gzip file is, and its id. */
6
+ export interface HubPackage {
7
+ id: string;
8
+ filePath: string;
9
+ }
10
+ /**
11
+ * @description The current package of this hub, packed now unless the cache already holds this exact source. Throws when the source
12
+ * (`dist/`, `package.json`, `remoteRun/runner.sh` under `ctx.packageRoot`) is missing. Safe without the registry lock: a cache file
13
+ * is written whole and named by its id, and two packers of one source write identical bytes.
14
+ */
15
+ export declare function getHubPackage(ctx: HubContext): HubPackage;
16
+ export interface OpenedHubPackage {
17
+ id: string;
18
+ /** The archive, open for reading; the caller closes it (a read stream made from it does). */
19
+ handle: fsp.FileHandle;
20
+ }
21
+ /** @description The current package, opened. Retries when a file vanishes between the lookup and the open (a sweep, a packer of a newer source). */
22
+ export declare function openHubPackage(ctx: HubContext): Promise<OpenedHubPackage>;
23
+ //# sourceMappingURL=hubPackage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hubPackage.d.ts","sourceRoot":"","sources":["../../src/runners/hubPackage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;AAMnC,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAuB9D,uIAAuI;AACvI,eAAO,MAAM,wBAAwB,QAAiB,CAAC;AAavD,2EAA2E;AAC3E,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB;AA6DD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,UAAU,CAoBzD;AAgBD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,6FAA6F;IAC7F,MAAM,EAAE,GAAG,CAAC,UAAU,CAAC;CACxB;AAED,oJAAoJ;AACpJ,wBAAsB,cAAc,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAS/E"}
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.supersededArchiveGraceMs = void 0;
37
+ exports.getHubPackage = getHubPackage;
38
+ exports.openHubPackage = openHubPackage;
39
+ const crypto_1 = require("crypto");
40
+ const fs = __importStar(require("fs"));
41
+ const fsp = __importStar(require("fs/promises"));
42
+ const path = __importStar(require("path"));
43
+ const zlib_1 = require("zlib");
44
+ const zod_1 = require("zod");
45
+ const configDirFile_1 = require("../configDirFile");
46
+ const hubLock_1 = require("./hubLock");
47
+ const hubPaths_1 = require("./hubPaths");
48
+ const tarArchive_1 = require("./tarArchive");
49
+ /**
50
+ * @description The charness package a runner installs: the hub's OWN `dist/`, `package.json` and `remoteRun/runner.sh`, packed into a
51
+ * gzip tar, so a runner and its hub never run different code and no npm release is needed. Its id is the sha256 of the tar before
52
+ * compression (stable — gzip's bytes depend on the zlib build), 16 hex digits. The packed file is cached in `package/`; whether the
53
+ * cache is current is decided by a stamp of the source files (path, size, mtime), so asking for the id costs a walk of `stat`s.
54
+ *
55
+ * Several gates and packers run at once, none of them coordinated, so nothing is deleted on a packer's word: an archive is published
56
+ * whole by a rename (named by its id, so two packers of one source write the same bytes), `current.json` is only a pointer that heals
57
+ * (a packer that is late writes an older pointer; the next call sees the stamp differ and packs again), an archive that is no longer
58
+ * current is removed only after {@link supersededArchiveGraceMs}, and a reader {@link openHubPackage OPENS} the archive at once — a file
59
+ * that is deleted afterwards stays readable through the open handle.
60
+ */
61
+ const packageIdLength = 16;
62
+ const gzipLevel = 9;
63
+ const cacheFileMode = 0o600;
64
+ const executableBits = 0o111;
65
+ const executableMode = 0o755;
66
+ const plainFileMode = 0o644;
67
+ const currentFileName = 'current.json';
68
+ /** An archive that is no longer the current one is kept this long: a gate that was handed its path a moment ago must still find it. */
69
+ exports.supersededArchiveGraceMs = 10 * 60 * 1000;
70
+ const archiveSuffix = '.tgz';
71
+ const temporarySuffix = '.tmp';
72
+ const maxOpenAttempts = 3;
73
+ /** `dist/` entries a runner never needs: tests, type declarations and source maps. */
74
+ const skippedFilePattern = /(?:\.d\.ts|\.d\.ts\.map|\.js\.map)$/;
75
+ const skippedFolderName = '__tests__';
76
+ const runnerScriptRelativePath = 'remoteRun/runner.sh';
77
+ const packageJsonRelativePath = 'package.json';
78
+ const distRelativePath = 'dist';
79
+ const currentSchema = zod_1.z.strictObject({ stamp: zod_1.z.string(), id: zod_1.z.string(), fileName: zod_1.z.string() });
80
+ function listDistFiles(distRoot, relativeFolder) {
81
+ const files = [];
82
+ const entries = fs.readdirSync(path.join(distRoot, relativeFolder), { withFileTypes: true }).sort((left, right) => (left.name < right.name ? -1 : 1));
83
+ for (const entry of entries) {
84
+ const relativePath = path.posix.join(relativeFolder, entry.name);
85
+ if (entry.isDirectory()) {
86
+ if (entry.name !== skippedFolderName)
87
+ files.push(...listDistFiles(distRoot, relativePath));
88
+ }
89
+ else if (entry.isFile() && !skippedFilePattern.test(entry.name)) {
90
+ files.push(statSourceFile(distRoot, relativePath));
91
+ }
92
+ }
93
+ return files;
94
+ }
95
+ function statSourceFile(root, relativePath) {
96
+ const absolutePath = path.join(root, relativePath);
97
+ const stat = fs.statSync(absolutePath);
98
+ return { relativePath, absolutePath, size: stat.size, mtimeMs: stat.mtimeMs, mode: stat.mode };
99
+ }
100
+ /** The files in archive order: `package.json`, the runner script, then everything under `dist/` sorted by path. */
101
+ function listPackageFiles(packageRoot) {
102
+ const distFiles = listDistFiles(packageRoot, distRelativePath);
103
+ return [statSourceFile(packageRoot, packageJsonRelativePath), statSourceFile(packageRoot, runnerScriptRelativePath), ...distFiles];
104
+ }
105
+ function createSourceStamp(files) {
106
+ const hash = (0, crypto_1.createHash)('sha256');
107
+ for (const file of files)
108
+ hash.update(`${file.relativePath}:${file.size}:${file.mtimeMs}\n`);
109
+ return hash.digest('hex');
110
+ }
111
+ function readCurrent(packageDir) {
112
+ try {
113
+ const parsed = currentSchema.safeParse(JSON.parse(fs.readFileSync(path.join(packageDir, currentFileName), 'utf8')));
114
+ return parsed.success ? parsed.data : null;
115
+ }
116
+ catch {
117
+ return null;
118
+ }
119
+ }
120
+ function packFiles(files) {
121
+ const entries = files.map((file) => ({
122
+ path: file.relativePath,
123
+ content: fs.readFileSync(file.absolutePath),
124
+ mode: (file.mode & executableBits) === 0 ? plainFileMode : executableMode,
125
+ }));
126
+ const tar = (0, tarArchive_1.createTarArchive)(entries);
127
+ return { id: (0, crypto_1.createHash)('sha256').update(tar).digest('hex').slice(0, packageIdLength), gzip: (0, zlib_1.gzipSync)(tar, { level: gzipLevel }) };
128
+ }
129
+ /**
130
+ * @description The current package of this hub, packed now unless the cache already holds this exact source. Throws when the source
131
+ * (`dist/`, `package.json`, `remoteRun/runner.sh` under `ctx.packageRoot`) is missing. Safe without the registry lock: a cache file
132
+ * is written whole and named by its id, and two packers of one source write identical bytes.
133
+ */
134
+ function getHubPackage(ctx) {
135
+ const packageDir = (0, hubPaths_1.getHubFilePaths)(ctx.dir).packageDir;
136
+ const files = listPackageFiles(ctx.packageRoot);
137
+ const stamp = createSourceStamp(files);
138
+ const current = readCurrent(packageDir);
139
+ if (current !== null && current.stamp === stamp && fs.existsSync(path.join(packageDir, current.fileName))) {
140
+ removeSupersededArchives(packageDir, current.fileName, Date.now());
141
+ return { id: current.id, filePath: path.join(packageDir, current.fileName) };
142
+ }
143
+ (0, hubLock_1.ensureHubDir)(ctx.dir);
144
+ const packed = packFiles(files);
145
+ const fileName = `${packed.id}${archiveSuffix}`;
146
+ const filePath = path.join(packageDir, fileName);
147
+ fs.mkdirSync(packageDir, { recursive: true, mode: 0o700 });
148
+ const temporaryPath = `${filePath}.${process.pid}.${Math.random().toString(36).slice(2)}${temporarySuffix}`;
149
+ fs.writeFileSync(temporaryPath, packed.gzip, { mode: cacheFileMode });
150
+ fs.renameSync(temporaryPath, filePath);
151
+ (0, configDirFile_1.writeJsonFileAtomically)(path.join(packageDir, currentFileName), { stamp, id: packed.id, fileName }, cacheFileMode);
152
+ removeSupersededArchives(packageDir, fileName, Date.now());
153
+ return { id: packed.id, filePath };
154
+ }
155
+ /** Remove archives (and temp files of a packer that died) that are not `currentFileName` and have not been touched for the grace period. */
156
+ function removeSupersededArchives(packageDir, currentFileName, nowMs) {
157
+ for (const name of fs.readdirSync(packageDir)) {
158
+ const isArchive = name.endsWith(archiveSuffix) && name !== currentFileName;
159
+ if (!isArchive && !name.endsWith(temporarySuffix))
160
+ continue;
161
+ const filePath = path.join(packageDir, name);
162
+ try {
163
+ if (nowMs - fs.statSync(filePath).mtimeMs > exports.supersededArchiveGraceMs)
164
+ fs.rmSync(filePath, { force: true });
165
+ }
166
+ catch {
167
+ // Already gone: another gate swept it.
168
+ }
169
+ }
170
+ }
171
+ /** @description The current package, opened. Retries when a file vanishes between the lookup and the open (a sweep, a packer of a newer source). */
172
+ async function openHubPackage(ctx) {
173
+ for (let attempt = 1;; attempt += 1) {
174
+ const hubPackage = getHubPackage(ctx);
175
+ try {
176
+ return { id: hubPackage.id, handle: await fsp.open(hubPackage.filePath, 'r') };
177
+ }
178
+ catch (error) {
179
+ if ((0, configDirFile_1.getCaughtErrnoCode)(error) !== 'ENOENT' || attempt >= maxOpenAttempts)
180
+ throw error;
181
+ }
182
+ }
183
+ }
184
+ //# sourceMappingURL=hubPackage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hubPackage.js","sourceRoot":"","sources":["../../src/runners/hubPackage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import type { RedeemReply, RedeemRequest } from './gateProtocol';
2
+ import { type HubContext } from './hubPaths';
3
+ import { type PairedRunner, type PendingPairing } from './hubRegistry';
4
+ import { type PairCodePayload } from './pairCode';
5
+ export interface CreatePairingParams {
6
+ /** The address the runner dials, and the hub's ssh host key found there. */
7
+ host: string;
8
+ port: number;
9
+ hostKey: string;
10
+ /** Whose charness it is, as the runner shows it. */
11
+ label: string;
12
+ /** What the offering instance wants to find again when the code is used or expires; the CLI sets none. */
13
+ messageRef?: string | null;
14
+ nowMs: number;
15
+ /** How long the code works (default: the production lifetime, 10 minutes). */
16
+ lifetimeMs?: number;
17
+ /** The account the runner logs in as (default: the account this process runs as). */
18
+ sshUser?: string;
19
+ }
20
+ export interface CreatedPairing {
21
+ pairId: string;
22
+ expiresAtMs: number;
23
+ /** The secret to hand to the runner machine. */
24
+ code: string;
25
+ payload: PairCodePayload;
26
+ }
27
+ /** @description Make a pairing code: a temporary key good for 10 minutes, its line in `authorized_keys`, its entry in `pending.json`. */
28
+ export declare function createPairing(ctx: HubContext, params: CreatePairingParams): Promise<CreatedPairing>;
29
+ /** @description Is the pairing code `pairId` still open (made, not used, not expired)? The gate asks before it sends the package. */
30
+ export declare function checkIsPairingOpen(ctx: HubContext, pairId: string, nowMs: number): boolean;
31
+ /**
32
+ * @description Forget the pairing codes that have expired (their lines are gone from `authorized_keys` too) and return them, so the
33
+ * offering instance can edit its messages. A code that was used but whose entry outlived a crash is dropped without being returned.
34
+ * Run at boot, on a timer and by the CLI; sshd already refuses an expired key by itself.
35
+ */
36
+ export declare function sweepExpiredPairings(ctx: HubContext, nowMs: number): Promise<PendingPairing[]>;
37
+ /** @description What a runner may call itself: lowercase letters and digits with single dashes, short, never empty. */
38
+ export declare function sanitizeRunnerName(suggestedName: string): string;
39
+ /** @description `name`, or `name-2`, `name-3`, … — the first that no paired or hand-made runner has. */
40
+ export declare function pickFreeRunnerName(suggestedName: string, takenNames: ReadonlySet<string>): string;
41
+ /**
42
+ * @description What `redeem` answered (or would answer) for the paired runner `runnerId` — for the runner that lost the answer.
43
+ * `ok: false` ONLY when the runner is not in the registry: that answer makes the runner stop its jobs, so a fault of the hub (a hub key
44
+ * that cannot be read, a file mode that changed) must not look like it — it throws, the gate fails without an answer, and the runner
45
+ * just tries again.
46
+ */
47
+ export declare function describeRunnerIdentity(ctx: HubContext, runnerId: string, packageId: string | null): RedeemReply;
48
+ /**
49
+ * @description Use the pairing code `pairId`: the runner's keys become a paired runner and the code is spent. A code that is unknown,
50
+ * used (by another key) or expired, and a key that is already registered, are refused with the reason (no values) and change nothing.
51
+ * The SAME machine asking again for a code it has already used — its answer was lost, or the hub failed after the registry was written —
52
+ * is answered again, and the derived files are repaired on the way. `packageId` is the hub's current package, told to the runner.
53
+ */
54
+ export declare function redeemPairing(ctx: HubContext, pairId: string, request: RedeemRequest, nowMs: number, packageId?: string | null): Promise<RedeemReply>;
55
+ /** @description Find a paired runner by its name or id. */
56
+ export declare function findPairedRunner(runners: readonly PairedRunner[], nameOrId: string): PairedRunner | undefined;
57
+ /** @description Is the runner `runnerId` in the registry? Every request of a runner's key asks, so a removed runner is refused at once even when its key line is still there. */
58
+ export declare function checkIsRunnerPaired(ctx: HubContext, runnerId: string): boolean;
59
+ /** @description Take a runner out: its entry leaves the registry, its line `authorized_keys`. `null` when there is no such runner. The link is cut by the caller (`linkControl.ts`). A retry after a failed step finds nothing to remove and repairs the files. */
60
+ export declare function removePairedRunner(ctx: HubContext, nameOrId: string, nowMs: number): Promise<PairedRunner | null>;
61
+ /** @description Pause or resume a runner from the hub: it stays attached but is never picked for a job while paused. `null` when there is no such runner. */
62
+ export declare function setPairedRunnerPaused(ctx: HubContext, nameOrId: string, isPaused: boolean): Promise<PairedRunner | null>;
63
+ //# sourceMappingURL=hubPairing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hubPairing.d.ts","sourceRoot":"","sources":["../../src/runners/hubPairing.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAA0B,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAGrE,OAAO,EAQL,KAAK,YAAY,EAEjB,KAAK,cAAc,EACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAqBlE,MAAM,WAAW,mBAAmB;IAClC,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,0GAA0G;IAC1G,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,eAAe,CAAC;CAC1B;AA0CD,yIAAyI;AACzI,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,CAAC,CA0BnG;AAED,qIAAqI;AACrI,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAG1F;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAK9F;AAED,uHAAuH;AACvH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAQhE;AAED,wGAAwG;AACxG,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,CAOjG;AAWD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,CAM/G;AAID;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,GAAG,IAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAkC3J;AAED,2DAA2D;AAC3D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAE7G;AAED,iLAAiL;AACjL,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE9E;AAED,mQAAmQ;AACnQ,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAMjH;AAED,6JAA6J;AAC7J,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAQxH"}
@@ -0,0 +1,261 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createPairing = createPairing;
37
+ exports.checkIsPairingOpen = checkIsPairingOpen;
38
+ exports.sweepExpiredPairings = sweepExpiredPairings;
39
+ exports.sanitizeRunnerName = sanitizeRunnerName;
40
+ exports.pickFreeRunnerName = pickFreeRunnerName;
41
+ exports.describeRunnerIdentity = describeRunnerIdentity;
42
+ exports.redeemPairing = redeemPairing;
43
+ exports.findPairedRunner = findPairedRunner;
44
+ exports.checkIsRunnerPaired = checkIsRunnerPaired;
45
+ exports.removePairedRunner = removePairedRunner;
46
+ exports.setPairedRunnerPaused = setPairedRunnerPaused;
47
+ const os = __importStar(require("os"));
48
+ const runnersConfig_1 = require("../remoteRun/runnersConfig");
49
+ const authorizedKeys_1 = require("./authorizedKeys");
50
+ const hubPaths_1 = require("./hubPaths");
51
+ const hubLock_1 = require("./hubLock");
52
+ const hubKey_1 = require("./hubKey");
53
+ const hubRegistry_1 = require("./hubRegistry");
54
+ const pairCode_1 = require("./pairCode");
55
+ const pairingTiming_1 = require("./pairingTiming");
56
+ const sshKeys_1 = require("./sshKeys");
57
+ /**
58
+ * @description The registry's operations — each one a transaction under the registry lock (`runTransaction`):
59
+ *
60
+ * 1. the `authorized_keys` block is checked first — a damaged one stops the operation before anything is written;
61
+ * 2. the AUTHORITATIVE files change: `paired.json`, then `pending.json`;
62
+ * 3. everything derived from them (`known_hosts`, the block) is rewritten from the registry — and this last step runs at the end of
63
+ * EVERY operation, whether it changed anything or not, so a step that failed (or a crash between two writes) is mended by the
64
+ * next operation, a plain `ls` included.
65
+ *
66
+ * Nothing in the middle can lose or double-spend a pairing: `redeem` records the runner with the id of the code that made it, so a
67
+ * code is single use even when the pending entry outlives a crash (the entry is dropped by the next transaction, before anything else), and
68
+ * a retry from the same machine is answered the same way (idempotent). A runner that is removed from `paired.json` is refused by every gate request at once, whatever its key line still says.
69
+ */
70
+ const maxRunnerNameLength = 24;
71
+ const fallbackRunnerName = 'runner';
72
+ function runTransaction(ctx, nowMs, work) {
73
+ return (0, hubLock_1.withHubLock)(ctx.dir, () => {
74
+ (0, authorizedKeys_1.assertManagedBlockIntact)(ctx.authorizedKeysPath);
75
+ const paired = (0, hubRegistry_1.readPairedFile)(ctx.dir);
76
+ // A pending entry whose code was already used (a crash between the two writes of a redemption) is dropped BEFORE anything else is
77
+ // done, and persisted: the paired runner is the only proof that the code is spent, and a later removal of that runner must not leave
78
+ // the entry — and with it the code's temporary key — behind to be redeemed again.
79
+ const pending = (0, hubRegistry_1.readPendingFile)(ctx.dir);
80
+ const openPending = { pending: pending.pending.filter((pairing) => !checkIsPairingUsed(paired, pairing.pairId)) };
81
+ if (openPending.pending.length !== pending.pending.length)
82
+ (0, hubRegistry_1.writePendingFile)(ctx.dir, openPending);
83
+ const state = { paired, pending: openPending };
84
+ const outcome = work(state);
85
+ if (outcome.paired !== undefined)
86
+ (0, hubRegistry_1.writePairedFile)(ctx.dir, outcome.paired);
87
+ if (outcome.pending !== undefined)
88
+ (0, hubRegistry_1.writePendingFile)(ctx.dir, outcome.pending);
89
+ (0, hubRegistry_1.syncDerivedHubFiles)(ctx, outcome.pending ?? state.pending, outcome.paired ?? state.paired, nowMs);
90
+ return outcome.result;
91
+ });
92
+ }
93
+ function removeExpired(pending, nowMs) {
94
+ const expired = pending.pending.filter((pairing) => pairing.expiresAtMs <= nowMs);
95
+ return { kept: { pending: pending.pending.filter((pairing) => pairing.expiresAtMs > nowMs) }, expired };
96
+ }
97
+ function checkIsPairingUsed(paired, pairId) {
98
+ return paired.runners.some((runner) => runner.pairId === pairId);
99
+ }
100
+ /** @description Make a pairing code: a temporary key good for 10 minutes, its line in `authorized_keys`, its entry in `pending.json`. */
101
+ function createPairing(ctx, params) {
102
+ return runTransaction(ctx, params.nowMs, (state) => {
103
+ const pairId = (0, sshKeys_1.createRandomId)();
104
+ const expiresAtMs = params.nowMs + (params.lifetimeMs ?? pairingTiming_1.pairingLifetimeMs);
105
+ const temporaryKey = (0, sshKeys_1.generateEd25519KeyPair)(`charness-pairing-${pairId}`);
106
+ const pairing = {
107
+ pairId,
108
+ publicKey: temporaryKey.publicKey,
109
+ keyFingerprint: (0, sshKeys_1.getPublicKeyFingerprint)(temporaryKey.publicKey),
110
+ expiresAtMs,
111
+ host: params.host,
112
+ port: params.port,
113
+ label: params.label,
114
+ messageRef: params.messageRef ?? null,
115
+ };
116
+ const payload = {
117
+ host: params.host,
118
+ port: params.port,
119
+ user: params.sshUser ?? os.userInfo().username,
120
+ hostKey: params.hostKey,
121
+ privateKey: temporaryKey.privateKey,
122
+ pairId,
123
+ };
124
+ // Codes that expired stay listed until `sweepExpiredPairings` hands them back: the instance that offered one still has a message to edit.
125
+ return { result: { pairId, expiresAtMs, code: (0, pairCode_1.encodePairCode)(payload), payload }, pending: { pending: [...state.pending.pending, pairing] } };
126
+ });
127
+ }
128
+ /** @description Is the pairing code `pairId` still open (made, not used, not expired)? The gate asks before it sends the package. */
129
+ function checkIsPairingOpen(ctx, pairId, nowMs) {
130
+ return (0, hubRegistry_1.readPendingFile)(ctx.dir).pending.some((pairing) => pairing.pairId === pairId && pairing.expiresAtMs > nowMs)
131
+ && !checkIsPairingUsed((0, hubRegistry_1.readPairedFile)(ctx.dir), pairId);
132
+ }
133
+ /**
134
+ * @description Forget the pairing codes that have expired (their lines are gone from `authorized_keys` too) and return them, so the
135
+ * offering instance can edit its messages. A code that was used but whose entry outlived a crash is dropped without being returned.
136
+ * Run at boot, on a timer and by the CLI; sshd already refuses an expired key by itself.
137
+ */
138
+ function sweepExpiredPairings(ctx, nowMs) {
139
+ return runTransaction(ctx, nowMs, (state) => {
140
+ const { kept, expired } = removeExpired(state.pending, nowMs);
141
+ return { result: expired, ...(kept.pending.length === state.pending.pending.length ? {} : { pending: kept }) };
142
+ });
143
+ }
144
+ /** @description What a runner may call itself: lowercase letters and digits with single dashes, short, never empty. */
145
+ function sanitizeRunnerName(suggestedName) {
146
+ const cleaned = suggestedName
147
+ .toLowerCase()
148
+ .replace(/[^a-z0-9]+/g, '-')
149
+ .replace(/^-+|-+$/g, '')
150
+ .slice(0, maxRunnerNameLength)
151
+ .replace(/-+$/g, '');
152
+ return cleaned === '' ? fallbackRunnerName : cleaned;
153
+ }
154
+ /** @description `name`, or `name-2`, `name-3`, … — the first that no paired or hand-made runner has. */
155
+ function pickFreeRunnerName(suggestedName, takenNames) {
156
+ const base = sanitizeRunnerName(suggestedName);
157
+ if (!takenNames.has(base))
158
+ return base;
159
+ for (let suffix = 2;; suffix += 1) {
160
+ const candidate = `${base}-${suffix}`;
161
+ if (!takenNames.has(candidate))
162
+ return candidate;
163
+ }
164
+ }
165
+ function getTakenRunnerNames(ctx, paired) {
166
+ const handMade = (0, runnersConfig_1.loadRunnersConfigAt)((0, hubPaths_1.getHandMadeRunnersPath)(ctx.dir)).config?.runners ?? [];
167
+ return new Set([...paired.map((runner) => runner.name), ...handMade.map((runner) => runner.name)]);
168
+ }
169
+ function buildRedeemReply(runner, hubPublicKey, packageId) {
170
+ return { ok: true, runnerId: runner.id, name: runner.name, hubPublicKey, label: runner.label, host: runner.host, port: runner.port, packageId };
171
+ }
172
+ /**
173
+ * @description What `redeem` answered (or would answer) for the paired runner `runnerId` — for the runner that lost the answer.
174
+ * `ok: false` ONLY when the runner is not in the registry: that answer makes the runner stop its jobs, so a fault of the hub (a hub key
175
+ * that cannot be read, a file mode that changed) must not look like it — it throws, the gate fails without an answer, and the runner
176
+ * just tries again.
177
+ */
178
+ function describeRunnerIdentity(ctx, runnerId, packageId) {
179
+ const runner = (0, hubRegistry_1.readPairedFile)(ctx.dir).runners.find((candidate) => candidate.id === runnerId);
180
+ if (runner === undefined)
181
+ return { ok: false, reason: 'this runner is not paired here' };
182
+ const hubKey = (0, hubKey_1.readHubKey)(ctx.dir);
183
+ if (hubKey === null)
184
+ throw new hubRegistry_1.HubRegistryError('the hub key cannot be read');
185
+ return buildRedeemReply(runner, hubKey.publicKey, packageId);
186
+ }
187
+ const unusableCodeReply = { ok: false, reason: 'this pairing code is unknown or already used' };
188
+ /**
189
+ * @description Use the pairing code `pairId`: the runner's keys become a paired runner and the code is spent. A code that is unknown,
190
+ * used (by another key) or expired, and a key that is already registered, are refused with the reason (no values) and change nothing.
191
+ * The SAME machine asking again for a code it has already used — its answer was lost, or the hub failed after the registry was written —
192
+ * is answered again, and the derived files are repaired on the way. `packageId` is the hub's current package, told to the runner.
193
+ */
194
+ function redeemPairing(ctx, pairId, request, nowMs, packageId = null) {
195
+ return runTransaction(ctx, nowMs, (state) => {
196
+ const used = state.paired.runners.find((runner) => runner.pairId === pairId);
197
+ if (used !== undefined) {
198
+ return { result: used.publicKey === request.publicKey ? buildRedeemReply(used, (0, hubKey_1.readOrCreateHubKeyLocked)(ctx.dir).publicKey, packageId) : unusableCodeReply };
199
+ }
200
+ const pairing = state.pending.pending.find((candidate) => candidate.pairId === pairId);
201
+ if (pairing === undefined)
202
+ return { result: unusableCodeReply };
203
+ if (pairing.expiresAtMs <= nowMs)
204
+ return { result: { ok: false, reason: 'this pairing code has expired' } };
205
+ if (state.paired.runners.some((runner) => runner.publicKey === request.publicKey))
206
+ return { result: { ok: false, reason: 'this machine is already paired' } };
207
+ const runner = {
208
+ id: (0, sshKeys_1.createRandomId)(),
209
+ name: pickFreeRunnerName(request.suggestedName, getTakenRunnerNames(ctx, state.paired.runners)),
210
+ publicKey: request.publicKey,
211
+ keyFingerprint: (0, sshKeys_1.getPublicKeyFingerprint)(request.publicKey),
212
+ hostKey: request.hostKey,
213
+ workDir: request.workDir,
214
+ os: request.os,
215
+ arch: request.arch,
216
+ version: request.version,
217
+ serviceKind: request.serviceKind,
218
+ pairedAtMs: nowMs,
219
+ pairId,
220
+ label: pairing.label,
221
+ host: pairing.host,
222
+ port: pairing.port,
223
+ isPaused: false,
224
+ };
225
+ return {
226
+ result: buildRedeemReply(runner, (0, hubKey_1.readOrCreateHubKeyLocked)(ctx.dir).publicKey, packageId),
227
+ paired: { rev: state.paired.rev + 1, runners: [...state.paired.runners, runner] },
228
+ pending: { pending: state.pending.pending.filter((candidate) => candidate.pairId !== pairId) },
229
+ };
230
+ });
231
+ }
232
+ /** @description Find a paired runner by its name or id. */
233
+ function findPairedRunner(runners, nameOrId) {
234
+ return runners.find((runner) => runner.name === nameOrId) ?? runners.find((runner) => runner.id === nameOrId);
235
+ }
236
+ /** @description Is the runner `runnerId` in the registry? Every request of a runner's key asks, so a removed runner is refused at once even when its key line is still there. */
237
+ function checkIsRunnerPaired(ctx, runnerId) {
238
+ return (0, hubRegistry_1.readPairedFile)(ctx.dir).runners.some((runner) => runner.id === runnerId);
239
+ }
240
+ /** @description Take a runner out: its entry leaves the registry, its line `authorized_keys`. `null` when there is no such runner. The link is cut by the caller (`linkControl.ts`). A retry after a failed step finds nothing to remove and repairs the files. */
241
+ function removePairedRunner(ctx, nameOrId, nowMs) {
242
+ return runTransaction(ctx, nowMs, (state) => {
243
+ const runner = findPairedRunner(state.paired.runners, nameOrId);
244
+ if (runner === undefined)
245
+ return { result: null };
246
+ return { result: runner, paired: { rev: state.paired.rev + 1, runners: state.paired.runners.filter((candidate) => candidate.id !== runner.id) } };
247
+ });
248
+ }
249
+ /** @description Pause or resume a runner from the hub: it stays attached but is never picked for a job while paused. `null` when there is no such runner. */
250
+ function setPairedRunnerPaused(ctx, nameOrId, isPaused) {
251
+ return runTransaction(ctx, Date.now(), (state) => {
252
+ const runner = findPairedRunner(state.paired.runners, nameOrId);
253
+ if (runner === undefined)
254
+ return { result: null };
255
+ const updated = { ...runner, isPaused };
256
+ if (runner.isPaused === isPaused)
257
+ return { result: updated };
258
+ return { result: updated, paired: { rev: state.paired.rev + 1, runners: state.paired.runners.map((candidate) => (candidate.id === runner.id ? updated : candidate)) } };
259
+ });
260
+ }
261
+ //# sourceMappingURL=hubPairing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hubPairing.js","sourceRoot":"","sources":["../../src/runners/hubPairing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /** @description Everything the hub side needs to know about the machine it runs on; tests build their own. */
2
+ export interface HubContext {
3
+ /** The registry folder (0700). */
4
+ dir: string;
5
+ /** The `authorized_keys` file sshd reads for the account (a flow test points its sshd at a temp one). */
6
+ authorizedKeysPath: string;
7
+ /** The node binary and the charness `cli.js` the gate wrapper runs. */
8
+ nodePath: string;
9
+ cliPath: string;
10
+ /** The folder with `package.json`, `dist/` and `remoteRun/` — the package a runner installs. */
11
+ packageRoot: string;
12
+ }
13
+ export interface HubFilePaths {
14
+ paired: string;
15
+ pending: string;
16
+ hubKey: string;
17
+ hubPublicKey: string;
18
+ knownHosts: string;
19
+ gate: string;
20
+ linkDir: string;
21
+ packageDir: string;
22
+ }
23
+ /** @description The hand-made `runners.json` that sits beside the registry folder (see {@link createHubContext}). */
24
+ export declare function getHandMadeRunnersPath(dir: string): string;
25
+ export interface RunnerLinkPaths {
26
+ socket: string;
27
+ state: string;
28
+ }
29
+ /** @description The context of the real machine for `homeDir`; every field can be overridden. */
30
+ export declare function createHubContext(overrides?: Partial<HubContext> & {
31
+ homeDir?: string;
32
+ }): HubContext;
33
+ export declare function getHubFilePaths(dir: string): HubFilePaths;
34
+ /** @description The socket the gate of runner `runnerId` listens on, and the file that says who holds it. */
35
+ export declare function getRunnerLinkPaths(dir: string, runnerId: string): RunnerLinkPaths;
36
+ /** @description The host alias of a runner in the hub's `known_hosts` (and the `HostKeyAlias` of the ssh calls to it). */
37
+ export declare function getRunnerHostAlias(runnerId: string): string;
38
+ //# sourceMappingURL=hubPaths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hubPaths.d.ts","sourceRoot":"","sources":["../../src/runners/hubPaths.ts"],"names":[],"mappings":"AAeA,8GAA8G;AAC9G,MAAM,WAAW,UAAU;IACzB,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,yGAAyG;IACzG,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qHAAqH;AACrH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAOD,iGAAiG;AACjG,wBAAgB,gBAAgB,CAAC,SAAS,GAAE,OAAO,CAAC,UAAU,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,UAAU,CAUvG;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAWzD;AAED,6GAA6G;AAC7G,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAGjF;AAED,0HAA0H;AAC1H,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE3D"}