@paperclipai/server 2026.817.0 → 2026.818.0-beta.1

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 (548) hide show
  1. package/dist/adapters/hermes-gateway-doc.d.ts +1 -1
  2. package/dist/adapters/hermes-gateway-doc.d.ts.map +1 -1
  3. package/dist/adapters/hermes-gateway-doc.js +1 -1
  4. package/dist/adapters/plugin-loader.d.ts.map +1 -1
  5. package/dist/adapters/plugin-loader.js +3 -2
  6. package/dist/adapters/plugin-loader.js.map +1 -1
  7. package/dist/agent-auth-jwt.d.ts.map +1 -1
  8. package/dist/agent-auth-jwt.js +8 -2
  9. package/dist/agent-auth-jwt.js.map +1 -1
  10. package/dist/app.d.ts +5 -1
  11. package/dist/app.d.ts.map +1 -1
  12. package/dist/app.js +202 -15
  13. package/dist/app.js.map +1 -1
  14. package/dist/built-ins/agents/summarizer/AGENTS.md +2 -2
  15. package/dist/built-ins/agents/summarizer/routines/refresh-stale-summaries.md +1 -0
  16. package/dist/db-errors.d.ts +9 -0
  17. package/dist/db-errors.d.ts.map +1 -1
  18. package/dist/db-errors.js +19 -0
  19. package/dist/db-errors.js.map +1 -1
  20. package/dist/errors.d.ts +1 -1
  21. package/dist/errors.d.ts.map +1 -1
  22. package/dist/errors.js +2 -2
  23. package/dist/errors.js.map +1 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +162 -38
  26. package/dist/index.js.map +1 -1
  27. package/dist/lib/request-promise-memo.d.ts +6 -0
  28. package/dist/lib/request-promise-memo.d.ts.map +1 -0
  29. package/dist/lib/request-promise-memo.js +25 -0
  30. package/dist/lib/request-promise-memo.js.map +1 -0
  31. package/dist/lib/request-promise-memo.test.d.ts +2 -0
  32. package/dist/lib/request-promise-memo.test.d.ts.map +1 -0
  33. package/dist/lib/request-promise-memo.test.js +74 -0
  34. package/dist/lib/request-promise-memo.test.js.map +1 -0
  35. package/dist/middleware/auth.d.ts +13 -1
  36. package/dist/middleware/auth.d.ts.map +1 -1
  37. package/dist/middleware/auth.js +92 -41
  38. package/dist/middleware/auth.js.map +1 -1
  39. package/dist/middleware/cloud-tenant-actor.test.js +26 -1
  40. package/dist/middleware/cloud-tenant-actor.test.js.map +1 -1
  41. package/dist/middleware/error-handler.d.ts.map +1 -1
  42. package/dist/middleware/error-handler.js +11 -2
  43. package/dist/middleware/error-handler.js.map +1 -1
  44. package/dist/middleware/logger.d.ts.map +1 -1
  45. package/dist/middleware/logger.js +7 -33
  46. package/dist/middleware/logger.js.map +1 -1
  47. package/dist/middleware/private-hostname-guard.d.ts.map +1 -1
  48. package/dist/middleware/private-hostname-guard.js +11 -6
  49. package/dist/middleware/private-hostname-guard.js.map +1 -1
  50. package/dist/middleware/private-json-etag.d.ts +3 -0
  51. package/dist/middleware/private-json-etag.d.ts.map +1 -0
  52. package/dist/middleware/private-json-etag.js +37 -0
  53. package/dist/middleware/private-json-etag.js.map +1 -0
  54. package/dist/middleware/redact-sensitive.d.ts.map +1 -1
  55. package/dist/middleware/redact-sensitive.js +11 -0
  56. package/dist/middleware/redact-sensitive.js.map +1 -1
  57. package/dist/realtime/live-events-ws.d.ts +12 -0
  58. package/dist/realtime/live-events-ws.d.ts.map +1 -1
  59. package/dist/realtime/live-events-ws.js +20 -0
  60. package/dist/realtime/live-events-ws.js.map +1 -1
  61. package/dist/redaction.js +1 -1
  62. package/dist/redaction.js.map +1 -1
  63. package/dist/routes/access.d.ts +2 -0
  64. package/dist/routes/access.d.ts.map +1 -1
  65. package/dist/routes/access.js +21 -10
  66. package/dist/routes/access.js.map +1 -1
  67. package/dist/routes/agents.d.ts +42 -0
  68. package/dist/routes/agents.d.ts.map +1 -1
  69. package/dist/routes/agents.js +875 -8
  70. package/dist/routes/agents.js.map +1 -1
  71. package/dist/routes/companies.d.ts +5 -1
  72. package/dist/routes/companies.d.ts.map +1 -1
  73. package/dist/routes/companies.js +467 -30
  74. package/dist/routes/companies.js.map +1 -1
  75. package/dist/routes/environments.d.ts +12 -3
  76. package/dist/routes/environments.d.ts.map +1 -1
  77. package/dist/routes/environments.js +139 -23
  78. package/dist/routes/environments.js.map +1 -1
  79. package/dist/routes/execution-workspaces.d.ts.map +1 -1
  80. package/dist/routes/execution-workspaces.js +240 -70
  81. package/dist/routes/execution-workspaces.js.map +1 -1
  82. package/dist/routes/file-resources.d.ts +14 -1
  83. package/dist/routes/file-resources.d.ts.map +1 -1
  84. package/dist/routes/file-resources.js +182 -3
  85. package/dist/routes/file-resources.js.map +1 -1
  86. package/dist/routes/index.d.ts +2 -1
  87. package/dist/routes/index.d.ts.map +1 -1
  88. package/dist/routes/index.js +2 -1
  89. package/dist/routes/index.js.map +1 -1
  90. package/dist/routes/instance-settings.d.ts.map +1 -1
  91. package/dist/routes/instance-settings.js +20 -1
  92. package/dist/routes/instance-settings.js.map +1 -1
  93. package/dist/routes/issues.d.ts.map +1 -1
  94. package/dist/routes/issues.js +750 -235
  95. package/dist/routes/issues.js.map +1 -1
  96. package/dist/routes/onboarding-seed.d.ts +27 -0
  97. package/dist/routes/onboarding-seed.d.ts.map +1 -0
  98. package/dist/routes/onboarding-seed.js +56 -0
  99. package/dist/routes/onboarding-seed.js.map +1 -0
  100. package/dist/routes/openapi.d.ts.map +1 -1
  101. package/dist/routes/openapi.js +316 -2
  102. package/dist/routes/openapi.js.map +1 -1
  103. package/dist/routes/secrets.d.ts.map +1 -1
  104. package/dist/routes/secrets.js +11 -1
  105. package/dist/routes/secrets.js.map +1 -1
  106. package/dist/routes/setup-token-route.test.d.ts +2 -0
  107. package/dist/routes/setup-token-route.test.d.ts.map +1 -0
  108. package/dist/routes/setup-token-route.test.js +896 -0
  109. package/dist/routes/setup-token-route.test.js.map +1 -0
  110. package/dist/routes/tool-access.d.ts.map +1 -1
  111. package/dist/routes/tool-access.js +87 -52
  112. package/dist/routes/tool-access.js.map +1 -1
  113. package/dist/routes/workspace-runtime-service-authz.d.ts +11 -1
  114. package/dist/routes/workspace-runtime-service-authz.d.ts.map +1 -1
  115. package/dist/routes/workspace-runtime-service-authz.js +18 -16
  116. package/dist/routes/workspace-runtime-service-authz.js.map +1 -1
  117. package/dist/services/access.d.ts.map +1 -1
  118. package/dist/services/activity.d.ts +1 -1
  119. package/dist/services/agents.d.ts +21 -0
  120. package/dist/services/agents.d.ts.map +1 -1
  121. package/dist/services/agents.js +121 -1
  122. package/dist/services/agents.js.map +1 -1
  123. package/dist/services/attention-resolver-audience.test.d.ts +2 -0
  124. package/dist/services/attention-resolver-audience.test.d.ts.map +1 -0
  125. package/dist/services/attention-resolver-audience.test.js +81 -0
  126. package/dist/services/attention-resolver-audience.test.js.map +1 -0
  127. package/dist/services/attention.d.ts +20 -1
  128. package/dist/services/attention.d.ts.map +1 -1
  129. package/dist/services/attention.js +45 -1
  130. package/dist/services/attention.js.map +1 -1
  131. package/dist/services/authorization.d.ts +2 -2
  132. package/dist/services/authorization.d.ts.map +1 -1
  133. package/dist/services/authorization.js +89 -46
  134. package/dist/services/authorization.js.map +1 -1
  135. package/dist/services/board-auth.d.ts.map +1 -1
  136. package/dist/services/board-auth.js +40 -1
  137. package/dist/services/board-auth.js.map +1 -1
  138. package/dist/services/board-auth.test.d.ts +2 -0
  139. package/dist/services/board-auth.test.d.ts.map +1 -0
  140. package/dist/services/board-auth.test.js +34 -0
  141. package/dist/services/board-auth.test.js.map +1 -0
  142. package/dist/services/built-in-agents.d.ts.map +1 -1
  143. package/dist/services/built-in-agents.js +20 -4
  144. package/dist/services/built-in-agents.js.map +1 -1
  145. package/dist/services/bundled-plugins.d.ts +11 -1
  146. package/dist/services/bundled-plugins.d.ts.map +1 -1
  147. package/dist/services/bundled-plugins.js +46 -1
  148. package/dist/services/bundled-plugins.js.map +1 -1
  149. package/dist/services/codex-device-login-reaper.d.ts +61 -0
  150. package/dist/services/codex-device-login-reaper.d.ts.map +1 -0
  151. package/dist/services/codex-device-login-reaper.js +219 -0
  152. package/dist/services/codex-device-login-reaper.js.map +1 -0
  153. package/dist/services/codex-device-login-service.d.ts +355 -0
  154. package/dist/services/codex-device-login-service.d.ts.map +1 -0
  155. package/dist/services/codex-device-login-service.js +775 -0
  156. package/dist/services/codex-device-login-service.js.map +1 -0
  157. package/dist/services/companies.d.ts.map +1 -1
  158. package/dist/services/companies.js +7 -0
  159. package/dist/services/companies.js.map +1 -1
  160. package/dist/services/company-export-readme.js +1 -1
  161. package/dist/services/company-export-readme.js.map +1 -1
  162. package/dist/services/company-import-transfers.d.ts +55 -0
  163. package/dist/services/company-import-transfers.d.ts.map +1 -0
  164. package/dist/services/company-import-transfers.js +151 -0
  165. package/dist/services/company-import-transfers.js.map +1 -0
  166. package/dist/services/company-portability.d.ts.map +1 -1
  167. package/dist/services/company-portability.js +128 -3
  168. package/dist/services/company-portability.js.map +1 -1
  169. package/dist/services/company-transfer-runs.d.ts +136 -0
  170. package/dist/services/company-transfer-runs.d.ts.map +1 -0
  171. package/dist/services/company-transfer-runs.js +243 -0
  172. package/dist/services/company-transfer-runs.js.map +1 -0
  173. package/dist/services/cross-issue-influence-limit.d.ts +7 -1
  174. package/dist/services/cross-issue-influence-limit.d.ts.map +1 -1
  175. package/dist/services/cross-issue-influence-limit.js.map +1 -1
  176. package/dist/services/environment-config.d.ts +15 -0
  177. package/dist/services/environment-config.d.ts.map +1 -1
  178. package/dist/services/environment-config.js +56 -10
  179. package/dist/services/environment-config.js.map +1 -1
  180. package/dist/services/environment-execution-target.d.ts.map +1 -1
  181. package/dist/services/environment-execution-target.js +61 -11
  182. package/dist/services/environment-execution-target.js.map +1 -1
  183. package/dist/services/environment-run-orchestrator.d.ts +16 -1
  184. package/dist/services/environment-run-orchestrator.d.ts.map +1 -1
  185. package/dist/services/environment-run-orchestrator.js +1 -1
  186. package/dist/services/environment-run-orchestrator.js.map +1 -1
  187. package/dist/services/environment-runtime.d.ts +178 -2
  188. package/dist/services/environment-runtime.d.ts.map +1 -1
  189. package/dist/services/environment-runtime.js +1035 -96
  190. package/dist/services/environment-runtime.js.map +1 -1
  191. package/dist/services/environments.d.ts +75 -0
  192. package/dist/services/environments.d.ts.map +1 -1
  193. package/dist/services/environments.js +199 -8
  194. package/dist/services/environments.js.map +1 -1
  195. package/dist/services/execution-allowlist.d.ts +16 -4
  196. package/dist/services/execution-allowlist.d.ts.map +1 -1
  197. package/dist/services/execution-allowlist.js +35 -16
  198. package/dist/services/execution-allowlist.js.map +1 -1
  199. package/dist/services/execution-allowlist.test.js +33 -0
  200. package/dist/services/execution-allowlist.test.js.map +1 -1
  201. package/dist/services/execution-workspace-policy.d.ts +14 -1
  202. package/dist/services/execution-workspace-policy.d.ts.map +1 -1
  203. package/dist/services/execution-workspace-policy.js +29 -12
  204. package/dist/services/execution-workspace-policy.js.map +1 -1
  205. package/dist/services/execution-workspaces.d.ts +89 -0
  206. package/dist/services/execution-workspaces.d.ts.map +1 -1
  207. package/dist/services/execution-workspaces.js +997 -125
  208. package/dist/services/execution-workspaces.js.map +1 -1
  209. package/dist/services/heartbeat-run-summary.d.ts +1 -0
  210. package/dist/services/heartbeat-run-summary.d.ts.map +1 -1
  211. package/dist/services/heartbeat-run-summary.js +19 -3
  212. package/dist/services/heartbeat-run-summary.js.map +1 -1
  213. package/dist/services/heartbeat.d.ts +18 -2
  214. package/dist/services/heartbeat.d.ts.map +1 -1
  215. package/dist/services/heartbeat.js +369 -16
  216. package/dist/services/heartbeat.js.map +1 -1
  217. package/dist/services/import-write-types.d.ts +12 -0
  218. package/dist/services/import-write-types.d.ts.map +1 -1
  219. package/dist/services/index.d.ts +2 -0
  220. package/dist/services/index.d.ts.map +1 -1
  221. package/dist/services/index.js +2 -0
  222. package/dist/services/index.js.map +1 -1
  223. package/dist/services/instance-settings.d.ts +10 -1
  224. package/dist/services/instance-settings.d.ts.map +1 -1
  225. package/dist/services/instance-settings.js +16 -9
  226. package/dist/services/instance-settings.js.map +1 -1
  227. package/dist/services/issue-review-policy.d.ts +4 -0
  228. package/dist/services/issue-review-policy.d.ts.map +1 -1
  229. package/dist/services/issue-review-policy.js +18 -7
  230. package/dist/services/issue-review-policy.js.map +1 -1
  231. package/dist/services/issue-thread-interaction-resolution.d.ts +92 -0
  232. package/dist/services/issue-thread-interaction-resolution.d.ts.map +1 -0
  233. package/dist/services/issue-thread-interaction-resolution.js +198 -0
  234. package/dist/services/issue-thread-interaction-resolution.js.map +1 -0
  235. package/dist/services/issue-thread-interaction-resolution.test.d.ts +2 -0
  236. package/dist/services/issue-thread-interaction-resolution.test.d.ts.map +1 -0
  237. package/dist/services/issue-thread-interaction-resolution.test.js +152 -0
  238. package/dist/services/issue-thread-interaction-resolution.test.js.map +1 -0
  239. package/dist/services/issue-thread-interactions.d.ts +24 -4
  240. package/dist/services/issue-thread-interactions.d.ts.map +1 -1
  241. package/dist/services/issue-thread-interactions.js +360 -145
  242. package/dist/services/issue-thread-interactions.js.map +1 -1
  243. package/dist/services/issue-thread-interactions.test.js +18 -11
  244. package/dist/services/issue-thread-interactions.test.js.map +1 -1
  245. package/dist/services/issues.d.ts +3 -0
  246. package/dist/services/issues.d.ts.map +1 -1
  247. package/dist/services/issues.js +157 -33
  248. package/dist/services/issues.js.map +1 -1
  249. package/dist/services/local-service-supervisor.d.ts +2 -0
  250. package/dist/services/local-service-supervisor.d.ts.map +1 -1
  251. package/dist/services/local-service-supervisor.js +53 -3
  252. package/dist/services/local-service-supervisor.js.map +1 -1
  253. package/dist/services/managed-environments.d.ts +4 -1
  254. package/dist/services/managed-environments.d.ts.map +1 -1
  255. package/dist/services/managed-environments.js +86 -2
  256. package/dist/services/managed-environments.js.map +1 -1
  257. package/dist/services/managed-environments.test.js +164 -0
  258. package/dist/services/managed-environments.test.js.map +1 -1
  259. package/dist/services/onboarding-greeting.d.ts +7 -0
  260. package/dist/services/onboarding-greeting.d.ts.map +1 -0
  261. package/dist/services/onboarding-greeting.js +27 -0
  262. package/dist/services/onboarding-greeting.js.map +1 -0
  263. package/dist/services/onboarding-greeting.test.d.ts +2 -0
  264. package/dist/services/onboarding-greeting.test.d.ts.map +1 -0
  265. package/dist/services/onboarding-greeting.test.js +32 -0
  266. package/dist/services/onboarding-greeting.test.js.map +1 -0
  267. package/dist/services/onboarding-seed.d.ts +57 -0
  268. package/dist/services/onboarding-seed.d.ts.map +1 -0
  269. package/dist/services/onboarding-seed.js +344 -0
  270. package/dist/services/onboarding-seed.js.map +1 -0
  271. package/dist/services/plan-review-context.d.ts +9 -1
  272. package/dist/services/plan-review-context.d.ts.map +1 -1
  273. package/dist/services/plan-review-context.js +192 -0
  274. package/dist/services/plan-review-context.js.map +1 -1
  275. package/dist/services/plugin-environment-driver.d.ts +46 -0
  276. package/dist/services/plugin-environment-driver.d.ts.map +1 -1
  277. package/dist/services/plugin-environment-driver.js +50 -0
  278. package/dist/services/plugin-environment-driver.js.map +1 -1
  279. package/dist/services/plugin-host-services.d.ts +1 -0
  280. package/dist/services/plugin-host-services.d.ts.map +1 -1
  281. package/dist/services/plugin-host-services.js +51 -28
  282. package/dist/services/plugin-host-services.js.map +1 -1
  283. package/dist/services/plugin-loader.d.ts +10 -1
  284. package/dist/services/plugin-loader.d.ts.map +1 -1
  285. package/dist/services/plugin-loader.js +43 -2
  286. package/dist/services/plugin-loader.js.map +1 -1
  287. package/dist/services/plugin-worker-manager.d.ts +61 -0
  288. package/dist/services/plugin-worker-manager.d.ts.map +1 -1
  289. package/dist/services/plugin-worker-manager.js +248 -1
  290. package/dist/services/plugin-worker-manager.js.map +1 -1
  291. package/dist/services/productivity-review.d.ts.map +1 -1
  292. package/dist/services/productivity-review.js +5 -0
  293. package/dist/services/productivity-review.js.map +1 -1
  294. package/dist/services/recovery/service.d.ts.map +1 -1
  295. package/dist/services/recovery/service.js +5 -1
  296. package/dist/services/recovery/service.js.map +1 -1
  297. package/dist/services/recovery/successful-run-handoff.d.ts +16 -1
  298. package/dist/services/recovery/successful-run-handoff.d.ts.map +1 -1
  299. package/dist/services/recovery/successful-run-handoff.js +32 -0
  300. package/dist/services/recovery/successful-run-handoff.js.map +1 -1
  301. package/dist/services/recovery/successful-run-handoff.test.js +51 -1
  302. package/dist/services/recovery/successful-run-handoff.test.js.map +1 -1
  303. package/dist/services/routines.d.ts.map +1 -1
  304. package/dist/services/routines.js +48 -4
  305. package/dist/services/routines.js.map +1 -1
  306. package/dist/services/runtime-exposure/broker-client.d.ts +88 -0
  307. package/dist/services/runtime-exposure/broker-client.d.ts.map +1 -0
  308. package/dist/services/runtime-exposure/broker-client.js +217 -0
  309. package/dist/services/runtime-exposure/broker-client.js.map +1 -0
  310. package/dist/services/runtime-exposure/broker-client.test.d.ts +2 -0
  311. package/dist/services/runtime-exposure/broker-client.test.d.ts.map +1 -0
  312. package/dist/services/runtime-exposure/broker-client.test.js +185 -0
  313. package/dist/services/runtime-exposure/broker-client.test.js.map +1 -0
  314. package/dist/services/runtime-exposure/exposure-manager.d.ts +135 -0
  315. package/dist/services/runtime-exposure/exposure-manager.d.ts.map +1 -0
  316. package/dist/services/runtime-exposure/exposure-manager.js +247 -0
  317. package/dist/services/runtime-exposure/exposure-manager.js.map +1 -0
  318. package/dist/services/runtime-exposure/exposure-manager.test.d.ts +2 -0
  319. package/dist/services/runtime-exposure/exposure-manager.test.d.ts.map +1 -0
  320. package/dist/services/runtime-exposure/exposure-manager.test.js +384 -0
  321. package/dist/services/runtime-exposure/exposure-manager.test.js.map +1 -0
  322. package/dist/services/runtime-exposure/loopback-listener.d.ts +33 -0
  323. package/dist/services/runtime-exposure/loopback-listener.d.ts.map +1 -0
  324. package/dist/services/runtime-exposure/loopback-listener.js +146 -0
  325. package/dist/services/runtime-exposure/loopback-listener.js.map +1 -0
  326. package/dist/services/runtime-exposure/loopback-listener.test.d.ts +2 -0
  327. package/dist/services/runtime-exposure/loopback-listener.test.d.ts.map +1 -0
  328. package/dist/services/runtime-exposure/loopback-listener.test.js +116 -0
  329. package/dist/services/runtime-exposure/loopback-listener.test.js.map +1 -0
  330. package/dist/services/runtime-exposure/port-pair.d.ts +47 -0
  331. package/dist/services/runtime-exposure/port-pair.d.ts.map +1 -0
  332. package/dist/services/runtime-exposure/port-pair.js +57 -0
  333. package/dist/services/runtime-exposure/port-pair.js.map +1 -0
  334. package/dist/services/runtime-exposure/port-pair.test.d.ts +2 -0
  335. package/dist/services/runtime-exposure/port-pair.test.d.ts.map +1 -0
  336. package/dist/services/runtime-exposure/port-pair.test.js +92 -0
  337. package/dist/services/runtime-exposure/port-pair.test.js.map +1 -0
  338. package/dist/services/runtime-exposure/port-reservation.d.ts +211 -0
  339. package/dist/services/runtime-exposure/port-reservation.d.ts.map +1 -0
  340. package/dist/services/runtime-exposure/port-reservation.js +380 -0
  341. package/dist/services/runtime-exposure/port-reservation.js.map +1 -0
  342. package/dist/services/runtime-exposure/port-reservation.test.d.ts +2 -0
  343. package/dist/services/runtime-exposure/port-reservation.test.d.ts.map +1 -0
  344. package/dist/services/runtime-exposure/port-reservation.test.js +456 -0
  345. package/dist/services/runtime-exposure/port-reservation.test.js.map +1 -0
  346. package/dist/services/runtime-exposure/tailscale-hostname.d.ts +11 -0
  347. package/dist/services/runtime-exposure/tailscale-hostname.d.ts.map +1 -0
  348. package/dist/services/runtime-exposure/tailscale-hostname.js +36 -0
  349. package/dist/services/runtime-exposure/tailscale-hostname.js.map +1 -0
  350. package/dist/services/runtime-exposure/tailscale-hostname.test.d.ts +2 -0
  351. package/dist/services/runtime-exposure/tailscale-hostname.test.d.ts.map +1 -0
  352. package/dist/services/runtime-exposure/tailscale-hostname.test.js +14 -0
  353. package/dist/services/runtime-exposure/tailscale-hostname.test.js.map +1 -0
  354. package/dist/services/sandbox-orphan-cleanup-spool.d.ts +64 -0
  355. package/dist/services/sandbox-orphan-cleanup-spool.d.ts.map +1 -0
  356. package/dist/services/sandbox-orphan-cleanup-spool.js +134 -0
  357. package/dist/services/sandbox-orphan-cleanup-spool.js.map +1 -0
  358. package/dist/services/sandbox-provider-runtime.d.ts +15 -0
  359. package/dist/services/sandbox-provider-runtime.d.ts.map +1 -1
  360. package/dist/services/sandbox-provider-runtime.js +1 -0
  361. package/dist/services/sandbox-provider-runtime.js.map +1 -1
  362. package/dist/services/secrets.d.ts +103 -0
  363. package/dist/services/secrets.d.ts.map +1 -1
  364. package/dist/services/secrets.js +432 -10
  365. package/dist/services/secrets.js.map +1 -1
  366. package/dist/services/setup-token-session.d.ts +630 -0
  367. package/dist/services/setup-token-session.d.ts.map +1 -0
  368. package/dist/services/setup-token-session.js +1005 -0
  369. package/dist/services/setup-token-session.js.map +1 -0
  370. package/dist/services/setup-token-session.test.d.ts +2 -0
  371. package/dist/services/setup-token-session.test.d.ts.map +1 -0
  372. package/dist/services/setup-token-session.test.js +1143 -0
  373. package/dist/services/setup-token-session.test.js.map +1 -0
  374. package/dist/services/setup-token-transport-binding.d.ts +202 -0
  375. package/dist/services/setup-token-transport-binding.d.ts.map +1 -0
  376. package/dist/services/setup-token-transport-binding.js +386 -0
  377. package/dist/services/setup-token-transport-binding.js.map +1 -0
  378. package/dist/services/setup-token-transport-binding.test.d.ts +2 -0
  379. package/dist/services/setup-token-transport-binding.test.d.ts.map +1 -0
  380. package/dist/services/setup-token-transport-binding.test.js +761 -0
  381. package/dist/services/setup-token-transport-binding.test.js.map +1 -0
  382. package/dist/services/summary-slots.d.ts.map +1 -1
  383. package/dist/services/summary-slots.js +40 -6
  384. package/dist/services/summary-slots.js.map +1 -1
  385. package/dist/services/task-watchdogs.js +2 -2
  386. package/dist/services/task-watchdogs.js.map +1 -1
  387. package/dist/services/tool-access-policy.d.ts +1 -1
  388. package/dist/services/tool-access.d.ts.map +1 -1
  389. package/dist/services/tool-access.js +29 -11
  390. package/dist/services/tool-access.js.map +1 -1
  391. package/dist/services/tool-gateway.d.ts +1 -1
  392. package/dist/services/tool-gateway.d.ts.map +1 -1
  393. package/dist/services/tool-gateway.js +56 -5
  394. package/dist/services/tool-gateway.js.map +1 -1
  395. package/dist/services/workspace-file-resources.d.ts +10 -1
  396. package/dist/services/workspace-file-resources.d.ts.map +1 -1
  397. package/dist/services/workspace-file-resources.js +258 -6
  398. package/dist/services/workspace-file-resources.js.map +1 -1
  399. package/dist/services/workspace-git-operation-scheduler.d.ts +135 -0
  400. package/dist/services/workspace-git-operation-scheduler.d.ts.map +1 -0
  401. package/dist/services/workspace-git-operation-scheduler.js +655 -0
  402. package/dist/services/workspace-git-operation-scheduler.js.map +1 -0
  403. package/dist/services/workspace-git-operation-scheduler.test.d.ts +2 -0
  404. package/dist/services/workspace-git-operation-scheduler.test.d.ts.map +1 -0
  405. package/dist/services/workspace-git-operation-scheduler.test.js +367 -0
  406. package/dist/services/workspace-git-operation-scheduler.test.js.map +1 -0
  407. package/dist/services/workspace-operations.d.ts +60 -0
  408. package/dist/services/workspace-operations.d.ts.map +1 -1
  409. package/dist/services/workspace-operations.js +384 -19
  410. package/dist/services/workspace-operations.js.map +1 -1
  411. package/dist/services/workspace-runtime-exposure-backfill.test.d.ts +2 -0
  412. package/dist/services/workspace-runtime-exposure-backfill.test.d.ts.map +1 -0
  413. package/dist/services/workspace-runtime-exposure-backfill.test.js +149 -0
  414. package/dist/services/workspace-runtime-exposure-backfill.test.js.map +1 -0
  415. package/dist/services/workspace-runtime-exposure.test.d.ts +2 -0
  416. package/dist/services/workspace-runtime-exposure.test.d.ts.map +1 -0
  417. package/dist/services/workspace-runtime-exposure.test.js +517 -0
  418. package/dist/services/workspace-runtime-exposure.test.js.map +1 -0
  419. package/dist/services/workspace-runtime-leases.d.ts +90 -0
  420. package/dist/services/workspace-runtime-leases.d.ts.map +1 -0
  421. package/dist/services/workspace-runtime-leases.js +252 -0
  422. package/dist/services/workspace-runtime-leases.js.map +1 -0
  423. package/dist/services/workspace-runtime-read-model.d.ts +12 -0
  424. package/dist/services/workspace-runtime-read-model.d.ts.map +1 -1
  425. package/dist/services/workspace-runtime-read-model.test.js +3 -0
  426. package/dist/services/workspace-runtime-read-model.test.js.map +1 -1
  427. package/dist/services/workspace-runtime-ready-comment.test.js +1 -0
  428. package/dist/services/workspace-runtime-ready-comment.test.js.map +1 -1
  429. package/dist/services/workspace-runtime.d.ts +160 -2
  430. package/dist/services/workspace-runtime.d.ts.map +1 -1
  431. package/dist/services/workspace-runtime.js +1693 -141
  432. package/dist/services/workspace-runtime.js.map +1 -1
  433. package/dist/shutdown.d.ts +24 -0
  434. package/dist/shutdown.d.ts.map +1 -1
  435. package/dist/shutdown.js +37 -0
  436. package/dist/shutdown.js.map +1 -1
  437. package/dist/shutdown.test.js +113 -1
  438. package/dist/shutdown.test.js.map +1 -1
  439. package/dist/startup-banner.js +1 -1
  440. package/dist/startup-banner.js.map +1 -1
  441. package/dist/url-utils.d.ts +26 -0
  442. package/dist/url-utils.d.ts.map +1 -0
  443. package/dist/url-utils.js +59 -0
  444. package/dist/url-utils.js.map +1 -0
  445. package/dist/url-utils.test.d.ts +2 -0
  446. package/dist/url-utils.test.d.ts.map +1 -0
  447. package/dist/url-utils.test.js +55 -0
  448. package/dist/url-utils.test.js.map +1 -0
  449. package/dist/worktree-config.d.ts.map +1 -1
  450. package/dist/worktree-config.js +3 -17
  451. package/dist/worktree-config.js.map +1 -1
  452. package/package.json +20 -20
  453. package/skills/paperclip/SKILL.md +16 -11
  454. package/skills/paperclip/references/api-reference.md +8 -5
  455. package/skills/paperclip-board/SKILL.md +1 -1
  456. package/ui-dist/assets/{abnfDiagram-VRR7QNED-wvSnvD6-.js → abnfDiagram-N423BO3Z-BvgoV-u5.js} +1 -1
  457. package/ui-dist/assets/{arc-Bx0V1JsN.js → arc-BInnUBUU.js} +1 -1
  458. package/ui-dist/assets/architectureDiagram-T3A2C74G-Dg4MziOm.js +36 -0
  459. package/ui-dist/assets/{blockDiagram-677ZJIJ3-BROcLaUk.js → blockDiagram-VBNYF7ZC-D9kzAkLN.js} +1 -1
  460. package/ui-dist/assets/{c4Diagram-LMCZKHZV-D-V3kgju.js → c4Diagram-5PPSVZJV-BwzsgV_0.js} +1 -1
  461. package/ui-dist/assets/channel-qoSYbCn0.js +1 -0
  462. package/ui-dist/assets/{chunk-32BRIVSS-qillH3H6.js → chunk-2GRJ4B5K-D2EQ9vrl.js} +1 -1
  463. package/ui-dist/assets/{chunk-2Q5K7J3B-D19cVnii.js → chunk-2Q5K7J3B-DOA_8fSd.js} +1 -1
  464. package/ui-dist/assets/{chunk-EX3LRPZG-CLUswrZg.js → chunk-5RXB4S5H-CT5ukRiT.js} +1 -1
  465. package/ui-dist/assets/{chunk-5VM5RSS4-Cwlp02Lx.js → chunk-5VM5RSS4-D2gOlkyB.js} +1 -1
  466. package/ui-dist/assets/{chunk-MOJQB5TN-yKciyq6E.js → chunk-6Q2QTUOP-DUb6aG8c.js} +1 -1
  467. package/ui-dist/assets/{chunk-V7JOEXUC-DjJ75g0_.js → chunk-GF5L2VYU-BPabG3Cx.js} +1 -1
  468. package/ui-dist/assets/{chunk-JWPE2WC7-BjepyzEb.js → chunk-JWPE2WC7-scNfhlZz.js} +1 -1
  469. package/ui-dist/assets/{chunk-VR4S4FIN-CiEmy8-R.js → chunk-KBJHAD2P-BcRAzRpq.js} +1 -1
  470. package/ui-dist/assets/{chunk-RYQCIY6F-ed7mQM9j.js → chunk-RYQCIY6F-BiZ0-EGh.js} +1 -1
  471. package/ui-dist/assets/{chunk-XXDRQBXY-BiI83zoO.js → chunk-XXDRQBXY-lJULxFIE.js} +1 -1
  472. package/ui-dist/assets/classDiagram-JCYQIIEL-B24u1REs.js +1 -0
  473. package/ui-dist/assets/classDiagram-v2-OCEON4UE-B24u1REs.js +1 -0
  474. package/ui-dist/assets/{cose-bilkent-JH36ORCC-DIdQf5ta.js → cose-bilkent-JH36ORCC-Do8pe8JB.js} +1 -1
  475. package/ui-dist/assets/{cynefin-VYW2F7L2-B2m9xxh8.js → cynefin-VYW2F7L2-B34jJY1x.js} +1 -1
  476. package/ui-dist/assets/{cynefinDiagram-TSTJHNR4-CGVdB0kX.js → cynefinDiagram-MW4NZA55-DQ8QK8JK.js} +1 -1
  477. package/ui-dist/assets/cytoscape.esm-DShqj__B.js +321 -0
  478. package/ui-dist/assets/{dagre-VKFMJZFB-CskKiZwJ.js → dagre-VZM6K2ZE-B7lSKgxH.js} +1 -1
  479. package/ui-dist/assets/{diagram-OA4YK3LP-D2cn5eIN.js → diagram-7IWD3JNH-B3hLAFGE.js} +1 -1
  480. package/ui-dist/assets/{diagram-FQU43EPY-oa5Zu0XG.js → diagram-B4RE2ZJO-CH9Ro9e0.js} +1 -1
  481. package/ui-dist/assets/{diagram-NH7WQ7WH-fymti5Js.js → diagram-LBJQPF4R-DdPVMii7.js} +1 -1
  482. package/ui-dist/assets/{diagram-G47NLZAW-BWF2ZCsw.js → diagram-Q27KOJAE-f5VXswjc.js} +1 -1
  483. package/ui-dist/assets/diagram-UB23O5K3-DGqxixsR.js +41 -0
  484. package/ui-dist/assets/{ebnfDiagram-CCIWWBDH-CJ1d3D5q.js → ebnfDiagram-BXEA7PRR-C-1klg_w.js} +1 -1
  485. package/ui-dist/assets/{erDiagram-Q63AITRT-BJCPa7kK.js → erDiagram-JOGREHBK-Dt4qK4gv.js} +1 -1
  486. package/ui-dist/assets/{flowDiagram-23GEKE2U-BWjWuz6r.js → flowDiagram-UKHOOZJN-9ZlrTuET.js} +5 -5
  487. package/ui-dist/assets/{ganttDiagram-NO4QXBWP-Dv1KKjoM.js → ganttDiagram-PKOTCBZU-CE3lyvFq.js} +1 -1
  488. package/ui-dist/assets/{gitGraphDiagram-IHSO6WYX-9X7vgL0A.js → gitGraphDiagram-DS77QQ5N-HH2fSgad.js} +1 -1
  489. package/ui-dist/assets/{index-CpaK48ok.js → index-B61ORkIb.js} +1 -1
  490. package/ui-dist/assets/index-BHiUiToL.css +1 -0
  491. package/ui-dist/assets/{index-D2YCrA-D.js → index-BY5ITKmG.js} +1 -1
  492. package/ui-dist/assets/{index-9JMDmXc5.js → index-BbAhzCq8.js} +1 -1
  493. package/ui-dist/assets/{index-C5qHatpp.js → index-Bc9g6q63.js} +1 -1
  494. package/ui-dist/assets/{index-DuI6e5mP.js → index-Bf7tyGxE.js} +1 -1
  495. package/ui-dist/assets/{index-BahRsj0s.js → index-BvFx-4KW.js} +1 -1
  496. package/ui-dist/assets/{index-DKlsEDV7.js → index-C1mpWCcn.js} +1 -1
  497. package/ui-dist/assets/{index-DIXaXZrW.js → index-CHXG4GPL.js} +1 -1
  498. package/ui-dist/assets/{index-DcfO6NoY.js → index-CLu3Tfpv.js} +1 -1
  499. package/ui-dist/assets/{index-Cfz6P0Qq.js → index-CQhaM6qd.js} +1 -1
  500. package/ui-dist/assets/{index-D9d3sl6K.js → index-CVTL3aAL.js} +1 -1
  501. package/ui-dist/assets/{index-BexA3NAl.js → index-CcRTJ93J.js} +1 -1
  502. package/ui-dist/assets/{index-CnBrDwGT.js → index-Cm6iEYPt.js} +247 -223
  503. package/ui-dist/assets/{index-ByGcu-MB.js → index-DQIrrn2L.js} +1 -1
  504. package/ui-dist/assets/{index-DKEzHO7c.js → index-DU4U1fuv.js} +1 -1
  505. package/ui-dist/assets/{index-pqJO8FsV.js → index-DV2FOgyD.js} +1 -1
  506. package/ui-dist/assets/{index-tDuieU3u.js → index-DceuCrr8.js} +1 -1
  507. package/ui-dist/assets/{index-CjN2lm_w.js → index-DlVBBF8o.js} +1 -1
  508. package/ui-dist/assets/{index-0yJtUsFh.js → index-DsdVneqe.js} +1 -1
  509. package/ui-dist/assets/{index-C2a4_IKU.js → index-DvFUXI-Q.js} +1 -1
  510. package/ui-dist/assets/{index-BTMiDMYv.js → index-FHzrJ7iQ.js} +1 -1
  511. package/ui-dist/assets/{index-cUQXJtLK.js → index-diFs0CNC.js} +1 -1
  512. package/ui-dist/assets/{index-C96LHV1A.js → index-hkanj4t6.js} +1 -1
  513. package/ui-dist/assets/{index-rDI1Q4r9.js → index-yRJnh4vx.js} +1 -1
  514. package/ui-dist/assets/{infoDiagram-FWYZ7A6U-CHIhutSb.js → infoDiagram-6WML65LV-2jai2fw-.js} +1 -1
  515. package/ui-dist/assets/{ishikawaDiagram-FXEZZL3T-ChaD7-5_.js → ishikawaDiagram-WSZJBQD7-CUmGhmEb.js} +1 -1
  516. package/ui-dist/assets/{journeyDiagram-5HDEW3XC-M5T2sMgn.js → journeyDiagram-NVQOT4AX-CGQuPDO1.js} +1 -1
  517. package/ui-dist/assets/{kanban-definition-HUTT4EX6-B8H6R_Wc.js → kanban-definition-27J2QSJJ-zgEPcbHl.js} +1 -1
  518. package/ui-dist/assets/{linear-cpPKlVCq.js → linear-BVf5VtLS.js} +1 -1
  519. package/ui-dist/assets/mermaid.core-D2TFkGfI.js +308 -0
  520. package/ui-dist/assets/{mindmap-definition-LN4V7U3C-Bf6POzvm.js → mindmap-definition-FAOFIHXS-xoAQ0Lb_.js} +1 -1
  521. package/ui-dist/assets/{pegDiagram-2B236MQR-BJbGktAV.js → pegDiagram-VL7TDLO6-CBR1PWLr.js} +1 -1
  522. package/ui-dist/assets/{pieDiagram-ENE6RG2P-BmSN9Bio.js → pieDiagram-7S7Q4E2Y-BMPnzK_e.js} +1 -1
  523. package/ui-dist/assets/{quadrantDiagram-ABIIQ3AL-JUpqQCx_.js → quadrantDiagram-CIZ2JOQS-CPtVUPkR.js} +1 -1
  524. package/ui-dist/assets/{railroadDiagram-RFXS5EU6-B8k8T4-2.js → railroadDiagram-AXF67PYL-DC0lsZV1.js} +1 -1
  525. package/ui-dist/assets/{requirementDiagram-TGXJPOKE-b32heq7Q.js → requirementDiagram-LRYGKXZP-BF6k05SB.js} +1 -1
  526. package/ui-dist/assets/{sankeyDiagram-HTMAVEWB-DC3s-xgf.js → sankeyDiagram-W5VNT64P-CRN0ibiP.js} +1 -1
  527. package/ui-dist/assets/{sequenceDiagram-DBY2YBRQ-BsCFyv_E.js → sequenceDiagram-SI44F4Z6-CQtTiPWm.js} +1 -1
  528. package/ui-dist/assets/{sizeCapture-X5ZJPWSS-S7xeCud3.js → sizeCapture-X5ZJPWSS-BdjuGZd1.js} +1 -1
  529. package/ui-dist/assets/{stateDiagram-2N3HPSRC-58O3ofoS.js → stateDiagram-OKZ733FA-B99onxyh.js} +1 -1
  530. package/ui-dist/assets/stateDiagram-v2-UEYNNEHI-bzFlYBZ1.js +1 -0
  531. package/ui-dist/assets/{swimlanes-5IMT3BWC-DFCVG0iF.js → swimlanes-SLNWSIFB-BIByPbrL.js} +2 -2
  532. package/ui-dist/assets/swimlanesDiagram-ULZ7WXOC-DgdkBnuK.js +8 -0
  533. package/ui-dist/assets/{timeline-definition-FHXFAJF6-C0c0SkQu.js → timeline-definition-Z64GVDOM-I1NgOcn9.js} +1 -1
  534. package/ui-dist/assets/{vennDiagram-L72KCM5P-B1cEx8GQ.js → vennDiagram-T6HMQDX7-D6t2Njcl.js} +1 -1
  535. package/ui-dist/assets/{wardleyDiagram-EHGQE667-BQhDkOx9.js → wardleyDiagram-T6FBY63Y-BiYKm9gh.js} +1 -1
  536. package/ui-dist/assets/{xychartDiagram-FW5EYKEG-YSQp1N0i.js → xychartDiagram-ELKLHX3M-BhwXKWIa.js} +4 -4
  537. package/ui-dist/index.html +3 -3
  538. package/ui-dist/sw.js +8 -3
  539. package/ui-dist/assets/architectureDiagram-ZJ3FMSHR-BcJt8Ia1.js +0 -36
  540. package/ui-dist/assets/channel-ZRpjyNiZ.js +0 -1
  541. package/ui-dist/assets/classDiagram-OUVF2IWQ-CCzzzCgk.js +0 -1
  542. package/ui-dist/assets/classDiagram-v2-EOCWNBFH-CCzzzCgk.js +0 -1
  543. package/ui-dist/assets/cytoscape.esm-D8joxN9f.js +0 -321
  544. package/ui-dist/assets/diagram-WEI45ONY-M3WOC2tK.js +0 -41
  545. package/ui-dist/assets/index-BqfqfoQX.css +0 -1
  546. package/ui-dist/assets/mermaid.core-MCazc_od.js +0 -308
  547. package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-_VY5dpDG.js +0 -1
  548. package/ui-dist/assets/swimlanesDiagram-G3AALYLV-BJhUjfns.js +0 -8
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Who holds (or wants) a port pair. Every field is optional evidence — a
3
+ * conflict report is only as specific as the views that produced it — but
4
+ * `executionWorkspaceId` is the identity that governs adoption.
5
+ */
6
+ export interface ExposureOwnerIdentity {
7
+ runtimeServiceId: string | null;
8
+ executionWorkspaceId: string | null;
9
+ projectWorkspaceId: string | null;
10
+ issueId: string | null;
11
+ }
12
+ /** Where a reservation came from, ordered by strength of evidence below. */
13
+ export type ExposureReservationSource =
14
+ /** This process is running the runtime that owns the pair. */
15
+ "in_memory_runtime"
16
+ /** The broker reports a live Paperclip-owned Serve mapping on the port. */
17
+ | "broker_mapping"
18
+ /** A persisted row still claims an exposure that is not `removed`. */
19
+ | "persisted_exposure"
20
+ /** A stopped/removed row whose execution-workspace lease is still open. */
21
+ | "leased_workspace"
22
+ /** Quarantined after an ambiguous cleanup; never reusable by anyone. */
23
+ | "quarantine";
24
+ export interface ExposurePortReservation {
25
+ port: number;
26
+ source: ExposureReservationSource;
27
+ owner: ExposureOwnerIdentity;
28
+ }
29
+ export interface ExposureReservationLedger {
30
+ /** Every port currently spoken for, whoever holds it. */
31
+ reservedPorts: ReadonlySet<number>;
32
+ /** Strongest-evidence reservation per port. */
33
+ reservationByPort: ReadonlyMap<number, ExposurePortReservation>;
34
+ }
35
+ /**
36
+ * The subset of a `workspace_runtime_services` row this module reasons about.
37
+ * Deliberately structural rather than the Drizzle row type: startup
38
+ * reconciliation, allocation, and tests all project into it from different
39
+ * queries.
40
+ */
41
+ export interface PersistedExposureRowSnapshot {
42
+ id: string;
43
+ status: string;
44
+ executionWorkspaceId: string | null;
45
+ projectWorkspaceId: string | null;
46
+ issueId: string | null;
47
+ /** App port column; survives teardown and is the lease's durable claim. */
48
+ port: number | null;
49
+ exposure: {
50
+ state: string;
51
+ listeners: ReadonlyArray<{
52
+ targetPort: number;
53
+ }>;
54
+ } | null;
55
+ }
56
+ /** A runtime this process is currently running with an exposure attached. */
57
+ export interface InMemoryExposureSnapshot {
58
+ runtimeServiceId: string;
59
+ executionWorkspaceId: string | null;
60
+ projectWorkspaceId: string | null;
61
+ issueId: string | null;
62
+ ports: ReadonlyArray<number>;
63
+ }
64
+ /** One Paperclip-owned listener as reported by the broker's `list()`. */
65
+ export interface BrokerMappingSnapshot {
66
+ runtimeId: string;
67
+ port: number;
68
+ }
69
+ export interface BuildExposureReservationLedgerInput {
70
+ persistedRows?: Iterable<PersistedExposureRowSnapshot>;
71
+ inMemoryRuntimes?: Iterable<InMemoryExposureSnapshot>;
72
+ brokerMappings?: Iterable<BrokerMappingSnapshot>;
73
+ quarantinedPorts?: Iterable<number>;
74
+ /**
75
+ * Execution workspaces whose exclusive lease is still open. A row belonging
76
+ * to one of these reserves its pair regardless of process or exposure state;
77
+ * that is the whole fix for "stopped-but-leased pair reuse".
78
+ */
79
+ activeExecutionWorkspaceIds?: Iterable<string>;
80
+ /** In-process pair claims held by starts that have not bound a listener yet. */
81
+ inFlightClaimedPorts?: Iterable<number>;
82
+ }
83
+ /**
84
+ * Every port a row's pair covers.
85
+ *
86
+ * The union of the exposure's declared listeners and the pair derived from the
87
+ * `port` column matters: `deprovisionExposure` replaces the status with a fresh
88
+ * `removed` one whose `listeners` is `[]`, so a torn-down row would otherwise
89
+ * contribute nothing at all. The `port` column is what still names the pair the
90
+ * lease paid for.
91
+ */
92
+ export declare function collectRowExposurePorts(row: PersistedExposureRowSnapshot): Set<number>;
93
+ /**
94
+ * Merge every reservation view into one ledger. Later, weaker evidence never
95
+ * overwrites a stronger claim already recorded for the same port.
96
+ */
97
+ export declare function buildExposureReservationLedger(input: BuildExposureReservationLedgerInput): ExposureReservationLedger;
98
+ /**
99
+ * May `claimant` take over a port currently attributed to `holder`?
100
+ *
101
+ * The rule is deliberately narrow, because the failure this prevents is a
102
+ * managed start silently adopting another issue's live service and then
103
+ * generating security evidence attributed to the wrong workspace:
104
+ *
105
+ * - the same runtime service reclaiming its own port is fine (restart);
106
+ * - otherwise both sides must name the *same, non-null* execution workspace.
107
+ *
108
+ * An unknown identity on either side is never adopted. "We could not tell whose
109
+ * it is" is a reason to fail closed, not a reason to assume it is ours.
110
+ */
111
+ export declare function isExposureAdoptionPermitted(holder: ExposureOwnerIdentity | null, claimant: ExposureOwnerIdentity): boolean;
112
+ export type ExposurePortConflictCode = "quarantined_port" | "reserved_by_other_workspace" | "listener_owned_by_other_workspace" | "serve_mapping_owned_by_other_workspace";
113
+ export interface ExposurePortConflict {
114
+ code: ExposurePortConflictCode;
115
+ port: number;
116
+ claimant: ExposureOwnerIdentity;
117
+ holder: ExposureOwnerIdentity | null;
118
+ source: ExposureReservationSource | null;
119
+ }
120
+ export interface FindExposurePairConflictInput {
121
+ pair: {
122
+ appPort: number;
123
+ hmrPort: number;
124
+ };
125
+ claimant: ExposureOwnerIdentity;
126
+ ledger: ExposureReservationLedger;
127
+ /**
128
+ * Identity behind the process actually listening on each port, when one could
129
+ * be resolved. `null` for a port with a live listener whose owner is unknown —
130
+ * which is itself a conflict, since an unattributable listener must never be
131
+ * adopted.
132
+ */
133
+ listenerOwners?: ReadonlyMap<number, ExposureOwnerIdentity | null>;
134
+ /** Identity behind each live Serve mapping, keyed by port. */
135
+ serveMappingOwners?: ReadonlyMap<number, ExposureOwnerIdentity | null>;
136
+ }
137
+ /**
138
+ * Complete mediation for one candidate pair: the first conflict across the
139
+ * persisted ledger, the live listeners, and the Serve mappings — or null when
140
+ * all three agree the claimant may have it.
141
+ */
142
+ export declare function findExposurePairConflict(input: FindExposurePairConflictInput): ExposurePortConflict | null;
143
+ /**
144
+ * Operator-facing conflict text. Always names the port and the conflicting
145
+ * workspace/issue identity: a bare "port unavailable" is what made the original
146
+ * incident take a manual `tailscale serve status` read to attribute.
147
+ */
148
+ export declare function describeExposurePortConflict(conflict: ExposurePortConflict): string;
149
+ /** Thrown on the allocation/start path so the failure is terminal and attributed. */
150
+ export declare class ExposurePortOwnershipConflictError extends Error {
151
+ readonly conflict: ExposurePortConflict;
152
+ readonly code: "exposure_port_ownership_conflict";
153
+ constructor(conflict: ExposurePortConflict);
154
+ }
155
+ export interface ExposureReservationDrift {
156
+ /** The row Paperclip believes is stopped/removed. */
157
+ runtimeServiceId: string;
158
+ owner: ExposureOwnerIdentity;
159
+ port: number;
160
+ reason: "live_listener" | "serve_mapping";
161
+ /** Who actually holds it, when that could be attributed. */
162
+ conflictingOwner: ExposureOwnerIdentity | null;
163
+ }
164
+ export interface FindExposureReservationDriftInput {
165
+ persistedRows: Iterable<PersistedExposureRowSnapshot>;
166
+ /** Ports with a live loopback listener right now. */
167
+ livePorts?: ReadonlySet<number>;
168
+ listenerOwners?: ReadonlyMap<number, ExposureOwnerIdentity | null>;
169
+ brokerMappings?: Iterable<BrokerMappingSnapshot>;
170
+ }
171
+ /**
172
+ * Rows whose state says "nothing here" while the host says otherwise.
173
+ *
174
+ * Reconciliation calls this so a lane reported `stopped` with its exposure
175
+ * `removed` — but whose reserved ports are live, or mapped to some other
176
+ * runtime — becomes a visible, attributable finding instead of a pair that
177
+ * quietly returns to the free list. A port still held by the row's *own*
178
+ * runtime is not drift; that is just a lane the sweep has yet to adopt.
179
+ */
180
+ export declare function findExposureReservationDrift(input: FindExposureReservationDriftInput): ExposureReservationDrift[];
181
+ /** Human-readable drift line for reconciliation logs and operator evidence. */
182
+ export declare function describeExposureReservationDrift(entry: ExposureReservationDrift): string;
183
+ /**
184
+ * In-process, pair-atomic claims for starts that have not bound a listener yet.
185
+ *
186
+ * Two concurrent allocators see identical persisted state and identical probe
187
+ * results, so without a claim they both walk away with the lowest free pair.
188
+ * Claiming is all-or-nothing across the two ports: a half-claimed pair would
189
+ * let one start own the app port and another the HMR port, which is the
190
+ * orphaned-companion failure the pairing exists to prevent.
191
+ */
192
+ export declare class ExposurePortPairClaims {
193
+ private readonly ttlMs;
194
+ private readonly heldUntilByPort;
195
+ constructor(ttlMs?: number);
196
+ private isHeld;
197
+ /** Claim both ports, or neither. Returns false when either is already held. */
198
+ claim(pair: {
199
+ appPort: number;
200
+ hmrPort: number;
201
+ }, nowMs?: number): boolean;
202
+ /** Release on lease release/teardown, or when a start reaches a terminal state. */
203
+ release(pair: {
204
+ appPort: number;
205
+ hmrPort: number;
206
+ }): void;
207
+ /** Ports still claimed, for folding into an allocator's reserved set. */
208
+ activePorts(nowMs?: number): Set<number>;
209
+ clear(): void;
210
+ }
211
+ //# sourceMappingURL=port-reservation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port-reservation.d.ts","sourceRoot":"","sources":["../../../src/services/runtime-exposure/port-reservation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,380 @@
1
+ /**
2
+ * Central reservation + ownership mediation for `tailscale_https` app/HMR port
3
+ * pairs (PAP-17419, from the PAP-17251 finding).
4
+ *
5
+ * ## Why this module exists
6
+ *
7
+ * Before it, "is this pair free?" was answered by three unrelated views that
8
+ * never had to agree:
9
+ *
10
+ * 1. the allocator's liveness probe — is anything *listening* right now,
11
+ * 2. `collectReservedExposurePorts` — persisted rows, but only those whose
12
+ * `exposure.state` was not yet `removed`,
13
+ * 3. the broker's Serve mapping — consulted nowhere on the allocation path.
14
+ *
15
+ * A workspace can hold an exclusive lease on a pair while satisfying none of
16
+ * those: stop the backend and the listener is gone; tear the exposure down and
17
+ * the row goes `stopped` with `exposure.state = "removed"` **and an emptied
18
+ * `listeners` array**, so the row stops contributing anything to the reserved
19
+ * set even though its `port` column still names the pair the lease owns. That
20
+ * is exactly how the pair leased to workspace `b7ce28b4` (`42001/52001`) was
21
+ * handed to the unrelated workspace `PAP-16986-add-posthog-mcp`, while
22
+ * Paperclip went on reporting the leased lane `stopped` and its exposure
23
+ * `removed`.
24
+ *
25
+ * ## The mediation this module centralizes
26
+ *
27
+ * - **Reservation follows the lease, not the process.** An execution workspace
28
+ * whose lease is still open reserves its pair through stop, teardown, and
29
+ * `removed` — until the lease is explicitly released. {@link
30
+ * buildExposureReservationLedger} derives the pair from the row's `port`
31
+ * column precisely because teardown erases `exposure.listeners`.
32
+ * - **Complete mediation on allocation.** {@link findExposurePairConflict}
33
+ * checks the persisted ledger *and* the live listener owner *and* the Serve
34
+ * mapping owner. Any of the three disagreeing fails the allocation closed,
35
+ * naming the conflicting workspace/issue.
36
+ * - **No adoption across execution workspaces, ever.** {@link
37
+ * isExposureAdoptionPermitted} is the single predicate for "may this claimant
38
+ * take over that holder's port", and it answers no whenever the two execution
39
+ * workspace IDs are not the identical, non-null value.
40
+ * - **Drift is surfaced, not silently reused.** {@link
41
+ * findExposureReservationDrift} reports a `stopped`/`removed` row whose
42
+ * reserved ports are live or mapped by someone else, so reconciliation can
43
+ * report a false-`stopped` lane instead of recycling it.
44
+ *
45
+ * Pure functions and one in-process claim registry: no sockets, no DB, no
46
+ * broker. Every caller injects its own view, which is what makes all five
47
+ * PAP-17419 regression cases testable without touching host Serve state.
48
+ */
49
+ import { deriveViteHmrPort, isRuntimeExposureAppPort } from "@paperclipai/shared";
50
+ /**
51
+ * Precedence when several views claim one port. Strongest first: the report
52
+ * should name the most concrete evidence available, so an operator reading
53
+ * "held by the live Serve mapping for workspace X" is not told "reserved by a
54
+ * lease" when both are true.
55
+ */
56
+ const RESERVATION_SOURCE_RANK = {
57
+ quarantine: 0,
58
+ in_memory_runtime: 1,
59
+ broker_mapping: 2,
60
+ persisted_exposure: 3,
61
+ leased_workspace: 4,
62
+ };
63
+ function emptyIdentity() {
64
+ return {
65
+ runtimeServiceId: null,
66
+ executionWorkspaceId: null,
67
+ projectWorkspaceId: null,
68
+ issueId: null,
69
+ };
70
+ }
71
+ /**
72
+ * Every port a row's pair covers.
73
+ *
74
+ * The union of the exposure's declared listeners and the pair derived from the
75
+ * `port` column matters: `deprovisionExposure` replaces the status with a fresh
76
+ * `removed` one whose `listeners` is `[]`, so a torn-down row would otherwise
77
+ * contribute nothing at all. The `port` column is what still names the pair the
78
+ * lease paid for.
79
+ */
80
+ export function collectRowExposurePorts(row) {
81
+ const ports = new Set();
82
+ for (const listener of row.exposure?.listeners ?? []) {
83
+ if (Number.isInteger(listener.targetPort))
84
+ ports.add(listener.targetPort);
85
+ }
86
+ if (row.port !== null && isRuntimeExposureAppPort(row.port)) {
87
+ ports.add(row.port);
88
+ ports.add(deriveViteHmrPort(row.port));
89
+ }
90
+ return ports;
91
+ }
92
+ /** True when the row's own exposure state still claims the mapping. */
93
+ function rowClaimsLiveExposure(row) {
94
+ return Boolean(row.exposure) && row.exposure.state !== "removed";
95
+ }
96
+ function rowIdentity(row) {
97
+ return {
98
+ runtimeServiceId: row.id,
99
+ executionWorkspaceId: row.executionWorkspaceId,
100
+ projectWorkspaceId: row.projectWorkspaceId,
101
+ issueId: row.issueId,
102
+ };
103
+ }
104
+ /**
105
+ * Merge every reservation view into one ledger. Later, weaker evidence never
106
+ * overwrites a stronger claim already recorded for the same port.
107
+ */
108
+ export function buildExposureReservationLedger(input) {
109
+ const reservationByPort = new Map();
110
+ const record = (port, source, owner) => {
111
+ if (!Number.isInteger(port))
112
+ return;
113
+ const existing = reservationByPort.get(port);
114
+ if (existing && RESERVATION_SOURCE_RANK[existing.source] <= RESERVATION_SOURCE_RANK[source])
115
+ return;
116
+ reservationByPort.set(port, { port, source, owner });
117
+ };
118
+ const activeLeases = new Set(input.activeExecutionWorkspaceIds ?? []);
119
+ for (const port of input.quarantinedPorts ?? [])
120
+ record(port, "quarantine", emptyIdentity());
121
+ // An in-flight claim has no identity yet by construction — the claiming start
122
+ // has not persisted a row. It still must block a concurrent allocator.
123
+ for (const port of input.inFlightClaimedPorts ?? [])
124
+ record(port, "in_memory_runtime", emptyIdentity());
125
+ for (const runtime of input.inMemoryRuntimes ?? []) {
126
+ const owner = {
127
+ runtimeServiceId: runtime.runtimeServiceId,
128
+ executionWorkspaceId: runtime.executionWorkspaceId,
129
+ projectWorkspaceId: runtime.projectWorkspaceId,
130
+ issueId: runtime.issueId,
131
+ };
132
+ for (const port of runtime.ports)
133
+ record(port, "in_memory_runtime", owner);
134
+ }
135
+ // Broker mappings identify a runtime, not a workspace; resolve the workspace
136
+ // from the persisted rows when we can so a conflict can name it.
137
+ const rows = [...(input.persistedRows ?? [])];
138
+ const identityByRuntimeId = new Map(rows.map((row) => [row.id, rowIdentity(row)]));
139
+ for (const mapping of input.brokerMappings ?? []) {
140
+ record(mapping.port, "broker_mapping", identityByRuntimeId.get(mapping.runtimeId)
141
+ ?? { ...emptyIdentity(), runtimeServiceId: mapping.runtimeId });
142
+ }
143
+ for (const row of rows) {
144
+ const leaseOpen = Boolean(row.executionWorkspaceId) && activeLeases.has(row.executionWorkspaceId);
145
+ const claimsExposure = rowClaimsLiveExposure(row);
146
+ if (!leaseOpen && !claimsExposure)
147
+ continue;
148
+ const source = claimsExposure ? "persisted_exposure" : "leased_workspace";
149
+ for (const port of collectRowExposurePorts(row))
150
+ record(port, source, rowIdentity(row));
151
+ }
152
+ return { reservationByPort, reservedPorts: new Set(reservationByPort.keys()) };
153
+ }
154
+ /**
155
+ * May `claimant` take over a port currently attributed to `holder`?
156
+ *
157
+ * The rule is deliberately narrow, because the failure this prevents is a
158
+ * managed start silently adopting another issue's live service and then
159
+ * generating security evidence attributed to the wrong workspace:
160
+ *
161
+ * - the same runtime service reclaiming its own port is fine (restart);
162
+ * - otherwise both sides must name the *same, non-null* execution workspace.
163
+ *
164
+ * An unknown identity on either side is never adopted. "We could not tell whose
165
+ * it is" is a reason to fail closed, not a reason to assume it is ours.
166
+ */
167
+ export function isExposureAdoptionPermitted(holder, claimant) {
168
+ if (!holder)
169
+ return true;
170
+ if (holder.runtimeServiceId !== null
171
+ && claimant.runtimeServiceId !== null
172
+ && holder.runtimeServiceId === claimant.runtimeServiceId) {
173
+ return true;
174
+ }
175
+ if (holder.executionWorkspaceId === null || claimant.executionWorkspaceId === null)
176
+ return false;
177
+ return holder.executionWorkspaceId === claimant.executionWorkspaceId;
178
+ }
179
+ /**
180
+ * Complete mediation for one candidate pair: the first conflict across the
181
+ * persisted ledger, the live listeners, and the Serve mappings — or null when
182
+ * all three agree the claimant may have it.
183
+ */
184
+ export function findExposurePairConflict(input) {
185
+ const ports = [input.pair.appPort, input.pair.hmrPort];
186
+ for (const port of ports) {
187
+ const reservation = input.ledger.reservationByPort.get(port);
188
+ if (!reservation)
189
+ continue;
190
+ if (reservation.source === "quarantine") {
191
+ return { code: "quarantined_port", port, claimant: input.claimant, holder: null, source: "quarantine" };
192
+ }
193
+ if (!isExposureAdoptionPermitted(reservation.owner, input.claimant)) {
194
+ return {
195
+ code: "reserved_by_other_workspace",
196
+ port,
197
+ claimant: input.claimant,
198
+ holder: reservation.owner,
199
+ source: reservation.source,
200
+ };
201
+ }
202
+ }
203
+ // Presence in these maps means the host has something on the port. A `null`
204
+ // value is therefore NOT "no holder" — it is "a holder we could not name",
205
+ // which is the one case that must never be adopted. `isExposureAdoptionPermitted`
206
+ // is only consulted once we have an identity to compare.
207
+ for (const port of ports) {
208
+ if (!input.listenerOwners?.has(port))
209
+ continue;
210
+ const owner = input.listenerOwners.get(port) ?? null;
211
+ if (owner === null || !isExposureAdoptionPermitted(owner, input.claimant)) {
212
+ return {
213
+ code: "listener_owned_by_other_workspace",
214
+ port,
215
+ claimant: input.claimant,
216
+ holder: owner,
217
+ source: null,
218
+ };
219
+ }
220
+ }
221
+ for (const port of ports) {
222
+ if (!input.serveMappingOwners?.has(port))
223
+ continue;
224
+ const owner = input.serveMappingOwners.get(port) ?? null;
225
+ if (owner === null || !isExposureAdoptionPermitted(owner, input.claimant)) {
226
+ return {
227
+ code: "serve_mapping_owned_by_other_workspace",
228
+ port,
229
+ claimant: input.claimant,
230
+ holder: owner,
231
+ source: null,
232
+ };
233
+ }
234
+ }
235
+ return null;
236
+ }
237
+ function describeIdentity(identity) {
238
+ if (!identity)
239
+ return "an unidentified owner";
240
+ const parts = [];
241
+ if (identity.executionWorkspaceId)
242
+ parts.push(`execution workspace ${identity.executionWorkspaceId}`);
243
+ if (identity.issueId)
244
+ parts.push(`issue ${identity.issueId}`);
245
+ if (identity.runtimeServiceId)
246
+ parts.push(`runtime service ${identity.runtimeServiceId}`);
247
+ if (identity.projectWorkspaceId && parts.length === 0) {
248
+ parts.push(`project workspace ${identity.projectWorkspaceId}`);
249
+ }
250
+ return parts.length > 0 ? parts.join(", ") : "an unidentified owner";
251
+ }
252
+ const CONFLICT_REASONS = {
253
+ quarantined_port: "is quarantined after an ambiguous exposure cleanup and can never be reused",
254
+ reserved_by_other_workspace: "is reserved by",
255
+ listener_owned_by_other_workspace: "has a live loopback listener owned by",
256
+ serve_mapping_owned_by_other_workspace: "is published by a Tailscale Serve mapping owned by",
257
+ };
258
+ /**
259
+ * Operator-facing conflict text. Always names the port and the conflicting
260
+ * workspace/issue identity: a bare "port unavailable" is what made the original
261
+ * incident take a manual `tailscale serve status` read to attribute.
262
+ */
263
+ export function describeExposurePortConflict(conflict) {
264
+ const subject = `port ${conflict.port}`;
265
+ if (conflict.code === "quarantined_port") {
266
+ return `${subject} ${CONFLICT_REASONS.quarantined_port}`;
267
+ }
268
+ const suffix = conflict.source === "leased_workspace"
269
+ ? " (the lane is stopped, but its lease is still open)"
270
+ : "";
271
+ return `${subject} ${CONFLICT_REASONS[conflict.code]} ${describeIdentity(conflict.holder)}${suffix}`;
272
+ }
273
+ /** Thrown on the allocation/start path so the failure is terminal and attributed. */
274
+ export class ExposurePortOwnershipConflictError extends Error {
275
+ conflict;
276
+ code = "exposure_port_ownership_conflict";
277
+ constructor(conflict) {
278
+ super(`HTTPS exposure allocation denied: ${describeExposurePortConflict(conflict)}`);
279
+ this.conflict = conflict;
280
+ this.name = "ExposurePortOwnershipConflictError";
281
+ }
282
+ }
283
+ /**
284
+ * Rows whose state says "nothing here" while the host says otherwise.
285
+ *
286
+ * Reconciliation calls this so a lane reported `stopped` with its exposure
287
+ * `removed` — but whose reserved ports are live, or mapped to some other
288
+ * runtime — becomes a visible, attributable finding instead of a pair that
289
+ * quietly returns to the free list. A port still held by the row's *own*
290
+ * runtime is not drift; that is just a lane the sweep has yet to adopt.
291
+ */
292
+ export function findExposureReservationDrift(input) {
293
+ const rows = [...input.persistedRows];
294
+ const identityByRuntimeId = new Map(rows.map((row) => [row.id, rowIdentity(row)]));
295
+ const mappingOwnerByPort = new Map();
296
+ for (const mapping of input.brokerMappings ?? []) {
297
+ mappingOwnerByPort.set(mapping.port, identityByRuntimeId.get(mapping.runtimeId)
298
+ ?? { ...emptyIdentity(), runtimeServiceId: mapping.runtimeId });
299
+ }
300
+ const drift = [];
301
+ for (const row of rows) {
302
+ const dormant = row.status === "stopped" || row.status === "failed" || !rowClaimsLiveExposure(row);
303
+ if (!dormant)
304
+ continue;
305
+ const owner = rowIdentity(row);
306
+ for (const port of collectRowExposurePorts(row)) {
307
+ const mappingOwner = mappingOwnerByPort.get(port) ?? null;
308
+ if (mappingOwner && mappingOwner.runtimeServiceId !== row.id) {
309
+ drift.push({ runtimeServiceId: row.id, owner, port, reason: "serve_mapping", conflictingOwner: mappingOwner });
310
+ continue;
311
+ }
312
+ if (!input.livePorts?.has(port))
313
+ continue;
314
+ const listenerOwner = input.listenerOwners?.get(port) ?? null;
315
+ if (listenerOwner && listenerOwner.runtimeServiceId === row.id)
316
+ continue;
317
+ drift.push({ runtimeServiceId: row.id, owner, port, reason: "live_listener", conflictingOwner: listenerOwner });
318
+ }
319
+ }
320
+ return drift;
321
+ }
322
+ /** Human-readable drift line for reconciliation logs and operator evidence. */
323
+ export function describeExposureReservationDrift(entry) {
324
+ const held = entry.reason === "serve_mapping"
325
+ ? "is still published by a Tailscale Serve mapping"
326
+ : "still has a live loopback listener";
327
+ return (`runtime service ${entry.runtimeServiceId} (${describeIdentity(entry.owner)}) is recorded stopped/removed, `
328
+ + `but its reserved port ${entry.port} ${held} owned by ${describeIdentity(entry.conflictingOwner)}`);
329
+ }
330
+ /**
331
+ * In-process, pair-atomic claims for starts that have not bound a listener yet.
332
+ *
333
+ * Two concurrent allocators see identical persisted state and identical probe
334
+ * results, so without a claim they both walk away with the lowest free pair.
335
+ * Claiming is all-or-nothing across the two ports: a half-claimed pair would
336
+ * let one start own the app port and another the HMR port, which is the
337
+ * orphaned-companion failure the pairing exists to prevent.
338
+ */
339
+ export class ExposurePortPairClaims {
340
+ ttlMs;
341
+ heldUntilByPort = new Map();
342
+ constructor(ttlMs = 120_000) {
343
+ this.ttlMs = ttlMs;
344
+ }
345
+ isHeld(port, nowMs) {
346
+ const heldUntil = this.heldUntilByPort.get(port);
347
+ if (heldUntil === undefined)
348
+ return false;
349
+ if (heldUntil > nowMs)
350
+ return true;
351
+ this.heldUntilByPort.delete(port);
352
+ return false;
353
+ }
354
+ /** Claim both ports, or neither. Returns false when either is already held. */
355
+ claim(pair, nowMs = Date.now()) {
356
+ if (this.isHeld(pair.appPort, nowMs) || this.isHeld(pair.hmrPort, nowMs))
357
+ return false;
358
+ this.heldUntilByPort.set(pair.appPort, nowMs + this.ttlMs);
359
+ this.heldUntilByPort.set(pair.hmrPort, nowMs + this.ttlMs);
360
+ return true;
361
+ }
362
+ /** Release on lease release/teardown, or when a start reaches a terminal state. */
363
+ release(pair) {
364
+ this.heldUntilByPort.delete(pair.appPort);
365
+ this.heldUntilByPort.delete(pair.hmrPort);
366
+ }
367
+ /** Ports still claimed, for folding into an allocator's reserved set. */
368
+ activePorts(nowMs = Date.now()) {
369
+ const active = new Set();
370
+ for (const port of [...this.heldUntilByPort.keys()]) {
371
+ if (this.isHeld(port, nowMs))
372
+ active.add(port);
373
+ }
374
+ return active;
375
+ }
376
+ clear() {
377
+ this.heldUntilByPort.clear();
378
+ }
379
+ }
380
+ //# sourceMappingURL=port-reservation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port-reservation.js","sourceRoot":"","sources":["../../../src/services/runtime-exposure/port-reservation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=port-reservation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port-reservation.test.d.ts","sourceRoot":"","sources":["../../../src/services/runtime-exposure/port-reservation.test.ts"],"names":[],"mappings":""}