@smthrs/gateway 0.35.0 → 1.0.0-rc.3

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 (605) hide show
  1. package/CHANGELOG.md +198 -0
  2. package/LICENSE +1 -1
  3. package/README.md +92 -0
  4. package/dist/cjs/Diagnosis.d.ts +275 -0
  5. package/dist/cjs/Diagnosis.d.ts.map +1 -0
  6. package/dist/cjs/Diagnosis.js +476 -0
  7. package/dist/cjs/Diagnosis.js.map +7 -0
  8. package/dist/cjs/EngineTrace.d.ts +76 -0
  9. package/dist/cjs/EngineTrace.d.ts.map +1 -0
  10. package/dist/cjs/EngineTrace.js +501 -0
  11. package/dist/cjs/EngineTrace.js.map +7 -0
  12. package/dist/cjs/GatewayError.d.ts +54 -0
  13. package/dist/cjs/GatewayError.d.ts.map +1 -0
  14. package/dist/cjs/GatewayError.js +51 -0
  15. package/dist/cjs/GatewayError.js.map +7 -0
  16. package/dist/cjs/GatewayProjection.d.ts +480 -0
  17. package/dist/cjs/GatewayProjection.d.ts.map +1 -0
  18. package/dist/cjs/GatewayProjection.js +462 -0
  19. package/dist/cjs/GatewayProjection.js.map +7 -0
  20. package/dist/cjs/GatewayRpcs.d.ts +1886 -0
  21. package/dist/cjs/GatewayRpcs.d.ts.map +1 -0
  22. package/dist/cjs/GatewayRpcs.js +121 -0
  23. package/dist/cjs/GatewayRpcs.js.map +7 -0
  24. package/dist/cjs/GatewaySchema.d.ts +3274 -0
  25. package/dist/cjs/GatewaySchema.d.ts.map +1 -0
  26. package/dist/cjs/GatewaySchema.js +141 -0
  27. package/dist/cjs/GatewaySchema.js.map +7 -0
  28. package/dist/cjs/GatewayServer.d.ts +427 -0
  29. package/dist/cjs/GatewayServer.d.ts.map +1 -0
  30. package/dist/cjs/GatewayServer.js +428 -0
  31. package/dist/cjs/GatewayServer.js.map +7 -0
  32. package/dist/cjs/HostBranchPresence.d.ts +12 -0
  33. package/dist/cjs/HostBranchPresence.d.ts.map +1 -0
  34. package/dist/cjs/HostBranchPresence.js +82 -0
  35. package/dist/cjs/HostBranchPresence.js.map +7 -0
  36. package/dist/cjs/Projections.d.ts +209 -0
  37. package/dist/cjs/Projections.d.ts.map +1 -0
  38. package/dist/cjs/Projections.js +906 -0
  39. package/dist/cjs/Projections.js.map +7 -0
  40. package/dist/cjs/RunDevTools.d.ts +181 -0
  41. package/dist/cjs/RunDevTools.d.ts.map +1 -0
  42. package/dist/cjs/RunDevTools.js +195 -0
  43. package/dist/cjs/RunDevTools.js.map +7 -0
  44. package/dist/cjs/RunHistory.d.ts +185 -0
  45. package/dist/cjs/RunHistory.d.ts.map +1 -0
  46. package/dist/cjs/RunHistory.js +68 -0
  47. package/dist/cjs/RunHistory.js.map +7 -0
  48. package/dist/cjs/RunTrace.d.ts +753 -0
  49. package/dist/cjs/RunTrace.d.ts.map +1 -0
  50. package/dist/cjs/RunTrace.js +1593 -0
  51. package/dist/cjs/RunTrace.js.map +7 -0
  52. package/dist/cjs/RuntimeBridge.d.ts +1386 -0
  53. package/dist/cjs/RuntimeBridge.d.ts.map +1 -0
  54. package/dist/cjs/RuntimeBridge.js +598 -0
  55. package/dist/cjs/RuntimeBridge.js.map +7 -0
  56. package/dist/cjs/bun/BunGateway.d.ts +20 -0
  57. package/dist/cjs/bun/BunGateway.d.ts.map +1 -0
  58. package/dist/cjs/bun/BunGateway.js +62 -0
  59. package/dist/cjs/bun/BunGateway.js.map +7 -0
  60. package/dist/cjs/index.d.ts +65 -0
  61. package/dist/cjs/index.d.ts.map +1 -0
  62. package/dist/cjs/index.js +59 -0
  63. package/dist/cjs/index.js.map +7 -0
  64. package/dist/cjs/internal/NativeGateway.d.ts +176 -0
  65. package/dist/cjs/internal/NativeGateway.d.ts.map +1 -0
  66. package/dist/cjs/internal/NativeGateway.js +187 -0
  67. package/dist/cjs/internal/NativeGateway.js.map +7 -0
  68. package/dist/cjs/internal/actionRenderings.d.ts +2 -0
  69. package/dist/cjs/internal/actionRenderings.d.ts.map +1 -0
  70. package/dist/cjs/internal/actionRenderings.js +224 -0
  71. package/dist/cjs/internal/actionRenderings.js.map +7 -0
  72. package/dist/cjs/internal/callEvents.d.ts +97 -0
  73. package/dist/cjs/internal/callEvents.d.ts.map +1 -0
  74. package/dist/cjs/internal/callEvents.js +169 -0
  75. package/dist/cjs/internal/callEvents.js.map +7 -0
  76. package/dist/cjs/internal/digestIndex.d.ts +31 -0
  77. package/dist/cjs/internal/digestIndex.d.ts.map +1 -0
  78. package/dist/cjs/internal/digestIndex.js +105 -0
  79. package/dist/cjs/internal/digestIndex.js.map +7 -0
  80. package/dist/cjs/internal/digestMemory.d.ts +19 -0
  81. package/dist/cjs/internal/digestMemory.d.ts.map +1 -0
  82. package/dist/cjs/internal/digestMemory.js +33 -0
  83. package/dist/cjs/internal/digestMemory.js.map +7 -0
  84. package/dist/cjs/internal/inspectLabels.d.ts +8 -0
  85. package/dist/cjs/internal/inspectLabels.d.ts.map +1 -0
  86. package/dist/cjs/internal/inspectLabels.js +29 -0
  87. package/dist/cjs/internal/inspectLabels.js.map +7 -0
  88. package/dist/cjs/internal/nativeResolution.d.ts +41 -0
  89. package/dist/cjs/internal/nativeResolution.d.ts.map +1 -0
  90. package/dist/cjs/internal/nativeResolution.js +62 -0
  91. package/dist/cjs/internal/nativeResolution.js.map +7 -0
  92. package/dist/cjs/internal/nodeEvents.d.ts +47 -0
  93. package/dist/cjs/internal/nodeEvents.d.ts.map +1 -0
  94. package/dist/cjs/internal/nodeEvents.js +60 -0
  95. package/dist/cjs/internal/nodeEvents.js.map +7 -0
  96. package/dist/cjs/node/NodeGateway.d.ts +16 -0
  97. package/dist/cjs/node/NodeGateway.d.ts.map +1 -0
  98. package/dist/cjs/node/NodeGateway.js +48 -0
  99. package/dist/cjs/node/NodeGateway.js.map +7 -0
  100. package/dist/cjs/package.json +1 -0
  101. package/dist/esm/Diagnosis.d.ts +275 -0
  102. package/dist/esm/Diagnosis.d.ts.map +1 -0
  103. package/dist/esm/Diagnosis.js +697 -0
  104. package/dist/esm/Diagnosis.js.map +1 -0
  105. package/dist/esm/EngineTrace.d.ts +76 -0
  106. package/dist/esm/EngineTrace.d.ts.map +1 -0
  107. package/dist/esm/EngineTrace.js +548 -0
  108. package/dist/esm/EngineTrace.js.map +1 -0
  109. package/dist/esm/GatewayError.d.ts +54 -0
  110. package/dist/esm/GatewayError.d.ts.map +1 -0
  111. package/dist/esm/GatewayError.js +60 -0
  112. package/dist/esm/GatewayError.js.map +1 -0
  113. package/dist/esm/GatewayProjection.d.ts +480 -0
  114. package/dist/esm/GatewayProjection.d.ts.map +1 -0
  115. package/dist/esm/GatewayProjection.js +792 -0
  116. package/dist/esm/GatewayProjection.js.map +1 -0
  117. package/dist/esm/GatewayRpcs.d.ts +1886 -0
  118. package/dist/esm/GatewayRpcs.d.ts.map +1 -0
  119. package/dist/esm/GatewayRpcs.js +145 -0
  120. package/dist/esm/GatewayRpcs.js.map +1 -0
  121. package/dist/esm/GatewaySchema.d.ts +3274 -0
  122. package/dist/esm/GatewaySchema.d.ts.map +1 -0
  123. package/dist/esm/GatewaySchema.js +244 -0
  124. package/dist/esm/GatewaySchema.js.map +1 -0
  125. package/dist/esm/GatewayServer.d.ts +427 -0
  126. package/dist/esm/GatewayServer.d.ts.map +1 -0
  127. package/dist/esm/GatewayServer.js +725 -0
  128. package/dist/esm/GatewayServer.js.map +1 -0
  129. package/dist/esm/HostBranchPresence.d.ts +12 -0
  130. package/dist/esm/HostBranchPresence.d.ts.map +1 -0
  131. package/dist/esm/HostBranchPresence.js +54 -0
  132. package/dist/esm/HostBranchPresence.js.map +1 -0
  133. package/dist/esm/Projections.d.ts +209 -0
  134. package/dist/esm/Projections.d.ts.map +1 -0
  135. package/dist/esm/Projections.js +1254 -0
  136. package/dist/esm/Projections.js.map +1 -0
  137. package/dist/esm/RunDevTools.d.ts +181 -0
  138. package/dist/esm/RunDevTools.d.ts.map +1 -0
  139. package/dist/esm/RunDevTools.js +281 -0
  140. package/dist/esm/RunDevTools.js.map +1 -0
  141. package/dist/esm/RunHistory.d.ts +185 -0
  142. package/dist/esm/RunHistory.d.ts.map +1 -0
  143. package/dist/esm/RunHistory.js +109 -0
  144. package/dist/esm/RunHistory.js.map +1 -0
  145. package/dist/esm/RunTrace.d.ts +753 -0
  146. package/dist/esm/RunTrace.d.ts.map +1 -0
  147. package/dist/esm/RunTrace.js +2105 -0
  148. package/dist/esm/RunTrace.js.map +1 -0
  149. package/dist/esm/RuntimeBridge.d.ts +1386 -0
  150. package/dist/esm/RuntimeBridge.d.ts.map +1 -0
  151. package/dist/esm/RuntimeBridge.js +659 -0
  152. package/dist/esm/RuntimeBridge.js.map +1 -0
  153. package/dist/esm/bun/BunGateway.d.ts +20 -0
  154. package/dist/esm/bun/BunGateway.d.ts.map +1 -0
  155. package/dist/esm/bun/BunGateway.js +32 -0
  156. package/dist/esm/bun/BunGateway.js.map +1 -0
  157. package/dist/esm/index.d.ts +65 -0
  158. package/dist/esm/index.d.ts.map +1 -0
  159. package/dist/esm/index.js +65 -0
  160. package/dist/esm/index.js.map +1 -0
  161. package/dist/esm/internal/NativeGateway.d.ts +176 -0
  162. package/dist/esm/internal/NativeGateway.d.ts.map +1 -0
  163. package/dist/esm/internal/NativeGateway.js +268 -0
  164. package/dist/esm/internal/NativeGateway.js.map +1 -0
  165. package/dist/esm/internal/actionRenderings.d.ts +2 -0
  166. package/dist/esm/internal/actionRenderings.d.ts.map +1 -0
  167. package/dist/esm/internal/actionRenderings.js +202 -0
  168. package/dist/esm/internal/actionRenderings.js.map +1 -0
  169. package/dist/esm/internal/callEvents.d.ts +97 -0
  170. package/dist/esm/internal/callEvents.d.ts.map +1 -0
  171. package/dist/esm/internal/callEvents.js +206 -0
  172. package/dist/esm/internal/callEvents.js.map +1 -0
  173. package/dist/esm/internal/digestIndex.d.ts +31 -0
  174. package/dist/esm/internal/digestIndex.d.ts.map +1 -0
  175. package/dist/esm/internal/digestIndex.js +87 -0
  176. package/dist/esm/internal/digestIndex.js.map +1 -0
  177. package/dist/esm/internal/digestMemory.d.ts +19 -0
  178. package/dist/esm/internal/digestMemory.d.ts.map +1 -0
  179. package/dist/esm/internal/digestMemory.js +23 -0
  180. package/dist/esm/internal/digestMemory.js.map +1 -0
  181. package/dist/esm/internal/inspectLabels.d.ts +8 -0
  182. package/dist/esm/internal/inspectLabels.d.ts.map +1 -0
  183. package/dist/esm/internal/inspectLabels.js +12 -0
  184. package/dist/esm/internal/inspectLabels.js.map +1 -0
  185. package/dist/esm/internal/nativeResolution.d.ts +41 -0
  186. package/dist/esm/internal/nativeResolution.d.ts.map +1 -0
  187. package/dist/esm/internal/nativeResolution.js +78 -0
  188. package/dist/esm/internal/nativeResolution.js.map +1 -0
  189. package/dist/esm/internal/nodeEvents.d.ts +47 -0
  190. package/dist/esm/internal/nodeEvents.d.ts.map +1 -0
  191. package/dist/esm/internal/nodeEvents.js +60 -0
  192. package/dist/esm/internal/nodeEvents.js.map +1 -0
  193. package/dist/esm/node/NodeGateway.d.ts +16 -0
  194. package/dist/esm/node/NodeGateway.d.ts.map +1 -0
  195. package/dist/esm/node/NodeGateway.js +13 -0
  196. package/dist/esm/node/NodeGateway.js.map +1 -0
  197. package/dist/vendor/adapters.json +2707 -0
  198. package/dist/vendor/bun/BunChildProcessSpawner.d.ts +7 -0
  199. package/dist/vendor/bun/BunChildProcessSpawner.js +14 -0
  200. package/dist/vendor/bun/BunClusterHttp.d.ts +83 -0
  201. package/dist/vendor/bun/BunClusterHttp.js +39 -0
  202. package/dist/vendor/bun/BunClusterSocket.d.ts +65 -0
  203. package/dist/vendor/bun/BunClusterSocket.js +22 -0
  204. package/dist/vendor/bun/BunCrypto.d.ts +10 -0
  205. package/dist/vendor/bun/BunCrypto.js +8 -0
  206. package/dist/vendor/bun/BunFileSystem.d.ts +10 -0
  207. package/dist/vendor/bun/BunFileSystem.js +9 -0
  208. package/dist/vendor/bun/BunHttpClient.d.ts +9 -0
  209. package/dist/vendor/bun/BunHttpClient.js +1 -0
  210. package/dist/vendor/bun/BunHttpPlatform.d.ts +10 -0
  211. package/dist/vendor/bun/BunHttpPlatform.js +11 -0
  212. package/dist/vendor/bun/BunHttpServer.d.ts +142 -0
  213. package/dist/vendor/bun/BunHttpServer.js +38 -0
  214. package/dist/vendor/bun/BunHttpServerRequest.d.ts +18 -0
  215. package/dist/vendor/bun/BunHttpServerRequest.js +7 -0
  216. package/dist/vendor/bun/BunMultipart.d.ts +31 -0
  217. package/dist/vendor/bun/BunMultipart.js +12 -0
  218. package/dist/vendor/bun/BunPath.d.ts +24 -0
  219. package/dist/vendor/bun/BunPath.js +12 -0
  220. package/dist/vendor/bun/BunRedis.d.ts +49 -0
  221. package/dist/vendor/bun/BunRedis.js +11 -0
  222. package/dist/vendor/bun/BunRuntime.d.ts +85 -0
  223. package/dist/vendor/bun/BunRuntime.js +8 -0
  224. package/dist/vendor/bun/BunServices.d.ts +34 -0
  225. package/dist/vendor/bun/BunServices.js +23 -0
  226. package/dist/vendor/bun/BunSink.d.ts +8 -0
  227. package/dist/vendor/bun/BunSink.js +12 -0
  228. package/dist/vendor/bun/BunSocket.d.ts +40 -0
  229. package/dist/vendor/bun/BunSocket.js +29 -0
  230. package/dist/vendor/bun/BunSocketServer.d.ts +8 -0
  231. package/dist/vendor/bun/BunSocketServer.js +21 -0
  232. package/dist/vendor/bun/BunStdio.d.ts +11 -0
  233. package/dist/vendor/bun/BunStdio.js +10 -0
  234. package/dist/vendor/bun/BunStream.d.ts +19 -0
  235. package/dist/vendor/bun/BunStream.js +30 -0
  236. package/dist/vendor/bun/BunTerminal.d.ts +21 -0
  237. package/dist/vendor/bun/BunTerminal.js +10 -0
  238. package/dist/vendor/bun/BunWorker.d.ts +20 -0
  239. package/dist/vendor/bun/BunWorker.js +9 -0
  240. package/dist/vendor/bun/BunWorkerRunner.d.ts +12 -0
  241. package/dist/vendor/bun/BunWorkerRunner.js +7 -0
  242. package/dist/vendor/bun/LICENSE +21 -0
  243. package/dist/vendor/bun/index.d.ts +92 -0
  244. package/dist/vendor/bun/index.js +107 -0
  245. package/dist/vendor/chunk-2GCOZTTW.js +48 -0
  246. package/dist/vendor/chunk-37CUR3PO.js +81 -0
  247. package/dist/vendor/chunk-3ARKKENZ.js +45 -0
  248. package/dist/vendor/chunk-3NV2UDBI.js +7 -0
  249. package/dist/vendor/chunk-3OSW7CT7.js +143 -0
  250. package/dist/vendor/chunk-62R63L74.js +62 -0
  251. package/dist/vendor/chunk-6AQLBC2I.js +118 -0
  252. package/dist/vendor/chunk-6C5H7S6B.js +18 -0
  253. package/dist/vendor/chunk-6DY5RBZD.js +85 -0
  254. package/dist/vendor/chunk-6UPBD47P.js +53 -0
  255. package/dist/vendor/chunk-AVVVN75Z.js +96 -0
  256. package/dist/vendor/chunk-B4DHEMBB.js +14 -0
  257. package/dist/vendor/chunk-BCK3NJOX.js +15 -0
  258. package/dist/vendor/chunk-BFBIHJ6X.js +0 -0
  259. package/dist/vendor/chunk-CES4OUM4.js +63 -0
  260. package/dist/vendor/chunk-D64L6YND.js +59 -0
  261. package/dist/vendor/chunk-DS2R6WOM.js +18 -0
  262. package/dist/vendor/chunk-DX4Z23DM.js +65 -0
  263. package/dist/vendor/chunk-DZ2VOUDP.js +564 -0
  264. package/dist/vendor/chunk-FOXN6JPJ.js +61 -0
  265. package/dist/vendor/chunk-FPQF7CR5.js +55 -0
  266. package/dist/vendor/chunk-FUTCTCEG.js +20 -0
  267. package/dist/vendor/chunk-GUPAV2YZ.js +18 -0
  268. package/dist/vendor/chunk-H2Z2Y4QH.js +70 -0
  269. package/dist/vendor/chunk-HAEDVSSM.js +129 -0
  270. package/dist/vendor/chunk-HY7BBL3K.js +93 -0
  271. package/dist/vendor/chunk-IFTTT6D5.js +31 -0
  272. package/dist/vendor/chunk-KQDSNB7M.js +26 -0
  273. package/dist/vendor/chunk-LIHLXXGQ.js +26 -0
  274. package/dist/vendor/chunk-LKCGQEE5.js +28 -0
  275. package/dist/vendor/chunk-MH2J3BYB.js +0 -0
  276. package/dist/vendor/chunk-ML2NAFH2.js +131 -0
  277. package/dist/vendor/chunk-MLFIZ5O2.js +0 -0
  278. package/dist/vendor/chunk-MLKGABMK.js +9 -0
  279. package/dist/vendor/chunk-MSCLEMYX.js +71 -0
  280. package/dist/vendor/chunk-OBWXQKVP.js +57 -0
  281. package/dist/vendor/chunk-QR557K66.js +20 -0
  282. package/dist/vendor/chunk-R4QUY7DH.js +18 -0
  283. package/dist/vendor/chunk-RGECXXJS.js +18 -0
  284. package/dist/vendor/chunk-TFY7W6D4.js +36 -0
  285. package/dist/vendor/chunk-TGPIVY4A.js +104 -0
  286. package/dist/vendor/chunk-TGXCX6W3.js +398 -0
  287. package/dist/vendor/chunk-TOHSFXMV.js +437 -0
  288. package/dist/vendor/chunk-UHIDPUFF.js +34 -0
  289. package/dist/vendor/chunk-ULT6CWUI.js +109 -0
  290. package/dist/vendor/chunk-UXBGYQR3.js +18 -0
  291. package/dist/vendor/chunk-V6LUGQ7O.js +21 -0
  292. package/dist/vendor/chunk-W4OASVX6.js +92 -0
  293. package/dist/vendor/chunk-WAII54GA.js +18 -0
  294. package/dist/vendor/chunk-WECQDT36.js +426 -0
  295. package/dist/vendor/chunk-WHKMOC7Z.js +28 -0
  296. package/dist/vendor/chunk-WVFOZ2UL.js +40 -0
  297. package/dist/vendor/chunk-X73E2UPI.js +18 -0
  298. package/dist/vendor/chunk-XCYARUII.js +63 -0
  299. package/dist/vendor/chunk-XFEVTDVD.js +34 -0
  300. package/dist/vendor/chunk-XFZZYSJ4.js +22 -0
  301. package/dist/vendor/chunk-XJWJXLXJ.js +18 -0
  302. package/dist/vendor/chunk-XY3Q62EO.js +18 -0
  303. package/dist/vendor/chunk-YDASSC75.js +394 -0
  304. package/dist/vendor/chunk-Z6C7SO5Z.js +507 -0
  305. package/dist/vendor/chunk-Z7QNPJEB.js +229 -0
  306. package/dist/vendor/chunk-Z7QPP4YH.js +249 -0
  307. package/dist/vendor/chunk-ZCHYLHJH.js +86 -0
  308. package/dist/vendor/chunk-ZIQVYVMA.js +22 -0
  309. package/dist/vendor/chunk-ZPIG2CUA.js +34 -0
  310. package/dist/vendor/cjs/bun/BunChildProcessSpawner.d.ts +7 -0
  311. package/dist/vendor/cjs/bun/BunChildProcessSpawner.js +1 -0
  312. package/dist/vendor/cjs/bun/BunClusterHttp.d.ts +83 -0
  313. package/dist/vendor/cjs/bun/BunClusterHttp.js +1 -0
  314. package/dist/vendor/cjs/bun/BunClusterSocket.d.ts +65 -0
  315. package/dist/vendor/cjs/bun/BunClusterSocket.js +1 -0
  316. package/dist/vendor/cjs/bun/BunCrypto.d.ts +10 -0
  317. package/dist/vendor/cjs/bun/BunCrypto.js +1 -0
  318. package/dist/vendor/cjs/bun/BunFileSystem.d.ts +10 -0
  319. package/dist/vendor/cjs/bun/BunFileSystem.js +1 -0
  320. package/dist/vendor/cjs/bun/BunHttpClient.d.ts +9 -0
  321. package/dist/vendor/cjs/bun/BunHttpClient.js +1 -0
  322. package/dist/vendor/cjs/bun/BunHttpPlatform.d.ts +10 -0
  323. package/dist/vendor/cjs/bun/BunHttpPlatform.js +1 -0
  324. package/dist/vendor/cjs/bun/BunHttpServer.d.ts +142 -0
  325. package/dist/vendor/cjs/bun/BunHttpServer.js +1 -0
  326. package/dist/vendor/cjs/bun/BunHttpServerRequest.d.ts +18 -0
  327. package/dist/vendor/cjs/bun/BunHttpServerRequest.js +1 -0
  328. package/dist/vendor/cjs/bun/BunMultipart.d.ts +31 -0
  329. package/dist/vendor/cjs/bun/BunMultipart.js +1 -0
  330. package/dist/vendor/cjs/bun/BunPath.d.ts +24 -0
  331. package/dist/vendor/cjs/bun/BunPath.js +1 -0
  332. package/dist/vendor/cjs/bun/BunRedis.d.ts +49 -0
  333. package/dist/vendor/cjs/bun/BunRedis.js +1 -0
  334. package/dist/vendor/cjs/bun/BunRuntime.d.ts +85 -0
  335. package/dist/vendor/cjs/bun/BunRuntime.js +1 -0
  336. package/dist/vendor/cjs/bun/BunServices.d.ts +34 -0
  337. package/dist/vendor/cjs/bun/BunServices.js +1 -0
  338. package/dist/vendor/cjs/bun/BunSink.d.ts +8 -0
  339. package/dist/vendor/cjs/bun/BunSink.js +1 -0
  340. package/dist/vendor/cjs/bun/BunSocket.d.ts +40 -0
  341. package/dist/vendor/cjs/bun/BunSocket.js +1 -0
  342. package/dist/vendor/cjs/bun/BunSocketServer.d.ts +8 -0
  343. package/dist/vendor/cjs/bun/BunSocketServer.js +1 -0
  344. package/dist/vendor/cjs/bun/BunStdio.d.ts +11 -0
  345. package/dist/vendor/cjs/bun/BunStdio.js +1 -0
  346. package/dist/vendor/cjs/bun/BunStream.d.ts +19 -0
  347. package/dist/vendor/cjs/bun/BunStream.js +1 -0
  348. package/dist/vendor/cjs/bun/BunTerminal.d.ts +21 -0
  349. package/dist/vendor/cjs/bun/BunTerminal.js +1 -0
  350. package/dist/vendor/cjs/bun/BunWorker.d.ts +20 -0
  351. package/dist/vendor/cjs/bun/BunWorker.js +1 -0
  352. package/dist/vendor/cjs/bun/BunWorkerRunner.d.ts +12 -0
  353. package/dist/vendor/cjs/bun/BunWorkerRunner.js +1 -0
  354. package/dist/vendor/cjs/bun/index.d.ts +92 -0
  355. package/dist/vendor/cjs/bun/index.js +1 -0
  356. package/dist/vendor/cjs/node/NodeChildProcessSpawner.d.ts +7 -0
  357. package/dist/vendor/cjs/node/NodeChildProcessSpawner.js +1 -0
  358. package/dist/vendor/cjs/node/NodeClusterHttp.d.ts +63 -0
  359. package/dist/vendor/cjs/node/NodeClusterHttp.js +1 -0
  360. package/dist/vendor/cjs/node/NodeClusterSocket.d.ts +79 -0
  361. package/dist/vendor/cjs/node/NodeClusterSocket.js +1 -0
  362. package/dist/vendor/cjs/node/NodeCrypto.d.ts +10 -0
  363. package/dist/vendor/cjs/node/NodeCrypto.js +1 -0
  364. package/dist/vendor/cjs/node/NodeFileSystem.d.ts +10 -0
  365. package/dist/vendor/cjs/node/NodeFileSystem.js +1 -0
  366. package/dist/vendor/cjs/node/NodeHttpClient.d.ts +179 -0
  367. package/dist/vendor/cjs/node/NodeHttpClient.js +1 -0
  368. package/dist/vendor/cjs/node/NodeHttpIncomingMessage.d.ts +62 -0
  369. package/dist/vendor/cjs/node/NodeHttpIncomingMessage.js +1 -0
  370. package/dist/vendor/cjs/node/NodeHttpPlatform.d.ts +36 -0
  371. package/dist/vendor/cjs/node/NodeHttpPlatform.js +1 -0
  372. package/dist/vendor/cjs/node/NodeHttpServer.d.ts +120 -0
  373. package/dist/vendor/cjs/node/NodeHttpServer.js +1 -0
  374. package/dist/vendor/cjs/node/NodeHttpServerRequest.d.ts +29 -0
  375. package/dist/vendor/cjs/node/NodeHttpServerRequest.js +1 -0
  376. package/dist/vendor/cjs/node/NodeMultipart.d.ts +46 -0
  377. package/dist/vendor/cjs/node/NodeMultipart.js +1 -0
  378. package/dist/vendor/cjs/node/NodeMultipartParser.d.ts +97 -0
  379. package/dist/vendor/cjs/node/NodeMultipartParser.js +1 -0
  380. package/dist/vendor/cjs/node/NodePath.d.ts +27 -0
  381. package/dist/vendor/cjs/node/NodePath.js +1 -0
  382. package/dist/vendor/cjs/node/NodeRedis.d.ts +74 -0
  383. package/dist/vendor/cjs/node/NodeRedis.js +1 -0
  384. package/dist/vendor/cjs/node/NodeRuntime.d.ts +85 -0
  385. package/dist/vendor/cjs/node/NodeRuntime.js +1 -0
  386. package/dist/vendor/cjs/node/NodeServices.d.ts +34 -0
  387. package/dist/vendor/cjs/node/NodeServices.js +1 -0
  388. package/dist/vendor/cjs/node/NodeSink.d.ts +8 -0
  389. package/dist/vendor/cjs/node/NodeSink.js +1 -0
  390. package/dist/vendor/cjs/node/NodeSocket.d.ts +38 -0
  391. package/dist/vendor/cjs/node/NodeSocket.js +1 -0
  392. package/dist/vendor/cjs/node/NodeSocketServer.d.ts +8 -0
  393. package/dist/vendor/cjs/node/NodeSocketServer.js +1 -0
  394. package/dist/vendor/cjs/node/NodeStdio.d.ts +11 -0
  395. package/dist/vendor/cjs/node/NodeStdio.js +1 -0
  396. package/dist/vendor/cjs/node/NodeStream.d.ts +8 -0
  397. package/dist/vendor/cjs/node/NodeStream.js +1 -0
  398. package/dist/vendor/cjs/node/NodeTerminal.d.ts +21 -0
  399. package/dist/vendor/cjs/node/NodeTerminal.js +1 -0
  400. package/dist/vendor/cjs/node/NodeWorker.d.ts +22 -0
  401. package/dist/vendor/cjs/node/NodeWorker.js +1 -0
  402. package/dist/vendor/cjs/node/NodeWorkerRunner.d.ts +12 -0
  403. package/dist/vendor/cjs/node/NodeWorkerRunner.js +1 -0
  404. package/dist/vendor/cjs/node/Undici.d.ts +28 -0
  405. package/dist/vendor/cjs/node/Undici.js +1 -0
  406. package/dist/vendor/cjs/node/index.d.ts +100 -0
  407. package/dist/vendor/cjs/node/index.js +1 -0
  408. package/dist/vendor/cjs/node-shared/NodeChildProcessSpawner.d.ts +57 -0
  409. package/dist/vendor/cjs/node-shared/NodeChildProcessSpawner.js +1 -0
  410. package/dist/vendor/cjs/node-shared/NodeClusterSocket.d.ts +22 -0
  411. package/dist/vendor/cjs/node-shared/NodeClusterSocket.js +1 -0
  412. package/dist/vendor/cjs/node-shared/NodeCrypto.d.ts +27 -0
  413. package/dist/vendor/cjs/node-shared/NodeCrypto.js +1 -0
  414. package/dist/vendor/cjs/node-shared/NodeFileSystem.d.ts +11 -0
  415. package/dist/vendor/cjs/node-shared/NodeFileSystem.js +1 -0
  416. package/dist/vendor/cjs/node-shared/NodeHttpCompression.d.ts +36 -0
  417. package/dist/vendor/cjs/node-shared/NodeHttpCompression.js +1 -0
  418. package/dist/vendor/cjs/node-shared/NodePath.d.ts +27 -0
  419. package/dist/vendor/cjs/node-shared/NodePath.js +1 -0
  420. package/dist/vendor/cjs/node-shared/NodeRuntime.d.ts +47 -0
  421. package/dist/vendor/cjs/node-shared/NodeRuntime.js +1 -0
  422. package/dist/vendor/cjs/node-shared/NodeSink.d.ts +69 -0
  423. package/dist/vendor/cjs/node-shared/NodeSink.js +1 -0
  424. package/dist/vendor/cjs/node-shared/NodeSocket.d.ts +134 -0
  425. package/dist/vendor/cjs/node-shared/NodeSocket.js +1 -0
  426. package/dist/vendor/cjs/node-shared/NodeSocketServer.d.ts +80 -0
  427. package/dist/vendor/cjs/node-shared/NodeSocketServer.js +1 -0
  428. package/dist/vendor/cjs/node-shared/NodeStdio.d.ts +12 -0
  429. package/dist/vendor/cjs/node-shared/NodeStdio.js +1 -0
  430. package/dist/vendor/cjs/node-shared/NodeStream.d.ts +179 -0
  431. package/dist/vendor/cjs/node-shared/NodeStream.js +1 -0
  432. package/dist/vendor/cjs/node-shared/NodeTerminal.d.ts +22 -0
  433. package/dist/vendor/cjs/node-shared/NodeTerminal.js +1 -0
  434. package/dist/vendor/cjs/node-shared/index.d.ts +56 -0
  435. package/dist/vendor/cjs/node-shared/index.js +1 -0
  436. package/dist/vendor/cjs/node-shared/internal/nodeChildProcessSpawner.d.ts +4 -0
  437. package/dist/vendor/cjs/node-shared/internal/nodeChildProcessSpawner.js +1 -0
  438. package/dist/vendor/cjs/node-shared/internal/utils.d.ts +2 -0
  439. package/dist/vendor/cjs/node-shared/internal/utils.js +1 -0
  440. package/dist/vendor/cjs/package.json +1 -0
  441. package/dist/vendor/cjs/platform-bun.d.ts +92 -0
  442. package/dist/vendor/cjs/platform-bun.js +1 -0
  443. package/dist/vendor/cjs/platform-node-shared.d.ts +56 -0
  444. package/dist/vendor/cjs/platform-node-shared.js +1 -0
  445. package/dist/vendor/cjs/platform-node.d.ts +100 -0
  446. package/dist/vendor/cjs/platform-node.js +1 -0
  447. package/dist/vendor/node/LICENSE +21 -0
  448. package/dist/vendor/node/NodeChildProcessSpawner.d.ts +7 -0
  449. package/dist/vendor/node/NodeChildProcessSpawner.js +14 -0
  450. package/dist/vendor/node/NodeClusterHttp.d.ts +63 -0
  451. package/dist/vendor/node/NodeClusterHttp.js +43 -0
  452. package/dist/vendor/node/NodeClusterSocket.d.ts +79 -0
  453. package/dist/vendor/node/NodeClusterSocket.js +30 -0
  454. package/dist/vendor/node/NodeCrypto.d.ts +10 -0
  455. package/dist/vendor/node/NodeCrypto.js +8 -0
  456. package/dist/vendor/node/NodeFileSystem.d.ts +10 -0
  457. package/dist/vendor/node/NodeFileSystem.js +9 -0
  458. package/dist/vendor/node/NodeHttpClient.d.ts +179 -0
  459. package/dist/vendor/node/NodeHttpClient.js +46 -0
  460. package/dist/vendor/node/NodeHttpIncomingMessage.d.ts +62 -0
  461. package/dist/vendor/node/NodeHttpIncomingMessage.js +10 -0
  462. package/dist/vendor/node/NodeHttpPlatform.d.ts +36 -0
  463. package/dist/vendor/node/NodeHttpPlatform.js +16 -0
  464. package/dist/vendor/node/NodeHttpServer.d.ts +120 -0
  465. package/dist/vendor/node/NodeHttpServer.js +46 -0
  466. package/dist/vendor/node/NodeHttpServerRequest.d.ts +29 -0
  467. package/dist/vendor/node/NodeHttpServerRequest.js +9 -0
  468. package/dist/vendor/node/NodeMultipart.d.ts +46 -0
  469. package/dist/vendor/node/NodeMultipart.js +15 -0
  470. package/dist/vendor/node/NodeMultipartParser.d.ts +97 -0
  471. package/dist/vendor/node/NodeMultipartParser.js +11 -0
  472. package/dist/vendor/node/NodePath.d.ts +27 -0
  473. package/dist/vendor/node/NodePath.js +12 -0
  474. package/dist/vendor/node/NodeRedis.d.ts +74 -0
  475. package/dist/vendor/node/NodeRedis.js +11 -0
  476. package/dist/vendor/node/NodeRuntime.d.ts +85 -0
  477. package/dist/vendor/node/NodeRuntime.js +8 -0
  478. package/dist/vendor/node/NodeServices.d.ts +34 -0
  479. package/dist/vendor/node/NodeServices.js +23 -0
  480. package/dist/vendor/node/NodeSink.d.ts +8 -0
  481. package/dist/vendor/node/NodeSink.js +12 -0
  482. package/dist/vendor/node/NodeSocket.d.ts +38 -0
  483. package/dist/vendor/node/NodeSocket.js +31 -0
  484. package/dist/vendor/node/NodeSocketServer.d.ts +8 -0
  485. package/dist/vendor/node/NodeSocketServer.js +21 -0
  486. package/dist/vendor/node/NodeStdio.d.ts +11 -0
  487. package/dist/vendor/node/NodeStdio.js +10 -0
  488. package/dist/vendor/node/NodeStream.d.ts +8 -0
  489. package/dist/vendor/node/NodeStream.js +27 -0
  490. package/dist/vendor/node/NodeTerminal.d.ts +21 -0
  491. package/dist/vendor/node/NodeTerminal.js +10 -0
  492. package/dist/vendor/node/NodeWorker.d.ts +22 -0
  493. package/dist/vendor/node/NodeWorker.js +9 -0
  494. package/dist/vendor/node/NodeWorkerRunner.d.ts +12 -0
  495. package/dist/vendor/node/NodeWorkerRunner.js +7 -0
  496. package/dist/vendor/node/Undici.d.ts +28 -0
  497. package/dist/vendor/node/Undici.js +9 -0
  498. package/dist/vendor/node/index.d.ts +100 -0
  499. package/dist/vendor/node/index.js +115 -0
  500. package/dist/vendor/node-shared/LICENSE +21 -0
  501. package/dist/vendor/node-shared/NodeChildProcessSpawner.d.ts +57 -0
  502. package/dist/vendor/node-shared/NodeChildProcessSpawner.js +13 -0
  503. package/dist/vendor/node-shared/NodeClusterSocket.d.ts +22 -0
  504. package/dist/vendor/node-shared/NodeClusterSocket.js +11 -0
  505. package/dist/vendor/node-shared/NodeCrypto.d.ts +27 -0
  506. package/dist/vendor/node-shared/NodeCrypto.js +9 -0
  507. package/dist/vendor/node-shared/NodeFileSystem.d.ts +11 -0
  508. package/dist/vendor/node-shared/NodeFileSystem.js +8 -0
  509. package/dist/vendor/node-shared/NodeHttpCompression.d.ts +36 -0
  510. package/dist/vendor/node-shared/NodeHttpCompression.js +13 -0
  511. package/dist/vendor/node-shared/NodePath.d.ts +27 -0
  512. package/dist/vendor/node-shared/NodePath.js +11 -0
  513. package/dist/vendor/node-shared/NodeRuntime.d.ts +47 -0
  514. package/dist/vendor/node-shared/NodeRuntime.js +7 -0
  515. package/dist/vendor/node-shared/NodeSink.d.ts +69 -0
  516. package/dist/vendor/node-shared/NodeSink.js +11 -0
  517. package/dist/vendor/node-shared/NodeSocket.d.ts +134 -0
  518. package/dist/vendor/node-shared/NodeSocket.js +23 -0
  519. package/dist/vendor/node-shared/NodeSocketServer.d.ts +80 -0
  520. package/dist/vendor/node-shared/NodeSocketServer.js +20 -0
  521. package/dist/vendor/node-shared/NodeStdio.d.ts +12 -0
  522. package/dist/vendor/node-shared/NodeStdio.js +9 -0
  523. package/dist/vendor/node-shared/NodeStream.d.ts +179 -0
  524. package/dist/vendor/node-shared/NodeStream.js +26 -0
  525. package/dist/vendor/node-shared/NodeTerminal.d.ts +22 -0
  526. package/dist/vendor/node-shared/NodeTerminal.js +9 -0
  527. package/dist/vendor/node-shared/index.d.ts +56 -0
  528. package/dist/vendor/node-shared/index.js +58 -0
  529. package/dist/vendor/node-shared/internal/nodeChildProcessSpawner.d.ts +4 -0
  530. package/dist/vendor/node-shared/internal/nodeChildProcessSpawner.js +7 -0
  531. package/dist/vendor/node-shared/internal/utils.d.ts +2 -0
  532. package/dist/vendor/node-shared/internal/utils.js +7 -0
  533. package/dist/vendor/platform-bun.d.ts +92 -0
  534. package/dist/vendor/platform-bun.js +107 -0
  535. package/dist/vendor/platform-node-shared.d.ts +56 -0
  536. package/dist/vendor/platform-node-shared.js +58 -0
  537. package/dist/vendor/platform-node.d.ts +100 -0
  538. package/dist/vendor/platform-node.js +115 -0
  539. package/docs/README.md +158 -0
  540. package/docs/api.md +601 -0
  541. package/docs/concepts/projections.md +250 -0
  542. package/docs/concepts/subscriptions.md +204 -0
  543. package/docs/concepts/trust-boundary.md +256 -0
  544. package/docs/guides/diagnose-a-run.md +115 -0
  545. package/docs/guides/follow-a-run.md +150 -0
  546. package/docs/guides/host-the-gateway.md +153 -0
  547. package/docs/guides/read-a-projection.md +138 -0
  548. package/docs/guides/serve-beyond-loopback.md +166 -0
  549. package/docs/guides/submit-an-approval.md +187 -0
  550. package/docs/guides/testing.md +148 -0
  551. package/docs/installation.md +89 -0
  552. package/docs/quickstart.md +200 -0
  553. package/docs/troubleshooting.md +355 -0
  554. package/package.json +264 -32
  555. package/src/Diagnosis.ts +892 -0
  556. package/src/EngineTrace.ts +605 -0
  557. package/src/GatewayError.ts +71 -0
  558. package/src/GatewayProjection.ts +948 -0
  559. package/src/GatewayRpcs.ts +179 -0
  560. package/src/GatewaySchema.ts +516 -0
  561. package/src/GatewayServer.ts +932 -0
  562. package/src/HostBranchPresence.ts +72 -0
  563. package/src/Projections.ts +1735 -0
  564. package/src/RunDevTools.ts +394 -0
  565. package/src/RunHistory.ts +174 -0
  566. package/src/RunTrace.ts +2793 -0
  567. package/src/RuntimeBridge.ts +835 -0
  568. package/src/bun/BunGateway.ts +52 -0
  569. package/src/index.ts +77 -0
  570. package/src/internal/NativeGateway.ts +360 -0
  571. package/src/internal/actionRenderings.ts +201 -0
  572. package/src/internal/callEvents.ts +257 -0
  573. package/src/internal/digestIndex.ts +134 -0
  574. package/src/internal/digestMemory.ts +27 -0
  575. package/src/internal/inspectLabels.ts +13 -0
  576. package/src/internal/nativeResolution.ts +103 -0
  577. package/src/internal/nodeEvents.ts +100 -0
  578. package/src/node/NodeGateway.ts +30 -0
  579. package/openapi.yaml +0 -29945
  580. package/src/README.md +0 -39
  581. package/src/api/README.md +0 -23
  582. package/src/api/apiCollectionNames.js +0 -10
  583. package/src/api/index.d.ts +0 -126
  584. package/src/api/index.js +0 -14
  585. package/src/api/normalizeApiRow.js +0 -36
  586. package/src/api/serializeAccountRow.js +0 -10
  587. package/src/api/serializeApprovalRow.js +0 -53
  588. package/src/api/serializeComparisonScoreRow.js +0 -18
  589. package/src/api/serializeCronRow.js +0 -30
  590. package/src/api/serializeDocRow.js +0 -20
  591. package/src/api/serializeMemoryFactRow.js +0 -21
  592. package/src/api/serializePromptRow.js +0 -10
  593. package/src/api/serializeRunEventRow.js +0 -28
  594. package/src/api/serializeRunRow.js +0 -93
  595. package/src/api/serializeScoreDetailRow.js +0 -25
  596. package/src/api/serializeScoreRow.js +0 -26
  597. package/src/api/serializeTicketRow.js +0 -20
  598. package/src/api/serializeWorkflowRow.js +0 -10
  599. package/src/auth/scopes.d.ts +0 -19
  600. package/src/auth/scopes.js +0 -164
  601. package/src/index.d.ts +0 -316
  602. package/src/index.js +0 -108
  603. package/src/rpc/gatewayRpcTypes.ts +0 -186
  604. package/src/rpc/index.d.ts +0 -223
  605. package/src/rpc/index.js +0 -2527
