@smthrs/gateway 0.34.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.
- package/CHANGELOG.md +198 -0
- package/LICENSE +1 -1
- package/README.md +92 -0
- package/dist/cjs/Diagnosis.d.ts +275 -0
- package/dist/cjs/Diagnosis.d.ts.map +1 -0
- package/dist/cjs/Diagnosis.js +476 -0
- package/dist/cjs/Diagnosis.js.map +7 -0
- package/dist/cjs/EngineTrace.d.ts +76 -0
- package/dist/cjs/EngineTrace.d.ts.map +1 -0
- package/dist/cjs/EngineTrace.js +501 -0
- package/dist/cjs/EngineTrace.js.map +7 -0
- package/dist/cjs/GatewayError.d.ts +54 -0
- package/dist/cjs/GatewayError.d.ts.map +1 -0
- package/dist/cjs/GatewayError.js +51 -0
- package/dist/cjs/GatewayError.js.map +7 -0
- package/dist/cjs/GatewayProjection.d.ts +480 -0
- package/dist/cjs/GatewayProjection.d.ts.map +1 -0
- package/dist/cjs/GatewayProjection.js +462 -0
- package/dist/cjs/GatewayProjection.js.map +7 -0
- package/dist/cjs/GatewayRpcs.d.ts +1886 -0
- package/dist/cjs/GatewayRpcs.d.ts.map +1 -0
- package/dist/cjs/GatewayRpcs.js +121 -0
- package/dist/cjs/GatewayRpcs.js.map +7 -0
- package/dist/cjs/GatewaySchema.d.ts +3274 -0
- package/dist/cjs/GatewaySchema.d.ts.map +1 -0
- package/dist/cjs/GatewaySchema.js +141 -0
- package/dist/cjs/GatewaySchema.js.map +7 -0
- package/dist/cjs/GatewayServer.d.ts +427 -0
- package/dist/cjs/GatewayServer.d.ts.map +1 -0
- package/dist/cjs/GatewayServer.js +428 -0
- package/dist/cjs/GatewayServer.js.map +7 -0
- package/dist/cjs/HostBranchPresence.d.ts +12 -0
- package/dist/cjs/HostBranchPresence.d.ts.map +1 -0
- package/dist/cjs/HostBranchPresence.js +82 -0
- package/dist/cjs/HostBranchPresence.js.map +7 -0
- package/dist/cjs/Projections.d.ts +209 -0
- package/dist/cjs/Projections.d.ts.map +1 -0
- package/dist/cjs/Projections.js +906 -0
- package/dist/cjs/Projections.js.map +7 -0
- package/dist/cjs/RunDevTools.d.ts +181 -0
- package/dist/cjs/RunDevTools.d.ts.map +1 -0
- package/dist/cjs/RunDevTools.js +195 -0
- package/dist/cjs/RunDevTools.js.map +7 -0
- package/dist/cjs/RunHistory.d.ts +185 -0
- package/dist/cjs/RunHistory.d.ts.map +1 -0
- package/dist/cjs/RunHistory.js +68 -0
- package/dist/cjs/RunHistory.js.map +7 -0
- package/dist/cjs/RunTrace.d.ts +753 -0
- package/dist/cjs/RunTrace.d.ts.map +1 -0
- package/dist/cjs/RunTrace.js +1593 -0
- package/dist/cjs/RunTrace.js.map +7 -0
- package/dist/cjs/RuntimeBridge.d.ts +1386 -0
- package/dist/cjs/RuntimeBridge.d.ts.map +1 -0
- package/dist/cjs/RuntimeBridge.js +598 -0
- package/dist/cjs/RuntimeBridge.js.map +7 -0
- package/dist/cjs/bun/BunGateway.d.ts +20 -0
- package/dist/cjs/bun/BunGateway.d.ts.map +1 -0
- package/dist/cjs/bun/BunGateway.js +62 -0
- package/dist/cjs/bun/BunGateway.js.map +7 -0
- package/dist/cjs/index.d.ts +65 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +59 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/internal/NativeGateway.d.ts +176 -0
- package/dist/cjs/internal/NativeGateway.d.ts.map +1 -0
- package/dist/cjs/internal/NativeGateway.js +187 -0
- package/dist/cjs/internal/NativeGateway.js.map +7 -0
- package/dist/cjs/internal/actionRenderings.d.ts +2 -0
- package/dist/cjs/internal/actionRenderings.d.ts.map +1 -0
- package/dist/cjs/internal/actionRenderings.js +224 -0
- package/dist/cjs/internal/actionRenderings.js.map +7 -0
- package/dist/cjs/internal/callEvents.d.ts +97 -0
- package/dist/cjs/internal/callEvents.d.ts.map +1 -0
- package/dist/cjs/internal/callEvents.js +169 -0
- package/dist/cjs/internal/callEvents.js.map +7 -0
- package/dist/cjs/internal/digestIndex.d.ts +31 -0
- package/dist/cjs/internal/digestIndex.d.ts.map +1 -0
- package/dist/cjs/internal/digestIndex.js +105 -0
- package/dist/cjs/internal/digestIndex.js.map +7 -0
- package/dist/cjs/internal/digestMemory.d.ts +19 -0
- package/dist/cjs/internal/digestMemory.d.ts.map +1 -0
- package/dist/cjs/internal/digestMemory.js +33 -0
- package/dist/cjs/internal/digestMemory.js.map +7 -0
- package/dist/cjs/internal/inspectLabels.d.ts +8 -0
- package/dist/cjs/internal/inspectLabels.d.ts.map +1 -0
- package/dist/cjs/internal/inspectLabels.js +29 -0
- package/dist/cjs/internal/inspectLabels.js.map +7 -0
- package/dist/cjs/internal/nativeResolution.d.ts +41 -0
- package/dist/cjs/internal/nativeResolution.d.ts.map +1 -0
- package/dist/cjs/internal/nativeResolution.js +62 -0
- package/dist/cjs/internal/nativeResolution.js.map +7 -0
- package/dist/cjs/internal/nodeEvents.d.ts +47 -0
- package/dist/cjs/internal/nodeEvents.d.ts.map +1 -0
- package/dist/cjs/internal/nodeEvents.js +60 -0
- package/dist/cjs/internal/nodeEvents.js.map +7 -0
- package/dist/cjs/node/NodeGateway.d.ts +16 -0
- package/dist/cjs/node/NodeGateway.d.ts.map +1 -0
- package/dist/cjs/node/NodeGateway.js +48 -0
- package/dist/cjs/node/NodeGateway.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/esm/Diagnosis.d.ts +275 -0
- package/dist/esm/Diagnosis.d.ts.map +1 -0
- package/dist/esm/Diagnosis.js +697 -0
- package/dist/esm/Diagnosis.js.map +1 -0
- package/dist/esm/EngineTrace.d.ts +76 -0
- package/dist/esm/EngineTrace.d.ts.map +1 -0
- package/dist/esm/EngineTrace.js +548 -0
- package/dist/esm/EngineTrace.js.map +1 -0
- package/dist/esm/GatewayError.d.ts +54 -0
- package/dist/esm/GatewayError.d.ts.map +1 -0
- package/dist/esm/GatewayError.js +60 -0
- package/dist/esm/GatewayError.js.map +1 -0
- package/dist/esm/GatewayProjection.d.ts +480 -0
- package/dist/esm/GatewayProjection.d.ts.map +1 -0
- package/dist/esm/GatewayProjection.js +792 -0
- package/dist/esm/GatewayProjection.js.map +1 -0
- package/dist/esm/GatewayRpcs.d.ts +1886 -0
- package/dist/esm/GatewayRpcs.d.ts.map +1 -0
- package/dist/esm/GatewayRpcs.js +145 -0
- package/dist/esm/GatewayRpcs.js.map +1 -0
- package/dist/esm/GatewaySchema.d.ts +3274 -0
- package/dist/esm/GatewaySchema.d.ts.map +1 -0
- package/dist/esm/GatewaySchema.js +244 -0
- package/dist/esm/GatewaySchema.js.map +1 -0
- package/dist/esm/GatewayServer.d.ts +427 -0
- package/dist/esm/GatewayServer.d.ts.map +1 -0
- package/dist/esm/GatewayServer.js +725 -0
- package/dist/esm/GatewayServer.js.map +1 -0
- package/dist/esm/HostBranchPresence.d.ts +12 -0
- package/dist/esm/HostBranchPresence.d.ts.map +1 -0
- package/dist/esm/HostBranchPresence.js +54 -0
- package/dist/esm/HostBranchPresence.js.map +1 -0
- package/dist/esm/Projections.d.ts +209 -0
- package/dist/esm/Projections.d.ts.map +1 -0
- package/dist/esm/Projections.js +1254 -0
- package/dist/esm/Projections.js.map +1 -0
- package/dist/esm/RunDevTools.d.ts +181 -0
- package/dist/esm/RunDevTools.d.ts.map +1 -0
- package/dist/esm/RunDevTools.js +281 -0
- package/dist/esm/RunDevTools.js.map +1 -0
- package/dist/esm/RunHistory.d.ts +185 -0
- package/dist/esm/RunHistory.d.ts.map +1 -0
- package/dist/esm/RunHistory.js +109 -0
- package/dist/esm/RunHistory.js.map +1 -0
- package/dist/esm/RunTrace.d.ts +753 -0
- package/dist/esm/RunTrace.d.ts.map +1 -0
- package/dist/esm/RunTrace.js +2105 -0
- package/dist/esm/RunTrace.js.map +1 -0
- package/dist/esm/RuntimeBridge.d.ts +1386 -0
- package/dist/esm/RuntimeBridge.d.ts.map +1 -0
- package/dist/esm/RuntimeBridge.js +659 -0
- package/dist/esm/RuntimeBridge.js.map +1 -0
- package/dist/esm/bun/BunGateway.d.ts +20 -0
- package/dist/esm/bun/BunGateway.d.ts.map +1 -0
- package/dist/esm/bun/BunGateway.js +32 -0
- package/dist/esm/bun/BunGateway.js.map +1 -0
- package/dist/esm/index.d.ts +65 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +65 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/NativeGateway.d.ts +176 -0
- package/dist/esm/internal/NativeGateway.d.ts.map +1 -0
- package/dist/esm/internal/NativeGateway.js +268 -0
- package/dist/esm/internal/NativeGateway.js.map +1 -0
- package/dist/esm/internal/actionRenderings.d.ts +2 -0
- package/dist/esm/internal/actionRenderings.d.ts.map +1 -0
- package/dist/esm/internal/actionRenderings.js +202 -0
- package/dist/esm/internal/actionRenderings.js.map +1 -0
- package/dist/esm/internal/callEvents.d.ts +97 -0
- package/dist/esm/internal/callEvents.d.ts.map +1 -0
- package/dist/esm/internal/callEvents.js +206 -0
- package/dist/esm/internal/callEvents.js.map +1 -0
- package/dist/esm/internal/digestIndex.d.ts +31 -0
- package/dist/esm/internal/digestIndex.d.ts.map +1 -0
- package/dist/esm/internal/digestIndex.js +87 -0
- package/dist/esm/internal/digestIndex.js.map +1 -0
- package/dist/esm/internal/digestMemory.d.ts +19 -0
- package/dist/esm/internal/digestMemory.d.ts.map +1 -0
- package/dist/esm/internal/digestMemory.js +23 -0
- package/dist/esm/internal/digestMemory.js.map +1 -0
- package/dist/esm/internal/inspectLabels.d.ts +8 -0
- package/dist/esm/internal/inspectLabels.d.ts.map +1 -0
- package/dist/esm/internal/inspectLabels.js +12 -0
- package/dist/esm/internal/inspectLabels.js.map +1 -0
- package/dist/esm/internal/nativeResolution.d.ts +41 -0
- package/dist/esm/internal/nativeResolution.d.ts.map +1 -0
- package/dist/esm/internal/nativeResolution.js +78 -0
- package/dist/esm/internal/nativeResolution.js.map +1 -0
- package/dist/esm/internal/nodeEvents.d.ts +47 -0
- package/dist/esm/internal/nodeEvents.d.ts.map +1 -0
- package/dist/esm/internal/nodeEvents.js +60 -0
- package/dist/esm/internal/nodeEvents.js.map +1 -0
- package/dist/esm/node/NodeGateway.d.ts +16 -0
- package/dist/esm/node/NodeGateway.d.ts.map +1 -0
- package/dist/esm/node/NodeGateway.js +13 -0
- package/dist/esm/node/NodeGateway.js.map +1 -0
- package/dist/vendor/adapters.json +2707 -0
- package/dist/vendor/bun/BunChildProcessSpawner.d.ts +7 -0
- package/dist/vendor/bun/BunChildProcessSpawner.js +14 -0
- package/dist/vendor/bun/BunClusterHttp.d.ts +83 -0
- package/dist/vendor/bun/BunClusterHttp.js +39 -0
- package/dist/vendor/bun/BunClusterSocket.d.ts +65 -0
- package/dist/vendor/bun/BunClusterSocket.js +22 -0
- package/dist/vendor/bun/BunCrypto.d.ts +10 -0
- package/dist/vendor/bun/BunCrypto.js +8 -0
- package/dist/vendor/bun/BunFileSystem.d.ts +10 -0
- package/dist/vendor/bun/BunFileSystem.js +9 -0
- package/dist/vendor/bun/BunHttpClient.d.ts +9 -0
- package/dist/vendor/bun/BunHttpClient.js +1 -0
- package/dist/vendor/bun/BunHttpPlatform.d.ts +10 -0
- package/dist/vendor/bun/BunHttpPlatform.js +11 -0
- package/dist/vendor/bun/BunHttpServer.d.ts +142 -0
- package/dist/vendor/bun/BunHttpServer.js +38 -0
- package/dist/vendor/bun/BunHttpServerRequest.d.ts +18 -0
- package/dist/vendor/bun/BunHttpServerRequest.js +7 -0
- package/dist/vendor/bun/BunMultipart.d.ts +31 -0
- package/dist/vendor/bun/BunMultipart.js +12 -0
- package/dist/vendor/bun/BunPath.d.ts +24 -0
- package/dist/vendor/bun/BunPath.js +12 -0
- package/dist/vendor/bun/BunRedis.d.ts +49 -0
- package/dist/vendor/bun/BunRedis.js +11 -0
- package/dist/vendor/bun/BunRuntime.d.ts +85 -0
- package/dist/vendor/bun/BunRuntime.js +8 -0
- package/dist/vendor/bun/BunServices.d.ts +34 -0
- package/dist/vendor/bun/BunServices.js +23 -0
- package/dist/vendor/bun/BunSink.d.ts +8 -0
- package/dist/vendor/bun/BunSink.js +12 -0
- package/dist/vendor/bun/BunSocket.d.ts +40 -0
- package/dist/vendor/bun/BunSocket.js +29 -0
- package/dist/vendor/bun/BunSocketServer.d.ts +8 -0
- package/dist/vendor/bun/BunSocketServer.js +21 -0
- package/dist/vendor/bun/BunStdio.d.ts +11 -0
- package/dist/vendor/bun/BunStdio.js +10 -0
- package/dist/vendor/bun/BunStream.d.ts +19 -0
- package/dist/vendor/bun/BunStream.js +30 -0
- package/dist/vendor/bun/BunTerminal.d.ts +21 -0
- package/dist/vendor/bun/BunTerminal.js +10 -0
- package/dist/vendor/bun/BunWorker.d.ts +20 -0
- package/dist/vendor/bun/BunWorker.js +9 -0
- package/dist/vendor/bun/BunWorkerRunner.d.ts +12 -0
- package/dist/vendor/bun/BunWorkerRunner.js +7 -0
- package/dist/vendor/bun/LICENSE +21 -0
- package/dist/vendor/bun/index.d.ts +92 -0
- package/dist/vendor/bun/index.js +107 -0
- package/dist/vendor/chunk-2GCOZTTW.js +48 -0
- package/dist/vendor/chunk-37CUR3PO.js +81 -0
- package/dist/vendor/chunk-3ARKKENZ.js +45 -0
- package/dist/vendor/chunk-3NV2UDBI.js +7 -0
- package/dist/vendor/chunk-3OSW7CT7.js +143 -0
- package/dist/vendor/chunk-62R63L74.js +62 -0
- package/dist/vendor/chunk-6AQLBC2I.js +118 -0
- package/dist/vendor/chunk-6C5H7S6B.js +18 -0
- package/dist/vendor/chunk-6DY5RBZD.js +85 -0
- package/dist/vendor/chunk-6UPBD47P.js +53 -0
- package/dist/vendor/chunk-AVVVN75Z.js +96 -0
- package/dist/vendor/chunk-B4DHEMBB.js +14 -0
- package/dist/vendor/chunk-BCK3NJOX.js +15 -0
- package/dist/vendor/chunk-BFBIHJ6X.js +0 -0
- package/dist/vendor/chunk-CES4OUM4.js +63 -0
- package/dist/vendor/chunk-D64L6YND.js +59 -0
- package/dist/vendor/chunk-DS2R6WOM.js +18 -0
- package/dist/vendor/chunk-DX4Z23DM.js +65 -0
- package/dist/vendor/chunk-DZ2VOUDP.js +564 -0
- package/dist/vendor/chunk-FOXN6JPJ.js +61 -0
- package/dist/vendor/chunk-FPQF7CR5.js +55 -0
- package/dist/vendor/chunk-FUTCTCEG.js +20 -0
- package/dist/vendor/chunk-GUPAV2YZ.js +18 -0
- package/dist/vendor/chunk-H2Z2Y4QH.js +70 -0
- package/dist/vendor/chunk-HAEDVSSM.js +129 -0
- package/dist/vendor/chunk-HY7BBL3K.js +93 -0
- package/dist/vendor/chunk-IFTTT6D5.js +31 -0
- package/dist/vendor/chunk-KQDSNB7M.js +26 -0
- package/dist/vendor/chunk-LIHLXXGQ.js +26 -0
- package/dist/vendor/chunk-LKCGQEE5.js +28 -0
- package/dist/vendor/chunk-MH2J3BYB.js +0 -0
- package/dist/vendor/chunk-ML2NAFH2.js +131 -0
- package/dist/vendor/chunk-MLFIZ5O2.js +0 -0
- package/dist/vendor/chunk-MLKGABMK.js +9 -0
- package/dist/vendor/chunk-MSCLEMYX.js +71 -0
- package/dist/vendor/chunk-OBWXQKVP.js +57 -0
- package/dist/vendor/chunk-QR557K66.js +20 -0
- package/dist/vendor/chunk-R4QUY7DH.js +18 -0
- package/dist/vendor/chunk-RGECXXJS.js +18 -0
- package/dist/vendor/chunk-TFY7W6D4.js +36 -0
- package/dist/vendor/chunk-TGPIVY4A.js +104 -0
- package/dist/vendor/chunk-TGXCX6W3.js +398 -0
- package/dist/vendor/chunk-TOHSFXMV.js +437 -0
- package/dist/vendor/chunk-UHIDPUFF.js +34 -0
- package/dist/vendor/chunk-ULT6CWUI.js +109 -0
- package/dist/vendor/chunk-UXBGYQR3.js +18 -0
- package/dist/vendor/chunk-V6LUGQ7O.js +21 -0
- package/dist/vendor/chunk-W4OASVX6.js +92 -0
- package/dist/vendor/chunk-WAII54GA.js +18 -0
- package/dist/vendor/chunk-WECQDT36.js +426 -0
- package/dist/vendor/chunk-WHKMOC7Z.js +28 -0
- package/dist/vendor/chunk-WVFOZ2UL.js +40 -0
- package/dist/vendor/chunk-X73E2UPI.js +18 -0
- package/dist/vendor/chunk-XCYARUII.js +63 -0
- package/dist/vendor/chunk-XFEVTDVD.js +34 -0
- package/dist/vendor/chunk-XFZZYSJ4.js +22 -0
- package/dist/vendor/chunk-XJWJXLXJ.js +18 -0
- package/dist/vendor/chunk-XY3Q62EO.js +18 -0
- package/dist/vendor/chunk-YDASSC75.js +394 -0
- package/dist/vendor/chunk-Z6C7SO5Z.js +507 -0
- package/dist/vendor/chunk-Z7QNPJEB.js +229 -0
- package/dist/vendor/chunk-Z7QPP4YH.js +249 -0
- package/dist/vendor/chunk-ZCHYLHJH.js +86 -0
- package/dist/vendor/chunk-ZIQVYVMA.js +22 -0
- package/dist/vendor/chunk-ZPIG2CUA.js +34 -0
- package/dist/vendor/cjs/bun/BunChildProcessSpawner.d.ts +7 -0
- package/dist/vendor/cjs/bun/BunChildProcessSpawner.js +1 -0
- package/dist/vendor/cjs/bun/BunClusterHttp.d.ts +83 -0
- package/dist/vendor/cjs/bun/BunClusterHttp.js +1 -0
- package/dist/vendor/cjs/bun/BunClusterSocket.d.ts +65 -0
- package/dist/vendor/cjs/bun/BunClusterSocket.js +1 -0
- package/dist/vendor/cjs/bun/BunCrypto.d.ts +10 -0
- package/dist/vendor/cjs/bun/BunCrypto.js +1 -0
- package/dist/vendor/cjs/bun/BunFileSystem.d.ts +10 -0
- package/dist/vendor/cjs/bun/BunFileSystem.js +1 -0
- package/dist/vendor/cjs/bun/BunHttpClient.d.ts +9 -0
- package/dist/vendor/cjs/bun/BunHttpClient.js +1 -0
- package/dist/vendor/cjs/bun/BunHttpPlatform.d.ts +10 -0
- package/dist/vendor/cjs/bun/BunHttpPlatform.js +1 -0
- package/dist/vendor/cjs/bun/BunHttpServer.d.ts +142 -0
- package/dist/vendor/cjs/bun/BunHttpServer.js +1 -0
- package/dist/vendor/cjs/bun/BunHttpServerRequest.d.ts +18 -0
- package/dist/vendor/cjs/bun/BunHttpServerRequest.js +1 -0
- package/dist/vendor/cjs/bun/BunMultipart.d.ts +31 -0
- package/dist/vendor/cjs/bun/BunMultipart.js +1 -0
- package/dist/vendor/cjs/bun/BunPath.d.ts +24 -0
- package/dist/vendor/cjs/bun/BunPath.js +1 -0
- package/dist/vendor/cjs/bun/BunRedis.d.ts +49 -0
- package/dist/vendor/cjs/bun/BunRedis.js +1 -0
- package/dist/vendor/cjs/bun/BunRuntime.d.ts +85 -0
- package/dist/vendor/cjs/bun/BunRuntime.js +1 -0
- package/dist/vendor/cjs/bun/BunServices.d.ts +34 -0
- package/dist/vendor/cjs/bun/BunServices.js +1 -0
- package/dist/vendor/cjs/bun/BunSink.d.ts +8 -0
- package/dist/vendor/cjs/bun/BunSink.js +1 -0
- package/dist/vendor/cjs/bun/BunSocket.d.ts +40 -0
- package/dist/vendor/cjs/bun/BunSocket.js +1 -0
- package/dist/vendor/cjs/bun/BunSocketServer.d.ts +8 -0
- package/dist/vendor/cjs/bun/BunSocketServer.js +1 -0
- package/dist/vendor/cjs/bun/BunStdio.d.ts +11 -0
- package/dist/vendor/cjs/bun/BunStdio.js +1 -0
- package/dist/vendor/cjs/bun/BunStream.d.ts +19 -0
- package/dist/vendor/cjs/bun/BunStream.js +1 -0
- package/dist/vendor/cjs/bun/BunTerminal.d.ts +21 -0
- package/dist/vendor/cjs/bun/BunTerminal.js +1 -0
- package/dist/vendor/cjs/bun/BunWorker.d.ts +20 -0
- package/dist/vendor/cjs/bun/BunWorker.js +1 -0
- package/dist/vendor/cjs/bun/BunWorkerRunner.d.ts +12 -0
- package/dist/vendor/cjs/bun/BunWorkerRunner.js +1 -0
- package/dist/vendor/cjs/bun/index.d.ts +92 -0
- package/dist/vendor/cjs/bun/index.js +1 -0
- package/dist/vendor/cjs/node/NodeChildProcessSpawner.d.ts +7 -0
- package/dist/vendor/cjs/node/NodeChildProcessSpawner.js +1 -0
- package/dist/vendor/cjs/node/NodeClusterHttp.d.ts +63 -0
- package/dist/vendor/cjs/node/NodeClusterHttp.js +1 -0
- package/dist/vendor/cjs/node/NodeClusterSocket.d.ts +79 -0
- package/dist/vendor/cjs/node/NodeClusterSocket.js +1 -0
- package/dist/vendor/cjs/node/NodeCrypto.d.ts +10 -0
- package/dist/vendor/cjs/node/NodeCrypto.js +1 -0
- package/dist/vendor/cjs/node/NodeFileSystem.d.ts +10 -0
- package/dist/vendor/cjs/node/NodeFileSystem.js +1 -0
- package/dist/vendor/cjs/node/NodeHttpClient.d.ts +179 -0
- package/dist/vendor/cjs/node/NodeHttpClient.js +1 -0
- package/dist/vendor/cjs/node/NodeHttpIncomingMessage.d.ts +62 -0
- package/dist/vendor/cjs/node/NodeHttpIncomingMessage.js +1 -0
- package/dist/vendor/cjs/node/NodeHttpPlatform.d.ts +36 -0
- package/dist/vendor/cjs/node/NodeHttpPlatform.js +1 -0
- package/dist/vendor/cjs/node/NodeHttpServer.d.ts +120 -0
- package/dist/vendor/cjs/node/NodeHttpServer.js +1 -0
- package/dist/vendor/cjs/node/NodeHttpServerRequest.d.ts +29 -0
- package/dist/vendor/cjs/node/NodeHttpServerRequest.js +1 -0
- package/dist/vendor/cjs/node/NodeMultipart.d.ts +46 -0
- package/dist/vendor/cjs/node/NodeMultipart.js +1 -0
- package/dist/vendor/cjs/node/NodeMultipartParser.d.ts +97 -0
- package/dist/vendor/cjs/node/NodeMultipartParser.js +1 -0
- package/dist/vendor/cjs/node/NodePath.d.ts +27 -0
- package/dist/vendor/cjs/node/NodePath.js +1 -0
- package/dist/vendor/cjs/node/NodeRedis.d.ts +74 -0
- package/dist/vendor/cjs/node/NodeRedis.js +1 -0
- package/dist/vendor/cjs/node/NodeRuntime.d.ts +85 -0
- package/dist/vendor/cjs/node/NodeRuntime.js +1 -0
- package/dist/vendor/cjs/node/NodeServices.d.ts +34 -0
- package/dist/vendor/cjs/node/NodeServices.js +1 -0
- package/dist/vendor/cjs/node/NodeSink.d.ts +8 -0
- package/dist/vendor/cjs/node/NodeSink.js +1 -0
- package/dist/vendor/cjs/node/NodeSocket.d.ts +38 -0
- package/dist/vendor/cjs/node/NodeSocket.js +1 -0
- package/dist/vendor/cjs/node/NodeSocketServer.d.ts +8 -0
- package/dist/vendor/cjs/node/NodeSocketServer.js +1 -0
- package/dist/vendor/cjs/node/NodeStdio.d.ts +11 -0
- package/dist/vendor/cjs/node/NodeStdio.js +1 -0
- package/dist/vendor/cjs/node/NodeStream.d.ts +8 -0
- package/dist/vendor/cjs/node/NodeStream.js +1 -0
- package/dist/vendor/cjs/node/NodeTerminal.d.ts +21 -0
- package/dist/vendor/cjs/node/NodeTerminal.js +1 -0
- package/dist/vendor/cjs/node/NodeWorker.d.ts +22 -0
- package/dist/vendor/cjs/node/NodeWorker.js +1 -0
- package/dist/vendor/cjs/node/NodeWorkerRunner.d.ts +12 -0
- package/dist/vendor/cjs/node/NodeWorkerRunner.js +1 -0
- package/dist/vendor/cjs/node/Undici.d.ts +28 -0
- package/dist/vendor/cjs/node/Undici.js +1 -0
- package/dist/vendor/cjs/node/index.d.ts +100 -0
- package/dist/vendor/cjs/node/index.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeChildProcessSpawner.d.ts +57 -0
- package/dist/vendor/cjs/node-shared/NodeChildProcessSpawner.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeClusterSocket.d.ts +22 -0
- package/dist/vendor/cjs/node-shared/NodeClusterSocket.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeCrypto.d.ts +27 -0
- package/dist/vendor/cjs/node-shared/NodeCrypto.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeFileSystem.d.ts +11 -0
- package/dist/vendor/cjs/node-shared/NodeFileSystem.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeHttpCompression.d.ts +36 -0
- package/dist/vendor/cjs/node-shared/NodeHttpCompression.js +1 -0
- package/dist/vendor/cjs/node-shared/NodePath.d.ts +27 -0
- package/dist/vendor/cjs/node-shared/NodePath.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeRuntime.d.ts +47 -0
- package/dist/vendor/cjs/node-shared/NodeRuntime.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeSink.d.ts +69 -0
- package/dist/vendor/cjs/node-shared/NodeSink.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeSocket.d.ts +134 -0
- package/dist/vendor/cjs/node-shared/NodeSocket.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeSocketServer.d.ts +80 -0
- package/dist/vendor/cjs/node-shared/NodeSocketServer.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeStdio.d.ts +12 -0
- package/dist/vendor/cjs/node-shared/NodeStdio.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeStream.d.ts +179 -0
- package/dist/vendor/cjs/node-shared/NodeStream.js +1 -0
- package/dist/vendor/cjs/node-shared/NodeTerminal.d.ts +22 -0
- package/dist/vendor/cjs/node-shared/NodeTerminal.js +1 -0
- package/dist/vendor/cjs/node-shared/index.d.ts +56 -0
- package/dist/vendor/cjs/node-shared/index.js +1 -0
- package/dist/vendor/cjs/node-shared/internal/nodeChildProcessSpawner.d.ts +4 -0
- package/dist/vendor/cjs/node-shared/internal/nodeChildProcessSpawner.js +1 -0
- package/dist/vendor/cjs/node-shared/internal/utils.d.ts +2 -0
- package/dist/vendor/cjs/node-shared/internal/utils.js +1 -0
- package/dist/vendor/cjs/package.json +1 -0
- package/dist/vendor/cjs/platform-bun.d.ts +92 -0
- package/dist/vendor/cjs/platform-bun.js +1 -0
- package/dist/vendor/cjs/platform-node-shared.d.ts +56 -0
- package/dist/vendor/cjs/platform-node-shared.js +1 -0
- package/dist/vendor/cjs/platform-node.d.ts +100 -0
- package/dist/vendor/cjs/platform-node.js +1 -0
- package/dist/vendor/node/LICENSE +21 -0
- package/dist/vendor/node/NodeChildProcessSpawner.d.ts +7 -0
- package/dist/vendor/node/NodeChildProcessSpawner.js +14 -0
- package/dist/vendor/node/NodeClusterHttp.d.ts +63 -0
- package/dist/vendor/node/NodeClusterHttp.js +43 -0
- package/dist/vendor/node/NodeClusterSocket.d.ts +79 -0
- package/dist/vendor/node/NodeClusterSocket.js +30 -0
- package/dist/vendor/node/NodeCrypto.d.ts +10 -0
- package/dist/vendor/node/NodeCrypto.js +8 -0
- package/dist/vendor/node/NodeFileSystem.d.ts +10 -0
- package/dist/vendor/node/NodeFileSystem.js +9 -0
- package/dist/vendor/node/NodeHttpClient.d.ts +179 -0
- package/dist/vendor/node/NodeHttpClient.js +46 -0
- package/dist/vendor/node/NodeHttpIncomingMessage.d.ts +62 -0
- package/dist/vendor/node/NodeHttpIncomingMessage.js +10 -0
- package/dist/vendor/node/NodeHttpPlatform.d.ts +36 -0
- package/dist/vendor/node/NodeHttpPlatform.js +16 -0
- package/dist/vendor/node/NodeHttpServer.d.ts +120 -0
- package/dist/vendor/node/NodeHttpServer.js +46 -0
- package/dist/vendor/node/NodeHttpServerRequest.d.ts +29 -0
- package/dist/vendor/node/NodeHttpServerRequest.js +9 -0
- package/dist/vendor/node/NodeMultipart.d.ts +46 -0
- package/dist/vendor/node/NodeMultipart.js +15 -0
- package/dist/vendor/node/NodeMultipartParser.d.ts +97 -0
- package/dist/vendor/node/NodeMultipartParser.js +11 -0
- package/dist/vendor/node/NodePath.d.ts +27 -0
- package/dist/vendor/node/NodePath.js +12 -0
- package/dist/vendor/node/NodeRedis.d.ts +74 -0
- package/dist/vendor/node/NodeRedis.js +11 -0
- package/dist/vendor/node/NodeRuntime.d.ts +85 -0
- package/dist/vendor/node/NodeRuntime.js +8 -0
- package/dist/vendor/node/NodeServices.d.ts +34 -0
- package/dist/vendor/node/NodeServices.js +23 -0
- package/dist/vendor/node/NodeSink.d.ts +8 -0
- package/dist/vendor/node/NodeSink.js +12 -0
- package/dist/vendor/node/NodeSocket.d.ts +38 -0
- package/dist/vendor/node/NodeSocket.js +31 -0
- package/dist/vendor/node/NodeSocketServer.d.ts +8 -0
- package/dist/vendor/node/NodeSocketServer.js +21 -0
- package/dist/vendor/node/NodeStdio.d.ts +11 -0
- package/dist/vendor/node/NodeStdio.js +10 -0
- package/dist/vendor/node/NodeStream.d.ts +8 -0
- package/dist/vendor/node/NodeStream.js +27 -0
- package/dist/vendor/node/NodeTerminal.d.ts +21 -0
- package/dist/vendor/node/NodeTerminal.js +10 -0
- package/dist/vendor/node/NodeWorker.d.ts +22 -0
- package/dist/vendor/node/NodeWorker.js +9 -0
- package/dist/vendor/node/NodeWorkerRunner.d.ts +12 -0
- package/dist/vendor/node/NodeWorkerRunner.js +7 -0
- package/dist/vendor/node/Undici.d.ts +28 -0
- package/dist/vendor/node/Undici.js +9 -0
- package/dist/vendor/node/index.d.ts +100 -0
- package/dist/vendor/node/index.js +115 -0
- package/dist/vendor/node-shared/LICENSE +21 -0
- package/dist/vendor/node-shared/NodeChildProcessSpawner.d.ts +57 -0
- package/dist/vendor/node-shared/NodeChildProcessSpawner.js +13 -0
- package/dist/vendor/node-shared/NodeClusterSocket.d.ts +22 -0
- package/dist/vendor/node-shared/NodeClusterSocket.js +11 -0
- package/dist/vendor/node-shared/NodeCrypto.d.ts +27 -0
- package/dist/vendor/node-shared/NodeCrypto.js +9 -0
- package/dist/vendor/node-shared/NodeFileSystem.d.ts +11 -0
- package/dist/vendor/node-shared/NodeFileSystem.js +8 -0
- package/dist/vendor/node-shared/NodeHttpCompression.d.ts +36 -0
- package/dist/vendor/node-shared/NodeHttpCompression.js +13 -0
- package/dist/vendor/node-shared/NodePath.d.ts +27 -0
- package/dist/vendor/node-shared/NodePath.js +11 -0
- package/dist/vendor/node-shared/NodeRuntime.d.ts +47 -0
- package/dist/vendor/node-shared/NodeRuntime.js +7 -0
- package/dist/vendor/node-shared/NodeSink.d.ts +69 -0
- package/dist/vendor/node-shared/NodeSink.js +11 -0
- package/dist/vendor/node-shared/NodeSocket.d.ts +134 -0
- package/dist/vendor/node-shared/NodeSocket.js +23 -0
- package/dist/vendor/node-shared/NodeSocketServer.d.ts +80 -0
- package/dist/vendor/node-shared/NodeSocketServer.js +20 -0
- package/dist/vendor/node-shared/NodeStdio.d.ts +12 -0
- package/dist/vendor/node-shared/NodeStdio.js +9 -0
- package/dist/vendor/node-shared/NodeStream.d.ts +179 -0
- package/dist/vendor/node-shared/NodeStream.js +26 -0
- package/dist/vendor/node-shared/NodeTerminal.d.ts +22 -0
- package/dist/vendor/node-shared/NodeTerminal.js +9 -0
- package/dist/vendor/node-shared/index.d.ts +56 -0
- package/dist/vendor/node-shared/index.js +58 -0
- package/dist/vendor/node-shared/internal/nodeChildProcessSpawner.d.ts +4 -0
- package/dist/vendor/node-shared/internal/nodeChildProcessSpawner.js +7 -0
- package/dist/vendor/node-shared/internal/utils.d.ts +2 -0
- package/dist/vendor/node-shared/internal/utils.js +7 -0
- package/dist/vendor/platform-bun.d.ts +92 -0
- package/dist/vendor/platform-bun.js +107 -0
- package/dist/vendor/platform-node-shared.d.ts +56 -0
- package/dist/vendor/platform-node-shared.js +58 -0
- package/dist/vendor/platform-node.d.ts +100 -0
- package/dist/vendor/platform-node.js +115 -0
- package/docs/README.md +158 -0
- package/docs/api.md +601 -0
- package/docs/concepts/projections.md +250 -0
- package/docs/concepts/subscriptions.md +204 -0
- package/docs/concepts/trust-boundary.md +256 -0
- package/docs/guides/diagnose-a-run.md +115 -0
- package/docs/guides/follow-a-run.md +150 -0
- package/docs/guides/host-the-gateway.md +153 -0
- package/docs/guides/read-a-projection.md +138 -0
- package/docs/guides/serve-beyond-loopback.md +166 -0
- package/docs/guides/submit-an-approval.md +187 -0
- package/docs/guides/testing.md +148 -0
- package/docs/installation.md +89 -0
- package/docs/quickstart.md +200 -0
- package/docs/troubleshooting.md +355 -0
- package/package.json +264 -32
- package/src/Diagnosis.ts +892 -0
- package/src/EngineTrace.ts +605 -0
- package/src/GatewayError.ts +71 -0
- package/src/GatewayProjection.ts +948 -0
- package/src/GatewayRpcs.ts +179 -0
- package/src/GatewaySchema.ts +516 -0
- package/src/GatewayServer.ts +932 -0
- package/src/HostBranchPresence.ts +72 -0
- package/src/Projections.ts +1735 -0
- package/src/RunDevTools.ts +394 -0
- package/src/RunHistory.ts +174 -0
- package/src/RunTrace.ts +2793 -0
- package/src/RuntimeBridge.ts +835 -0
- package/src/bun/BunGateway.ts +52 -0
- package/src/index.ts +77 -0
- package/src/internal/NativeGateway.ts +360 -0
- package/src/internal/actionRenderings.ts +201 -0
- package/src/internal/callEvents.ts +257 -0
- package/src/internal/digestIndex.ts +134 -0
- package/src/internal/digestMemory.ts +27 -0
- package/src/internal/inspectLabels.ts +13 -0
- package/src/internal/nativeResolution.ts +103 -0
- package/src/internal/nodeEvents.ts +100 -0
- package/src/node/NodeGateway.ts +30 -0
- package/openapi.yaml +0 -29182
- package/src/README.md +0 -39
- package/src/api/README.md +0 -23
- package/src/api/apiCollectionNames.js +0 -10
- package/src/api/index.d.ts +0 -126
- package/src/api/index.js +0 -14
- package/src/api/normalizeApiRow.js +0 -36
- package/src/api/serializeAccountRow.js +0 -10
- package/src/api/serializeApprovalRow.js +0 -53
- package/src/api/serializeComparisonScoreRow.js +0 -18
- package/src/api/serializeCronRow.js +0 -30
- package/src/api/serializeDocRow.js +0 -20
- package/src/api/serializeMemoryFactRow.js +0 -21
- package/src/api/serializePromptRow.js +0 -10
- package/src/api/serializeRunEventRow.js +0 -28
- package/src/api/serializeRunRow.js +0 -61
- package/src/api/serializeScoreDetailRow.js +0 -25
- package/src/api/serializeScoreRow.js +0 -26
- package/src/api/serializeTicketRow.js +0 -20
- package/src/api/serializeWorkflowRow.js +0 -10
- package/src/auth/scopes.d.ts +0 -19
- package/src/auth/scopes.js +0 -164
- package/src/index.d.ts +0 -316
- package/src/index.js +0 -108
- package/src/rpc/gatewayRpcTypes.ts +0 -183
- package/src/rpc/index.d.ts +0 -221
- package/src/rpc/index.js +0 -2431
|
@@ -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.
|