@nimbus-sh/worker 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/NOTICE.md +5 -0
  2. package/README.md +10 -0
  3. package/dist/_shared/session-router.d.ts +7 -0
  4. package/dist/_shared/session-router.d.ts.map +1 -1
  5. package/dist/_shared/session-router.js +7 -0
  6. package/dist/bindings/body.d.ts +6 -0
  7. package/dist/bindings/body.d.ts.map +1 -0
  8. package/dist/bindings/body.js +37 -0
  9. package/dist/bindings/kv.d.ts +0 -2
  10. package/dist/bindings/kv.d.ts.map +1 -1
  11. package/dist/bindings/kv.js +3 -42
  12. package/dist/bindings/r2.d.ts +0 -2
  13. package/dist/bindings/r2.d.ts.map +1 -1
  14. package/dist/bindings/r2.js +4 -44
  15. package/dist/esbuild-cli-artifact.generated.d.ts +18 -0
  16. package/dist/esbuild-cli-artifact.generated.d.ts.map +1 -0
  17. package/dist/esbuild-cli-artifact.generated.js +17 -0
  18. package/dist/facets/cirrus-real.d.ts.map +1 -1
  19. package/dist/facets/cirrus-real.js +9 -4
  20. package/dist/facets/compose.d.ts +11 -7
  21. package/dist/facets/compose.d.ts.map +1 -1
  22. package/dist/facets/compose.js +8 -38
  23. package/dist/facets/data-plan.d.ts +79 -0
  24. package/dist/facets/data-plan.d.ts.map +1 -0
  25. package/dist/facets/data-plan.js +477 -0
  26. package/dist/facets/esbuild-transform.d.ts +36 -10
  27. package/dist/facets/esbuild-transform.d.ts.map +1 -1
  28. package/dist/facets/esbuild-transform.js +216 -20
  29. package/dist/facets/exec-telemetry.d.ts +7 -3
  30. package/dist/facets/exec-telemetry.d.ts.map +1 -1
  31. package/dist/facets/manager.d.ts +179 -78
  32. package/dist/facets/manager.d.ts.map +1 -1
  33. package/dist/facets/manager.js +1221 -649
  34. package/dist/facets/opencode-staging.d.ts +0 -2
  35. package/dist/facets/opencode-staging.d.ts.map +1 -1
  36. package/dist/facets/opencode-staging.js +5 -11
  37. package/dist/facets/process.d.ts +4 -0
  38. package/dist/facets/process.d.ts.map +1 -1
  39. package/dist/facets/process.js +3 -0
  40. package/dist/facets/read-profile.d.ts +149 -0
  41. package/dist/facets/read-profile.d.ts.map +1 -0
  42. package/dist/facets/read-profile.js +483 -0
  43. package/dist/facets/resident-identity.d.ts +0 -1
  44. package/dist/facets/resident-identity.d.ts.map +1 -1
  45. package/dist/facets/resident-identity.js +0 -3
  46. package/dist/facets/wasm-swap-registry.d.ts +34 -25
  47. package/dist/facets/wasm-swap-registry.d.ts.map +1 -1
  48. package/dist/facets/wasm-swap-registry.js +62 -56
  49. package/dist/facets/ws-terminal.d.ts +4 -4
  50. package/dist/facets/ws-terminal.d.ts.map +1 -1
  51. package/dist/facets/ws-terminal.js +4 -5
  52. package/dist/git/commands.d.ts +16 -9
  53. package/dist/git/commands.d.ts.map +1 -1
  54. package/dist/git/commands.js +1818 -188
  55. package/dist/git/network-facet.d.ts +10 -2
  56. package/dist/git/network-facet.d.ts.map +1 -1
  57. package/dist/git/network-facet.js +62 -16
  58. package/dist/git/unified-diff.d.ts +74 -0
  59. package/dist/git/unified-diff.d.ts.map +1 -0
  60. package/dist/git/unified-diff.js +676 -0
  61. package/dist/git-bundle.generated.d.ts +7 -11
  62. package/dist/git-bundle.generated.d.ts.map +1 -1
  63. package/dist/git-bundle.generated.js +7 -11
  64. package/dist/hosted/commands.d.ts.map +1 -1
  65. package/dist/hosted/commands.js +62 -243
  66. package/dist/hosted/runtime.d.ts +19 -13
  67. package/dist/hosted/runtime.d.ts.map +1 -1
  68. package/dist/hosted/runtime.js +71 -14
  69. package/dist/hosted/services.d.ts +6 -7
  70. package/dist/hosted/services.d.ts.map +1 -1
  71. package/dist/hosted/services.js +10 -14
  72. package/dist/hosted/session.d.ts +165 -0
  73. package/dist/hosted/session.d.ts.map +1 -0
  74. package/dist/hosted/session.js +132 -0
  75. package/dist/loaders/generated-workers.d.ts +5 -2
  76. package/dist/loaders/generated-workers.d.ts.map +1 -1
  77. package/dist/loaders/generated-workers.js +6 -3
  78. package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -1
  79. package/dist/loaders/npm-resolve-preamble.js +0 -27
  80. package/dist/node-shims-artifact.generated.d.ts +13 -4
  81. package/dist/node-shims-artifact.generated.d.ts.map +1 -1
  82. package/dist/node-shims-artifact.generated.js +16 -7
  83. package/dist/npm/bin-links.d.ts +3 -1
  84. package/dist/npm/bin-links.d.ts.map +1 -1
  85. package/dist/npm/bin-links.js +32 -8
  86. package/dist/npm/cache.d.ts +5 -0
  87. package/dist/npm/cache.d.ts.map +1 -1
  88. package/dist/npm/cache.js +13 -1
  89. package/dist/npm/install-batch-facet.d.ts +2 -2
  90. package/dist/npm/install-batch-facet.js +3 -3
  91. package/dist/npm/installer.d.ts +17 -1
  92. package/dist/npm/installer.d.ts.map +1 -1
  93. package/dist/npm/installer.js +159 -20
  94. package/dist/npm/package-lock.d.ts +32 -0
  95. package/dist/npm/package-lock.d.ts.map +1 -0
  96. package/dist/npm/package-lock.js +65 -0
  97. package/dist/npm/pre-bundle-facet.d.ts +1 -30
  98. package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
  99. package/dist/npm/pre-bundle-facet.js +3 -5
  100. package/dist/npm/r2-cache.d.ts +2 -0
  101. package/dist/npm/r2-cache.d.ts.map +1 -1
  102. package/dist/npm/r2-cache.js +2 -0
  103. package/dist/npm/resolve-one-facet.d.ts.map +1 -1
  104. package/dist/npm/resolve-one-facet.js +14 -3
  105. package/dist/npm/resolver.d.ts +0 -7
  106. package/dist/npm/resolver.d.ts.map +1 -1
  107. package/dist/npm/resolver.js +0 -22
  108. package/dist/opencode-artifact.generated.js +2 -2
  109. package/dist/replica/routing.d.ts +2 -38
  110. package/dist/replica/routing.d.ts.map +1 -1
  111. package/dist/replica/routing.js +3 -55
  112. package/dist/router/index.d.ts.map +1 -1
  113. package/dist/router/index.js +15 -2
  114. package/dist/router/public-directory.d.ts +18 -0
  115. package/dist/router/public-directory.d.ts.map +1 -1
  116. package/dist/router/public-directory.js +1 -1
  117. package/dist/router/remote-api.d.ts +3 -1
  118. package/dist/router/remote-api.d.ts.map +1 -1
  119. package/dist/router/remote-api.js +42 -79
  120. package/dist/runtime/bash-repl.js +2 -2
  121. package/dist/runtime/bun-repl.d.ts.map +1 -1
  122. package/dist/runtime/bun-repl.js +2 -13
  123. package/dist/runtime/esbuild-wasm-bytes.d.ts +17 -5
  124. package/dist/runtime/esbuild-wasm-bytes.d.ts.map +1 -1
  125. package/dist/runtime/esbuild-wasm-bytes.js +43 -94
  126. package/dist/runtime/git-bundle-artifact.d.ts +17 -0
  127. package/dist/runtime/git-bundle-artifact.d.ts.map +1 -0
  128. package/dist/runtime/git-bundle-artifact.js +25 -0
  129. package/dist/runtime/node-repl.d.ts.map +1 -1
  130. package/dist/runtime/node-repl.js +2 -13
  131. package/dist/runtime/node-shims-artifact.d.ts +22 -23
  132. package/dist/runtime/node-shims-artifact.d.ts.map +1 -1
  133. package/dist/runtime/node-shims-artifact.js +48 -78
  134. package/dist/runtime/node-shims.d.ts.map +1 -1
  135. package/dist/runtime/node-shims.js +1567 -864
  136. package/dist/runtime/opencode-artifact.d.ts.map +1 -1
  137. package/dist/runtime/opencode-artifact.js +17 -53
  138. package/dist/runtime/opencode-facet-runner.d.ts +3 -6
  139. package/dist/runtime/opencode-facet-runner.d.ts.map +1 -1
  140. package/dist/runtime/opencode-facet-runner.js +45 -10
  141. package/dist/runtime/opentui-wasm-bytes.d.ts.map +1 -1
  142. package/dist/runtime/opentui-wasm-bytes.js +16 -49
  143. package/dist/runtime/package-manager.d.ts +0 -2
  144. package/dist/runtime/package-manager.d.ts.map +1 -1
  145. package/dist/runtime/package-manager.js +0 -3
  146. package/dist/runtime/python-repl.d.ts.map +1 -1
  147. package/dist/runtime/python-repl.js +2 -2
  148. package/dist/runtime/repl-session.d.ts +10 -0
  149. package/dist/runtime/repl-session.d.ts.map +1 -1
  150. package/dist/runtime/repl-session.js +7 -0
  151. package/dist/runtime/ruby-repl.d.ts.map +1 -1
  152. package/dist/runtime/ruby-repl.js +2 -2
  153. package/dist/runtime/ruby-resident.d.ts.map +1 -1
  154. package/dist/runtime/ruby-resident.js +36 -35
  155. package/dist/runtime/runtime-catalog.d.ts +10 -3
  156. package/dist/runtime/runtime-catalog.d.ts.map +1 -1
  157. package/dist/runtime/runtime-catalog.js +125 -15
  158. package/dist/runtime/sqlite-wasm-bytes.d.ts +4 -4
  159. package/dist/runtime/sqlite-wasm-bytes.d.ts.map +1 -1
  160. package/dist/runtime/sqlite-wasm-bytes.js +21 -57
  161. package/dist/runtime/staged-source.d.ts +67 -0
  162. package/dist/runtime/staged-source.d.ts.map +1 -0
  163. package/dist/runtime/staged-source.js +113 -0
  164. package/dist/runtime/wasi/preamble.d.ts.map +1 -1
  165. package/dist/runtime/wasi/preamble.js +0 -24
  166. package/dist/runtime-catalog.generated.js +1 -1
  167. package/dist/session/agent.d.ts +14 -2
  168. package/dist/session/agent.d.ts.map +1 -1
  169. package/dist/session/agent.js +57 -19
  170. package/dist/session/ai.d.ts +0 -11
  171. package/dist/session/ai.d.ts.map +1 -1
  172. package/dist/session/ai.js +0 -4
  173. package/dist/session/fs-watch.d.ts +0 -11
  174. package/dist/session/fs-watch.d.ts.map +1 -1
  175. package/dist/session/fs-watch.js +0 -21
  176. package/dist/session/hibernation.d.ts +34 -11
  177. package/dist/session/hibernation.d.ts.map +1 -1
  178. package/dist/session/hibernation.js +46 -29
  179. package/dist/session/init-phases.d.ts +1 -2
  180. package/dist/session/init-phases.d.ts.map +1 -1
  181. package/dist/session/init-phases.js +1 -2
  182. package/dist/session/init.d.ts.map +1 -1
  183. package/dist/session/init.js +7 -20
  184. package/dist/session/keys.d.ts +0 -3
  185. package/dist/session/keys.d.ts.map +1 -1
  186. package/dist/session/keys.js +0 -3
  187. package/dist/session/legacy-reset.d.ts +11 -0
  188. package/dist/session/legacy-reset.d.ts.map +1 -0
  189. package/dist/session/legacy-reset.js +16 -0
  190. package/dist/session/nimbus-session.d.ts +41 -15
  191. package/dist/session/nimbus-session.d.ts.map +1 -1
  192. package/dist/session/nimbus-session.js +64 -70
  193. package/dist/session/npm-install-port.d.ts.map +1 -1
  194. package/dist/session/npm-install-port.js +1 -0
  195. package/dist/session/programmatic.d.ts +13 -18
  196. package/dist/session/programmatic.d.ts.map +1 -1
  197. package/dist/session/programmatic.js +53 -39
  198. package/dist/session/replica-routes.d.ts +2 -3
  199. package/dist/session/replica-routes.d.ts.map +1 -1
  200. package/dist/session/replica-routes.js +3 -10
  201. package/dist/session/routes.d.ts.map +1 -1
  202. package/dist/session/routes.js +7 -10
  203. package/dist/session/rpc.d.ts +104 -20
  204. package/dist/session/rpc.d.ts.map +1 -1
  205. package/dist/session/rpc.js +184 -37
  206. package/dist/session/start-real-vite.js +2 -2
  207. package/dist/session/state-store.d.ts +1 -17
  208. package/dist/session/state-store.d.ts.map +1 -1
  209. package/dist/session/state-store.js +3 -53
  210. package/dist/session/supervisor-op.d.ts +7 -0
  211. package/dist/session/supervisor-op.d.ts.map +1 -1
  212. package/dist/session/supervisor-op.js +6 -1
  213. package/dist/session/supervisor-rpc.d.ts +104 -15
  214. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  215. package/dist/session/supervisor-rpc.js +188 -71
  216. package/dist/session/vite-command.d.ts.map +1 -1
  217. package/dist/session/vite-command.js +17 -14
  218. package/dist/session/ws.d.ts.map +1 -1
  219. package/dist/session/ws.js +20 -8
  220. package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
  221. package/dist/shell/npm-bin-entrypoints.js +30 -5
  222. package/dist/vfs/facet-resident-limits.d.ts +33 -0
  223. package/dist/vfs/facet-resident-limits.d.ts.map +1 -0
  224. package/dist/vfs/facet-resident-limits.js +33 -0
  225. package/dist/vfs/facet-resident-store.d.ts +2 -10
  226. package/dist/vfs/facet-resident-store.d.ts.map +1 -1
  227. package/dist/vfs/facet-resident-store.js +1594 -219
  228. package/dist/workspace-host.d.ts +2 -0
  229. package/dist/workspace-host.d.ts.map +1 -1
  230. package/dist/workspace-host.js +2 -0
  231. package/dist/wrangler/nimbus-wrangler.d.ts +0 -2
  232. package/dist/wrangler/nimbus-wrangler.d.ts.map +1 -1
  233. package/dist/wrangler/nimbus-wrangler.js +5 -22
  234. package/package.json +8 -7
  235. package/public/_assets/opencode/1.16.2/index-attach.js +2 -2
  236. package/public/_assets/runtime/esbuild-cli-c4fda380d52befc1.js +6892 -0
  237. package/public/_assets/runtime/git-de3e60c9f3ff006a.js +103 -0
  238. package/public/_assets/runtime/{node-shims-7b4dd7a76d95d21e.js → node-shims-06565b121555c194.js} +2089 -861
  239. package/public/_assets/runtime/resident-store-6ffb1939c53d982f.js +2264 -0
  240. package/public/_assets/runtime/vfs-write-ledger-e501e8fc793bc2c1.js +889 -0
  241. package/scripts/build-opencode-attach-entry.mjs +51 -1
  242. package/scripts/bundle-facet-workers.mjs +114 -3
  243. package/scripts/bundle-git.mjs +88 -27
  244. package/scripts/bundle-node-shims.mjs +72 -46
  245. package/scripts/bundle-runtime.mjs +18 -421
  246. package/scripts/cf-git-patch.mjs +137 -0
  247. package/scripts/patch-install-deps.mjs +49 -96
  248. package/scripts/runtime-specs.mjs +435 -0
  249. package/vendor/git-http.generated.d.ts +82 -0
  250. package/vendor/git-upstream.generated.d.ts +4378 -0
  251. package/vendor/git.LICENSE +7 -0
  252. package/vendor/git.generated.d.mts +21 -0
  253. package/vendor/git.generated.mjs +103 -0
  254. package/dist/replica/suspension.d.ts +0 -36
  255. package/dist/replica/suspension.d.ts.map +0 -1
  256. package/dist/replica/suspension.js +0 -49
  257. package/dist/runtime/static-server.d.ts +0 -3
  258. package/dist/runtime/static-server.d.ts.map +0 -1
  259. package/dist/runtime/static-server.js +0 -133
  260. package/scripts/clean-dist.mjs +0 -7
