@shipfox/api-runners 4.0.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (414) hide show
  1. package/.turbo/turbo-build.log +6 -6
  2. package/CHANGELOG.md +83 -0
  3. package/dist/config.d.ts +5 -1
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +53 -6
  6. package/dist/config.js.map +1 -1
  7. package/dist/core/capacity-assignments.d.ts +7 -0
  8. package/dist/core/capacity-assignments.d.ts.map +1 -0
  9. package/dist/core/capacity-assignments.js +6 -0
  10. package/dist/core/capacity-assignments.js.map +1 -0
  11. package/dist/core/demand.d.ts +6 -6
  12. package/dist/core/demand.d.ts.map +1 -1
  13. package/dist/core/demand.js +10 -10
  14. package/dist/core/demand.js.map +1 -1
  15. package/dist/core/entities/capacity-assignment.d.ts +9 -0
  16. package/dist/core/entities/capacity-assignment.d.ts.map +1 -0
  17. package/dist/core/entities/capacity-assignment.js +3 -0
  18. package/dist/core/entities/capacity-assignment.js.map +1 -0
  19. package/dist/core/entities/ephemeral-registration-token.d.ts +1 -1
  20. package/dist/core/entities/ephemeral-registration-token.d.ts.map +1 -1
  21. package/dist/core/entities/ephemeral-registration-token.js.map +1 -1
  22. package/dist/core/entities/provisioner-capability-snapshot.d.ts +13 -0
  23. package/dist/core/entities/provisioner-capability-snapshot.d.ts.map +1 -0
  24. package/dist/core/entities/provisioner-capability-snapshot.js +3 -0
  25. package/dist/core/entities/provisioner-capability-snapshot.js.map +1 -0
  26. package/dist/core/entities/provisioner-token.d.ts +10 -2
  27. package/dist/core/entities/provisioner-token.d.ts.map +1 -1
  28. package/dist/core/entities/provisioner-token.js.map +1 -1
  29. package/dist/core/entities/{provisioned-runner.d.ts → runner-instance.d.ts} +6 -6
  30. package/dist/core/entities/runner-instance.d.ts.map +1 -0
  31. package/dist/core/entities/runner-instance.js +3 -0
  32. package/dist/core/entities/runner-instance.js.map +1 -0
  33. package/dist/core/entities/runner-session.d.ts +4 -2
  34. package/dist/core/entities/runner-session.d.ts.map +1 -1
  35. package/dist/core/entities/runner-session.js.map +1 -1
  36. package/dist/core/ephemeral-registration-tokens.d.ts +5 -5
  37. package/dist/core/ephemeral-registration-tokens.d.ts.map +1 -1
  38. package/dist/core/ephemeral-registration-tokens.js +12 -12
  39. package/dist/core/ephemeral-registration-tokens.js.map +1 -1
  40. package/dist/core/errors.d.ts +16 -4
  41. package/dist/core/errors.d.ts.map +1 -1
  42. package/dist/core/errors.js +22 -4
  43. package/dist/core/errors.js.map +1 -1
  44. package/dist/core/index.d.ts +10 -4
  45. package/dist/core/index.d.ts.map +1 -1
  46. package/dist/core/index.js +6 -2
  47. package/dist/core/index.js.map +1 -1
  48. package/dist/core/job-executions.d.ts +2 -0
  49. package/dist/core/job-executions.d.ts.map +1 -1
  50. package/dist/core/job-executions.js +1 -2
  51. package/dist/core/job-executions.js.map +1 -1
  52. package/dist/core/maintenance.d.ts +1 -1
  53. package/dist/core/maintenance.d.ts.map +1 -1
  54. package/dist/core/maintenance.js +5 -5
  55. package/dist/core/maintenance.js.map +1 -1
  56. package/dist/core/provisioner-capability-snapshots.d.ts +5 -0
  57. package/dist/core/provisioner-capability-snapshots.d.ts.map +1 -0
  58. package/dist/core/provisioner-capability-snapshots.js +10 -0
  59. package/dist/core/provisioner-capability-snapshots.js.map +1 -0
  60. package/dist/core/provisioner-tokens.d.ts +10 -0
  61. package/dist/core/provisioner-tokens.d.ts.map +1 -1
  62. package/dist/core/provisioner-tokens.js +23 -1
  63. package/dist/core/provisioner-tokens.js.map +1 -1
  64. package/dist/core/rate-limit.d.ts.map +1 -1
  65. package/dist/core/rate-limit.js +2 -7
  66. package/dist/core/rate-limit.js.map +1 -1
  67. package/dist/core/runner-activation.d.ts +13 -0
  68. package/dist/core/runner-activation.d.ts.map +1 -0
  69. package/dist/core/runner-activation.js +36 -0
  70. package/dist/core/runner-activation.js.map +1 -0
  71. package/dist/core/runner-control-sessions.d.ts +46 -0
  72. package/dist/core/runner-control-sessions.d.ts.map +1 -0
  73. package/dist/core/runner-control-sessions.js +121 -0
  74. package/dist/core/runner-control-sessions.js.map +1 -0
  75. package/dist/core/runner-instances.d.ts +79 -0
  76. package/dist/core/runner-instances.d.ts.map +1 -0
  77. package/dist/core/runner-instances.js +168 -0
  78. package/dist/core/runner-instances.js.map +1 -0
  79. package/dist/core/runner-sessions.d.ts +8 -2
  80. package/dist/core/runner-sessions.d.ts.map +1 -1
  81. package/dist/core/runner-sessions.js +8 -5
  82. package/dist/core/runner-sessions.js.map +1 -1
  83. package/dist/db/capacity-assignments.d.ts +7 -0
  84. package/dist/db/capacity-assignments.d.ts.map +1 -0
  85. package/dist/db/capacity-assignments.js +72 -0
  86. package/dist/db/capacity-assignments.js.map +1 -0
  87. package/dist/db/db.d.ts +2837 -1009
  88. package/dist/db/db.d.ts.map +1 -1
  89. package/dist/db/db.js +11 -2
  90. package/dist/db/db.js.map +1 -1
  91. package/dist/db/ephemeral-registration-tokens.d.ts +2 -2
  92. package/dist/db/ephemeral-registration-tokens.d.ts.map +1 -1
  93. package/dist/db/ephemeral-registration-tokens.js +21 -21
  94. package/dist/db/ephemeral-registration-tokens.js.map +1 -1
  95. package/dist/db/index.d.ts +7 -4
  96. package/dist/db/index.d.ts.map +1 -1
  97. package/dist/db/index.js +5 -2
  98. package/dist/db/index.js.map +1 -1
  99. package/dist/db/job-executions.d.ts +6 -6
  100. package/dist/db/job-executions.d.ts.map +1 -1
  101. package/dist/db/job-executions.js +20 -19
  102. package/dist/db/job-executions.js.map +1 -1
  103. package/dist/db/provisioner-capability-snapshots.d.ts +21 -0
  104. package/dist/db/provisioner-capability-snapshots.d.ts.map +1 -0
  105. package/dist/db/provisioner-capability-snapshots.js +57 -0
  106. package/dist/db/provisioner-capability-snapshots.js.map +1 -0
  107. package/dist/db/provisioner-tokens.d.ts +7 -2
  108. package/dist/db/provisioner-tokens.d.ts.map +1 -1
  109. package/dist/db/provisioner-tokens.js +59 -10
  110. package/dist/db/provisioner-tokens.js.map +1 -1
  111. package/dist/db/reservations.d.ts +18 -0
  112. package/dist/db/reservations.d.ts.map +1 -1
  113. package/dist/db/reservations.js +88 -1
  114. package/dist/db/reservations.js.map +1 -1
  115. package/dist/db/runner-instances.d.ts +91 -0
  116. package/dist/db/runner-instances.d.ts.map +1 -0
  117. package/dist/db/runner-instances.js +511 -0
  118. package/dist/db/runner-instances.js.map +1 -0
  119. package/dist/db/runner-sessions.d.ts +5 -0
  120. package/dist/db/runner-sessions.d.ts.map +1 -1
  121. package/dist/db/runner-sessions.js +48 -2
  122. package/dist/db/runner-sessions.js.map +1 -1
  123. package/dist/db/schema/capacity-assignments.d.ts +113 -0
  124. package/dist/db/schema/capacity-assignments.d.ts.map +1 -0
  125. package/dist/db/schema/capacity-assignments.js +29 -0
  126. package/dist/db/schema/capacity-assignments.js.map +1 -0
  127. package/dist/db/schema/ephemeral-registration-tokens.d.ts +2 -2
  128. package/dist/db/schema/ephemeral-registration-tokens.js +3 -3
  129. package/dist/db/schema/ephemeral-registration-tokens.js.map +1 -1
  130. package/dist/db/schema/provisioner-capability-snapshots.d.ts +207 -0
  131. package/dist/db/schema/provisioner-capability-snapshots.d.ts.map +1 -0
  132. package/dist/db/schema/provisioner-capability-snapshots.js +38 -0
  133. package/dist/db/schema/provisioner-capability-snapshots.js.map +1 -0
  134. package/dist/db/schema/provisioner-tokens.d.ts +19 -1
  135. package/dist/db/schema/provisioner-tokens.d.ts.map +1 -1
  136. package/dist/db/schema/provisioner-tokens.js +29 -3
  137. package/dist/db/schema/provisioner-tokens.js.map +1 -1
  138. package/dist/db/schema/runner-activation-tokens.d.ts +161 -0
  139. package/dist/db/schema/runner-activation-tokens.d.ts.map +1 -0
  140. package/dist/db/schema/runner-activation-tokens.js +27 -0
  141. package/dist/db/schema/runner-activation-tokens.js.map +1 -0
  142. package/dist/db/schema/runner-control-sessions.d.ts +338 -0
  143. package/dist/db/schema/runner-control-sessions.d.ts.map +1 -0
  144. package/dist/db/schema/runner-control-sessions.js +52 -0
  145. package/dist/db/schema/runner-control-sessions.js.map +1 -0
  146. package/dist/db/schema/{provisioned-runners.d.ts → runner-instances.d.ts} +88 -34
  147. package/dist/db/schema/runner-instances.d.ts.map +1 -0
  148. package/dist/db/schema/{provisioned-runners.js → runner-instances.js} +19 -14
  149. package/dist/db/schema/runner-instances.js.map +1 -0
  150. package/dist/db/schema/runner-sessions.d.ts +39 -5
  151. package/dist/db/schema/runner-sessions.d.ts.map +1 -1
  152. package/dist/db/schema/runner-sessions.js +13 -6
  153. package/dist/db/schema/runner-sessions.js.map +1 -1
  154. package/dist/db/schema/running-job-executions.d.ts +2 -2
  155. package/dist/db/schema/running-job-executions.js +4 -4
  156. package/dist/db/schema/running-job-executions.js.map +1 -1
  157. package/dist/index.d.ts +7 -2
  158. package/dist/index.d.ts.map +1 -1
  159. package/dist/index.js +45 -38
  160. package/dist/index.js.map +1 -1
  161. package/dist/installation-provisioning.d.ts +14 -0
  162. package/dist/installation-provisioning.d.ts.map +1 -0
  163. package/dist/installation-provisioning.js +7 -0
  164. package/dist/installation-provisioning.js.map +1 -0
  165. package/dist/metrics/index.d.ts +1 -1
  166. package/dist/metrics/index.d.ts.map +1 -1
  167. package/dist/metrics/index.js +1 -1
  168. package/dist/metrics/index.js.map +1 -1
  169. package/dist/metrics/instance.d.ts +11 -7
  170. package/dist/metrics/instance.d.ts.map +1 -1
  171. package/dist/metrics/instance.js +13 -7
  172. package/dist/metrics/instance.js.map +1 -1
  173. package/dist/presentation/auth/index.d.ts +1 -0
  174. package/dist/presentation/auth/index.d.ts.map +1 -1
  175. package/dist/presentation/auth/index.js +1 -0
  176. package/dist/presentation/auth/index.js.map +1 -1
  177. package/dist/presentation/auth/provisioner-token-auth.d.ts.map +1 -1
  178. package/dist/presentation/auth/provisioner-token-auth.js +5 -1
  179. package/dist/presentation/auth/provisioner-token-auth.js.map +1 -1
  180. package/dist/presentation/auth/runner-control-session-auth.d.ts +4 -0
  181. package/dist/presentation/auth/runner-control-session-auth.d.ts.map +1 -0
  182. package/dist/presentation/auth/runner-control-session-auth.js +29 -0
  183. package/dist/presentation/auth/runner-control-session-auth.js.map +1 -0
  184. package/dist/presentation/auth/runner-registration-token-auth.d.ts +5 -1
  185. package/dist/presentation/auth/runner-registration-token-auth.d.ts.map +1 -1
  186. package/dist/presentation/auth/runner-registration-token-auth.js +21 -1
  187. package/dist/presentation/auth/runner-registration-token-auth.js.map +1 -1
  188. package/dist/presentation/dto/index.d.ts +2 -2
  189. package/dist/presentation/dto/index.d.ts.map +1 -1
  190. package/dist/presentation/dto/index.js +2 -2
  191. package/dist/presentation/dto/index.js.map +1 -1
  192. package/dist/presentation/dto/mint-registration-tokens.d.ts +5 -3
  193. package/dist/presentation/dto/mint-registration-tokens.d.ts.map +1 -1
  194. package/dist/presentation/dto/mint-registration-tokens.js +4 -4
  195. package/dist/presentation/dto/mint-registration-tokens.js.map +1 -1
  196. package/dist/presentation/dto/poll-demand.d.ts.map +1 -1
  197. package/dist/presentation/dto/poll-demand.js +7 -1
  198. package/dist/presentation/dto/poll-demand.js.map +1 -1
  199. package/dist/presentation/dto/provisioner-token.d.ts +1 -0
  200. package/dist/presentation/dto/provisioner-token.d.ts.map +1 -1
  201. package/dist/presentation/dto/provisioner-token.js +5 -1
  202. package/dist/presentation/dto/provisioner-token.js.map +1 -1
  203. package/dist/presentation/dto/{provisioned-runners.d.ts → runner-instances.d.ts} +9 -9
  204. package/dist/presentation/dto/runner-instances.d.ts.map +1 -0
  205. package/dist/presentation/dto/{provisioned-runners.js → runner-instances.js} +6 -6
  206. package/dist/presentation/dto/runner-instances.js.map +1 -0
  207. package/dist/presentation/index.d.ts +2 -2
  208. package/dist/presentation/index.d.ts.map +1 -1
  209. package/dist/presentation/index.js +2 -2
  210. package/dist/presentation/index.js.map +1 -1
  211. package/dist/presentation/inter-module.d.ts +5 -0
  212. package/dist/presentation/inter-module.d.ts.map +1 -0
  213. package/dist/presentation/inter-module.js +43 -0
  214. package/dist/presentation/inter-module.js.map +1 -0
  215. package/dist/presentation/routes/assign-capacity.d.ts +2 -0
  216. package/dist/presentation/routes/assign-capacity.d.ts.map +1 -0
  217. package/dist/presentation/routes/assign-capacity.js +44 -0
  218. package/dist/presentation/routes/assign-capacity.js.map +1 -0
  219. package/dist/presentation/routes/get-provisioner-me.d.ts.map +1 -1
  220. package/dist/presentation/routes/get-provisioner-me.js +5 -1
  221. package/dist/presentation/routes/get-provisioner-me.js.map +1 -1
  222. package/dist/presentation/routes/heartbeat.d.ts +2 -1
  223. package/dist/presentation/routes/heartbeat.d.ts.map +1 -1
  224. package/dist/presentation/routes/heartbeat.js +60 -50
  225. package/dist/presentation/routes/heartbeat.js.map +1 -1
  226. package/dist/presentation/routes/index.d.ts +3 -1
  227. package/dist/presentation/routes/index.d.ts.map +1 -1
  228. package/dist/presentation/routes/index.js +83 -50
  229. package/dist/presentation/routes/index.js.map +1 -1
  230. package/dist/presentation/routes/mint-registration-tokens.d.ts.map +1 -1
  231. package/dist/presentation/routes/mint-registration-tokens.js +5 -5
  232. package/dist/presentation/routes/mint-registration-tokens.js.map +1 -1
  233. package/dist/presentation/routes/planned-capacity.d.ts +3 -0
  234. package/dist/presentation/routes/planned-capacity.d.ts.map +1 -0
  235. package/dist/presentation/routes/planned-capacity.js +54 -0
  236. package/dist/presentation/routes/planned-capacity.js.map +1 -0
  237. package/dist/presentation/routes/poll-demand.d.ts +2 -0
  238. package/dist/presentation/routes/poll-demand.d.ts.map +1 -1
  239. package/dist/presentation/routes/poll-demand.js +86 -45
  240. package/dist/presentation/routes/poll-demand.js.map +1 -1
  241. package/dist/presentation/routes/reconcile-runner-instances.d.ts +2 -0
  242. package/dist/presentation/routes/reconcile-runner-instances.d.ts.map +1 -0
  243. package/dist/presentation/routes/reconcile-runner-instances.js +27 -0
  244. package/dist/presentation/routes/reconcile-runner-instances.js.map +1 -0
  245. package/dist/presentation/routes/register.d.ts +2 -1
  246. package/dist/presentation/routes/register.d.ts.map +1 -1
  247. package/dist/presentation/routes/register.js +55 -52
  248. package/dist/presentation/routes/register.js.map +1 -1
  249. package/dist/presentation/routes/report-runner-instances.d.ts +2 -0
  250. package/dist/presentation/routes/report-runner-instances.d.ts.map +1 -0
  251. package/dist/presentation/routes/report-runner-instances.js +37 -0
  252. package/dist/presentation/routes/report-runner-instances.js.map +1 -0
  253. package/dist/presentation/routes/request-job.d.ts +2 -1
  254. package/dist/presentation/routes/request-job.d.ts.map +1 -1
  255. package/dist/presentation/routes/request-job.js +39 -36
  256. package/dist/presentation/routes/request-job.js.map +1 -1
  257. package/dist/presentation/routes/runner-enrollment.d.ts +7 -0
  258. package/dist/presentation/routes/runner-enrollment.d.ts.map +1 -0
  259. package/dist/presentation/routes/runner-enrollment.js +185 -0
  260. package/dist/presentation/routes/runner-enrollment.js.map +1 -0
  261. package/dist/temporal/activities/index.d.ts +2 -2
  262. package/dist/temporal/activities/index.d.ts.map +1 -1
  263. package/dist/temporal/activities/index.js +2 -2
  264. package/dist/temporal/activities/index.js.map +1 -1
  265. package/dist/temporal/activities/maintenance-activities.d.ts +1 -1
  266. package/dist/temporal/activities/maintenance-activities.d.ts.map +1 -1
  267. package/dist/temporal/activities/maintenance-activities.js +3 -3
  268. package/dist/temporal/activities/maintenance-activities.js.map +1 -1
  269. package/dist/temporal/workflows/index.bundle.js +3 -3
  270. package/dist/temporal/workflows/stuck-job-detector.js +2 -2
  271. package/dist/temporal/workflows/stuck-job-detector.js.map +1 -1
  272. package/dist/tsconfig.test.tsbuildinfo +1 -1
  273. package/drizzle/0000_initial.sql +102 -24
  274. package/drizzle/meta/0000_snapshot.json +483 -63
  275. package/package.json +31 -36
  276. package/src/config.test.ts +0 -26
  277. package/src/config.ts +47 -6
  278. package/src/core/capacity-assignments.ts +10 -0
  279. package/src/core/demand.test.ts +29 -29
  280. package/src/core/demand.ts +22 -22
  281. package/src/core/entities/capacity-assignment.ts +8 -0
  282. package/src/core/entities/ephemeral-registration-token.ts +1 -1
  283. package/src/core/entities/provisioner-capability-snapshot.ts +12 -0
  284. package/src/core/entities/provisioner-token.ts +8 -2
  285. package/src/core/entities/{provisioned-runner.ts → runner-instance.ts} +5 -5
  286. package/src/core/entities/runner-session.ts +4 -2
  287. package/src/core/ephemeral-registration-tokens.test.ts +11 -11
  288. package/src/core/ephemeral-registration-tokens.ts +18 -20
  289. package/src/core/errors.ts +23 -4
  290. package/src/core/index.ts +39 -17
  291. package/src/core/job-executions.ts +3 -2
  292. package/src/core/maintenance.test.ts +13 -17
  293. package/src/core/maintenance.ts +5 -5
  294. package/src/core/provisioner-capability-snapshots.test.ts +35 -0
  295. package/src/core/provisioner-capability-snapshots.ts +12 -0
  296. package/src/core/provisioner-tokens.test.ts +20 -0
  297. package/src/core/provisioner-tokens.ts +33 -0
  298. package/src/core/rate-limit.test.ts +11 -27
  299. package/src/core/rate-limit.ts +3 -11
  300. package/src/core/runner-activation.ts +72 -0
  301. package/src/core/runner-control-sessions.ts +190 -0
  302. package/src/core/{provisioned-runners.test.ts → runner-instances.test.ts} +24 -24
  303. package/src/core/runner-instances.ts +310 -0
  304. package/src/core/runner-sessions.test.ts +112 -22
  305. package/src/core/runner-sessions.ts +25 -14
  306. package/src/db/capacity-assignments.test.ts +159 -0
  307. package/src/db/capacity-assignments.ts +116 -0
  308. package/src/db/db.ts +11 -2
  309. package/src/db/ephemeral-registration-tokens.test.ts +9 -9
  310. package/src/db/ephemeral-registration-tokens.ts +26 -26
  311. package/src/db/index.ts +31 -21
  312. package/src/db/job-executions.test.ts +13 -11
  313. package/src/db/job-executions.ts +33 -27
  314. package/src/db/provisioner-capability-snapshots.test.ts +175 -0
  315. package/src/db/provisioner-capability-snapshots.ts +130 -0
  316. package/src/db/provisioner-tokens.test.ts +139 -2
  317. package/src/db/provisioner-tokens.ts +123 -15
  318. package/src/db/reservations.test.ts +49 -0
  319. package/src/db/reservations.ts +146 -1
  320. package/src/db/{provisioned-runners.test.ts → runner-instances.test.ts} +429 -353
  321. package/src/db/runner-instances.ts +942 -0
  322. package/src/db/runner-sessions.test.ts +19 -6
  323. package/src/db/runner-sessions.ts +78 -2
  324. package/src/db/schema/capacity-assignments.ts +34 -0
  325. package/src/db/schema/ephemeral-registration-tokens.ts +4 -4
  326. package/src/db/schema/provisioner-capability-snapshots.ts +46 -0
  327. package/src/db/schema/provisioner-tokens.ts +33 -2
  328. package/src/db/schema/runner-activation-tokens.ts +22 -0
  329. package/src/db/schema/runner-control-sessions.ts +46 -0
  330. package/src/db/schema/{provisioned-runners.ts → runner-instances.ts} +26 -27
  331. package/src/db/schema/runner-sessions.ts +11 -7
  332. package/src/db/schema/running-job-executions.ts +5 -5
  333. package/src/index.test.ts +26 -0
  334. package/src/index.ts +39 -19
  335. package/src/installation-provisioning.ts +14 -0
  336. package/src/metrics/index.ts +5 -5
  337. package/src/metrics/instance.ts +25 -14
  338. package/src/presentation/auth/index.ts +4 -0
  339. package/src/presentation/auth/provisioner-token-auth.ts +8 -4
  340. package/src/presentation/auth/runner-control-session-auth.ts +31 -0
  341. package/src/presentation/auth/runner-registration-token-auth.ts +39 -3
  342. package/src/presentation/dto/index.ts +5 -5
  343. package/src/presentation/dto/mint-registration-tokens.ts +8 -15
  344. package/src/presentation/dto/poll-demand.ts +3 -1
  345. package/src/presentation/dto/provisioner-token.ts +5 -0
  346. package/src/presentation/dto/{provisioned-runners.ts → runner-instances.ts} +13 -15
  347. package/src/presentation/index.ts +2 -1
  348. package/src/presentation/inter-module.test.ts +15 -0
  349. package/src/presentation/inter-module.ts +53 -0
  350. package/src/presentation/routes/assign-capacity.ts +48 -0
  351. package/src/presentation/routes/get-provisioner-me.ts +3 -4
  352. package/src/presentation/routes/heartbeat.test.ts +4 -3
  353. package/src/presentation/routes/heartbeat.ts +67 -64
  354. package/src/presentation/routes/index.ts +93 -43
  355. package/src/presentation/routes/list-active-runners.test.ts +23 -23
  356. package/src/presentation/routes/manual-registration-tokens.test.ts +4 -3
  357. package/src/presentation/routes/mint-registration-tokens.test.ts +12 -12
  358. package/src/presentation/routes/mint-registration-tokens.ts +5 -7
  359. package/src/presentation/routes/planned-capacity.ts +49 -0
  360. package/src/presentation/routes/poll-demand-release.test.ts +4 -4
  361. package/src/presentation/routes/poll-demand.test.ts +161 -22
  362. package/src/presentation/routes/poll-demand.ts +105 -45
  363. package/src/presentation/routes/provisioner-me.test.ts +37 -3
  364. package/src/presentation/routes/{reconcile-provisioned-runners.test.ts → reconcile-runner-instances.test.ts} +66 -61
  365. package/src/presentation/routes/reconcile-runner-instances.ts +30 -0
  366. package/src/presentation/routes/register.test.ts +9 -5
  367. package/src/presentation/routes/register.ts +61 -57
  368. package/src/presentation/routes/{report-provisioned-runners.test.ts → report-runner-instances.test.ts} +28 -28
  369. package/src/presentation/routes/{report-provisioned-runners.ts → report-runner-instances.ts} +14 -14
  370. package/src/presentation/routes/request-job.test.ts +5 -3
  371. package/src/presentation/routes/request-job.ts +41 -37
  372. package/src/presentation/routes/runner-enrollment.test.ts +259 -0
  373. package/src/presentation/routes/runner-enrollment.ts +174 -0
  374. package/src/temporal/activities/index.ts +2 -2
  375. package/src/temporal/activities/maintenance-activities.test.ts +7 -7
  376. package/src/temporal/activities/maintenance-activities.ts +3 -3
  377. package/src/temporal/workflows/stuck-job-detector.test.ts +3 -3
  378. package/src/temporal/workflows/stuck-job-detector.ts +2 -2
  379. package/test/env.ts +1 -3
  380. package/test/factories/ephemeral-registration-token.ts +2 -2
  381. package/test/factories/provisioner-token.ts +3 -1
  382. package/test/factories/runner-instance.ts +57 -0
  383. package/test/factories/runner-session.ts +3 -1
  384. package/test/fixtures/auth-inter-module.ts +30 -0
  385. package/test/globalSetup.ts +5 -1
  386. package/test/index.ts +2 -1
  387. package/tsconfig.build.tsbuildinfo +1 -1
  388. package/dist/core/entities/provisioned-runner.d.ts.map +0 -1
  389. package/dist/core/entities/provisioned-runner.js +0 -3
  390. package/dist/core/entities/provisioned-runner.js.map +0 -1
  391. package/dist/core/provisioned-runners.d.ts +0 -67
  392. package/dist/core/provisioned-runners.d.ts.map +0 -1
  393. package/dist/core/provisioned-runners.js +0 -162
  394. package/dist/core/provisioned-runners.js.map +0 -1
  395. package/dist/db/provisioned-runners.d.ts +0 -79
  396. package/dist/db/provisioned-runners.d.ts.map +0 -1
  397. package/dist/db/provisioned-runners.js +0 -466
  398. package/dist/db/provisioned-runners.js.map +0 -1
  399. package/dist/db/schema/provisioned-runners.d.ts.map +0 -1
  400. package/dist/db/schema/provisioned-runners.js.map +0 -1
  401. package/dist/presentation/dto/provisioned-runners.d.ts.map +0 -1
  402. package/dist/presentation/dto/provisioned-runners.js.map +0 -1
  403. package/dist/presentation/routes/reconcile-provisioned-runners.d.ts +0 -2
  404. package/dist/presentation/routes/reconcile-provisioned-runners.d.ts.map +0 -1
  405. package/dist/presentation/routes/reconcile-provisioned-runners.js +0 -27
  406. package/dist/presentation/routes/reconcile-provisioned-runners.js.map +0 -1
  407. package/dist/presentation/routes/report-provisioned-runners.d.ts +0 -2
  408. package/dist/presentation/routes/report-provisioned-runners.d.ts.map +0 -1
  409. package/dist/presentation/routes/report-provisioned-runners.js +0 -37
  410. package/dist/presentation/routes/report-provisioned-runners.js.map +0 -1
  411. package/src/core/provisioned-runners.ts +0 -301
  412. package/src/db/provisioned-runners.ts +0 -886
  413. package/src/presentation/routes/reconcile-provisioned-runners.ts +0 -30
  414. package/test/factories/provisioned-runner.ts +0 -78
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipfox/api-runners",
3
3
  "license": "MIT",
