deepline 0.3.460 → 0.3.462

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 (297) hide show
  1. package/dist/bundling-sources/sdk/src/client-core.ts +7593 -0
  2. package/dist/bundling-sources/sdk/src/client.ts +8 -7366
  3. package/dist/bundling-sources/sdk/src/http-core.ts +1239 -0
  4. package/dist/bundling-sources/sdk/src/http.ts +6 -1231
  5. package/dist/bundling-sources/sdk/src/index.ts +4 -1
  6. package/dist/bundling-sources/sdk/src/play.ts +5 -5
  7. package/dist/bundling-sources/sdk/src/plays/client-core.ts +437 -0
  8. package/dist/bundling-sources/sdk/src/plays/client.ts +4 -421
  9. package/dist/bundling-sources/sdk/src/plays/input-example.ts +3 -4
  10. package/dist/bundling-sources/sdk/src/plays/play-description.ts +1 -1
  11. package/dist/bundling-sources/sdk/src/plays/run-request.ts +1 -1
  12. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  13. package/dist/bundling-sources/sdk/src/server.ts +43 -0
  14. package/dist/bundling-sources/sdk/src/types.ts +15 -5
  15. package/dist/bundling-sources/shared_libs/integration-contracts/billing-entitlements.ts +15 -0
  16. package/dist/bundling-sources/shared_libs/monitors/billing/state.ts +28 -0
  17. package/dist/bundling-sources/shared_libs/monitors/callback-security.ts +0 -307
  18. package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +3 -0
  19. package/dist/bundling-sources/shared_libs/monitors/lifecycle-notifications.ts +3 -2
  20. package/dist/bundling-sources/shared_libs/monitors/package.json +2 -0
  21. package/dist/bundling-sources/shared_libs/monitors/provider-callback-verification.ts +34 -0
  22. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +59 -0
  23. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-upstream-identity.ts +94 -1
  24. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-dead-letter.ts +35 -1
  25. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-failure-codes.ts +24 -0
  26. package/dist/bundling-sources/shared_libs/observability/dlq.ts +32 -0
  27. package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +57 -3
  28. package/dist/bundling-sources/shared_libs/observability/scheduled-work.ts +1 -0
  29. package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +66 -1
  30. package/dist/bundling-sources/shared_libs/play-data-plane/sheet-column-storage.ts +36 -7
  31. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +250 -11
  32. package/dist/bundling-sources/shared_libs/play-runtime/array-input-store.ts +319 -0
  33. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +991 -359
  34. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +17 -0
  35. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +13 -0
  36. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +110 -0
  37. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +155 -6
  38. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +110 -6
  39. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +127 -13
  40. package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +14 -1
  41. package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +57 -1
  42. package/dist/bundling-sources/shared_libs/play-runtime/free-company-lookup-batching.ts +218 -0
  43. package/dist/bundling-sources/shared_libs/play-runtime/gateway-postgres-admission.ts +42 -5
  44. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-budget-state-backend.ts +6 -1
  45. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +92 -31
  46. package/dist/bundling-sources/shared_libs/play-runtime/governor/block-reserving-budget-state-backend.ts +69 -14
  47. package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +93 -23
  48. package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +15 -4
  49. package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +22 -18
  50. package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +5 -0
  51. package/dist/bundling-sources/shared_libs/play-runtime/launch-identity.ts +2 -0
  52. package/dist/bundling-sources/shared_libs/play-runtime/map-memory-limits.ts +190 -14
  53. package/dist/bundling-sources/shared_libs/play-runtime/memory-ledger.ts +131 -0
  54. package/dist/bundling-sources/shared_libs/play-runtime/modal-runtime-config.ts +77 -2
  55. package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +271 -2
  56. package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +51 -0
  57. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/contracts.ts +2 -0
  58. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/job.ts +27 -1
  59. package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-batching-registry.ts +2 -0
  60. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +3 -0
  61. package/dist/bundling-sources/shared_libs/play-runtime/provider-text-for-log.ts +63 -0
  62. package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +19 -0
  63. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-event-transport.ts +112 -16
  64. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +104 -2
  65. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +265 -151
  66. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-gateway-transport.ts +17 -0
  67. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-progress-push.ts +35 -14
  68. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-sheet-persistence-retry.ts +12 -1
  69. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-control-transport.ts +4 -0
  70. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-labels.ts +36 -0
  71. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +136 -70
  72. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +237 -36
  73. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +148 -4
  74. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +6 -0
  75. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +285 -32
  76. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/modal.ts +251 -56
  77. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +29 -4
  78. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/sandbox-create-outcome.ts +27 -0
  79. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +22 -1
  80. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +1397 -382
  81. package/dist/bundling-sources/shared_libs/play-runtime/runtime-array-input-receipts.ts +920 -0
  82. package/dist/bundling-sources/shared_libs/play-runtime/runtime-constants.ts +16 -0
  83. package/dist/bundling-sources/shared_libs/play-runtime/runtime-environment.ts +38 -0
  84. package/dist/bundling-sources/shared_libs/play-runtime/runtime-flow.ts +6 -0
  85. package/dist/bundling-sources/shared_libs/play-runtime/runtime-incident-drills.ts +26 -1
  86. package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +30 -0
  87. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-store-adapter.ts +14 -3
  88. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-writer.ts +31 -4
  89. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-transition.ts +47 -0
  90. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-compute-usage.ts +20 -7
  91. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +12 -0
  92. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/index.ts +9 -0
  93. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +10 -0
  94. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +4 -0
  95. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +1496 -320
  96. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +31 -1
  97. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +1389 -129
  98. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +36 -0
  99. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-dispatch-authority.ts +4 -0
  100. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +162 -23
  101. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +499 -115
  102. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +377 -9
  103. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-ledger-reconciliation.ts +117 -8
  104. package/dist/bundling-sources/shared_libs/play-runtime/secret-resolution-retry-policy.ts +25 -0
  105. package/dist/bundling-sources/shared_libs/play-runtime/terminal-runtime-performance.ts +391 -0
  106. package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +40 -0
  107. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/index.ts +6 -0
  108. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/mapped-calls.ts +171 -0
  109. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/receipt-cohort.ts +16 -1
  110. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +26 -3
  111. package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +16 -2
  112. package/dist/bundling-sources/shared_libs/play-runtime/transport-error-diagnostics.ts +28 -0
  113. package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-storage-contract.ts +55 -5
  114. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +41 -1
  115. package/dist/bundling-sources/shared_libs/plays/contracts.ts +4 -0
  116. package/dist/bundling-sources/shared_libs/plays/dataset.ts +9 -3
  117. package/dist/bundling-sources/shared_libs/plays/deploy/manifest-contract.ts +2 -0
  118. package/dist/bundling-sources/shared_libs/plays/deploy/manifest.ts +3 -2
  119. package/dist/bundling-sources/shared_libs/plays/deploy/project-serializer.ts +2 -2
  120. package/dist/bundling-sources/shared_libs/plays/run-output-summary.ts +66 -0
  121. package/dist/bundling-sources/shared_libs/plays/script-entry.ts +1 -1
  122. package/dist/bundling-sources/shared_libs/product-notifications/catalog.ts +43 -1
  123. package/dist/bundling-sources/shared_libs/product-notifications/content.ts +9 -0
  124. package/dist/bundling-sources/shared_libs/product-notifications/email.ts +91 -13
  125. package/dist/bundling-sources/shared_libs/product-notifications/events.ts +3 -0
  126. package/dist/bundling-sources/shared_libs/product-notifications/slack-delivery.ts +41 -24
  127. package/dist/bundling-sources/shared_libs/security/attested-client-ip.ts +91 -0
  128. package/dist/bundling-sources/shared_libs/security/internal-actor.ts +0 -11
  129. package/dist/cli/{auth-HKA6ZVHQ.mjs → auth-JDLEY7VU.mjs} +5 -4
  130. package/dist/cli/auth-UXKY6TCC.js +41 -0
  131. package/dist/cli/{billing-MTO2ZZ3G.js → billing-HXAXB3XZ.js} +152 -78
  132. package/dist/cli/{billing-26G44S5N.mjs → billing-SDHLBLMV.mjs} +84 -10
  133. package/dist/cli/{chunk-BHGII2D6.js → chunk-3ACMRZRV.js} +8 -6
  134. package/dist/cli/{chunk-S4Q2XCGM.mjs → chunk-3KZCFOZ6.mjs} +1 -1
  135. package/dist/cli/chunk-4KQ6SIBC.mjs +1038 -0
  136. package/dist/cli/{chunk-Z2GUFYT6.js → chunk-5LEAXRHV.js} +11 -11
  137. package/dist/cli/{chunk-XAYO3Q2X.mjs → chunk-6NNVJDVR.mjs} +7 -5
  138. package/dist/cli/{chunk-NMJ4D2WO.js → chunk-6PMCRYDA.js} +216 -91
  139. package/dist/cli/{chunk-OMM54B3X.mjs → chunk-6RNQGWFD.mjs} +16 -806
  140. package/dist/cli/{chunk-EBU7LQ64.js → chunk-6V7KVRR5.js} +3 -3
  141. package/dist/cli/{chunk-RDPTDDKX.js → chunk-7LFIMWMW.js} +2 -2
  142. package/dist/cli/chunk-7MJ6VI2T.mjs +19 -0
  143. package/dist/cli/chunk-7SWNPNML.js +1039 -0
  144. package/dist/cli/{chunk-CTRPCARW.mjs → chunk-7U3XNPOA.mjs} +267 -38
  145. package/dist/cli/{chunk-RBTTUYZZ.js → chunk-7VZHXVOQ.js} +1 -1
  146. package/dist/cli/{chunk-YVBWO647.mjs → chunk-AT636LLU.mjs} +2 -2
  147. package/dist/cli/{chunk-VTODQWQA.js → chunk-BGTPIMSM.js} +392 -261
  148. package/dist/cli/{chunk-KADIT5NV.mjs → chunk-CKSOY47X.mjs} +2 -2
  149. package/dist/cli/{chunk-7DH2FD7Y.mjs → chunk-D464JW3N.mjs} +5 -85
  150. package/dist/cli/chunk-D6DXOUTO.mjs +827 -0
  151. package/dist/cli/{describe-QW54QQNB.js → chunk-EM4TXCCI.js} +27 -44
  152. package/dist/cli/chunk-F6QV42MC.mjs +91 -0
  153. package/dist/cli/chunk-FKVYR3QA.mjs +1039 -0
  154. package/dist/cli/{chunk-LMAULZLF.js → chunk-GEGW5HPZ.js} +29 -27
  155. package/dist/cli/{chunk-M52JQSLK.js → chunk-HUB3CCM2.js} +13 -4
  156. package/dist/cli/{chunk-YHTQM5XI.js → chunk-I6VHOU5O.js} +27 -27
  157. package/dist/cli/{chunk-Z2XUZC34.js → chunk-IAYSWZDJ.js} +188 -76
  158. package/dist/cli/chunk-JF3TLIMQ.js +19 -0
  159. package/dist/cli/{chunk-HDFRJ4IT.mjs → chunk-JVHOS3K3.mjs} +177 -65
  160. package/dist/cli/{chunk-LAWEURCT.mjs → chunk-LFXLQEZN.mjs} +1 -1
  161. package/dist/cli/{chunk-2PBN4SZE.js → chunk-LROWFPGN.js} +16 -16
  162. package/dist/cli/{chunk-SLEUWLJE.mjs → chunk-MSY22NQW.mjs} +5 -5
  163. package/dist/cli/{chunk-LVJOFUU7.mjs → chunk-MUUQZIOF.mjs} +23 -49
  164. package/dist/cli/{chunk-2XHWOQF4.js → chunk-NBLSCHKK.js} +52 -50
  165. package/dist/cli/{chunk-526R2HON.mjs → chunk-NHRWZPWZ.mjs} +4 -2
  166. package/dist/cli/{chunk-KXMNM4AQ.js → chunk-NMU3VR5U.js} +4 -5
  167. package/dist/cli/{chunk-W3BE3CHK.mjs → chunk-O2RX5A66.mjs} +14 -12
  168. package/dist/cli/{chunk-UKFZT7RF.js → chunk-OMQ23IXL.js} +2 -2
  169. package/dist/cli/{chunk-LJTFZOHU.js → chunk-OPJAJBD4.js} +28 -54
  170. package/dist/cli/{chunk-MLFR6DVF.mjs → chunk-PHSEINNH.mjs} +5 -5
  171. package/dist/cli/{chunk-3DNKFH2G.mjs → chunk-PKHVSIJG.mjs} +19 -1
  172. package/dist/cli/{chunk-WIYWSYDS.mjs → chunk-Q2EIZKVX.mjs} +3 -3
  173. package/dist/cli/{chunk-VJAEA4CS.js → chunk-QJZ6WNWD.js} +8 -8
  174. package/dist/cli/{chunk-EIMG75BT.mjs → chunk-S3A4IXBQ.mjs} +4 -5
  175. package/dist/cli/{chunk-RZSTT45F.mjs → chunk-S42YIQNE.mjs} +13 -8
  176. package/dist/cli/{chunk-YULBYKAK.mjs → chunk-S6UAJR6V.mjs} +3 -3
  177. package/dist/cli/{chunk-G7L27KZB.mjs → chunk-TKAQR3IB.mjs} +31 -21
  178. package/dist/cli/{chunk-QWRHGGUH.js → chunk-UAJFWWZE.js} +20 -2
  179. package/dist/cli/{chunk-ZR2RLI4O.mjs → chunk-UDRPEZ5F.mjs} +223 -92
  180. package/dist/cli/{chunk-QGAWTBIR.js → chunk-ULK7JGGI.js} +511 -282
  181. package/dist/cli/chunk-V335HGX5.js +1038 -0
  182. package/dist/cli/{chunk-NH6JSJW6.mjs → chunk-V3MEA7NB.mjs} +7 -5
  183. package/dist/cli/{chunk-NRGGFVVB.js → chunk-VFGVXXZP.js} +37 -35
  184. package/dist/cli/chunk-VLEVVDWG.js +91 -0
  185. package/dist/cli/{chunk-R2GLGLDR.mjs → chunk-VPHN2HAL.mjs} +216 -91
  186. package/dist/cli/{chunk-CFUTOWE4.js → chunk-WG3KGAII.js} +8 -88
  187. package/dist/cli/{describe-TOMIAT37.mjs → chunk-WIY6U6GD.mjs} +19 -36
  188. package/dist/cli/{chunk-YS2YBSJB.js → chunk-XANRM3QA.js} +6 -6
  189. package/dist/cli/{chunk-KGQNIA37.js → chunk-XQCTG5OO.js} +44 -34
  190. package/dist/cli/{chunk-EJGBLXDZ.mjs → chunk-XZAFIOUQ.mjs} +1 -1
  191. package/dist/cli/chunk-Y4DPU4OM.js +827 -0
  192. package/dist/cli/chunk-YT5EODJO.js +920 -0
  193. package/dist/cli/{chunk-2WRO2UJ5.js → chunk-ZGQSFYD2.js} +56 -51
  194. package/dist/cli/{chunk-OJ6RUKVT.mjs → chunk-ZUK6LIJB.mjs} +10 -1
  195. package/dist/cli/command-docs.d.mts +5 -0
  196. package/dist/cli/command-docs.d.ts +5 -0
  197. package/dist/cli/command-docs.js +2 -2
  198. package/dist/cli/command-docs.mjs +1 -1
  199. package/dist/cli/{csv-6FNFYJUC.js → csv-C56GSCEU.js} +13 -12
  200. package/dist/cli/{csv-MDHT4BKK.mjs → csv-L54JS7TF.mjs} +4 -3
  201. package/dist/cli/{db-D6AMVOEW.js → db-MOGRMZTA.js} +30 -27
  202. package/dist/cli/{db-74O3RFWY.mjs → db-YVBUW2DX.mjs} +10 -7
  203. package/dist/cli/describe-KYEULWPG.js +48 -0
  204. package/dist/cli/describe-NLZKKT7C.mjs +48 -0
  205. package/dist/cli/describe-core.d.mts +153 -5
  206. package/dist/cli/describe-core.d.ts +153 -5
  207. package/dist/cli/describe-core.js +9 -5
  208. package/dist/cli/describe-core.mjs +10 -6
  209. package/dist/cli/{executions-N4FMGVSC.js → executions-A7L4ULPP.js} +9 -7
  210. package/dist/cli/{executions-PVSF4HUF.mjs → executions-ZBGSTT37.mjs} +7 -5
  211. package/dist/cli/{feedback-OB7NANZW.mjs → feedback-G6GU37FD.mjs} +6 -5
  212. package/dist/cli/{feedback-WFSPCAI2.js → feedback-OHLY7RYD.js} +10 -9
  213. package/dist/cli/getting-started.d.mts +6 -6
  214. package/dist/cli/getting-started.d.ts +6 -6
  215. package/dist/cli/getting-started.js +2 -2
  216. package/dist/cli/getting-started.mjs +1 -1
  217. package/dist/cli/git-P76N4NDQ.js +25 -0
  218. package/dist/cli/{git-FHUSPAEU.mjs → git-PKZW3QD5.mjs} +5 -4
  219. package/dist/cli/index.js +152 -142
  220. package/dist/cli/index.mjs +56 -46
  221. package/dist/cli/{legacy-noops-ECHNA5HN.js → legacy-noops-5LM3D724.js} +8 -7
  222. package/dist/cli/{legacy-noops-HMK4BSCI.mjs → legacy-noops-LJJYG6YA.mjs} +5 -4
  223. package/dist/cli/{monitors-U7VQ3EZM.mjs → monitors-72QV4ALO.mjs} +19 -6
  224. package/dist/cli/{monitors-XLLFNENH.js → monitors-UX3H5DC2.js} +103 -90
  225. package/dist/cli/{org-6H3USO5M.mjs → org-6RRRKOCP.mjs} +9 -6
  226. package/dist/cli/{org-QX6ER2HN.js → org-IF7ISUVB.js} +70 -67
  227. package/dist/cli/pages-3SU3HKL7.js +252 -0
  228. package/dist/cli/pages-DXDYYKEK.mjs +252 -0
  229. package/dist/cli/{play-MOB2WYOR.mjs → play-AHASKRLA.mjs} +512 -1508
  230. package/dist/cli/{play-WNB7HBZK.js → play-EUIUVLUH.js} +1090 -2086
  231. package/dist/cli/{providers-CXEZ23E2.mjs → providers-GWGE3WY3.mjs} +7 -5
  232. package/dist/cli/{providers-7M3DISKX.js → providers-V5WU4VXJ.js} +10 -8
  233. package/dist/cli/{quickstart-ZFCHKHF6.mjs → quickstart-OXKQ5ZST.mjs} +5 -4
  234. package/dist/cli/{quickstart-CLJT4AZL.js → quickstart-QP65I5PF.js} +13 -12
  235. package/dist/cli/run-6MM72IGL.mjs +443 -0
  236. package/dist/cli/run-F3FTYS56.js +443 -0
  237. package/dist/cli/search-OYKOOI7A.js +32 -0
  238. package/dist/cli/{search-FVYWYIC3.mjs → search-ZMEBVJZB.mjs} +8 -6
  239. package/dist/cli/{secrets-YRLKZQS5.js → secrets-ACND5N6A.js} +16 -14
  240. package/dist/cli/{secrets-WAMPTQFC.mjs → secrets-XRCJFF3L.mjs} +7 -5
  241. package/dist/cli/{sessions-IQ332BJH.mjs → sessions-RTK3CEW6.mjs} +5 -4
  242. package/dist/cli/{sessions-44J6WIVU.js → sessions-ZGRJPCFF.js} +6 -5
  243. package/dist/cli/{settings-4IJR2I2T.js → settings-PD5KWQQZ.js} +80 -77
  244. package/dist/cli/{settings-22S6NIFQ.mjs → settings-XDRBPRDE.mjs} +14 -11
  245. package/dist/cli/{setup-OZUPKKPW.mjs → setup-3HPYAOCC.mjs} +12 -10
  246. package/dist/cli/{setup-3FWSRNOX.js → setup-E2Q6PXHC.js} +53 -51
  247. package/dist/cli/{skills-5CW3NFP3.mjs → skills-OOQFMPOV.mjs} +7 -6
  248. package/dist/cli/skills-XYWV52KB.js +31 -0
  249. package/dist/cli/tools-ASCDZJCK.js +55 -0
  250. package/dist/cli/tools-C5ZT3UIC.mjs +55 -0
  251. package/dist/cli/update-5RQSEIFM.js +33 -0
  252. package/dist/cli/{update-IBULOV7P.mjs → update-ZWJTADIW.mjs} +9 -8
  253. package/dist/cli/{workflow-MVZT7MWT.mjs → workflow-23NMPAJ7.mjs} +10 -8
  254. package/dist/cli/{workflow-Z7FW6GT2.js → workflow-TCXU5YJV.js} +20 -18
  255. package/dist/client-DS2IWYZF.d.ts +10 -0
  256. package/dist/client-DTwnz_AW.d.mts +10 -0
  257. package/dist/{client-CYqG23K1.d.ts → client-core-B_6HAIBy.d.ts} +385 -12
  258. package/dist/{client-BbU5_j7n.d.mts → client-core-DzBSlY1U.d.mts} +385 -12
  259. package/dist/{compiler-manifest-CWz_sNOQ.d.mts → compiler-manifest-Dcyd3-Zd.d.mts} +43 -1
  260. package/dist/{compiler-manifest-CWz_sNOQ.d.ts → compiler-manifest-Dcyd3-Zd.d.ts} +43 -1
  261. package/dist/errors-d-sTrZhe.d.mts +142 -0
  262. package/dist/errors-yQwfgrcX.d.ts +142 -0
  263. package/dist/{index-BF2JB_Ug.d.mts → index-C6oXchjN.d.mts} +1 -1
  264. package/dist/{index-4NPXDzlD.d.ts → index-P56zy_z5.d.ts} +1 -1
  265. package/dist/index.d.mts +11 -147
  266. package/dist/index.d.ts +11 -147
  267. package/dist/index.js +15 -11
  268. package/dist/index.mjs +14 -10
  269. package/dist/install-integrity.json +141 -104
  270. package/dist/plays/bundle-play-file.d.mts +3 -3
  271. package/dist/plays/bundle-play-file.d.ts +3 -3
  272. package/dist/plays/bundle-play-file.mjs +2 -1
  273. package/dist/plays/play-description.d.mts +2 -2
  274. package/dist/plays/play-description.d.ts +2 -2
  275. package/dist/plays/play-description.js +2 -2
  276. package/dist/plays/play-description.mjs +1 -1
  277. package/dist/plays/run-request.d.mts +2 -2
  278. package/dist/plays/run-request.d.ts +2 -2
  279. package/dist/release.d.mts +1 -1
  280. package/dist/release.d.ts +1 -1
  281. package/dist/release.js +2 -2
  282. package/dist/release.mjs +1 -1
  283. package/dist/server.d.mts +17 -0
  284. package/dist/server.d.ts +17 -0
  285. package/dist/server.js +76 -0
  286. package/dist/server.mjs +76 -0
  287. package/package.json +6 -1
  288. package/dist/cli/auth-VDOCNR7H.js +0 -40
  289. package/dist/cli/chunk-PQUUWFXY.js +0 -95
  290. package/dist/cli/chunk-QJLKYYPX.js +0 -1710
  291. package/dist/cli/chunk-YBWAG72P.mjs +0 -95
  292. package/dist/cli/git-4PMBJSH5.js +0 -24
  293. package/dist/cli/search-4CCQCTVD.js +0 -30
  294. package/dist/cli/skills-LMNM6B5F.js +0 -30
  295. package/dist/cli/tools-AGBBDJ7P.js +0 -45
  296. package/dist/cli/tools-NOPBDRGW.mjs +0 -45
  297. package/dist/cli/update-U3W6USVD.js +0 -32