@@ -46,11 +46,11 @@
46
46
  * makes a stale pin a cache miss rather than an outage.
47
47
  */
48
48
  import { z } from 'zod/v4';
49
- import { sha256Hex } from '@nimbus-sh/core/_shared/crypto.js';
49
+ import { sha256Hex, sha256Incremental } from '@nimbus-sh/core/_shared/crypto.js';
50
50
  import { RUNTIME_CATALOG_SHA256 } from '../runtime-catalog.generated.js';
51
51
  import { HexSha256Schema, parseRuntimeManifest, } from '@nimbus-sh/core/runtime/runtime-manifest.js';
52
52
  import { runtimeEntrypoints } from '@nimbus-sh/core/runtime/installed-runtimes.js';
53
- import { splitRuntimeSpec, SUPERSEDED_RUNTIMES, } from '@nimbus-sh/core/runtime/runtime-package.js';
53
+ import { blobPieces, RuntimeBlobDigestMismatch, splitRuntimeSpec, SUPERSEDED_RUNTIMES, } from '@nimbus-sh/core/runtime/runtime-package.js';
54
54
  import { NIMBUS_RUNTIME_ABIS, NATIVE_UNSUPPORTED_ABI, } from '@nimbus-sh/core/runtime/os-contracts.js';
55
55
  const CatalogVersionEntrySchema = z.object({
56
56
  manifest: z.string().min(1),
@@ -162,8 +162,14 @@ export async function fetchManifest(env, entry) {
162
162
  return parseRuntimeManifest(parseJsonBytes(bytes));
163
163
  }
164
164
  /**
165
- * Fetch the blob a manifest file entry points at, verified against the
166
- * digest that same entry carries.
165
+ * Stream the blob a manifest file entry points at, verified against the
166
+ * digest that same entry carries: from the colo cache when it has it, else
167
+ * from R2, read once either way. The stream errors at its end, rather than
168
+ * closing, with a {@link RuntimeBlobDigestMismatch} when its bytes do not
169
+ * hash to the digest; a colo-cache entry that fails is evicted and
170
+ * distrusted first, so the installer's second read of that blob comes from
171
+ * R2 whatever the cache holds by then. The installer commits
172
+ * a blob only after that clean close, so no step holds a blob whole.
167
173
  *
168
174
  * The digest is not optional and does not travel separately from the key:
169
175
  * a `ManifestFile` always has both, and it is the only thing this takes.
@@ -175,9 +181,15 @@ export async function fetchBlob(env, file) {
175
181
  if (!address) {
176
182
  throw new Error(`manifest entry ${file.path} has no usable sha256 (${file.sha256})`);
177
183
  }
178
- const cached = await l2Get(address);
179
- if (cached)
180
- return cached;
184
+ const cached = l2Distrusted.has(address.sha256) ? null : await l2GetBody(address);
185
+ if (cached) {
186
+ return verifiedRead(address, cached, null, async (actual) => {
187
+ l2Distrusted.add(address.sha256);
188
+ await l2Evict(address);
189
+ return `sha256 mismatch for blob ${file.content}: manifest expects ${address.sha256}, `
190
+ + `the colo cache held ${actual} and was evicted`;
191
+ });
192
+ }
181
193
  const r2 = env.NIMBUS_RUNTIME_CACHE;
182
194
  if (!r2) {
183
195
  throw new Error('NIMBUS_RUNTIME_CACHE binding missing — blob cannot be fetched');
@@ -186,14 +198,59 @@ export async function fetchBlob(env, file) {
186
198
  if (!obj) {
187
199
  throw new Error(`blob ${file.content} not in R2 — manifest references a missing blob`);
188
200
  }
189
- const bytes = new Uint8Array(await obj.arrayBuffer());
190
- const verified = await verifyBytes(address, bytes);
191
- if (!verified) {
192
- throw new Error(`sha256 mismatch for blob ${file.content}: manifest expects ${address.sha256}, ` +
193
- `R2 holds ${await sha256Hex(bytes)}`);
194
- }
195
- await l2Put(verified, 'application/octet-stream');
196
- return verified.bytes;
201
+ return verifiedRead(address, obj.body, l2FillWriter(address), (actual) => `sha256 mismatch for blob ${file.content}: manifest expects ${address.sha256}, R2 holds ${actual}`);
202
+ }
203
+ /**
204
+ * `body` as a stream that errors at its end, with a
205
+ * {@link RuntimeBlobDigestMismatch}, rather than closing, unless it hashed to
206
+ * `address`. It is read once. When `fill` is given, the same read feeds L2:
207
+ * each piece reaches the cache before the consumer, and the cache entry is
208
+ * closed only after the digest matched; a mismatch, a failed read or an
209
+ * abandoned stream aborts it, and an aborted body stores nothing. The
210
+ * cache's own pace bounds the pair, so neither side buffers what the other
211
+ * lags by.
212
+ */
213
+ function verifiedRead(address, body, fill, mismatch) {
214
+ const pieces = blobPieces(body);
215
+ const digest = sha256Incremental();
216
+ const drop = (reason) => {
217
+ fill?.abort(reason).catch(() => { });
218
+ fill = null;
219
+ };
220
+ return new ReadableStream({
221
+ async pull(controller) {
222
+ try {
223
+ const next = await pieces.next();
224
+ if (next.done) {
225
+ const actual = await digest.hex();
226
+ if (actual !== address.sha256)
227
+ throw new RuntimeBlobDigestMismatch(await mismatch(actual));
228
+ fill?.close().catch(() => { });
229
+ controller.close();
230
+ return;
231
+ }
232
+ await digest.update(next.value);
233
+ if (fill) {
234
+ try {
235
+ await fill.ready;
236
+ fill.write(next.value).catch(() => { });
237
+ }
238
+ catch (error) {
239
+ drop(error);
240
+ }
241
+ }
242
+ controller.enqueue(next.value);
243
+ }
244
+ catch (error) {
245
+ drop(error);
246
+ throw error;
247
+ }
248
+ },
249
+ async cancel(reason) {
250
+ drop(reason);
251
+ await pieces.return(undefined);
252
+ },
253
+ }, { highWaterMark: 0 });
197
254
  }
198
255
  // ── RuntimeSource ────────────────────────────────────────────────────
199
256
  export function runtimeAbiForCatalogName(name) {
@@ -314,6 +371,59 @@ async function l2Put(verified, contentType) {
314
371
  }
315
372
  catch { /* best-effort */ }
316
373
  }
374
+ /**
375
+ * The body of the blob entry at `address`, or null on a miss or a stripped
376
+ * Cache API. Unverified: served only through {@link verifiedRead}, whose
377
+ * mismatch evicts it and sends later reads of that blob to R2. Hashing an entry before serving it would read every
378
+ * blob from the cache twice, which was most of an install's time.
379
+ */
380
+ async function l2GetBody(address) {
381
+ try {
382
+ const caches = globalThis.caches;
383
+ if (!caches?.default)
384
+ return null;
385
+ const hit = await caches.default.match(new Request(l2Url(address)));
386
+ return hit?.ok && hit.body ? hit.body : null;
387
+ }
388
+ catch {
389
+ return null;
390
+ }
391
+ }
392
+ /**
393
+ * Blob digests whose colo-cache entry failed verification in this isolate.
394
+ * Their reads go to R2 from then on: a purge lands some time after it is
395
+ * asked for, and a shared cache can be poisoned again, so the installer's
396
+ * second read of a failed blob must not depend on either.
397
+ */
398
+ const l2Distrusted = new Set();
399
+ /** Drop the entry at `address` from the colo cache for other isolates. */
400
+ async function l2Evict(address) {
401
+ try {
402
+ await globalThis.caches?.default?.delete(new Request(l2Url(address)));
403
+ }
404
+ catch { /* best-effort */ }
405
+ }
406
+ /** A writer whose bytes become the L2 entry at `address` when it closes;
407
+ * aborting it stores nothing. Null where there is no cache. */
408
+ function l2FillWriter(address) {
409
+ try {
410
+ const caches = globalThis.caches;
411
+ if (!caches?.default)
412
+ return null;
413
+ const { readable, writable } = new TransformStream();
414
+ const resp = new Response(readable, {
415
+ headers: {
416
+ 'Content-Type': 'application/octet-stream',
417
+ 'Cache-Control': 'public, max-age=31536000, immutable',
418
+ },
419
+ });
420
+ caches.default.put(new Request(l2Url(address)), resp).catch(() => { });
421
+ return writable.getWriter();
422
+ }
423
+ catch {
424
+ return null;
425
+ }
426
+ }
317
427
  function l2Url(address) {
318
428
  return `${L2_NS}/${address.scope}/${address.sha256}`;
319
429
  }
@@ -10,10 +10,10 @@
10
10
  * via its `instantiateWasm` hook with that pre-compiled module —
11
11
  * request-time WebAssembly.compile(bytes) is blocked inside facets.
12
12
  *
13
- * Mirrors esbuild-wasm-bytes.ts: NO module-scope cache (no supervisor
14
- * residency), L2 colo cache via caches.default keyed by the version-pinned
15
- * asset URL, ASSETS as the source of truth, and a sha-256 integrity check on
16
- * both tiers so a stale or tampered asset never gets compiled.
13
+ * NO module-scope cache (no supervisor residency). The read itself is
14
+ * runtime/staged-source.ts: L2 keyed by the version-pinned asset URL, ASSETS
15
+ * as the source of truth, and a sha-256 check on both tiers so a stale or
16
+ * tampered asset never gets compiled.
17
17
  */
18
18
  /**
19
19
  * Path inside env.ASSETS where the sql.js wasm binary lives. Versioned so
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-wasm-bytes.d.ts","sourceRoot":"","sources":["../../src/runtime/sqlite-wasm-bytes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,+BAAyC,CAAC;AAE7E,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE;QAAE,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAC;CACpD;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,2DAAqE,CAAC;AAErG;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAwDxF"}
1
+ {"version":3,"file":"sqlite-wasm-bytes.d.ts","sourceRoot":"","sources":["../../src/runtime/sqlite-wasm-bytes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,+BAAyC,CAAC;AAE7E,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE;QAAE,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAC;CACpD;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,2DAAqE,CAAC;AAErG;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAElF"}
@@ -10,15 +10,14 @@
10
10
  * via its `instantiateWasm` hook with that pre-compiled module —
11
11
  * request-time WebAssembly.compile(bytes) is blocked inside facets.
12
12
  *
13
- * Mirrors esbuild-wasm-bytes.ts: NO module-scope cache (no supervisor
14
- * residency), L2 colo cache via caches.default keyed by the version-pinned
15
- * asset URL, ASSETS as the source of truth, and a sha-256 integrity check on
16
- * both tiers so a stale or tampered asset never gets compiled.
13
+ * NO module-scope cache (no supervisor residency). The read itself is
14
+ * runtime/staged-source.ts: L2 keyed by the version-pinned asset URL, ASSETS
15
+ * as the source of truth, and a sha-256 check on both tiers so a stale or
16
+ * tampered asset never gets compiled.
17
17
  */
18
18
  import { SQLJS_VERSION } from '@nimbus-sh/core/constants.js';
19
19
  import { SQLITE_WASM_SHA256 } from '../sqlite-wasm-bundle.generated.js';
20
- import { disposeRpcResource } from '@nimbus-sh/platform/rpc-dispose.js';
21
- import { sha256Hex } from '@nimbus-sh/core/_shared/crypto.js';
20
+ import { fetchStagedBytes } from './staged-source.js';
22
21
  /**
23
22
  * Path inside env.ASSETS where the sql.js wasm binary lives. Versioned so
24
23
  * a future sql.js bump produces a different asset name and forces a fresh
@@ -38,55 +37,20 @@ export const SQLITE_WASM_L2_KEY = `https://nimbus-cache.invalid/_assets/sqljs-${
38
37
  * failures are silent — ASSETS is always the source of truth. A non-200
39
38
  * from ASSETS, or a digest mismatch on either tier, throws.
40
39
  */
41
- export async function fetchSqliteWasmBytes(env) {
42
- const caches = globalThis.caches;
43
- // ── L2 fast path ────────────────────────────────────────────────
44
- let ab = null;
45
- try {
46
- if (caches?.default) {
47
- const hit = await caches.default.match(new Request(SQLITE_WASM_L2_KEY));
48
- if (hit && hit.ok)
49
- ab = await hit.arrayBuffer();
50
- }
51
- }
52
- catch { /* fall through to ASSETS */ }
53
- const fromCache = ab !== null;
54
- if (!ab) {
55
- // ── ASSETS path ───────────────────────────────────────────────
56
- const url = `https://nimbus-internal.invalid${SQLITE_WASM_ASSET_PATH}`;
57
- const res = await env.ASSETS.fetch(new Request(url));
58
- try {
59
- if (!res.ok) {
60
- throw new Error(`sql.js wasm asset fetch failed: ${res.status} ${res.statusText} ` +
61
- `for ${SQLITE_WASM_ASSET_PATH} — deploy is missing the wasm asset`);
62
- }
63
- ab = await res.arrayBuffer();
64
- }
65
- finally {
66
- disposeRpcResource(res);
67
- }
68
- }
69
- const digest = await sha256Hex(ab);
70
- if (digest !== SQLITE_WASM_SHA256) {
71
- throw new Error(`sql.js wasm integrity check failed: expected ${SQLITE_WASM_SHA256}, got ` +
72
- `${digest} (${fromCache ? 'L2 cache' : 'ASSETS'}) for ${SQLITE_WASM_ASSET_PATH} — ` +
73
- 'the staged asset is corrupt or out of sync; rerun ' +
74
- 'scripts/bundle-sqlite-wasm.mjs and redeploy');
75
- }
76
- // ── L2 write-back (best-effort) ─────────────────────────────────
77
- if (!fromCache) {
78
- try {
79
- if (caches?.default) {
80
- const writeBack = new Response(new Uint8Array(ab), {
81
- headers: {
82
- 'Content-Type': 'application/wasm',
83
- 'Cache-Control': 'public, max-age=31536000, immutable',
84
- },
85
- });
86
- await caches.default.put(new Request(SQLITE_WASM_L2_KEY), writeBack);
87
- }
88
- }
89
- catch { /* silent */ }
90
- }
91
- return ab;
40
+ export function fetchSqliteWasmBytes(env) {
41
+ return fetchStagedBytes(env, SQLITE_WASM_ASSET);
92
42
  }
43
+ const SQLITE_WASM_ASSET = {
44
+ path: SQLITE_WASM_ASSET_PATH,
45
+ l2Key: SQLITE_WASM_L2_KEY,
46
+ sha256: SQLITE_WASM_SHA256,
47
+ contentType: 'application/wasm',
48
+ poisonedCache: 'reject',
49
+ missingBinding: `Nimbus: node:sqlite requires an env.ASSETS binding (serves ${SQLITE_WASM_ASSET_PATH})`,
50
+ fetchFailed: (res) => `sql.js wasm asset fetch failed: ${res.status} ${res.statusText} ` +
51
+ `for ${SQLITE_WASM_ASSET_PATH} — deploy is missing the wasm asset`,
52
+ integrityFailed: (digest, from) => `sql.js wasm integrity check failed: expected ${SQLITE_WASM_SHA256}, got ` +
53
+ `${digest} (${from}) for ${SQLITE_WASM_ASSET_PATH} — ` +
54
+ 'the staged asset is corrupt or out of sync; rerun ' +
55
+ 'scripts/bundle-sqlite-wasm.mjs and redeploy',
56
+ };
@@ -0,0 +1,67 @@
1
+ /**
2
+ * staged-source.ts — the one supervisor-side read of a build artifact a bundle
3
+ * script staged under public/_assets/ instead of inlining it in the Worker
4
+ * bundle (wasm modules, facet source texts).
5
+ *
6
+ * The staging script pins each artifact by sha-256 in a `.generated.ts`. This
7
+ * module reads it through L2 (caches.default) under a key that changes with
8
+ * the bytes, with ASSETS as the source of truth, and hands out nothing that
9
+ * fails the pinned digest: a stale or partial asset never reaches workerd's
10
+ * loader or a facet. L2 is written only with verified bytes read from ASSETS.
11
+ *
12
+ * Artifacts differ only in what they name in errors and in what a bad L2 entry
13
+ * means to their caller (`poisonedCache`), so each passes those in.
14
+ */
15
+ /** Minimal env shape — any env with an ASSETS Fetcher binding. */
16
+ export interface StagedSourceEnv {
17
+ ASSETS?: {
18
+ fetch(req: Request): Promise<Response>;
19
+ };
20
+ }
21
+ /** One staged artifact, as its `.generated.ts` pins it. */
22
+ export interface StagedAsset {
23
+ /** Asset path ASSETS serves, e.g. `/_assets/runtime/node-shims-<buildId>.js`. */
24
+ path: string;
25
+ /** L2 key; carries the build id or version, so it changes with the bytes. */
26
+ l2Key: string;
27
+ /** Full digest the bytes must match. */
28
+ sha256: string;
29
+ /** Content-Type of the L2 copy, where the artifact has one. */
30
+ contentType?: string;
31
+ /**
32
+ * An L2 entry that fails the digest: `reject` throws, `refetch` deletes the
33
+ * entry and reads ASSETS instead (whose bytes then replace it).
34
+ */
35
+ poisonedCache: 'reject' | 'refetch';
36
+ /** Message for a deploy with no ASSETS binding. */
37
+ missingBinding: string;
38
+ /** Message for a non-OK ASSETS response. */
39
+ fetchFailed(res: Response): string;
40
+ /** Message for bytes that do not match `sha256`. */
41
+ integrityFailed(digest: string, from: 'L2 cache' | 'ASSETS'): string;
42
+ }
43
+ /** Fetch a staged artifact's bytes and verify them against its pinned digest. */
44
+ export declare function fetchStagedBytes(env: StagedSourceEnv, asset: StagedAsset): Promise<ArrayBuffer>;
45
+ /** {@link fetchStagedBytes}, decoded as UTF-8. */
46
+ export declare function fetchStagedText(env: StagedSourceEnv, asset: StagedAsset): Promise<string>;
47
+ /**
48
+ * One load per isolate: every caller shares the first call's promise, and a
49
+ * rejected one is dropped so the next call loads again instead of pinning the
50
+ * error.
51
+ */
52
+ export declare function memoizeUntilRejected<A, T>(load: (arg: A) => Promise<T>): (arg: A) => Promise<T>;
53
+ /**
54
+ * The `StagedAsset` of a facet source text staged under
55
+ * public/_assets/runtime/ by `stagedBy` and needed by `requiredBy`: a bad L2
56
+ * entry is replaced from ASSETS, since every later fetch in the colo for the
57
+ * build would otherwise fail on it.
58
+ */
59
+ export declare function stagedRuntimeSource(source: {
60
+ label: string;
61
+ entry: string;
62
+ buildId: string;
63
+ sha256: string;
64
+ stagedBy: string;
65
+ requiredBy: string;
66
+ }): StagedAsset;
67
+ //# sourceMappingURL=staged-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staged-source.d.ts","sourceRoot":"","sources":["../../src/runtime/staged-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAC;CACrD;AAED,2DAA2D;AAC3D,MAAM,WAAW,WAAW;IAC1B,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,aAAa,EAAE,QAAQ,GAAG,SAAS,CAAC;IACpC,mDAAmD;IACnD,cAAc,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,WAAW,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAAC;IACnC,oDAAoD;IACpD,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;CACtE;AAED,iFAAiF;AACjF,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CA2CrG;AAED,kDAAkD;AAClD,wBAAsB,eAAe,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAE/F;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAU/F;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,WAAW,CAkBd"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * staged-source.ts — the one supervisor-side read of a build artifact a bundle
3
+ * script staged under public/_assets/ instead of inlining it in the Worker
4
+ * bundle (wasm modules, facet source texts).
5
+ *
6
+ * The staging script pins each artifact by sha-256 in a `.generated.ts`. This
7
+ * module reads it through L2 (caches.default) under a key that changes with
8
+ * the bytes, with ASSETS as the source of truth, and hands out nothing that
9
+ * fails the pinned digest: a stale or partial asset never reaches workerd's
10
+ * loader or a facet. L2 is written only with verified bytes read from ASSETS.
11
+ *
12
+ * Artifacts differ only in what they name in errors and in what a bad L2 entry
13
+ * means to their caller (`poisonedCache`), so each passes those in.
14
+ */
15
+ import { disposeRpcResource } from '@nimbus-sh/platform/rpc-dispose.js';
16
+ import { sha256Hex } from '@nimbus-sh/core/_shared/crypto.js';
17
+ /** Fetch a staged artifact's bytes and verify them against its pinned digest. */
18
+ export async function fetchStagedBytes(env, asset) {
19
+ if (!env.ASSETS)
20
+ throw new Error(asset.missingBinding);
21
+ // The colo cache, where the runtime has one: workerd does, a test harness may not.
22
+ const cache = typeof caches === 'undefined' ? undefined : caches.default;
23
+ if (cache) {
24
+ let cached = null;
25
+ try {
26
+ const hit = await cache.match(new Request(asset.l2Key));
27
+ if (hit && hit.ok)
28
+ cached = await hit.arrayBuffer();
29
+ }
30
+ catch { /* fall through to ASSETS */ }
31
+ if (cached !== null) {
32
+ const digest = await sha256Hex(cached);
33
+ if (digest === asset.sha256)
34
+ return cached;
35
+ if (asset.poisonedCache === 'reject')
36
+ throw new Error(asset.integrityFailed(digest, 'L2 cache'));
37
+ try {
38
+ await cache.delete(new Request(asset.l2Key));
39
+ }
40
+ catch { /* the ASSETS read below still decides */ }
41
+ }
42
+ }
43
+ // ASSETS routes by pathname only; `.invalid` (RFC 2606) marks the host as
44
+ // internal to the binding.
45
+ const res = await env.ASSETS.fetch(new Request(`https://nimbus-internal.invalid${asset.path}`));
46
+ let bytes;
47
+ try {
48
+ if (!res.ok)
49
+ throw new Error(asset.fetchFailed(res));
50
+ bytes = await res.arrayBuffer();
51
+ }
52
+ finally {
53
+ disposeRpcResource(res);
54
+ }
55
+ const digest = await sha256Hex(bytes);
56
+ if (digest !== asset.sha256)
57
+ throw new Error(asset.integrityFailed(digest, 'ASSETS'));
58
+ // Best-effort: ASSETS stays the source of truth. The cache copies the body
59
+ // at put time, so the caller's buffer is unaffected.
60
+ try {
61
+ if (cache) {
62
+ const headers = { 'Cache-Control': 'public, max-age=31536000, immutable' };
63
+ if (asset.contentType)
64
+ headers['Content-Type'] = asset.contentType;
65
+ await cache.put(new Request(asset.l2Key), new Response(new Uint8Array(bytes), { headers }));
66
+ }
67
+ }
68
+ catch { /* silent */ }
69
+ return bytes;
70
+ }
71
+ /** {@link fetchStagedBytes}, decoded as UTF-8. */
72
+ export async function fetchStagedText(env, asset) {
73
+ return new TextDecoder().decode(await fetchStagedBytes(env, asset));
74
+ }
75
+ /**
76
+ * One load per isolate: every caller shares the first call's promise, and a
77
+ * rejected one is dropped so the next call loads again instead of pinning the
78
+ * error.
79
+ */
80
+ export function memoizeUntilRejected(load) {
81
+ let memo = null;
82
+ return (arg) => {
83
+ if (!memo) {
84
+ const loading = load(arg);
85
+ memo = loading;
86
+ loading.catch(() => { if (memo === loading)
87
+ memo = null; });
88
+ }
89
+ return memo;
90
+ };
91
+ }
92
+ /**
93
+ * The `StagedAsset` of a facet source text staged under
94
+ * public/_assets/runtime/ by `stagedBy` and needed by `requiredBy`: a bad L2
95
+ * entry is replaced from ASSETS, since every later fetch in the colo for the
96
+ * build would otherwise fail on it.
97
+ */
98
+ export function stagedRuntimeSource(source) {
99
+ return {
100
+ path: source.entry,
101
+ l2Key: `https://nimbus-cache.invalid${source.entry}?build=${source.buildId}`,
102
+ sha256: source.sha256,
103
+ poisonedCache: 'refetch',
104
+ missingBinding: `Nimbus: ${source.requiredBy} requires an env.ASSETS binding (serves the ` +
105
+ `staged ${source.label} source at ${source.entry}) — add the assets ` +
106
+ 'binding from the embed config (see packages/worker README)',
107
+ fetchFailed: (res) => `${source.label} asset fetch failed: ${res.status} ${res.statusText} for ` +
108
+ `${source.entry} — deploy is missing the staged source (run ${source.stagedBy})`,
109
+ integrityFailed: (digest) => `${source.label} asset integrity mismatch for ${source.entry}: ` +
110
+ `expected ${source.sha256.slice(0, 16)}…, got ${digest.slice(0, 16)}… — ` +
111
+ `the staged asset is stale or corrupt; rerun ${source.stagedBy} and redeploy`,
112
+ };
113
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"preamble.d.ts","sourceRoot":"","sources":["../../../src/runtime/wasi/preamble.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAEV,OAAO,EAMP,eAAe,EACf,kBAAkB,EAClB,sBAAsB,EAGtB,aAAa,EAEb,iBAAiB,EACjB,kBAAkB,EAInB,MAAM,uCAAuC,CAAC;AAmJ/C,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAE1E;AAiBD,wBAAgB,YAAY,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CA0BxD;AAwOD,eAAO,MAAM,OAAO,sBAA6B,CAAC;AAsElD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,sBAAsB,GAAG,kBAAkB,CAikClF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,aAAa,CAcxF;AAeD,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAyB5G"}
1
+ {"version":3,"file":"preamble.d.ts","sourceRoot":"","sources":["../../../src/runtime/wasi/preamble.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAEV,OAAO,EAMP,eAAe,EACf,kBAAkB,EAClB,sBAAsB,EAGtB,aAAa,EAEb,iBAAiB,EACjB,kBAAkB,EAInB,MAAM,uCAAuC,CAAC;AAmJ/C,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAE1E;AAiBD,wBAAgB,YAAY,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CA0BxD;AAwOD,eAAO,MAAM,OAAO,sBAA6B,CAAC;AAsElD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,sBAAsB,GAAG,kBAAkB,CA4iClF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,aAAa,CAcxF;AAeD,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAyB5G"}
@@ -549,30 +549,6 @@ export function __wasiMakeImports(opts) {
549
549
  stderrBuf += s;
550
550
  }
551
551
  }
552
- /** Scatter the given bytes across the iovec list; returns bytes consumed. */
553
- function scatterIovs(bytes, iovsPtr, iovsLen, dv, memU8) {
554
- let done = 0;
555
- for (let i = 0; i < iovsLen && done < bytes.length; i++) {
556
- const iov = iovsPtr + i * 8;
557
- const bufPtr = dv.getUint32(iov, true);
558
- const bufLen = dv.getUint32(iov + 4, true);
559
- const n = Math.min(bufLen, bytes.length - done);
560
- if (n <= 0)
561
- break;
562
- memU8.set(bytes.subarray(done, done + n), bufPtr);
563
- done += n;
564
- if (n < bufLen)
565
- break;
566
- }
567
- return done;
568
- }
569
- /** Total capacity of an iovec list. */
570
- function iovsCapacity(iovsPtr, iovsLen, dv) {
571
- let total = 0;
572
- for (let i = 0; i < iovsLen; i++)
573
- total += dv.getUint32(iovsPtr + i * 8 + 4, true);
574
- return total;
575
- }
576
552
  const imports = {
577
553
  // ── args / env ──
578
554
  args_get(argvPtr, argvBufPtr) {
@@ -24,4 +24,4 @@
24
24
  * The empty string means "not pinned yet" — the catalog stays out of L2 and
25
25
  * the supervisor warns once per isolate.
26
26
  */
27
- export const RUNTIME_CATALOG_SHA256 = "9cdc9cc0d96667234c6fed2adc81e7890fef96b3afe5bd80dd80612e822d3d3a";
27
+ export const RUNTIME_CATALOG_SHA256 = "2827a7f7245403cb7644c27f0075423dd1ba00313b8c40f70f4dfa5bcd097ed0";
@@ -13,13 +13,25 @@ interface Host extends ProgrammaticHost, SessionAiHost {
13
13
  ctx: ProgrammaticHost['ctx'];
14
14
  env: ProgrammaticHost['env'] & Record<string, unknown>;
15
15
  }
16
- interface OAuthStatePayload {
16
+ export interface OAuthStatePayload {
17
17
  v: 1;
18
18
  nonce: string;
19
19
  sessionId: string;
20
20
  tenantSegment: string;
21
+ /** Expiry (ms since the epoch), signed with the rest. */
22
+ exp: number;
21
23
  }
22
24
  export declare function handleAgentRequest(self: Host, request: Request, url: URL): Promise<Response>;
23
- export declare function parseAgentOAuthStateParam(state: string | null): OAuthStatePayload | null;
25
+ /**
26
+ * The OAuth `state` a callback carries, if this deployment signed it. The
27
+ * router routes a callback by the session and tenant segment in `state`, so an
28
+ * unsigned one would let any client wake or create a Durable Object under any
29
+ * tenant segment; the signature (HMAC-SHA256 under the agent cookie secret)
30
+ * makes the router refuse it before routing. An expired one (its signed `exp`
31
+ * at or before `now`) is refused the same way. Null for anything else.
32
+ */
33
+ export declare function parseAgentOAuthStateParam(state: string | null, env: Record<string, unknown>, now?: number): Promise<OAuthStatePayload | null>;
34
+ /** The `state` an OAuth flow carries: `<payload>.<signature>`, both base64url. */
35
+ export declare function signAgentOAuthState(payload: OAuthStatePayload, env: Record<string, unknown>): Promise<string>;
24
36
  export {};
25
37
  //# sourceMappingURL=agent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/session/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgCH,OAAO,EASL,KAAK,aAAa,EACnB,MAAM,SAAS,CAAC;AACjB,OAAO,EAYL,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAkB3B,UAAU,IAAK,SAAQ,gBAAgB,EAAE,aAAa;IACpD,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC7B,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxD;AAED,UAAU,iBAAiB;IACzB,CAAC,EAAE,CAAC,CAAC;IACL,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AA2BD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2ClG;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,iBAAiB,GAAG,IAAI,CAQxF"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/session/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAkCH,OAAO,EASL,KAAK,aAAa,EACnB,MAAM,SAAS,CAAC;AACjB,OAAO,EAYL,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAkB3B,UAAU,IAAK,SAAQ,gBAAgB,EAAE,aAAa;IACpD,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC7B,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,iBAAiB;IAChC,CAAC,EAAE,CAAC,CAAC;IACL,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAC;CACb;AA0BD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2ClG;AAED;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,GAAG,SAAa,GACf,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAWnC;AAs/BD,kFAAkF;AAClF,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAKnH"}