4
- "version": "4.0.0",
4
+ "version": "6.0.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/ShipfoxHQ/shipfox.git",
@@ -13,43 +13,35 @@
13
13
  "types": "dist/index.d.ts",
14
14
  "imports": {
15
15
  "#test/*": "./test/*",
16
- "#*": {
17
- "workspace-source": "./src/*",
18
- "development": "./src/*",
19
- "default": "./dist/*"
20
- }
16
+ "#*": "./dist/*"
21
17
  },
22
18
  "exports": {
23
19
  ".": {
24
- "development": {
25
- "types": "./src/index.ts",
26
- "default": "./src/index.ts"
27
- },
28
- "default": {
29
- "types": "./dist/index.d.ts",
30
- "default": "./dist/index.js"
31
- }
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.js"
32
22
  }
33
23
  },
34
24
  "dependencies": {
35
25
  "@temporalio/workflow": "1.18.1",
36
26
  "drizzle-orm": "^0.45.2",
37
27
  "zod": "^4.4.3",
38
- "@shipfox/api-auth": "4.0.0",
39
- "@shipfox/api-auth-context": "3.0.0",
40
- "@shipfox/api-runners-dto": "2.0.0",
41
- "@shipfox/api-workflows-dto": "2.0.0",
42
- "@shipfox/config": "1.2.1",
43
- "@shipfox/node-drizzle": "0.3.0",
44
- "@shipfox/node-fastify": "0.2.2",
45
- "@shipfox/node-module": "0.3.1",
46
- "@shipfox/node-opentelemetry": "0.5.1",
47
- "@shipfox/node-outbox": "0.2.2",
48
- "@shipfox/node-postgres": "0.4.1",
49
- "@shipfox/node-rate-limit": "0.2.0",
50
- "@shipfox/node-temporal": "0.3.0",
51
- "@shipfox/node-tokens": "0.2.0",
52
- "@shipfox/runner-labels": "0.1.0"
28
+ "@shipfox/api-auth-context": "6.0.0",
29
+ "@shipfox/api-auth-dto": "6.0.0",
30
+ "@shipfox/api-runners-dto": "6.0.0",
31
+ "@shipfox/api-workflows-dto": "6.0.0",
32
+ "@shipfox/config": "1.2.2",
33
+ "@shipfox/node-drizzle": "0.3.2",
34
+ "@shipfox/node-auth-root-key": "0.2.0",
35
+ "@shipfox/node-fastify": "0.2.4",
36
+ "@shipfox/node-opentelemetry": "0.5.2",
37
+ "@shipfox/node-outbox": "0.2.4",
38
+ "@shipfox/inter-module": "0.2.0",
39
+ "@shipfox/node-module": "0.4.0",
40
+ "@shipfox/node-postgres": "0.4.2",
41
+ "@shipfox/node-tokens": "0.3.0",
42
+ "@shipfox/node-temporal": "0.3.2",
43
+ "@shipfox/runner-labels": "0.1.1",
44
+ "@shipfox/node-rate-limit": "0.3.0"
53
45
  },