@@ -525,6 +525,8 @@ export interface MapExecutionFrame {
525
525
  /** Digest of the authored input before Runtime Sheet outputs were merged. */
526
526
  authoredInputDigest?: string;
527
527
  }>;
528
+ /** A sealed, bounded array source is readable by page after a wake. */
529
+ arrayInput?: { hasSourceIdentities: boolean };
528
530
  /** Successful inputs, including reused inputs with no distinct stored key. */
529
531
  completedRowsCount?: number;
530
532
  pendingRowsCount?: number;
@@ -982,6 +984,10 @@ export interface ContextOptions {
982
984
  columnTypes?: PlayDatasetColumnTypes;
983
985
  },
984
986
  ) => Promise<MapStartResult>;
987
+ /** Internal transport pages; each yielded value is one actual admission response. */
988
+ onMapStartPages?: (
989
+ ...args: Parameters<NonNullable<ContextOptions['onMapStart']>>
990
+ ) => AsyncIterable<MapStartResult>;
985
991
  /**
986
992
  * Called as ctx.dataset() rows complete — persists executed rows (data +
987
993
  * cell meta) into the tenant runtime sheet so the sheet, not an in-memory
@@ -1082,6 +1088,10 @@ export interface ContextOptions {
1082
1088
  * in-memory callback tests can omit it and keep local result resolvers.
1083
1089
  */
