@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.
- package/NOTICE.md +5 -0
- package/README.md +10 -0
- package/dist/_shared/session-router.d.ts +7 -0
- package/dist/_shared/session-router.d.ts.map +1 -1
- package/dist/_shared/session-router.js +7 -0
- package/dist/bindings/body.d.ts +6 -0
- package/dist/bindings/body.d.ts.map +1 -0
- package/dist/bindings/body.js +37 -0
- package/dist/bindings/kv.d.ts +0 -2
- package/dist/bindings/kv.d.ts.map +1 -1
- package/dist/bindings/kv.js +3 -42
- package/dist/bindings/r2.d.ts +0 -2
- package/dist/bindings/r2.d.ts.map +1 -1
- package/dist/bindings/r2.js +4 -44
- package/dist/esbuild-cli-artifact.generated.d.ts +18 -0
- package/dist/esbuild-cli-artifact.generated.d.ts.map +1 -0
- package/dist/esbuild-cli-artifact.generated.js +17 -0
- package/dist/facets/cirrus-real.d.ts.map +1 -1
- package/dist/facets/cirrus-real.js +9 -4
- package/dist/facets/compose.d.ts +11 -7
- package/dist/facets/compose.d.ts.map +1 -1
- package/dist/facets/compose.js +8 -38
- package/dist/facets/data-plan.d.ts +79 -0
- package/dist/facets/data-plan.d.ts.map +1 -0
- package/dist/facets/data-plan.js +477 -0
- package/dist/facets/esbuild-transform.d.ts +36 -10
- package/dist/facets/esbuild-transform.d.ts.map +1 -1
- package/dist/facets/esbuild-transform.js +216 -20
- package/dist/facets/exec-telemetry.d.ts +7 -3
- package/dist/facets/exec-telemetry.d.ts.map +1 -1
- package/dist/facets/manager.d.ts +179 -78
- package/dist/facets/manager.d.ts.map +1 -1
- package/dist/facets/manager.js +1221 -649
- package/dist/facets/opencode-staging.d.ts +0 -2
- package/dist/facets/opencode-staging.d.ts.map +1 -1
- package/dist/facets/opencode-staging.js +5 -11
- package/dist/facets/process.d.ts +4 -0
- package/dist/facets/process.d.ts.map +1 -1
- package/dist/facets/process.js +3 -0
- package/dist/facets/read-profile.d.ts +149 -0
- package/dist/facets/read-profile.d.ts.map +1 -0
- package/dist/facets/read-profile.js +483 -0
- package/dist/facets/resident-identity.d.ts +0 -1
- package/dist/facets/resident-identity.d.ts.map +1 -1
- package/dist/facets/resident-identity.js +0 -3
- package/dist/facets/wasm-swap-registry.d.ts +34 -25
- package/dist/facets/wasm-swap-registry.d.ts.map +1 -1
- package/dist/facets/wasm-swap-registry.js +62 -56
- package/dist/facets/ws-terminal.d.ts +4 -4
- package/dist/facets/ws-terminal.d.ts.map +1 -1
- package/dist/facets/ws-terminal.js +4 -5
- package/dist/git/commands.d.ts +16 -9
- package/dist/git/commands.d.ts.map +1 -1
- package/dist/git/commands.js +1818 -188
- package/dist/git/network-facet.d.ts +10 -2
- package/dist/git/network-facet.d.ts.map +1 -1
- package/dist/git/network-facet.js +62 -16
- package/dist/git/unified-diff.d.ts +74 -0
- package/dist/git/unified-diff.d.ts.map +1 -0
- package/dist/git/unified-diff.js +676 -0
- package/dist/git-bundle.generated.d.ts +7 -11
- package/dist/git-bundle.generated.d.ts.map +1 -1
- package/dist/git-bundle.generated.js +7 -11
- package/dist/hosted/commands.d.ts.map +1 -1
- package/dist/hosted/commands.js +62 -243
- package/dist/hosted/runtime.d.ts +19 -13
- package/dist/hosted/runtime.d.ts.map +1 -1
- package/dist/hosted/runtime.js +71 -14
- package/dist/hosted/services.d.ts +6 -7
- package/dist/hosted/services.d.ts.map +1 -1
- package/dist/hosted/services.js +10 -14
- package/dist/hosted/session.d.ts +165 -0
- package/dist/hosted/session.d.ts.map +1 -0
- package/dist/hosted/session.js +132 -0
- package/dist/loaders/generated-workers.d.ts +5 -2
- package/dist/loaders/generated-workers.d.ts.map +1 -1
- package/dist/loaders/generated-workers.js +6 -3
- package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -1
- package/dist/loaders/npm-resolve-preamble.js +0 -27
- package/dist/node-shims-artifact.generated.d.ts +13 -4
- package/dist/node-shims-artifact.generated.d.ts.map +1 -1
- package/dist/node-shims-artifact.generated.js +16 -7
- package/dist/npm/bin-links.d.ts +3 -1
- package/dist/npm/bin-links.d.ts.map +1 -1
- package/dist/npm/bin-links.js +32 -8
- package/dist/npm/cache.d.ts +5 -0
- package/dist/npm/cache.d.ts.map +1 -1
- package/dist/npm/cache.js +13 -1
- package/dist/npm/install-batch-facet.d.ts +2 -2
- package/dist/npm/install-batch-facet.js +3 -3
- package/dist/npm/installer.d.ts +17 -1
- package/dist/npm/installer.d.ts.map +1 -1
- package/dist/npm/installer.js +159 -20
- package/dist/npm/package-lock.d.ts +32 -0
- package/dist/npm/package-lock.d.ts.map +1 -0
- package/dist/npm/package-lock.js +65 -0
- package/dist/npm/pre-bundle-facet.d.ts +1 -30
- package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
- package/dist/npm/pre-bundle-facet.js +3 -5
- package/dist/npm/r2-cache.d.ts +2 -0
- package/dist/npm/r2-cache.d.ts.map +1 -1
- package/dist/npm/r2-cache.js +2 -0
- package/dist/npm/resolve-one-facet.d.ts.map +1 -1
- package/dist/npm/resolve-one-facet.js +14 -3
- package/dist/npm/resolver.d.ts +0 -7
- package/dist/npm/resolver.d.ts.map +1 -1
- package/dist/npm/resolver.js +0 -22
- package/dist/opencode-artifact.generated.js +2 -2
- package/dist/replica/routing.d.ts +2 -38
- package/dist/replica/routing.d.ts.map +1 -1
- package/dist/replica/routing.js +3 -55
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +15 -2
- package/dist/router/public-directory.d.ts +18 -0
- package/dist/router/public-directory.d.ts.map +1 -1
- package/dist/router/public-directory.js +1 -1
- package/dist/router/remote-api.d.ts +3 -1
- package/dist/router/remote-api.d.ts.map +1 -1
- package/dist/router/remote-api.js +42 -79
- package/dist/runtime/bash-repl.js +2 -2
- package/dist/runtime/bun-repl.d.ts.map +1 -1
- package/dist/runtime/bun-repl.js +2 -13
- package/dist/runtime/esbuild-wasm-bytes.d.ts +17 -5
- package/dist/runtime/esbuild-wasm-bytes.d.ts.map +1 -1
- package/dist/runtime/esbuild-wasm-bytes.js +43 -94
- package/dist/runtime/git-bundle-artifact.d.ts +17 -0
- package/dist/runtime/git-bundle-artifact.d.ts.map +1 -0
- package/dist/runtime/git-bundle-artifact.js +25 -0
- package/dist/runtime/node-repl.d.ts.map +1 -1
- package/dist/runtime/node-repl.js +2 -13
- package/dist/runtime/node-shims-artifact.d.ts +22 -23
- package/dist/runtime/node-shims-artifact.d.ts.map +1 -1
- package/dist/runtime/node-shims-artifact.js +48 -78
- package/dist/runtime/node-shims.d.ts.map +1 -1
- package/dist/runtime/node-shims.js +1567 -864
- package/dist/runtime/opencode-artifact.d.ts.map +1 -1
- package/dist/runtime/opencode-artifact.js +17 -53
- package/dist/runtime/opencode-facet-runner.d.ts +3 -6
- package/dist/runtime/opencode-facet-runner.d.ts.map +1 -1
- package/dist/runtime/opencode-facet-runner.js +45 -10
- package/dist/runtime/opentui-wasm-bytes.d.ts.map +1 -1
- package/dist/runtime/opentui-wasm-bytes.js +16 -49
- package/dist/runtime/package-manager.d.ts +0 -2
- package/dist/runtime/package-manager.d.ts.map +1 -1
- package/dist/runtime/package-manager.js +0 -3
- package/dist/runtime/python-repl.d.ts.map +1 -1
- package/dist/runtime/python-repl.js +2 -2
- package/dist/runtime/repl-session.d.ts +10 -0
- package/dist/runtime/repl-session.d.ts.map +1 -1
- package/dist/runtime/repl-session.js +7 -0
- package/dist/runtime/ruby-repl.d.ts.map +1 -1
- package/dist/runtime/ruby-repl.js +2 -2
- package/dist/runtime/ruby-resident.d.ts.map +1 -1
- package/dist/runtime/ruby-resident.js +36 -35
- package/dist/runtime/runtime-catalog.d.ts +10 -3
- package/dist/runtime/runtime-catalog.d.ts.map +1 -1
- package/dist/runtime/runtime-catalog.js +125 -15
- package/dist/runtime/sqlite-wasm-bytes.d.ts +4 -4
- package/dist/runtime/sqlite-wasm-bytes.d.ts.map +1 -1
- package/dist/runtime/sqlite-wasm-bytes.js +21 -57
- package/dist/runtime/staged-source.d.ts +67 -0
- package/dist/runtime/staged-source.d.ts.map +1 -0
- package/dist/runtime/staged-source.js +113 -0
- package/dist/runtime/wasi/preamble.d.ts.map +1 -1
- package/dist/runtime/wasi/preamble.js +0 -24
- package/dist/runtime-catalog.generated.js +1 -1
- package/dist/session/agent.d.ts +14 -2
- package/dist/session/agent.d.ts.map +1 -1
- package/dist/session/agent.js +57 -19
- package/dist/session/ai.d.ts +0 -11
- package/dist/session/ai.d.ts.map +1 -1
- package/dist/session/ai.js +0 -4
- package/dist/session/fs-watch.d.ts +0 -11
- package/dist/session/fs-watch.d.ts.map +1 -1
- package/dist/session/fs-watch.js +0 -21
- package/dist/session/hibernation.d.ts +34 -11
- package/dist/session/hibernation.d.ts.map +1 -1
- package/dist/session/hibernation.js +46 -29
- package/dist/session/init-phases.d.ts +1 -2
- package/dist/session/init-phases.d.ts.map +1 -1
- package/dist/session/init-phases.js +1 -2
- package/dist/session/init.d.ts.map +1 -1
- package/dist/session/init.js +7 -20
- package/dist/session/keys.d.ts +0 -3
- package/dist/session/keys.d.ts.map +1 -1
- package/dist/session/keys.js +0 -3
- package/dist/session/legacy-reset.d.ts +11 -0
- package/dist/session/legacy-reset.d.ts.map +1 -0
- package/dist/session/legacy-reset.js +16 -0
- package/dist/session/nimbus-session.d.ts +41 -15
- package/dist/session/nimbus-session.d.ts.map +1 -1
- package/dist/session/nimbus-session.js +64 -70
- package/dist/session/npm-install-port.d.ts.map +1 -1
- package/dist/session/npm-install-port.js +1 -0
- package/dist/session/programmatic.d.ts +13 -18
- package/dist/session/programmatic.d.ts.map +1 -1
- package/dist/session/programmatic.js +53 -39
- package/dist/session/replica-routes.d.ts +2 -3
- package/dist/session/replica-routes.d.ts.map +1 -1
- package/dist/session/replica-routes.js +3 -10
- package/dist/session/routes.d.ts.map +1 -1
- package/dist/session/routes.js +7 -10
- package/dist/session/rpc.d.ts +104 -20
- package/dist/session/rpc.d.ts.map +1 -1
- package/dist/session/rpc.js +184 -37
- package/dist/session/start-real-vite.js +2 -2
- package/dist/session/state-store.d.ts +1 -17
- package/dist/session/state-store.d.ts.map +1 -1
- package/dist/session/state-store.js +3 -53
- package/dist/session/supervisor-op.d.ts +7 -0
- package/dist/session/supervisor-op.d.ts.map +1 -1
- package/dist/session/supervisor-op.js +6 -1
- package/dist/session/supervisor-rpc.d.ts +104 -15
- package/dist/session/supervisor-rpc.d.ts.map +1 -1
- package/dist/session/supervisor-rpc.js +188 -71
- package/dist/session/vite-command.d.ts.map +1 -1
- package/dist/session/vite-command.js +17 -14
- package/dist/session/ws.d.ts.map +1 -1
- package/dist/session/ws.js +20 -8
- package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
- package/dist/shell/npm-bin-entrypoints.js +30 -5
- package/dist/vfs/facet-resident-limits.d.ts +33 -0
- package/dist/vfs/facet-resident-limits.d.ts.map +1 -0
- package/dist/vfs/facet-resident-limits.js +33 -0
- package/dist/vfs/facet-resident-store.d.ts +2 -10
- package/dist/vfs/facet-resident-store.d.ts.map +1 -1
- package/dist/vfs/facet-resident-store.js +1594 -219
- package/dist/workspace-host.d.ts +2 -0
- package/dist/workspace-host.d.ts.map +1 -1
- package/dist/workspace-host.js +2 -0
- package/dist/wrangler/nimbus-wrangler.d.ts +0 -2
- package/dist/wrangler/nimbus-wrangler.d.ts.map +1 -1
- package/dist/wrangler/nimbus-wrangler.js +5 -22
- package/package.json +8 -7
- package/public/_assets/opencode/1.16.2/index-attach.js +2 -2
- package/public/_assets/runtime/esbuild-cli-c4fda380d52befc1.js +6892 -0
- package/public/_assets/runtime/git-de3e60c9f3ff006a.js +103 -0
- package/public/_assets/runtime/{node-shims-7b4dd7a76d95d21e.js → node-shims-06565b121555c194.js} +2089 -861
- package/public/_assets/runtime/resident-store-6ffb1939c53d982f.js +2264 -0
- package/public/_assets/runtime/vfs-write-ledger-e501e8fc793bc2c1.js +889 -0
- package/scripts/build-opencode-attach-entry.mjs +51 -1
- package/scripts/bundle-facet-workers.mjs +114 -3
- package/scripts/bundle-git.mjs +88 -27
- package/scripts/bundle-node-shims.mjs +72 -46
- package/scripts/bundle-runtime.mjs +18 -421
- package/scripts/cf-git-patch.mjs +137 -0
- package/scripts/patch-install-deps.mjs +49 -96
- package/scripts/runtime-specs.mjs +435 -0
- package/vendor/git-http.generated.d.ts +82 -0
- package/vendor/git-upstream.generated.d.ts +4378 -0
- package/vendor/git.LICENSE +7 -0
- package/vendor/git.generated.d.mts +21 -0
- package/vendor/git.generated.mjs +103 -0
- package/dist/replica/suspension.d.ts +0 -36
- package/dist/replica/suspension.d.ts.map +0 -1
- package/dist/replica/suspension.js +0 -49
- package/dist/runtime/static-server.d.ts +0 -3
- package/dist/runtime/static-server.d.ts.map +0 -1
- package/dist/runtime/static-server.js +0 -133
- 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
|
-
*
|
|
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
|
|
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
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
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;
|
|
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
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
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 {
|
|
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
|
|
42
|
-
|
|
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,
|
|
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 = "
|
|
27
|
+
export const RUNTIME_CATALOG_SHA256 = "2827a7f7245403cb7644c27f0075423dd1ba00313b8c40f70f4dfa5bcd097ed0";
|
package/dist/session/agent.d.ts
CHANGED
|
@@ -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
|
-
|
|
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;
|
|
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"}
|