54
46
  "devDependencies": {
55
47
  "@temporalio/activity": "1.18.1",
@@ -62,18 +54,21 @@
62
54
  "fastify": "^5.3.3",
63
55
  "fastify-type-provider-zod": "^6.0.0",
64
56
  "fishery": "^2.4.0",
65
- "@shipfox/api-auth-dto": "2.0.0",
66
- "@shipfox/biome": "1.8.1",
67
- "@shipfox/node-jwt": "0.2.0",
68
- "@shipfox/swc": "1.2.5",
69
- "@shipfox/ts-config": "1.3.8",
70
- "@shipfox/typescript": "1.1.6",
71
- "@shipfox/vitest": "1.2.2"
57
+ "@shipfox/api-auth": "6.0.0",
58
+ "@shipfox/api-auth-dto": "6.0.0",
59
+ "@shipfox/biome": "1.8.2",
60
+ "@shipfox/depcruise": "1.0.2",
61
+ "@shipfox/node-jwt": "0.3.0",
62
+ "@shipfox/swc": "1.2.6",
63
+ "@shipfox/typescript": "1.1.7",
64
+ "@shipfox/vitest": "1.2.3",
65
+ "@shipfox/ts-config": "1.3.8"
72
66
  },
73
67
  "scripts": {
74
68
  "build": "shipfox-swc && shipfox-temporal-bundle dist/temporal/workflows/index.js",
75
69
  "check": "shipfox-biome-check",
76
70
  "check:fix": "shipfox-biome-check --write",
71
+ "depcruise": "shipfox-depcruise",
77
72
  "test": "shipfox-vitest-run",
78
73
  "test:watch": "shipfox-vitest-watch",
79
74
  "type": "shipfox-tsc-check",
@@ -27,7 +27,6 @@ describe('EPHEMERAL_REGISTRATION_TOKEN_TTL_SECONDS validation', () => {
27
27
  expect(config.EPHEMERAL_REGISTRATION_TOKEN_TTL_SECONDS).toBe(3600);
28
28
  });
29
29
  });