1084
1090
  runtimeSheetBackedMapDatasets?: boolean;
1091
+ /** Runner-owned durable source pages for arrays that cannot fit a second resident copy. */
1092
+ runtimeArrayInputStore?: import('./array-input-store').RuntimeArrayInputStore;
1093
+ /** Internal rollout switch for new array snapshots; existing snapshots always replay. */
1094
+ runtimeArrayInputStagingEnabled?: boolean;
1085
1095
  resolvePlay?: (playRef: string) => Promise<ResolvedPlayExecution | null>;
1086
1096
  /** Admit an independently scheduled scalar/HITL Play Run. */
1087
1097
  launchPlayAsync?: (
@@ -1284,6 +1294,13 @@ export interface ProviderRetryCursor {
1284
1294
  }
1285
1295
 
1286
1296
  export interface PlayCheckpoint {
1297
+ /** Scheduler silence proof for one exact detached-runner heartbeat. Older
1298
+ * checkpoints acquire a fresh proof through the existing durable park. */
1299
+ detachedRunnerSilenceConfirmation?: {
1300
+ boundaryId: string;
1301
+ runnerAttempt: number;
1302
+ heartbeatIdentity: string | null;
1303
+ };
1287
1304
  /** Last completed runner invocation within the current scheduler attempt. */
1288
1305
  workCounterInvocationAttempt?: number;
1289
1306
  workCounterInvocationSeq?: number;
@@ -1,3 +1,4 @@
1
+ import { createRateLimitedRuntimeLogger } from '../observability/runtime-console';
1
2
  import { withRuntimeSchedulerClient } from './/scheduler-backends/postgres-pool';
2
3
  import { RUNTIME_CAPACITY_POLICY } from './/runtime-capacity-policy';
3
4
  import { isIsolatedRuntimeSchedulerSchema } from './/runtime-scheduler-topology';
@@ -6,6 +7,12 @@ import { isIsolatedRuntimeSchedulerSchema } from './/runtime-scheduler-topology'
6
7
  * their own attempts; they do not each enumerate the shared Daytona account. */
7
8
  export const DAYTONA_JANITOR_INTERVAL_MS = 5 * 60 * 1_000;
8
9
 
10
+ /**
11
+ * Spacing of the `[daytona-janitor.stale_list]` line. The page does not depend
12
+ * on it: the monitor reads every pass summary and holds one open incident.
13
+ */
14
+ export const DAYTONA_STALE_LIST_ALERT_INTERVAL_MS = 30 * 60 * 1_000;
15
+
9
16
  export type DaytonaSandboxJanitorOptions = {
10
17
  url: string;
11
18
  schema: string;
@@ -36,6 +43,11 @@ export function startDaytonaSandboxJanitor(
36
43
  }
37
44
 
38
45
  let running = false;
46
+ // Spans passes, so it cannot live in the per-pass reaper.
47
+ const reportStaleList = createRateLimitedRuntimeLogger({
48
+ log: (...args) => console.warn(...args),
49
+ intervalMs: DAYTONA_STALE_LIST_ALERT_INTERVAL_MS,
50
+ });
39
51
  const runPass = async (): Promise<void> => {
40
52
  if (running) {
41
53
  console.info('[daytona-janitor.controller] skip (previous pass running)');
@@ -80,6 +92,7 @@ export function startDaytonaSandboxJanitor(
80
92
  },
81
93
  schema: options.schema,
82
94
  }),
95
+ options: { reportStaleList },
83
96
  });
84
97
  } catch (error) {
85
98
  // This is a best-effort resource backstop. A failed sweep must never
@@ -38,6 +38,12 @@
38
38
  * authorization failure is logged and the sweep continues — one wedged sandbox
39
39
  * must never abort the fleet-wide pass. The only hard failure is an inability
40
40
  * to enumerate at all.
41
+ *
42
+ * A successful list can still be wrong. From Oct 29 23:00 to Oct 30 06:00 UTC it
43
+ * returned about 75 sandboxes from other lanes and none of the 1 to 3 live
44
+ * production ones, so `scanned` never reached zero and every pass reported
45
+ * errors=0. Each pass therefore compares the list with the durable ledger. A
46
+ * mismatch only alerts: absence from a list never proves a sandbox is gone.
41
47
  */
42
48
  import { PLAY_RUNNER_TERMINAL_GRACE_SECONDS } from './/runtime-constants';
43
49
  import { DAYTONA_PLAY_RUNNER_LABEL_SOURCE } from './/runner-backends/backends/daytona-labels';
@@ -52,6 +58,15 @@ export { DAYTONA_PLAY_RUNNER_LABEL_SOURCE };
52
58
  */
53
59
  export const REAP_AGE_GRACE_MS = 5 * 60 * 1000;
54
60
 
61
+ /**
62
+ * A sandbox must be this old when the list begins before the list missing it
63
+ * means anything, which leaves room for clock skew and Daytona's own lag.
64
+ */
65
+ export const DAYTONA_DURABLE_LIVE_SETTLE_MS = 60 * 1000;
66
+ /** A live sandbox whose runner has been silent this long may be lost, so one
67
+ * such sandbox missing from the list is not evidence of a blind list. */
68
+ export const DAYTONA_DURABLE_LIVE_HEARTBEAT_STALE_MS = 5 * 60 * 1000;
69
+
55
70
  /**
56
71
  * A single sandbox as seen by the janitor. Structurally a subset of the Daytona
57
72
  * SDK `Sandbox`, so a real `Sandbox` satisfies it directly.
@@ -133,6 +148,11 @@ export type DaytonaJanitorOwnershipPort = {
133
148
  runId: string;
134
149
  attempt: number;
135
150
  }): Promise<DaytonaJanitorCleanupAuthorization>;
151
+ /** One statement per pass; its cost never scales with the provider list. */
152
+ countDurableLive(input: {
153
+ createdBeforeMs: number;
154
+ heartbeatStaleMs: number;
155
+ }): Promise<{ live: number; heartbeating: number }>;
136
156
  };