@@ -0,0 +1,256 @@
1
+ ---
2
+ title: "The trust boundary"
3
+ description: "What one gateway credential authorizes, why a network bind needs two opt-ins, which paths are checked at the edge and which authenticate in band, and what a refusal is allowed to say."
4
+ sidebar:
5
+ order: 3
6
+ ---
7
+
8
+ A gateway is a control plane on a socket. It can launch runs, cancel them,
9
+ steer them, and approve capability grants. Every rule here exists because the
10
+ failure it prevents is silent: an unauthenticated control plane on a laptop's
11
+ network address is a remote execution service that looks like a dev server.
12
+
13
+ ## One credential, one principal
14
+
15
+ One shared bearer credential authenticates every mount and binds one identity;
16
+ it is not a per-user or per-run authorization system. Approval decisions have a
17
+ separate host-owned `ApprovalAuthority`, checked before reads/replay and again
18
+ at resolution. The default policy permits only the fixed local identities.
19
+ A gateway bearer needs explicit delegation to approve or deny.
20
+
21
+ That principal is server-owned, never client-supplied. A configured credential
22
+ stamps `{ id: "gateway", kind: "bearer" }`; a loopback bind with no credential
23
+ runs as `{ id: "local", kind: "operator" }`. A decision journaled under the
24
+ composition's default operator when a bearer holder made it would name the
25
+ wrong one, so `Approval.Submit` reads the authenticated principal and passes it
26
+ through to Control rather than letting the runtime default apply.
27
+
28
+ Delegating approval to `gateway/bearer` delegates it to every holder of that
29
+ credential. In particular, an agent sharing it has the same approval authority
30
+ as a human. Do not describe such a deployment as independent human approval.
31
+ For finer restrictions, supply a host policy over the authenticated principal,
32
+ target, decision, and scope. Approval policy is not a sandbox for callers with
33
+ arbitrary host code or direct database access.
34
+
35
+ A credential-free loopback gateway treats all native callers that can reach it
36
+ as the local operator. Host/Origin checks block browser-origin attacks; they do
37
+ not distinguish a human from a local agent that can make its own HTTP requests.
38
+ Use authenticated, independently authorized access and restrict that local
39
+ endpoint when human approval must be independent of the agent.
40
+
41
+ ## Scoped, expiring tokens
42
+
43
+ The bearer credential is one credential, and it grants everything the gateway
44
+ serves for as long as it is configured. `smthrs token mint --scope read:runs
45
+ --ttl 1h` mints a narrower grant under it: an HMAC-SHA256 token carrying the
46
+ procedures the scopes name, an optional run or flow, and an expiry. The gateway
47
+ verifies it with the credential it already holds and stores nothing, so
48
+ rotating the credential revokes every token minted under it, and nothing else
49
+ does.
50
+
51
+ The edge admits a scoped token on its signature and expiry alone, because an
52
+ upgrade names no procedure, and only toward `/rpc`, `/projections`, their
53
+ sockets, and `/auth/ticket`; journal sync and the runtime bridge take the
54
+ bearer alone, and a ticket issued against a scoped token opens only the
55
+ sockets the token could open itself. Every RPC frame is then judged in band: a procedure
56
+ the token does not name, a run or flow it does not name, or a call that names
57
+ none when the token is confined, is refused with the same typed `Unauthorized`
58
+ a wrong credential earns. A `Watch` or `Projection.Subscribe` opened before the
59
+ expiry keeps streaming after it, since the check runs when the stream opens;
60
+ end the socket to end the grant.
61
+
62
+ A scoped token stamps `{ id: "gateway", kind: "scoped" }`. Delegating approval
63
+ to `gateway/bearer` does not delegate it to every token minted from the bearer;
64
+ a host that wants an `approve:runs` token to decide delegates to
65
+ `gateway/scoped` explicitly. The runtime bridge accepts the bearer alone.
66
+
67
+ ## Two rules gate a bind, and both fail closed
68
+
69
+ 1. **A non-loopback host requires an explicit `listen` opt-in.** Binding
70
+ `0.0.0.0` because a port was free is how a workspace gateway ends up on a
71
+ shared network by accident.
72
+ 2. **A non-loopback bind requires a bearer credential.** Reachable from another
73
+ machine, an unauthenticated control plane is a remote execution service.
74
+
75
+ A loopback bind with no credential is allowed, and is the local default.
76
+ Loopback alone does not exclude malicious web pages. Every HTTP request and
77
+ WebSocket upgrade must pass the Host allowlist and, when present, an Origin
78
+ check against the request's authority, including its port. Cross-origin and
79
+ opaque (`null`) origins receive 403 before any RPC runs. Native clients may
80
+ omit Origin. Forwarded headers do not override these checks.
81
+
82
+ A loopback bind with no credential is allowed, and is the local default. The
83
+ trust boundary there is the machine account, so the ingress guard requires a
84
+ loopback `Host` value. A browser request carrying `Origin` must also carry a
85
+ canonical `http` or `https` origin whose host and port equal that `Host`. That
86
+ rejects cross-site WebSockets and DNS-rebound hostnames without
87
+ requiring a CLI to invent a credential: non-browser clients carrying no
88
+ `Origin` remain accepted.
89
+ The default accepted Host names are `127.0.0.1`, `localhost`, and `[::1]`.
90
+ The Node host also admits a concrete bind host. Network and reverse-proxy
91
+ names must be listed explicitly in `NodeGateway.ServerOptions.allowedHosts`
92
+ (hostnames without ports); wildcard binds do not allow arbitrary Host names.
93
+ `NodeGateway.isLoopbackHost` accepts `127.0.0.1`, `::1`, and `localhost`, and
94
+ nothing else.
95
+
96
+ `NodeGateway.bindRefusal` answers the policy as a value, so a host can inspect
97
+ it before composing anything. `listenOptions` returns the same refusal in its
98
+ typed effect channel, and `layer` fails through its layer channel. Operating
99
+ system listen failures, an address already in use among them, are mapped to the
100
+ same sanitized `bind_failed` contract, so a caller has one shape to handle.
101
+
102
+ ## Local request identity is checked before authentication
103
+
104
+ `NodeGateway.layer` enables `IngressOptions.loopbackOnly` whenever no bearer
105
+ credential is configured. Before any route, request body, or WebSocket upgrade
106
+ is handled, `layerIngress` refuses a foreign or absent `Host` with 421
107
+ `invalid_host`. It refuses an `Origin` whose host and port differ from the
108
+ request's `Host`, or that is not a canonical HTTP(S) origin, with 403
109
+ `invalid_origin`.
110
+
111
+ The Origin header is optional on purpose. Browsers attach it to WebSocket and
112
+ cross-origin requests; CLI clients normally do not. A same-origin Origin and an
113
+ Origin-less request both continue to reach the mount. A bearer-protected
114
+ non-loopback gateway does not enable the loopback `Host` rule, but the Origin
115
+ check still runs there: a browser client is served from the gateway's origin or
116
+ through a same-origin proxy.
117
+
118
+ ## Edge authentication, and where it deliberately stops
119
+
120
+ `GatewayServer.protectedPaths` is checked before a body is read or an upgrade
121
+ is answered: `/projections`, `/sync`, `/rpc/ws`, `/projections/ws`, and
122
+ `/sync/ws`.
123
+
124
+ `POST /rpc` is deliberately not on that list. The control mount authenticates
125
+ in band through `ControlRpcs.ControlAuth`, whose declared error is
126
+ `ControlError.Unauthorized`, and that typed control error is the refusal
127
+ [the control plane publishes](/docs/guides/control-plane/): missing, malformed,
128
+ empty, and incorrect credentials all return the same typed error.
129
+
130
+ An edge 401 answered ahead of the mount would erase that. `ControlClient`
131
+ filters a non-2xx status, so every refusal would reach a caller as a
132
+ `TransportError`: the one class `@smthrs/control` reserves for a request that
133
+ failed _before_ a declared control response reached it. It would also make the
134
+ gateway refuse a call differently from `NodeControl.layerServer` hosting the
135
+ very same `ControlRpcs`.
136
+
137
+ The body limit still applies to `/rpc`, so an unauthenticated caller buys one
138
+ bounded body read and nothing else.
139
+
140
+ `/rpc/ws` stays edge-authenticated for a different reason. A socket is a
141
+ resource the server holds open, the RPC middleware can only refuse frames on a
142
+ socket that already exists, and a refused handshake has no RPC channel to
143
+ answer a typed error on. Its refusal is a transport fact either way.
144
+
145
+ ## Browsers open sockets with a single-use ticket
146
+
147
+ A browser `WebSocket` cannot set an `Authorization` header, and a bearer in a
148
+ query string would land in logs and history. A credentialed gateway therefore
149
+ serves `POST /auth/ticket`: a request carrying an accepted bearer receives
150
+ `{ "ticket": "<64 hex>", "expiresInMs": 30000 }`. The client then opens
151
+ `/rpc/ws`, `/projections/ws`, or `/sync/ws` as `<mount>?ticket=<ticket>`.
152
+
153
+ - The ticket request passes the same Host and Origin checks as every other
154
+ request, so a page from another origin cannot mint one.
155
+ - The first upgrade that presents a ticket consumes it, whether or not the
156
+ upgrade completes. A replay, an unknown ticket, or one presented after 30
157
+ seconds is refused with 401 `unauthorized`.
158
+ - The socket runs under the bearer the ticket was issued for, so every RPC
159
+ frame authenticates exactly as it would with the header.
160
+ - A ticket opens only those three sockets. It never unlocks a request/response
161
+ mount.
162
+ - Tickets live in the gateway's memory; a restart invalidates every
163
+ outstanding one. At most 1,024 are outstanding; the oldest is dropped first.
164
+
165
+ A gateway with no bearer credential needs no ticket and does not serve
166
+ `/auth/ticket`.
167
+
168
+ ## A path is classified the way the router will resolve it
169
+
170
+ The guard runs before the router, so it has to reach the router's verdict. An
171
+ alias it did not recognize would walk past the credential check and the body
172
+ limit and be answered by the mount anyway.
173
+
174
+ Measured against the `HttpRouter` this package is built on, all of `/%72pc`,
175
+ `/rpc;transport-parameter`, `/rpc/`, `//rpc`, `///rpc`, `/rpc//`, `/RPC`,
176
+ `/./rpc`, and `/foo/../rpc` reach the `/rpc` handler, while `/rpc%2f`,
177
+ `/rpc%3Bp`, `/%2frpc`, and `/rpc%20` do not.
178
+
179
+ `GatewayServer.routedPath` reproduces that. It resolves dot segments with
180
+ `URL`, takes each segment without its `;` parameter, drops empty segments,
181
+ decodes the rest with `decodeURI`, and compares without regard to case.
182
+ `decodeURI` rather than `decodeURIComponent` is what leaves a reserved
183
+ character encoded, which is what keeps `/rpc%2f` a different path here exactly
184
+ as it is to the router. An invalid escape is left as written, because it names
185
+ no mount either way.
186
+
187
+ This is not only about crafted aliases. `ControlClient`'s HTTP protocol posts
188
+ every call to `/rpc/`, so a literal comparison skipped the body limit on the
189
+ path `@smthrs/control`'s own client uses.
190
+
191
+ The normalization errs toward matching: a spelling it resolves to a mount that
192
+ the router then refuses is answered 401 rather than 404, which costs an
193
+ unauthenticated caller nothing it was entitled to.
194
+
195
+ ## Ingress runs before the transport parses anything
196
+
197
+ `GatewayServer.layerIngress` is one global middleware, and it applies these
198
+ checks in order:
199
+
200
+ 1. Refuses a `Host` outside `allowedHosts`, or a non-loopback `Host` when
201
+ configured as `loopbackOnly`, with 421 `invalid_host`, then a browser
202
+ `Origin` whose host and port differ from the request's `Host` with 403
203
+ `invalid_origin`. These checks cover HTTP and WebSocket upgrades alike.
204
+ 2. Refuses an unauthenticated request to a protected path with 401
205
+ `unauthorized`.
206
+ 3. For a `POST` to an RPC mount, refuses a declared `content-length` over the limit with 413
207
+ `request_too_large`. A body that declares no length is measured as it is
208
+ read; the Node host destroys its source as soon as it crosses the limit, so
209
+ a streaming client may observe a connection reset instead of a response.
210
+ 4. Refuses a body carrying no RPC request message with 400
211
+ `malformed_request`.
212
+
213
+ The fourth check exists because `effect/unstable/rpc` hands every decoded
214
+ message to the server loop, and a body that decodes to something else, `{}`,
215
+ `[]`, prose, or nothing at all, reached it as a message with no tag and died
216
+ there. The gateway answered `500 Internal Server Error` with an empty body,
217
+ which is the wrong half of the contract twice over: it tells an operator the
218
+ gateway broke, and it tells a client to retry a request that can never succeed.
219
+
220
+ The transport's own parser answers that question, not a second reading of the
221
+ wire format, so whatever `RpcSerialization` the host composed is the one
222
+ authority. A body naming a procedure that does not exist is a _yes_: that is an
223
+ RPC-level defect the protocol itself reports. A binary framing is always a yes,
224
+ because its body is not text and the mount owns it.
225
+
226
+ ## Health carries identity and nothing else
227
+
228
+ `GET /health` is unauthenticated on purpose. A supervisor decides whether to
229
+ keep or replace a gateway process by asking which workspace it belongs to, and
230
+ a probe that needed a credential could not answer that about a gateway it did
231
+ not start.
232
+
233
+ The response carries the workspace hash, the gateway id, the protocol version,
234
+ and the package version. It never carries a token, a run, or a path. The
235
+ workspace hash is a digest of the resolved project root rather than the root
236
+ itself, because the path names directories on the operator's machine.
237
+
238
+ `/health` also answers while the rest of the process is degraded. A gateway
239
+ whose read path cannot read still comes up and still answers the identity
240
+ question, because startup must never be blocked by a subsystem that failed to
241
+ recover.
242
+
243
+ ## A refusal says the least it can
244
+
245
+ `GatewayError.cause` carries a redacted summary of an internal failure: its tag
246
+ and its stable code, never its message, its nested cause, or the SQL and file
247
+ paths a `PersistenceError` carries. Projection logs contain only an
248
+ allowlisted operation identifier and known control error tag/code pairs. The
249
+ runtime bridge answers with a stable code and logs the full cause of any failure
250
+ the caller did not cause to the host log, so a failed launch can be diagnosed
251
+ from the host.
252
+
253
+ The reason is the error's reach. `GatewayError` is the RPC error schema, so
254
+ anything left on it is serialized to every bearer holder and forwarded to a
255
+ browser by a relay, and a cause JSON cannot encode would make the error frame
256
+ itself fail to encode.
@@ -0,0 +1,115 @@
1
+ ---
2
+ title: "Diagnose what happened to a run"
3
+ description: "Read the verdict and diagnosis a run summary already carries, or fold your own from a run's control events with the Diagnosis module."
4
+ sidebar:
5
+ order: 6
6
+ ---
7
+
8
+ Every `run-summary` row already answers "what happened to this run". Two of its
9
+ fields are the whole diagnosis:
10
+
11
+ - `verdict`: one line, the status plus the reason that most explains it.
12
+ - `diagnosis`: the whole card, folded by `Diagnosis.digest`, which is also
13
+ what [`smthrs runs show`](/cli/runs) folds. The terminal card adds lines a
14
+ client does not need, such as the command that unblocks a parked run, so the
15
+ two read the same facts and print different cards.
16
+
17
+ A client that renders a run card renders those two strings. Nothing else is
18
+ needed, and nothing has to be recomputed.
19
+
20
+ ```json
21
+ "Verdict completed \u2014 shipped\nRun run-1 · deploy · opus · 5s\nActivity 1 turns · 1 calls (0 refused) · edits 1/1\nTokens 0 in / 0 out\nOutput shipped"
22
+ ```
23
+
24
+ ## What the verdict leads with
25
+
26
+ `Diagnosis.verdict` picks the one thing a reader needs first, in this order:
27
+
28
+ 1. A recorded failure cause, or the fact that a failed run recorded none.
29
+ 2. A park's question, so a waiting run says what it is waiting for.
30
+ 3. The "worked but never edited" pathology, which a green status would
31
+ otherwise hide.
32
+ 4. The resolved output.
33
+ 5. The bare status, when none of the above applies.
34
+
35
+ ```json
36
+ [
37
+ "failed \u2014 could not resolve seat anthropic:claude-sonnet-4-5",
38
+ "failed \u2014 no cause recorded in the journal",
39
+ "waiting-approval \u2014 asks: Write to src/index.ts?",
40
+ "completed \u2014 but 0 of 12 calls attempted an edit; the run only read",
41
+ "completed \u2014 shipped"
42
+ ]
43
+ ```
44
+
45
+ An unlaunched run, one with no status event at all, reads `unlaunched`.
46
+ Status events use the vocabulary from `ControlSchema.RunStatus.literals`.
47
+
48
+ ## Fold your own
49
+
50
+ The module is exported, so a client holding a run's ordered control events can
51
+ compute the same facts without a served projection:
52
+
53
+ ```ts
54
+ import * as Diagnosis from "@smthrs/gateway/Diagnosis"
55
+
56
+ const facts = Diagnosis.digest(events)
57
+ const line = Diagnosis.verdict(facts)
58
+ const card = Diagnosis.render({ runId, flowId }, facts)
59
+ const span = Diagnosis.duration(facts)
60
+ ```
61
+
62
+ `Diagnosis.Digest` carries the status, the failure cause, the model seat, turn
63
+ and call counts, edit attempts and successes, token totals, the refusals
64
+ aggregated by message, the final output, the pending question, and the span the
65
+ events cover.
66
+
67
+ The fold is total on purpose: an event kind outside its vocabulary contributes
68
+ nothing rather than failing it, and a payload that is not a record reads as an
69
+ empty one. A malformed journal produces a sparse digest, never a throw.
70
+ Unknown kinds include `__proto__`, `hasOwnProperty`, and `toString`; none changes
71
+ the digest or its timestamps. The unknown-kind cases in
72
+ [`Diagnosis.test.ts`](../../test/Diagnosis.test.ts) pin this guarantee.
73
+
74
+ ## What counts as an edit
75
+
76
+ `editsAttempted` counts calls to the `write`, `edit`, and `apply_patch` flows.
77
+ `editsSucceeded` counts the ones that settled without a failure. That pair is
78
+ what makes the "only read" verdict possible, and it is why a run that reported
79
+ success while touching nothing is visible on its own card.
80
+
81
+ ## What counts as time
82
+
83
+ Only an event kind the fold handles widens the reported span. This matters
84
+ because the gateway merges a keepalive event into every followed `Watch`
85
+ stream, and a fold that let an unhandled kind contribute its timestamp reported
86
+ a run that ran for as long as somebody watched it.
87
+
88
+ ## Refusals
89
+
90
+ Failed calls are aggregated by their first-line message, descending by count.
91
+ `Diagnosis.render` prints the top three:
92
+
93
+ ```text
94
+ Refusals 3× permission denied: capability "shell" is not in the envelope
95
+ ```
96
+
97
+ ## Clipping text for a wire
98
+
99
+ `Diagnosis.clip(text, width)` is the truncation the card and the verdict use,
100
+ and it is exported because a client rendering its own summary needs the same
101
+ guarantee. The cut is made on code points, never on UTF-16 code units: slicing
102
+ code units splits an astral character in half and puts a lone surrogate on the
103
+ wire, where a Go decoder silently replaces it and a strict decoder rejects the
104
+ whole frame.
105
+
106
+ A clipped result is exactly `width` code points, so `width` 1 is the ellipsis
107
+ alone, and `width` 0 or any negative width is the empty string.
108
+
109
+ ## Reading further
110
+
111
+ `run-tree` and `node-output` answer the next two questions a diagnosis raises:
112
+ which calls the run made, and what one of them produced. Both key their rows by
113
+ the ordinal a call opened on, so a node id from the tree is a node id
114
+ [`smthrs runs output`](/cli/runs) accepts. See
115
+ [Projections](../concepts/projections.md#how-a-node-gets-its-id).
@@ -0,0 +1,150 @@
1
+ ---
2
+ title: "Follow a run over a WebSocket"
3
+ description: "Subscribe to a projection, read the snapshot and delta frames it answers with, resume from a cursor after a disconnect, and keep an idle connection alive."
4
+ sidebar:
5
+ order: 3
6
+ ---
7
+
8
+ `Projection.Subscribe` answers a snapshot followed by a live tail. Mount it on
9
+ the socket: `/projections/ws` is where the streaming half of the read path
10
+ belongs, because a request/response route would have to buffer the whole
11
+ stream.
12
+
13
+ ## Subscribe
14
+
15
+ ```ts
16
+ import { Projections } from "@smthrs/gateway/Projections"
17
+ import { Effect, Stream } from "effect"
18
+
19
+ const frames = Effect.gen(function*() {
20
+ const projections = yield* Projections
21
+ return projections.subscribe({ _tag: "run-summary", runId })
22
+ })
23
+ ```
24
+
25
+ Over the wire, the request frame is the same shape as a snapshot's, with
26
+ `Projection.Subscribe` as the tag:
27
+
28
+ ```json
29
+ {
30
+ "_tag": "Request",
31
+ "id": 1,
32
+ "tag": "Projection.Subscribe",
33
+ "payload": { "selector": { "_tag": "run-summary", "runId": "run-1" } },
34
+ "headers": []
35
+ }
36
+ ```
37
+
38
+ Send it on `/projections/ws` immediately after the upgrade. The socket is a
39
+ protected path, so a gateway bound with a credential needs
40
+ `Authorization: Bearer <token>` on the upgrade request itself. Node's global
41
+ `WebSocket` cannot set headers on an upgrade, so a credentialed client needs a
42
+ socket library that can, or a relay that adds the header for it.
43
+
44
+ ## Read the frames
45
+
46
+ ```text
47
+ snapshot-start the snapshot begins, at this cursor
48
+ row one row of the snapshot, repeated
49
+ snapshot-end the snapshot is complete
50
+ delta the selector's rows after one change
51
+ heartbeat nothing changed, the connection is alive
52
+ ```
53
+
54
+ Three rules make the tail easy to consume:
55
+
56
+ - **A delta is the whole row set**, recomputed rather than patched. Replace
57
+ what you hold; do not merge. `run-events` is the exception, because its rows
58
+ are the events themselves, so its delta is the one event that arrived.
59
+ - **The snapshot and the tail share one reconciled event buffer**, so a client that follows
60
+ from the advertised cursor sees each later change exactly once.
61
+ - **Every frame but the heartbeat carries its selector**, so several
62
+ subscriptions can share one socket.
63
+
64
+ ## Resume after a disconnect
65
+
66
+ Keep the cursor from the last frame of a complete snapshot, or from the last
67
+ delta, and pass it as `after`. The subscription skips the snapshot and answers
68
+ only the deltas past it:
69
+
70
+ ```ts
71
+ const resumed = projections.subscribe({ _tag: "run-summary", runId }, lastCursor)
72
+ ```
73
+
74
+ ```json
75
+ {
76
+ "_tag": "Request",
77
+ "id": 1,
78
+ "tag": "Projection.Subscribe",
79
+ "payload": {
80
+ "selector": { "_tag": "run-summary", "runId": "run-1" },
81
+ "after": {
82
+ "selector": { "_tag": "run-summary", "runId": "run-1" },
83
+ "projection": "run-summary",
84
+ "runId": "run-1",
85
+ "value": 6,
86
+ "offset": 0
87
+ }
88
+ },
89
+ "headers": []
90
+ }
91
+ ```
92
+
93
+ Send back the cursor exactly as it arrived. It embeds the selector that issued
94
+ it, so a cursor from another selector, another run, or another projection is
95
+ refused with `malformed_request` rather than quietly resuming the wrong thing.
96
+ The full refusal list is in
97
+ [Subscriptions and cursors](../concepts/subscriptions.md#resuming).
98
+
99
+ Every snapshot frame carries the same cursor: the position the whole read
100
+ reached, not progress through delivery. Buffer the rows from `snapshot-start`
101
+ and commit them, and the cursor, only when `snapshot-end` arrives. If the
102
+ connection drops before `snapshot-end`, discard the partial snapshot and
103
+ re-subscribe without `after`. Resuming from a row you received before the cut
104
+ is accepted, because the cursor is valid, and answers only the deltas past the
105
+ snapshot, so the rows you never received are gone from your view until you
106
+ take a fresh snapshot.
107
+
108
+ A workspace subscription cannot resume. Re-subscribe without `after` and take
109
+ the snapshot again.
110
+
111
+ ## Keep an idle connection alive
112
+
113
+ A followed subscription that has nothing to report emits a `heartbeat` every 30
114
+ seconds. A relay cuts an idle tunnel at 600 seconds, so this is what keeps a
115
+ quiet run's followers connected. If something in front of your gateway cuts
116
+ sooner, shorten the cadence at the bind:
117
+
118
+ ```ts
119
+ import * as NodeGateway from "@smthrs/gateway/node/NodeGateway"
120
+
121
+ const gateway = NodeGateway.layer(health, { host: "127.0.0.1", port: 7331, heartbeatMillis: 10_000 })
122
+ ```
123
+
124
+ One option governs both keepalives: the `Projection.Subscribe` heartbeat on
125
+ `/projections/ws` and the `Watch` keepalive on `/rpc/ws`. Unset, `Watch` beats
126
+ every 30 seconds and the projection socket beats at whatever cadence the
127
+ supplied `Projections` service was built with, which is also 30 seconds for
128
+ `Projections.layer`. To shorten the projection cadence alone, build the read
129
+ path with `Projections.layerWith({ heartbeatMillis: 10_000 })` instead.
130
+
131
+ `heartbeatMillis` must be a positive safe integer. Zero would turn the
132
+ keepalive into a tight loop, so a composition that asks for it is refused with
133
+ `bind_failed` before anything binds.
134
+
135
+ ## Following the control plane instead
136
+
137
+ `ControlRpcs.Watch` on `/rpc/ws` follows a run's raw control events rather than
138
+ a projection, and the gateway merges the same kind of keepalive into it. It
139
+ arrives as a `ControlEvent` whose kind is
140
+ `GatewayServer.watchHeartbeatKind`, the literal `control.gateway.heartbeat`,
141
+ because `Watch` has no frame type of its own for a keepalive.
142
+
143
+ Ignore that kind, as every fold in this package already does with an unknown
144
+ kind. It repeats the last delivered sequence, so resuming from the last
145
+ sequence you saw does not rewind, and it carries the watched run id so routing
146
+ by run keeps working. A snapshot read, `follow: false`, never carries one: it
147
+ has to end.
148
+
149
+ For what `Watch` itself answers, see
150
+ [Watch a run](/pkg/control/guides/watch-a-run).
@@ -0,0 +1,153 @@
1
+ ---
2
+ title: "Host the gateway in your own process"
3
+ description: "Compose NodeGateway.layer with the four services the mounts read through, launch it, and read back the port it bound."
4
+ sidebar:
5
+ order: 1
6
+ ---
7
+
8
+ `NodeGateway.layer` is the whole gateway on a Node HTTP server. It supplies the
9
+ bind policy, the shared-credential authentication both RPC groups run under,
10
+ and newline-delimited JSON as the wire serialization. Four services stay yours,
11
+ because only a project on disk can provide them.
12
+
13
+ Reach for this when [`smthrs serve`](/cli/serve) is not the host you want: an
14
+ embedded gateway inside a larger process, a test harness, or a deployment that
15
+ already owns its own storage layer.
16
+
17
+ ## Supply the four services
18
+
19
+ ```ts
20
+ import type * as GatewayServer from "@smthrs/gateway/GatewayServer"
21
+ import * as NodeGateway from "@smthrs/gateway/node/NodeGateway"
22
+ import * as GatewayProjections from "@smthrs/gateway/Projections"
23
+ import type * as Journal from "@smthrs/journal/Journal"
24
+ import * as RunCatalog from "@smthrs/sync/RunCatalog"
25
+ import * as SyncAuth from "@smthrs/sync/SyncAuth"
26
+ import * as SyncServer from "@smthrs/sync/SyncServer"
27
+ import * as WorkspaceShare from "@smthrs/sync/WorkspaceShare"
28
+ import { Layer } from "effect"
29
+
30
+ export const gateway = (
31
+ health: GatewayServer.Health,
32
+ options: NodeGateway.ServerOptions,
33
+ journal: Layer.Layer<Journal.Journal>
34
+ ) =>
35
+ NodeGateway.layer(health, options).pipe(
36
+ Layer.provide([
37
+ // The read path, over whatever Control the caller provides.
38
+ GatewayProjections.layer,
39
+ // The journal read path. A local gateway publishes no catalog and
40
+ // shares nothing, so both sync ports are the no-op implementations.
41
+ SyncServer.layer.pipe(Layer.provide([journal, RunCatalog.layerNoop])),
42
+ SyncAuth.layer.pipe(Layer.provide(WorkspaceShare.layerNoop))
43
+ ])
44
+ )
45
+ ```
46
+
47
+ The journal is the host's own, so [`@smthrs/journal`](/api/journal) is a
48
+ dependency you add rather than one this package installs for you.
49
+
50
+ Those three provisions discharge every gateway input except `Control`, which
51
+ stays a requirement on purpose: a host should serve the same control plane its
52
+ own code talks to rather than opening a second one over the same database.
53
+ Provide it last, from `ControlLive.layer` over your control runtime. See
54
+ [Serve the control plane over RPC](/pkg/control/guides/serve-over-rpc).
55
+
56
+ `GatewayProjections.layer` reads through the ambient `Control`, so it inherits
57
+ whatever you provide. When a relay in front of you cuts idle connections sooner
58
+ than 600 seconds, set `heartbeatMillis` at the bind, which re-times both the
59
+ projection heartbeat and the `Watch` keepalive, or use
60
+ `GatewayProjections.layerWith({ heartbeatMillis })` to shorten the projection
61
+ heartbeat alone.
62
+
63
+ ## The health identity
64
+
65
+ `NodeGateway.layer` takes the identity `GET /health` will answer with. It is
66
+ `GatewaySchema.GatewayHealth` plus the version of the package serving it:
67
+
68
+ ```ts
69
+ import type * as GatewayServer from "@smthrs/gateway/GatewayServer"
70
+ import { createHash } from "node:crypto"
71
+ import { resolve } from "node:path"
72
+
73
+ /** A stable short hash of the project root, so the path is never published. */
74
+ const workspaceHash = (root: string): string => createHash("sha256").update(resolve(root)).digest("hex").slice(0, 16)
75
+
76
+ export const health = (root: string, version: string): GatewayServer.Health => ({
77
+ workspaceHash: workspaceHash(root),
78
+ gatewayId: `host-${process.pid}`,
79
+ protocolVersion: "1",
80
+ version
81
+ })
82
+ ```
83
+
84
+ Derive `workspaceHash` from the workspace and from nothing else. A supervisor
85
+ that finds a gateway already on a port asks `/health` whether it is this
86
+ workspace's before deciding to keep or replace it, and an identity derived from
87
+ anything else cannot answer that.
88
+
89
+ ## Launch it
90
+
91
+ The layer is the server. Launching it serves until the fiber is interrupted:
92
+
93
+ ```ts
94
+ import { Effect, Layer } from "effect"
95
+
96
+ const program = Layer.launch(gateway(health(root, "1.0.0-rc.0"), { host: "127.0.0.1", port: 7331 }, journal))
97
+
98
+ Effect.runFork(program.pipe(Effect.provide(control)))
99
+ ```
100
+
101
+ `NodeGateway.defaultServerOptions` is `{ host: "127.0.0.1", port: 7331 }`. The
102
+ CLI binds port 3000 instead; neither is privileged, and the port is yours to
103
+ choose.
104
+
105
+ ## Read back the port you got
106
+
107
+ The returned layer retains the concrete `HttpServer` service, so a caller that
108
+ bound port 0 can read the ephemeral address the operating system gave it. This
109
+ is what a test harness wants:
110
+
111
+ ```ts
112
+ import { Effect } from "effect"
113
+ import { HttpServer } from "effect/unstable/http"
114
+
115
+ const baseUrl = Effect.map(HttpServer.HttpServer, (server) => {
116
+ if (server.address._tag !== "InetAddressV4" && server.address._tag !== "InetAddressV6") {
117
+ throw new Error("expected a TCP gateway")
118
+ }
119
+ return `http://127.0.0.1:${server.address.port}`
120
+ })
121
+ ```
122
+
123
+ ## Refuse a bad bind before you compose
124
+
125
+ Policy refusals and operating system listen failures both fail the layer as
126
+ sanitized `bind_failed` `GatewayError` values. A host that would rather report
127
+ a refusal than fail a layer asks first:
128
+
129
+ ```ts
130
+ import * as NodeGateway from "@smthrs/gateway/node/NodeGateway"
131
+
132
+ const refusal = NodeGateway.bindRefusal({ host: "0.0.0.0", port: 7331 })
133
+ // GatewayError {
134
+ // code: "bind_failed",
135
+ // message: "Refusing non-loopback gateway bind 0.0.0.0 without an explicit --listen opt-in"
136
+ // }
137
+ ```
138
+
139
+ `bindRefusal` answers the same value `listenOptions` fails with and `layer`
140
+ fails through, so there is one rule and one message, not a copy per call site.
141
+ The rules themselves are in [Serve beyond loopback](./serve-beyond-loopback.md).
142
+
143
+ ## Mount only part of the surface
144
+
145
+ `GatewayServer` exposes each mount as its own layer for a host that assembles
146
+ its own router: `layerControlHttp`, `layerProjectionsHttp`, `layerSyncHttp`,
147
+ `layerHealth`, and `layerIngress`. `GatewayServer.layer` is those five merged,
148
+ and `NodeGateway.layer` is that plus a socket, a serialization, and an
149
+ authentication layer.
150
+
151
+ Splitting them is for hosts with an existing router, not for dropping a mount:
152
+ the ingress guard reads `rpcPaths` and `protectedPaths`, which name all three
153
+ RPC mounts, and a surface that serves fewer of them still pays the same guard.