30
-
31
30
  describe('REGISTRATION_TOKEN_BATCH_MAX validation', () => {
32
31
  afterEach(() => {
33
32
  vi.unstubAllEnvs();
@@ -85,31 +84,6 @@ describe.each([
85
84
  });
86
85
  });
87
86
 
88
- describe('RATE_LIMIT_IDENTIFIER_SECRET validation', () => {
89
- afterEach(() => {
90
- vi.unstubAllEnvs();
91
- vi.resetModules();
92
- });
93
-
94
- it('allows the secret to be omitted', async () => {
95
- const previous = process.env.RATE_LIMIT_IDENTIFIER_SECRET;
96
- delete process.env.RATE_LIMIT_IDENTIFIER_SECRET;
97
- vi.resetModules();
98
-
99
- try {
100
- const {config} = await import('#config.js');
101
-
102
- expect(config.RATE_LIMIT_IDENTIFIER_SECRET).toBeUndefined();
103
- } finally {
104
- if (previous === undefined) {
105
- delete process.env.RATE_LIMIT_IDENTIFIER_SECRET;
106
- } else {
107
- process.env.RATE_LIMIT_IDENTIFIER_SECRET = previous;
108
- }
109
- }
110
- });
111
- });
112
-
113
87
  describe('RUNNER_NO_FIRST_HEARTBEAT_GRACE_SECONDS validation', () => {
114
88
  afterEach(() => {
115
89
  vi.unstubAllEnvs();
package/src/config.ts CHANGED
@@ -1,10 +1,31 @@
1
1
  import {REGISTRATION_TOKEN_BATCH_HARD_MAX} from '@shipfox/api-runners-dto';
2
- import {bool, createConfig, num, str} from '@shipfox/config';
2
+ import {bool, createConfig, num} from '@shipfox/config';
3
3
  import {STUCK_JOB_THRESHOLD_SECONDS} from '#core/maintenance-policy.js';
4
4
 
5
5
  const EPHEMERAL_REGISTRATION_TOKEN_TTL_HARD_MAX_SECONDS = 3600;
6
+ const RUNNER_CONTROL_PLANE_TOKEN_TTL_HARD_MAX_SECONDS = 3600;
6
7
 
7
8
  export const config = createConfig({
9
+ RUNNER_BOOTSTRAP_TOKEN_TTL_SECONDS: num({
10
+ desc: 'Lifetime of a one-use runner bootstrap token in seconds. The token can only create one runner-control session before it expires.',
11
+ default: 300,
12
+ }),
13
+ RUNNER_CONTROL_SESSION_TTL_SECONDS: num({
14
+ desc: 'Lifetime of a pre-workspace runner-control session in seconds. This session can only enroll, attach its provider identity, and report its own liveness.',
15
+ default: 3600,
16
+ }),
17
+ RUNNER_ACTIVATION_TOKEN_TTL_SECONDS: num({
18
+ desc: 'Lifetime of a one-use activation token in seconds. The token is issued only to an assigned runner-control session and creates one workspace runner session.',
19
+ default: 300,
20
+ }),
21
+ RUNNER_ASSIGNMENT_POLL_MAX_WAIT_SECONDS: num({
22
+ desc: 'Maximum time the runner assignment poll waits before returning no assignment, in seconds.',
23
+ default: 30,
24
+ }),
25
+ RUNNER_ASSIGNMENT_POLL_INTERVAL_MS: num({
26
+ desc: 'Delay between durable assignment reads while a runner-control session waits for an assignment, in milliseconds.',
27
+ default: 1000,
28
+ }),
8
29
  EPHEMERAL_REGISTRATION_TOKEN_TTL_SECONDS: num({
9
30
  desc: `Lifetime of a provisioner-minted runner registration token, in seconds. The token can be exchanged once by a runner before this time passes. Set this between 1 and ${EPHEMERAL_REGISTRATION_TOKEN_TTL_HARD_MAX_SECONDS}.`,
10
31
  default: 300,
@@ -33,10 +54,6 @@ export const config = createConfig({
33
54
  desc: 'Maximum time, in milliseconds, a runners rate-limit storage check may wait before the request fails closed.',
34
55
  default: 250,
35
56
  }),
36
- RATE_LIMIT_IDENTIFIER_SECRET: str({
37
- desc: 'Optional secret used to HMAC identifiers before storing rate-limit counters. Leave it unset to derive a stable key from AUTH_JWT_SECRET.',
38
- default: undefined,
39
- }),
40
57
  RESERVATION_TTL_SECONDS: num({
41
58
  desc: 'Lifetime of a count-based runner reservation, in seconds. Expired reservations stop counting against queued demand.',
42
59
  default: 60,
@@ -110,7 +127,7 @@ export const config = createConfig({
110
127
  default: 10,
111
128
  }),
112
129
  PROVISIONED_RUNNER_COUNT_DIVERGENCE_TEMPLATE_KEY_LABEL_ENABLED: bool({
113
- desc: 'Whether runners_provisioned_runner_count_divergence includes template_key as a metric label. Use true or false. Defaults to false because template keys can create high-cardinality metric series. Set true only when template keys are bounded and stable.',
130
+ desc: 'Whether runners_provider_runner_count_divergence includes template_key as a metric label. Use true or false. Defaults to false because template keys can create high-cardinality metric series. Set true only when template keys are bounded and stable.',
114
131
  default: false,
115
132
  }),
116
133
  });
@@ -126,6 +143,30 @@ if (
126
143
  );
127
144
  }
128
145
 
146
+ for (const [name, value] of [
147
+ ['RUNNER_BOOTSTRAP_TOKEN_TTL_SECONDS', config.RUNNER_BOOTSTRAP_TOKEN_TTL_SECONDS],
148
+ ['RUNNER_CONTROL_SESSION_TTL_SECONDS', config.RUNNER_CONTROL_SESSION_TTL_SECONDS],
149
+ ['RUNNER_ACTIVATION_TOKEN_TTL_SECONDS', config.RUNNER_ACTIVATION_TOKEN_TTL_SECONDS],
150
+ ] as const) {
151
+ if (
152
+ !Number.isInteger(value) ||
153
+ value < 1 ||
154
+ value > RUNNER_CONTROL_PLANE_TOKEN_TTL_HARD_MAX_SECONDS
155
+ ) {
156
+ throw new Error(
157
+ `${name} (${value}) must be a whole number of seconds between 1 and ${RUNNER_CONTROL_PLANE_TOKEN_TTL_HARD_MAX_SECONDS}.`,
158
+ );
159
+ }
160
+ }
161
+
162
+ for (const [name, value] of [
163
+ ['RUNNER_ASSIGNMENT_POLL_MAX_WAIT_SECONDS', config.RUNNER_ASSIGNMENT_POLL_MAX_WAIT_SECONDS],
164
+ ['RUNNER_ASSIGNMENT_POLL_INTERVAL_MS', config.RUNNER_ASSIGNMENT_POLL_INTERVAL_MS],
165
+ ] as const) {
166
+ if (!Number.isInteger(value) || value < 0)
167
+ throw new Error(`${name} (${value}) must be a whole number >= 0.`);
168
+ }
169
+
129
170
  if (
130
171
  !Number.isInteger(config.REGISTRATION_TOKEN_BATCH_MAX) ||
131
172
  config.REGISTRATION_TOKEN_BATCH_MAX < 1 ||
@@ -0,0 +1,10 @@
1
+ import {assignCapacityBatch as assignCapacityBatchDb} from '#db/capacity-assignments.js';
2
+ import type {CapacityAssignment} from './entities/capacity-assignment.js';
3
+
4
+ export function assignCapacityBatch(params: {
5
+ provisionerId: string;
6
+ reservationId: string;
7
+ capacityIds: string[];
8
+ }): Promise<CapacityAssignment[]> {
9
+ return assignCapacityBatchDb(params);
10
+ }
@@ -1,12 +1,12 @@
1
1
  import {
2
- calculateProvisionedRunnerCountDivergences,
2
+ calculateRunnerInstanceCountDivergences,
3
3
  nextBackoffInterval,
4
4
  pollDemand,
5
5
  shouldReturn,
6
6
  } from '#core/demand.js';
7
7
 
8
8
  describe('shouldReturn', () => {
9
- const emptyResult = {stats: [], reservations: [], terminateProvisionedRunnerIds: []};
9
+ const emptyResult = {stats: [], reservations: [], terminateRunnerInstanceIds: []};
10
10
 
11
11
  it('returns true for observe-only requests', () => {
12
12
  const result = shouldReturn(emptyResult, 0, 1, false);
@@ -27,7 +27,7 @@ describe('shouldReturn', () => {
27
27
  reservations: [
28
28
  {reservationId: crypto.randomUUID(), labels: ['linux'], count: 1, expiresAt: new Date()},
29
29
  ],
30
- terminateProvisionedRunnerIds: [],
30
+ terminateRunnerInstanceIds: [],
31
31
  },
32
32
  1,
33
33
  1,
@@ -39,7 +39,7 @@ describe('shouldReturn', () => {
39
39
 
40
40
  it('returns true when terminate intents exist', () => {
41
41
  const result = shouldReturn(
42
- {...emptyResult, terminateProvisionedRunnerIds: ['provisioned-runner-1']},
42
+ {...emptyResult, terminateRunnerInstanceIds: ['provisioned-runner-1']},
43
43
  1,
44
44
  1,
45
45
  false,
@@ -76,7 +76,7 @@ describe('pollDemand', () => {
76
76
  signal: new AbortController().signal,
77
77
  });
78
78
 
79
- expect(result).toEqual({stats: [], reservations: [], terminateProvisionedRunnerIds: []});
79
+ expect(result).toEqual({stats: [], reservations: [], terminateRunnerInstanceIds: []});
80
80
  });
81
81
 
82
82
  it('returns immediately when terminate intents exist without reservation demand', async () => {
@@ -84,8 +84,8 @@ describe('pollDemand', () => {
84
84
  const pollDemandAndReserveTx = vi.fn().mockResolvedValue({stats: [], reservations: []});
85
85
  const listProvisionerTerminateIntentRowsTx = vi
86
86
  .fn()
87
- .mockResolvedValue([{provisionedRunnerId: 'provisioned-runner-1', reason: 'job-cancelled'}]);
88
- const listActiveProvisionedRunnerCountsByTemplateTx = vi.fn().mockResolvedValue([]);
87
+ .mockResolvedValue([{providerRunnerId: 'provisioned-runner-1', reason: 'job-cancelled'}]);
88
+ const listActiveRunnerInstanceCountsByTemplateTx = vi.fn().mockResolvedValue([]);
89
89
  vi.doMock('#db/db.js', () => ({
90
90
  db: () => ({transaction: (callback: (tx: unknown) => Promise<unknown>) => callback({})}),
91
91
  }));
@@ -93,8 +93,8 @@ describe('pollDemand', () => {
93
93
  deleteReservationsByIds: vi.fn(),
94
94
  pollDemandAndReserveTx,
95
95
  }));
96
- vi.doMock('#db/provisioned-runners.js', () => ({
97
- listActiveProvisionedRunnerCountsByTemplateTx,
96
+ vi.doMock('#db/runner-instances.js', () => ({
97
+ listActiveRunnerInstanceCountsByTemplateTx,
98
98
  listProvisionerTerminateIntentRowsTx,
99
99
  }));
100
100
 
@@ -117,14 +117,14 @@ describe('pollDemand', () => {
117
117
  expect(result).toEqual({
118
118
  stats: [],
119
119
  reservations: [],
120
- terminateProvisionedRunnerIds: ['provisioned-runner-1'],
120
+ terminateRunnerInstanceIds: ['provisioned-runner-1'],
121
121
  });
122
122
  expect(pollDemandAndReserveTx).toHaveBeenCalledOnce();
123
123
  expect(listProvisionerTerminateIntentRowsTx).toHaveBeenCalledOnce();
124
124
  } finally {
125
125
  vi.doUnmock('#db/db.js');
126
126
  vi.doUnmock('#db/reservations.js');
127
- vi.doUnmock('#db/provisioned-runners.js');
127
+ vi.doUnmock('#db/runner-instances.js');
128
128
  vi.resetModules();
129
129
  }
130
130
  });
@@ -137,7 +137,7 @@ describe('pollDemand', () => {
137
137
  abortController.abort();
138
138
  return [];
139
139
  });
140
- const listActiveProvisionedRunnerCountsByTemplateTx = vi.fn().mockResolvedValue([]);
140
+ const listActiveRunnerInstanceCountsByTemplateTx = vi.fn().mockResolvedValue([]);
141
141
  vi.doMock('#db/db.js', () => ({
142
142
  db: () => ({transaction: (callback: (tx: unknown) => Promise<unknown>) => callback({})}),
143
143
  }));
@@ -145,8 +145,8 @@ describe('pollDemand', () => {
145
145
  deleteReservationsByIds: vi.fn(),
146
146
  pollDemandAndReserveTx,
147
147
  }));
148
- vi.doMock('#db/provisioned-runners.js', () => ({
149
- listActiveProvisionedRunnerCountsByTemplateTx,
148
+ vi.doMock('#db/runner-instances.js', () => ({
149
+ listActiveRunnerInstanceCountsByTemplateTx,
150
150
  listProvisionerTerminateIntentRowsTx,
151
151
  }));
152
152
 
@@ -166,12 +166,12 @@ describe('pollDemand', () => {
166
166
  signal: abortController.signal,
167
167
  });
168
168
 
169
- expect(result).toEqual({stats: [], reservations: [], terminateProvisionedRunnerIds: []});
170
- expect(listActiveProvisionedRunnerCountsByTemplateTx).not.toHaveBeenCalled();
169
+ expect(result).toEqual({stats: [], reservations: [], terminateRunnerInstanceIds: []});
170
+ expect(listActiveRunnerInstanceCountsByTemplateTx).not.toHaveBeenCalled();
171
171
  } finally {
172
172
  vi.doUnmock('#db/db.js');
173
173
  vi.doUnmock('#db/reservations.js');
174
- vi.doUnmock('#db/provisioned-runners.js');
174
+ vi.doUnmock('#db/runner-instances.js');
175
175
  vi.resetModules();
176
176
  }
177
177
  });
@@ -182,7 +182,7 @@ describe('pollDemand', () => {
182
182
  const divergenceAdd = vi.fn();
183
183
  const pollDemandAndReserveTx = vi.fn().mockResolvedValue({stats: [], reservations: []});
184
184
  const listProvisionerTerminateIntentRowsTx = vi.fn().mockResolvedValue([]);
185
- const listActiveProvisionedRunnerCountsByTemplateTx = vi
185
+ const listActiveRunnerInstanceCountsByTemplateTx = vi
186
186
  .fn()
187
187
  .mockResolvedValue([{templateKey: 'linux', state: 'running', count: 2}]);
188
188
  vi.doMock('#db/db.js', () => ({
@@ -192,13 +192,13 @@ describe('pollDemand', () => {
192
192
  deleteReservationsByIds: vi.fn(),
193
193
  pollDemandAndReserveTx,
194
194
  }));
195
- vi.doMock('#db/provisioned-runners.js', () => ({
196
- listActiveProvisionedRunnerCountsByTemplateTx,
195
+ vi.doMock('#db/runner-instances.js', () => ({
196
+ listActiveRunnerInstanceCountsByTemplateTx,
197
197
  listProvisionerTerminateIntentRowsTx,
198
198
  }));
199
199
  vi.doMock('#metrics/instance.js', () => ({
200
- provisionedRunnerCountDivergenceCount: {add: divergenceAdd},
201
- provisionedRunnerTerminateIntentIssuedCount: {add: vi.fn()},
200
+ providerRunnerCountDivergenceCount: {add: divergenceAdd},
201
+ providerRunnerTerminateIntentIssuedCount: {add: vi.fn()},
202
202
  }));
203
203
 
204
204
  try {
@@ -217,7 +217,7 @@ describe('pollDemand', () => {
217
217
  signal: new AbortController().signal,
218
218
  });
219
219
 
220
- expect(result).toEqual({stats: [], reservations: [], terminateProvisionedRunnerIds: []});
220
+ expect(result).toEqual({stats: [], reservations: [], terminateRunnerInstanceIds: []});
221
221
  expect(divergenceAdd).toHaveBeenCalledWith(1, {
222
222
  template_key: 'linux',
223
223
  state: 'running',
@@ -227,16 +227,16 @@ describe('pollDemand', () => {
227
227
  vi.unstubAllEnvs();
228
228
  vi.doUnmock('#db/db.js');
229
229
  vi.doUnmock('#db/reservations.js');
230
- vi.doUnmock('#db/provisioned-runners.js');
230
+ vi.doUnmock('#db/runner-instances.js');
231
231
  vi.doUnmock('#metrics/instance.js');
232
232
  vi.resetModules();
233
233
  }
234
234
  });
235
235
  });
236
236
 
237
- describe('calculateProvisionedRunnerCountDivergences', () => {
237
+ describe('calculateRunnerInstanceCountDivergences', () => {
238
238
  it('returns no divergences when advertised and backend counts match', () => {
239
- const result = calculateProvisionedRunnerCountDivergences({
239
+ const result = calculateRunnerInstanceCountDivergences({
240
240
  advertisedTemplates: [template('linux', 1, 2)],
241
241
  backendCounts: [
242
242
  {templateKey: 'linux', state: 'starting', count: 1},
@@ -248,7 +248,7 @@ describe('calculateProvisionedRunnerCountDivergences', () => {
248
248
  });
249
249
 
250
250
  it('detects backend-higher and advertised-higher counts', () => {
251
- const result = calculateProvisionedRunnerCountDivergences({
251
+ const result = calculateRunnerInstanceCountDivergences({
252
252
  advertisedTemplates: [template('linux', 1, 5)],
253
253
  backendCounts: [
254
254
  {templateKey: 'linux', state: 'starting', count: 3},
@@ -263,7 +263,7 @@ describe('calculateProvisionedRunnerCountDivergences', () => {
263
263
  });
264
264
 
265
265
  it('aggregates duplicate advertised template keys before comparing', () => {
266
- const result = calculateProvisionedRunnerCountDivergences({
266
+ const result = calculateRunnerInstanceCountDivergences({
267
267
  advertisedTemplates: [template('linux', 1, 1), template('linux', 2, 3)],
268
268
  backendCounts: [
269
269
  {templateKey: 'linux', state: 'starting', count: 3},
@@ -275,7 +275,7 @@ describe('calculateProvisionedRunnerCountDivergences', () => {
275
275
  });
276
276
 
277
277
  it('detects backend-only template keys as backend-higher', () => {
278
- const result = calculateProvisionedRunnerCountDivergences({
278
+ const result = calculateRunnerInstanceCountDivergences({
279
279
  advertisedTemplates: [template('linux', 0, 0)],
280
280
  backendCounts: [{templateKey: 'gpu', state: 'running', count: 2}],
281
281
  });
@@ -2,12 +2,6 @@ import {setTimeout as sleep} from 'node:timers/promises';
2
2
  import {logger} from '@shipfox/node-opentelemetry';
3
3
  import {config} from '#config.js';
4
4
  import {db} from '#db/db.js';
5
- import {
6
- type ActiveProvisionedRunnerTemplateCount,
7
- listActiveProvisionedRunnerCountsByTemplateTx,
8
- listProvisionerTerminateIntentRowsTx,
9
- type ProvisionedRunnerTerminateIntent,
10
- } from '#db/provisioned-runners.js';
11
5
  import {
12
6
  type DemandStat,
13
7
  deleteReservationsByIds,
@@ -16,8 +10,14 @@ import {
16
10
  type ReservationTemplate,
17
11
  } from '#db/reservations.js';
18
12
  import {
19
- provisionedRunnerCountDivergenceCount,
20
- provisionedRunnerTerminateIntentIssuedCount,
13
+ type ActiveRunnerInstanceTemplateCount,
14
+ listActiveRunnerInstanceCountsByTemplateTx,
15
+ listProvisionerTerminateIntentRowsTx,
16
+ type RunnerInstanceTerminateIntent,
17
+ } from '#db/runner-instances.js';
18
+ import {
19
+ providerRunnerCountDivergenceCount,
20
+ providerRunnerTerminateIntentIssuedCount,
21
21
  } from '#metrics/instance.js';
22
22
 
23
23
  export interface PollDemandParams {
@@ -34,10 +34,10 @@ export interface PollDemandParams {
34
34
  export interface PollDemandResult {
35
35
  stats: DemandStat[];
36
36
  reservations: ReservationGrant[];
37
- terminateProvisionedRunnerIds: string[];
37
+ terminateRunnerInstanceIds: string[];
38
38
  }
39
39
 
40
- export interface ProvisionedRunnerCountDivergence {
40
+ export interface RunnerInstanceCountDivergence {
41
41
  templateKey: string;
42
42
  state: 'starting' | 'running';
43
43
  direction: 'backend-higher' | 'advertised-higher';
@@ -46,8 +46,8 @@ export interface ProvisionedRunnerCountDivergence {
46
46
 
47
47
  interface PollDemandSnapshot {
48
48
  result: PollDemandResult;
49
- divergences: ProvisionedRunnerCountDivergence[];
50
- terminateIntents: ProvisionedRunnerTerminateIntent[];
49
+ divergences: RunnerInstanceCountDivergence[];
50
+ terminateIntents: RunnerInstanceTerminateIntent[];
51
51
  }
52
52
 
53
53
  export async function pollDemand(params: PollDemandParams): Promise<PollDemandResult> {
@@ -62,7 +62,7 @@ export async function pollDemand(params: PollDemandParams): Promise<PollDemandRe
62
62
  );
63
63
  let interval = config.RESERVATION_POLL_INTERVAL_MS;
64
64
  let lastSnapshot: PollDemandSnapshot = {
65
- result: {stats: [], reservations: [], terminateProvisionedRunnerIds: []},
65
+ result: {stats: [], reservations: [], terminateRunnerInstanceIds: []},
66
66
  divergences: [],
67
67
  terminateIntents: [],
68
68
  };
@@ -87,7 +87,7 @@ export async function pollDemand(params: PollDemandParams): Promise<PollDemandRe
87
87
  });
88
88
  const result: PollDemandResult = {
89
89
  ...demand,
90
- terminateProvisionedRunnerIds: terminateIntents.map((intent) => intent.provisionedRunnerId),
90
+ terminateRunnerInstanceIds: terminateIntents.map((intent) => intent.providerRunnerId),
91
91
  };
92
92
 
93
93
  if (!shouldReturn(result, params.maxReservations, totalCapacity, deadlinePassed)) {
@@ -97,9 +97,9 @@ export async function pollDemand(params: PollDemandParams): Promise<PollDemandRe
97
97
  return {
98
98
  result,
99
99
  terminateIntents,
100
- divergences: calculateProvisionedRunnerCountDivergences({
100
+ divergences: calculateRunnerInstanceCountDivergences({
101
101
  advertisedTemplates: params.templates,
102
- backendCounts: await listActiveProvisionedRunnerCountsByTemplateTx(tx, {
102
+ backendCounts: await listActiveRunnerInstanceCountsByTemplateTx(tx, {
103
103
  workspaceId: params.workspaceId,
104
104
  provisionerId: params.provisionerId,
105
105
  }),
@@ -145,7 +145,7 @@ export function shouldReturn(
145
145
  maxReservations === 0 ||
146
146
  totalCapacity === 0 ||
147
147
  result.reservations.length > 0 ||
148
- result.terminateProvisionedRunnerIds.length > 0 ||
148
+ result.terminateRunnerInstanceIds.length > 0 ||
149
149
  deadlinePassed
150
150
  );
151
151
  }
@@ -158,10 +158,10 @@ export function withJitter(ms: number): number {
158
158
  return Math.random() * ms;
159
159
  }
160
160
 
161
- export function calculateProvisionedRunnerCountDivergences(params: {
161
+ export function calculateRunnerInstanceCountDivergences(params: {
162
162
  advertisedTemplates: ReservationTemplate[];
163
- backendCounts: ActiveProvisionedRunnerTemplateCount[];
164
- }): ProvisionedRunnerCountDivergence[] {
163
+ backendCounts: ActiveRunnerInstanceTemplateCount[];
164
+ }): RunnerInstanceCountDivergence[] {
165
165
  const advertisedCounts = new Map<string, number>();
166
166
  const backendCounts = new Map<string, number>();
167
167
 
@@ -212,10 +212,10 @@ function recordPollDemandMetrics(params: PollDemandParams, snapshot: PollDemandS
212
212
  ? {template_key: divergence.templateKey}
213
213
  : {}),
214
214
  };
215
- provisionedRunnerCountDivergenceCount.add(divergence.delta, attributes);
215
+ providerRunnerCountDivergenceCount.add(divergence.delta, attributes);
216
216
  }
217
217
  for (const intent of snapshot.terminateIntents) {
218
- provisionedRunnerTerminateIntentIssuedCount.add(1, {
218
+ providerRunnerTerminateIntentIssuedCount.add(1, {
219
219
  surface: 'poll-demand',
220
220
  reason: intent.reason,
221
221
  });
@@ -0,0 +1,8 @@
1
+ export interface CapacityAssignment {
2
+ id: string;
3
+ capacityId: string;
4
+ reservationId: string;
5
+ workspaceId: string;
6
+ provisionerId: string;
7
+ createdAt: Date;
8
+ }
@@ -3,7 +3,7 @@ export interface EphemeralRegistrationToken {
3
3
  workspaceId: string;
4
4
  provisionerId: string;
5
5
  reservationId: string | null;
6
- provisionedRunnerId: string;
6
+ providerRunnerId: string;
7
7
  hashedToken: string;
8
8
  prefix: string;
9
9
  expiresAt: Date;
@@ -0,0 +1,12 @@
1
+ export interface ProvisionerCapabilitySnapshot {
2
+ id: string;
3
+ workspaceId: string;
4
+ provisionerId: string;
5
+ templateKey: string;
6
+ labels: string[];
7
+ availableSlots: number;
8
+ starting: number;
9
+ running: number;
10
+ advertisedAt: Date;
11
+ createdAt: Date;
12
+ }
@@ -1,6 +1,8 @@
1
- export interface ProvisionerToken {
1
+ export type ProvisionerScope = 'installation' | 'workspace';
2
+
3
+ export interface ProvisionerTokenBase {
2
4
  id: string;
3
- workspaceId: string;
5
+ scope: ProvisionerScope;
4
6
  hashedToken: string;
5
7
  prefix: string;
6
8
  name: string | null;
@@ -13,4 +15,8 @@ export interface ProvisionerToken {
13
15
  updatedAt: Date;
14
16
  }
15
17
 
18
+ export type ProvisionerToken =
19
+ | (ProvisionerTokenBase & {scope: 'installation'; workspaceId: null})
20
+ | (ProvisionerTokenBase & {scope: 'workspace'; workspaceId: string});
21
+
16
22
  export type ActiveProvisionerToken = ProvisionerToken & {lastSeenAt: Date};
@@ -1,4 +1,4 @@
1
- export type ProvisionedRunnerState =
1
+ export type RunnerInstanceState =
2
2
  | 'starting'
3
3
  | 'running'
4
4
  | 'stopping'
@@ -6,15 +6,15 @@ export type ProvisionedRunnerState =
6
6
  | 'failed'
7
7
  | 'terminated';
8
8
 
9
- export interface ProvisionedRunner {
9
+ export interface RunnerInstance {
10
10
  id: string;
11
- workspaceId: string;
11
+ workspaceId: string | null;
12
12
  provisionerId: string;
13
- provisionedRunnerId: string;
13
+ providerRunnerId: string;
14
14
  reservationId: string | null;
15
15
  templateKey: string | null;
16
16
  labels: string[];
17
- state: ProvisionedRunnerState;
17
+ state: RunnerInstanceState;
18
18
  reason: string | null;
19
19
  runnerSessionId: string | null;
20
20
  providerKind: string | null;
@@ -5,14 +5,16 @@ export interface RunnerSession {
5
5
  workspaceId: string;
6
6
  scope: 'workspace';
7
7
  registrationTokenId: string;
8
- registrationTokenKind: 'manual' | 'ephemeral';
8
+ registrationTokenKind: 'manual' | 'ephemeral' | 'activation';
9
+ runnerInstanceId: string | null;
9
10
  provisionerId: string | null;
10
- provisionedRunnerId: string | null;
11
+ providerRunnerId: string | null;
11
12
  labels: string[];
12
13
  toolCapabilities: RunnerToolCapabilitiesDto | null;
13
14
  toolCapabilitiesReportedAt: Date | null;
14
15
  maxClaims: number | null;
15
16
  claimsUsed: number;
17
+ revokedAt: Date | null;
16
18
  createdAt: Date;
17
19
  updatedAt: Date;
18
20
  }