137
157
 
138
158
  export type ReapOptions = {
@@ -142,6 +162,8 @@ export type ReapOptions = {
142
162
  dryRun?: boolean;
143
163
  /** Structured logger; defaults to console. */
144
164
  logger?: Pick<Console, 'info' | 'warn'>;
165
+ /** Rate limited by the long-lived controller; defaults to `logger.warn`. */
166
+ reportStaleList?: (message: string, detail: Record<string, unknown>) => void;
145
167
  };
146
168
 
147
169
  export type ReapSummary = {
@@ -152,6 +174,14 @@ export type ReapSummary = {
152
174
  spared: number;
153
175
  alerts: number;
154
176
  errors: number;
177
+ /** Sandboxes the ledger held live throughout this list; null if unreadable. */
178
+ durableLive: number | null;
179
+ /** Of `durableLive`, those whose runner heartbeat is recent or not started. */
180
+ durableLiveHeartbeating: number | null;
181
+ /** Listed sandboxes that the ledger holds live. */
182
+ listedDurableLive: number;
183
+ /** The list succeeded but showed none of `durableLive`. */
184
+ listStale: boolean;
155
185
  };
156
186
 
157
187
  type ReapDecision =
@@ -232,8 +262,14 @@ export async function reapOrphanDaytonaSandboxes(input: {
232
262
  spared: 0,
233
263
  alerts: 0,
234
264
  errors: 0,
265
+ durableLive: null,
266
+ durableLiveHeartbeating: null,
267
+ listedDurableLive: 0,
268
+ listStale: false,
235
269
  };
270
+ let ownershipReadFailed = false;
236
271
 
272
+ const listStartedAtMs = now();
237
273
  const iterator = input.daytona.list({
238
274
  labels: { source: DAYTONA_PLAY_RUNNER_LABEL_SOURCE },
239
275
  });
@@ -253,6 +289,7 @@ export async function reapOrphanDaytonaSandboxes(input: {
253
289
  routingDomain,
254
290
  });
255
291
  } catch (error) {
292
+ ownershipReadFailed = true;
256
293
  summary.errors += 1;
257
294
  summary.spared += 1;
258
295
  logger.warn('[daytona-janitor.ownership_read_failed]', {
@@ -279,6 +316,8 @@ export async function reapOrphanDaytonaSandboxes(input: {
279
316
  continue;
280
317
  }
281
318
 
319
+ if (ownership.operationState === 'live') summary.listedDurableLive += 1;
320
+
282
321
  if (labelRunId && labelRunId !== ownership.runId) {
283
322
  logger.info('[daytona-janitor.label_correlation_mismatch]', {
284
323
  sandboxId: sandbox.id,
@@ -388,6 +427,42 @@ export async function reapOrphanDaytonaSandboxes(input: {
388
427
  }
389
428
  }
390
429
 
430
+ // Read after the list ends: a row still live now, and created before the list
431
+ // began, was live for the whole list, so a miss cannot be a race.
432
+ try {
433
+ const durable = await input.ownership.countDurableLive({
434
+ createdBeforeMs: listStartedAtMs - DAYTONA_DURABLE_LIVE_SETTLE_MS,
435
+ heartbeatStaleMs: DAYTONA_DURABLE_LIVE_HEARTBEAT_STALE_MS,
436
+ });
437
+ summary.durableLive = durable.live;
438
+ summary.durableLiveHeartbeating = durable.heartbeating;
439
+ } catch (error) {
440
+ summary.errors += 1;
441
+ logger.warn('[daytona-janitor.durable_live_read_failed]', {
442
+ error: error instanceof Error ? error.message : String(error),
443
+ });
444
+ }
445
+ // One missing sandbox whose runner went silent is likely a loss whose run
446
+ // has not settled. A missing runner that still heartbeats, or several
447
+ // missing at once (a gateway outage silences them all), is a blind list.
448
+ summary.listStale =
449
+ summary.durableLive !== null &&
450
+ summary.durableLiveHeartbeating !== null &&
451
+ summary.listedDurableLive === 0 &&
452
+ (summary.durableLiveHeartbeating > 0 || summary.durableLive >= 2) &&
453
+ !ownershipReadFailed;
454
+ if (summary.listStale) {
455
+ const reportStaleList =
456
+ input.options?.reportStaleList ??
457
+ ((message, detail) => logger.warn(message, detail));
458
+ reportStaleList('[daytona-janitor.stale_list]', {
459
+ provider: 'daytona',
460
+ durableLive: summary.durableLive,
461
+ scanned: summary.scanned,
462
+ dryRun,
463
+ });
464
+ }
465
+
391
466
  logger.info('[daytona-janitor.summary]', { ...summary, dryRun });
392
467
  return summary;
393
468
  }
@@ -453,6 +528,7 @@ export function createPostgresDaytonaJanitorOwnershipPort(input: {
453
528
  schema: string;
454
529
  }): DaytonaJanitorOwnershipPort {
455
530
  const runs = `${quoteIdent(input.schema)}.${quoteIdent('runs')}`;
531
+ const attempts = `${quoteIdent(input.schema)}.${quoteIdent('attempts')}`;
456
532
  const operations = `${quoteIdent(input.schema)}.${quoteIdent(
457
533
  'runtime_sandbox_operations',
458
534
  )}`;
@@ -652,6 +728,40 @@ export function createPostgresDaytonaJanitorOwnershipPort(input: {
652
728
  }
653
729
  return row.inserted ? 'scheduled' : 'already_authorized';
654
730
  },
731
+ async countDurableLive({ createdBeforeMs, heartbeatStaleMs }) {
732
+ // The schema already scopes this to one lane. Listing both environments
733
+ // keeps the reconcile index usable. A finished run's sandbox is cleanup's
734
+ // to settle, so it says nothing about whether the list is current.
735
+ const result = await input.client.query<{
736
+ live: string;
737
+ heartbeating: string;
738
+ }>(
739
+ `
740
+ SELECT count(*)::text AS live,
741
+ count(*) FILTER (
742
+ WHERE attempt.heartbeat_at IS NULL
743
+ OR attempt.heartbeat_at > clock_timestamp()
744
+ - make_interval(secs => $2::double precision / 1000.0)
745
+ )::text AS heartbeating
746
+ FROM ${operations} AS operation
747
+ JOIN ${runs} AS run ON run.run_id = operation.run_id
748
+ LEFT JOIN ${attempts} AS attempt
749
+ ON attempt.run_id = operation.run_id
750
+ AND attempt.attempt = operation.attempt
751
+ WHERE operation.provider = 'daytona'
752
+ AND operation.environment IN ('production', 'preview')
753
+ AND operation.state = 'live'
754
+ AND operation.provider_created_at
755
+ <= to_timestamp($1::double precision / 1000.0)
756
+ AND run.status IN ('queued', 'running', 'waiting')
757
+ `,
758
+ [createdBeforeMs, heartbeatStaleMs],
759
+ );
760
+ return {
761
+ live: Number(result.rows[0]?.live ?? 0),
762
+ heartbeating: Number(result.rows[0]?.heartbeating ?? 0),
763
+ };
764
+ },
655
765
  };
656
766
  }
657
767
 
@@ -27,6 +27,7 @@
27
27
  * secret and correctly lives in the environment.
28
28
  */
29
29
  import { spawnSync } from 'node:child_process';
30
+ import { randomBytes } from 'node:crypto';
30
31
  import { appendFileSync } from 'node:fs';
31
32
  import { RUNTIME_CAPACITY_POLICY } from '../runtime-capacity-policy';
32
33
  import { ABSURD_RELEASE_ID_RE } from '../runtime-scheduler-topology';
@@ -228,6 +229,13 @@ export type FlyMachine = {
228
229
  * routing event as an explicit legacy-drain fence. */
229
230
  events?: Array<{ type?: string; timestamp?: number }>;
230
231
  region?: string;
232
+ /** Native resolved identity; config.image can omit its immutable digest. */
233
+ image_ref?: {
234
+ registry?: string;
235
+ repository?: string;
236
+ tag?: string;
237
+ digest?: string;
238
+ } | null;
231
239
  config?: {
232
240
  image?: string;
233
241
  metadata?: Record<string, string>;
@@ -279,6 +287,12 @@ export function parseArgs(argv: readonly string[]): ParsedArgs {
279
287
  index += 1;
280
288
  }
281
289
  }
290
+ if (
291
+ 'image-ref' in flags &&
292
+ !['boot', 'replace', 'plan-image'].includes(command)
293
+ ) {
294
+ throw new Error(`--image-ref is unsupported for ${command}.`);
295
+ }
282
296
  return { command, flags };
283
297
  }
284
298
 
@@ -346,6 +360,58 @@ export function laneImageRef(app: string, sha: string): string {
346
360
  return `${FLY_REGISTRY_HOST}/${app}:git-${sha}`;
347
361
  }
348
362
 
363
+ /** Preserve the registered image identity instead of deriving a tag in the target app.
364
+ * Shared Preview images must retain both their exact source tag and native digest.
365
+ */
366
+ export function resolveWorkerLaneImage(input: {
367
+ app: string;
368
+ sha?: string;
369
+ imageRef: string;
370
+ }): { sha: string; imageRef: string } {
371
+ const prefix = `${FLY_REGISTRY_HOST}/${input.app}:git-`;
372
+ const legacySha = input.imageRef.startsWith(prefix)
373
+ ? input.imageRef.slice(prefix.length)
374
+ : null;
375
+ const sharedSha =
376
+ /^registry\.fly\.io\/deepline-absurd-worker-preview-cache:git-([a-f0-9]{40})-worker-[a-f0-9]{64}@sha256:[a-f0-9]{64}$/.exec(
377
+ input.imageRef,
378
+ )?.[1];
379
+ const sha =
380
+ sharedSha ?? (legacySha && GIT_SHA_RE.test(legacySha) ? legacySha : null);
381
+ if (!sha)
382
+ throw new Error(`Invalid worker image reference: ${input.imageRef}`);
383
+ if (input.sha !== undefined && sha !== input.sha) {
384
+ throw new Error(
385
+ `Worker image source ${sha} disagrees with requested source ${input.sha}.`,
386
+ );
387
+ }
388
+ return { sha, imageRef: input.imageRef };
389
+ }
390
+
391
+ /** Exact native immutable identity, shared semantically with the release gate's
392
+ * jq predicates. Config equality alone proves a requested tag, not its digest. */
393
+ export function flyMachineMatchesImage(
394
+ machine: FlyMachine,
395
+ image: string,
396
+ ): boolean {
397
+ if (!image.includes('@')) return machine.config?.image === image;
398
+ const requested =
399
+ /^([A-Za-z0-9.-]+(?::[0-9]+)?)\/([A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*):([A-Za-z0-9_][A-Za-z0-9_.-]*)@(sha256:[a-f0-9]{64})$/.exec(
400
+ image,
401
+ );
402
+ const resolved = machine.image_ref;
403
+ if (!requested || !resolved || typeof resolved !== 'object') return false;
404
+ const [, registry, repository, imageTag, digest] = requested;
405
+ const tag = `${registry}/${repository}:${imageTag}`;
406
+ return (
407
+ (machine.config?.image === image || machine.config?.image === tag) &&
408
+ resolved.registry === registry &&
409
+ resolved.repository === repository &&
410
+ resolved.tag === imageTag &&
411
+ resolved.digest === digest
412
+ );
413
+ }
414
+
349
415
  export function laneQueueName(releaseId: string): string {
350
416
  return `runs_${releaseId}`;
351
417
  }
@@ -366,16 +432,32 @@ export function buildBootMachineConfig(input: {
366
432
  app: string;
367
433
  releaseId: string;
368
434
  sha: string;
435
+ imageRef?: string;
369
436
  runtimeSurfaceHash?: string;
370
437
  componentInputHash?: string;
371
438
  region?: string;
372
439
  rollbackHoldUntilMs?: number;
373
440
  draining?: boolean;
441
+ /** Provider secrets propagation fence; never a runtime schema or wire floor. */
442
+ secretsPropagationFence?: number;
374
443
  }): Record<string, unknown> {
444
+ if (input.secretsPropagationFence !== undefined) {
445
+ assertMinSecretsVersion(input.secretsPropagationFence);
446
+ }
375
447
  return {
376
448
  region: input.region ?? DEFAULT_ABSURD_FLY_REGION,
449
+ ...(input.secretsPropagationFence === undefined
450
+ ? {}
451
+ : { min_secrets_version: input.secretsPropagationFence }),
377
452
  config: {
378
- image: laneImageRef(input.app, input.sha),
453
+ image:
454
+ input.imageRef === undefined
455
+ ? laneImageRef(input.app, input.sha)
456
+ : resolveWorkerLaneImage({
457
+ app: input.app,
458
+ sha: input.sha,
459
+ imageRef: input.imageRef,
460
+ }).imageRef,
379
461
  metadata: {
380
462
  [RELEASE_METADATA_KEY]: input.releaseId,
381
463
  ...(input.runtimeSurfaceHash
@@ -569,6 +651,12 @@ export function requireFlyToken(
569
651
  return token;
570
652
  }
571
653
 
654
+ function assertMinSecretsVersion(value: unknown): asserts value is number {
655
+ if (typeof value !== 'number' || !Number.isSafeInteger(value) || value <= 0) {
656
+ throw new Error('Fly secrets version must be a positive safe integer.');
657
+ }
658
+ }
659
+
572
660
  export class FlyMachinesClient {
573
661
  constructor(
574
662
  private readonly app: string,
@@ -681,6 +769,22 @@ export class FlyMachinesClient {
681
769
  return (await this.request('POST', '/machines', config)) as FlyMachine;
682
770
  }
683
771
 
772
+ /**
773
+ * Match native `flyctl secrets sync` without consulting its local config.
774
+ * The native protocol unsets a random nonexistent name to obtain a version;
775
+ * GET /secrets returns metadata only and cannot establish this fence.
776
+ * https://github.com/superfly/flyctl/blob/b3263736a487b5c713fc7733633cfbb2e2976dd6/internal/appsecrets/secrets.go#L48-L57
777
+ */
778
+ async syncAppSecretsVersion(): Promise<number> {
779
+ const name = `BogusDummySecret_${randomBytes(8).toString('hex')}`;
780
+ const result = await this.request('POST', '/secrets', {
781
+ values: { [name]: null },
782
+ });
783
+ const version = (result as { version?: unknown } | null)?.version;
784
+ assertMinSecretsVersion(version);
785
+ return version;
786
+ }
787
+
684
788
  async updateMachine(
685
789
  id: string,
686
790
  config: Record<string, unknown>,
@@ -1063,8 +1167,11 @@ export async function bootLane(input: {
1063
1167
  app: string;
1064
1168
  releaseId: string;
1065
1169
  sha: string;
1170
+ imageRef?: string;
1066
1171
  runtimeSurfaceHash?: string;
1067
1172
  componentInputHash?: string;
1173
+ /** Provider secrets propagation fence; never a runtime schema or wire floor. */
1174
+ secretsPropagationFence?: number;
1068
1175
  count: number;
1069
1176
  region?: string;
1070
1177
  timeoutMs?: number;
@@ -1078,6 +1185,9 @@ export async function bootLane(input: {
1078
1185
  rollbackHoldUntilMs?: number;
1079
1186
  rollbackHoldScalerQuiescenceMs?: number;
1080
1187
  }): Promise<FlyMachine[]> {
1188
+ if (input.secretsPropagationFence !== undefined) {
1189
+ assertMinSecretsVersion(input.secretsPropagationFence);
1190
+ }
1081
1191
  const now = input.now ?? (() => Date.now());
1082
1192
  const wait = input.wait ?? sleep;
1083
1193
  const timeoutMs = input.timeoutMs ?? DEFAULT_BOOT_TIMEOUT_MS;
@@ -1086,7 +1196,14 @@ export async function bootLane(input: {
1086
1196
  input.imagePropagationRetryDelaysMs ??
1087
1197
  DEFAULT_IMAGE_PROPAGATION_RETRY_DELAYS_MS;
1088
1198
 
1089
- const expectedImage = laneImageRef(input.app, input.sha);
1199
+ const expectedImage =
1200
+ input.imageRef === undefined
1201
+ ? laneImageRef(input.app, input.sha)
1202
+ : resolveWorkerLaneImage({
1203
+ app: input.app,
1204
+ sha: input.sha,
1205
+ imageRef: input.imageRef,
1206
+ }).imageRef;
1090
1207
  const reusableStates = new Set([
1091
1208
  'started',
1092
1209
  'created',
@@ -1105,7 +1222,7 @@ export async function bootLane(input: {
1105
1222
  ? (await input.client.machinesInLane(input.releaseId))
1106
1223
  .filter(
1107
1224
  (machine) =>
1108
- machine.config?.image === expectedImage &&
1225
+ flyMachineMatchesImage(machine, expectedImage) &&
1109
1226
  (!input.runtimeSurfaceHash ||
1110
1227
  machine.config?.metadata?.[RUNTIME_SURFACE_METADATA_KEY] ===
1111
1228
  input.runtimeSurfaceHash) &&
@@ -1113,7 +1230,7 @@ export async function bootLane(input: {
1113
1230
  machine.config?.metadata?.[COMPONENT_INPUT_METADATA_KEY] ===
1114
1231
  input.componentInputHash) &&
1115
1232
  (input.rollbackHoldUntilMs !== undefined ||
1116
- machine.config.env?.[DRAIN_EXIT_ENV] !== '1') &&
1233
+ machine.config?.env?.[DRAIN_EXIT_ENV] !== '1') &&
1117
1234
  reusableStates.has(machine.state ?? ''),
1118
1235
  )
1119
1236
  .sort((left, right) => statePriority(left) - statePriority(right))
@@ -1151,8 +1268,10 @@ export async function bootLane(input: {
1151
1268
  app: input.app,
1152
1269
  releaseId: input.releaseId,
1153
1270
  sha: input.sha,
1271
+ imageRef: input.imageRef,
1154
1272
  runtimeSurfaceHash: input.runtimeSurfaceHash,
1155
1273
  componentInputHash: input.componentInputHash,
1274
+ secretsPropagationFence: input.secretsPropagationFence,
1156
1275
  region: input.region,
1157
1276
  rollbackHoldUntilMs: input.rollbackHoldUntilMs,
1158
1277
  }),
@@ -1243,8 +1362,11 @@ export async function replaceLane(input: {
1243
1362
  app: string;
1244
1363
  releaseId: string;
1245
1364
  sha: string;
1365
+ imageRef?: string;
1246
1366
  runtimeSurfaceHash?: string;
1247
1367
  componentInputHash?: string;
1368
+ /** Provider secrets propagation fence; never a runtime schema or wire floor. */
1369
+ secretsPropagationFence?: number;
1248
1370
  count: number;
1249
1371
  region?: string;
1250
1372
  stopTimeoutMs?: number;
@@ -1253,12 +1375,21 @@ export async function replaceLane(input: {
1253
1375
  wait?: (ms: number) => Promise<void>;
1254
1376
  machineLogs?: (machineId: string) => string;
1255
1377
  }): Promise<FlyMachine[]> {
1378
+ if (input.secretsPropagationFence !== undefined) {
1379
+ assertMinSecretsVersion(input.secretsPropagationFence);
1380
+ }
1256
1381
  const now = input.now ?? (() => Date.now());
1257
1382
  const wait = input.wait ?? sleep;
1258
1383
  const stopTimeoutMs =
1259
1384
  input.stopTimeoutMs ?? DEFAULT_LANE_REPLACEMENT_STOP_WAIT_MS;
1260
1385
  const stopPollIntervalMs =
1261
1386
  input.stopPollIntervalMs ?? DEFAULT_LANE_REPLACEMENT_STOP_POLL_INTERVAL_MS;
1387
+ if (input.imageRef !== undefined)
1388
+ resolveWorkerLaneImage({
1389
+ app: input.app,
1390
+ sha: input.sha,
1391
+ imageRef: input.imageRef,
1392
+ });
1262
1393
  const predecessors = await input.client.machinesInLane(input.releaseId);
1263
1394
  const predecessorIds = new Set(predecessors.map((machine) => machine.id));
1264
1395
 
@@ -1303,8 +1434,10 @@ export async function replaceLane(input: {
1303
1434
  app: input.app,
1304
1435
  releaseId: input.releaseId,
1305
1436
  sha: input.sha,
1437
+ imageRef: input.imageRef,
1306
1438
  runtimeSurfaceHash: input.runtimeSurfaceHash,
1307
1439
  componentInputHash: input.componentInputHash,
1440
+ secretsPropagationFence: input.secretsPropagationFence,
1308
1441
  count: input.count,
1309
1442
  region: input.region,
1310
1443
  now,
@@ -1329,6 +1462,10 @@ async function cmdBoot(flags: Record<string, string | boolean>): Promise<void> {
1329
1462
  const app = resolveApp(flags);
1330
1463
  const releaseId = requireReleaseId(flags);
1331
1464
  const sha = requireSha(flags);
1465
+ const imageRef =
1466
+ flags['image-ref'] === undefined
1467
+ ? undefined
1468
+ : requireStringFlag(flags, 'image-ref');
1332
1469
  const count = requireCount(flags);
1333
1470
  const region = typeof flags.region === 'string' ? flags.region : undefined;
1334
1471
  const reuseExisting = flags['reuse-existing'] === true;
@@ -1374,12 +1511,16 @@ async function cmdBoot(flags: Record<string, string | boolean>): Promise<void> {
1374
1511
  app,
1375
1512
  releaseId,
1376
1513
  sha,
1514
+ imageRef,
1377
1515
  runtimeSurfaceHash,
1378
1516
  componentInputHash,
1379
1517
  count,
1380
1518
  region,
1381
1519
  reuseExisting,
1382
1520
  rollbackHoldUntilMs,
1521
+ ...(flags.environment === 'preview'
1522
+ ? { secretsPropagationFence: await client.syncAppSecretsVersion() }
1523
+ : {}),
1383
1524
  });
1384
1525
  }
1385
1526
 
@@ -1389,6 +1530,10 @@ async function cmdReplace(
1389
1530
  const app = resolveApp(flags);
1390
1531
  const releaseId = requireReleaseId(flags);
1391
1532
  const sha = requireSha(flags);
1533
+ const imageRef =
1534
+ flags['image-ref'] === undefined
1535
+ ? undefined
1536
+ : requireStringFlag(flags, 'image-ref');
1392
1537
  const count = requireCount(flags);
1393
1538
  const region = typeof flags.region === 'string' ? flags.region : undefined;
1394
1539
  const componentInputHash =
@@ -1410,9 +1555,13 @@ async function cmdReplace(
1410
1555
  app,
1411
1556
  releaseId,
1412
1557
  sha,
1558
+ imageRef,
1413
1559
  componentInputHash,
1414
1560
  count,
1415
1561
  region,
1562
+ ...(flags.environment === 'preview'
1563
+ ? { secretsPropagationFence: await client.syncAppSecretsVersion() }
1564
+ : {}),
1416
1565
  });
1417
1566
  }
1418
1567
 
@@ -2065,8 +2214,8 @@ const USAGE = `fly-absurd-lane <command> [flags]
2065
2214
  Commands:
2066
2215
  push-image --sha <sha> --release <id> [--app <app>]
2067
2216
  plan-image --release <id> [--image-ref <ref>] [--app <app>]
2068
- boot --release <id> --sha <sha> --count <K> [--reuse-existing] [--component-input-hash <sha256>] [--rollback-hold-until-ms <ms>] [--app <app>] [--region <r>]
2069
- replace --release <id> --sha <sha> --count <K> --environment preview [--component-input-hash <sha256>] [--app <app>] [--region <r>]
2217
+ boot --release <id> --sha <sha> --count <K> [--image-ref <ref>] [--reuse-existing] [--component-input-hash <sha256>] [--rollback-hold-until-ms <ms>] [--app <app>] [--region <r>]
2218
+ replace --release <id> --sha <sha> --count <K> [--image-ref <ref>] --environment preview [--component-input-hash <sha256>] [--app <app>] [--region <r>]
2070
2219
  list [--release <id>] [--json] [--app <app>]
2071
2220
  drain --release <id> [--if-present] [--app <app>]
2072
2221
  stop-claiming --release <id> [--environment production|preview]