diff --git a/AGENTS.md b/AGENTS.md index bc211cd..7c7c7ce 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -77,7 +77,7 @@ design record. | --- | --- | | `just check` | fmt, clippy (all features), workspace tests (RFC 9001 vectors, profile/provider pinning, class-D key rejection), wasm build | | `just ci` | every gating CI job's body, exactly as CI runs it — each CI job runs one gha:: job recipe (.github/justfile). The timing lab is schedule-only and excluded | -| `just conformance` | the cross-implementation conformance suite (see `conformance/README.md`): the shared guest suite composed with each delivery — the `tls` world's in-guest Ed25519 posture and the `tls-delegated` world with the fixture signer — run under the pinned component-test runner, runtime-linked under deltic on stock Deno (the deltic-deno targets — no transpile, no engine flag; release-pinned in `conformance/driver-ct/deltic/`), and runtime-linked in headless Chromium (the deltic-browser targets; CI or CONFORMANCE_BROWSER=1), with import-satisfaction and signer-reachability gates, validated against the committed case inventory (`tests.lock`) and target manifest, and diffed against the committed matrix. `just conformance-ct::run-webcrypto` (on demand: clones the sibling repo) adds the delegated posture over a real `polymorph:webcrypto` provider | +| `just conformance` | the cross-implementation conformance suite (see `conformance/README.md`): the shared guest suite composed with each delivery — the `tls` world's in-guest Ed25519 posture and the `tls-delegated` world with the fixture signer — run under the pinned component-test runner, runtime-linked under deltic on stock Deno (the deltic-deno targets — no transpile, no engine flag; JSR-pinned in `conformance/driver-ct/deltic/`), and runtime-linked in headless Chromium (the deltic-browser targets; CI or CONFORMANCE_BROWSER=1), with import-satisfaction and signer-reachability gates, validated against the committed case inventory (`tests.lock`) and target manifest, and diffed against the committed matrix. `just conformance-ct::run-webcrypto` (on demand: clones the sibling repo) adds the delegated posture over a real `polymorph:webcrypto` provider | | `just smoke-quic` | QUIC over `wasi:sockets` UDP under Wasmtime | | `just smoke-tls-virt` | both tls-virt deliveries against `openssl s_server` over real TCP (needs openssl + python3): the composed guest virtualizer (handle-address and import-satisfaction gates), and the wasmtime host provider on both sockets generations — wasip3 and `std::net`/0.2 guests — with handle-address and profile-cipher-suite gates plus plain-TCP passthrough-delegation legs | | `just interop` | cross-implementation, over real transports, fresh Ed25519 private PKI per run: the composed TLS component against OpenSSL and Go peers over TCP in both directions (including the close_notify-vs-truncation and reset scenarios), and the noq leg against quic-go over UDP in both directions | diff --git a/conformance/README.md b/conformance/README.md index c0d53fc..f468621 100644 --- a/conformance/README.md +++ b/conformance/README.md @@ -27,7 +27,7 @@ A target is a composition, not a runtime configuration: the suite is `wac plug`-ged with one TLS stack, and the resulting artifact imports only wasi and `polymorph:test/test-context`. The wasmtime rows run under the generic component-test host runner; the deltic rows -runtime-link the same artifacts under the release-pinned deltic +runtime-link the same artifacts under the JSR-pinned deltic runtime (`driver-ct/deltic/`) — one suite, one composition, two engines. diff --git a/conformance/driver-ct/deltic/README.md b/conformance/driver-ct/deltic/README.md index f27d8c8..abbcc68 100644 --- a/conformance/driver-ct/deltic/README.md +++ b/conformance/driver-ct/deltic/README.md @@ -26,11 +26,17 @@ target here. ## Pinning -deltic is pinned to a release tag in `deno.json` (import-map URLs; -`deno.lock` carries the module-graph integrity, enforced with -`--frozen`) and `fetch-translator.ts` (TAG + sha256 for the -`deltic-translator-shim.wasm` release asset, cached under -`target/deltic//`), cross-checked at run time. To bump: update the -tag in both files and the sha from the release's `SHA256SUMS`, delete -`deno.lock`, re-run `deno cache run.ts fetch-translator.ts` here, and -commit the diff. +deltic is pinned to an exact JSR prerelease (`0.1.0-pre.ga67ee83`; the +hash names one upstream commit) via `deno.json`'s import-map (`deno.lock` +carries module-graph integrity, enforced with `--frozen`). The browser +leg's embedder bundle and translator wasm are built from that SAME +pinned graph (`../justfile`'s `_deltic-browser-build` recipe: `deno +bundle` for the embedder, `deno info` + copy for the translator wasm) — +no sha256 bookkeeping, no GitHub release-asset fetch. A repo-wide pin +gate (`../justfile`'s `_deltic-pin-check`) asserts every `deno.json` in +the repo agrees on one `@deltic` version. + +To bump: update the version in this directory's `deno.json` import-map +entries, delete `deno.lock`, run `deno install --config deno.json +--entrypoint run.ts browser-bundle-entry.ts` here, and commit the diff +(the pin gate asserts agreement). diff --git a/conformance/driver-ct/deltic/browser-bundle-entry.ts b/conformance/driver-ct/deltic/browser-bundle-entry.ts new file mode 100644 index 0000000..c58f8a7 --- /dev/null +++ b/conformance/driver-ct/deltic/browser-bundle-entry.ts @@ -0,0 +1,10 @@ +// Bundle entry for the deltic-browser leg: this is upstream +// tools/release-bundle/entry.ts's exact public surface, vendored here so +// the browser bundle is built from the SAME pinned JSR graph as the Deno +// legs instead of a sha256-pinned release asset (see README.md's +// "Pinning" section and ../justfile's `_deltic-browser-build` recipe). +export * from "@deltic/runtime/embedder"; +export { Translator } from "@deltic/runtime/shim"; +export * from "@deltic/ct-runner"; +export { wasiShims } from "@deltic/wasi-shims"; +export type { WasiShims, WasiShimsOptions } from "@deltic/wasi-shims"; diff --git a/conformance/driver-ct/deltic/deno.json b/conformance/driver-ct/deltic/deno.json index 6fd1543..7455a0c 100644 --- a/conformance/driver-ct/deltic/deno.json +++ b/conformance/driver-ct/deltic/deno.json @@ -1,12 +1,14 @@ { - "//": "The deltic release pin (TAG in fetch-translator.ts must match; its assertPinConsistency checks). @deltic/runtime/embedder is mapped because wasi-shims imports it by bare specifier internally.", + "//": "The deltic pin: every @deltic/* import is an exact-pinned JSR prerelease (0.1.0-pre.ga67ee83); the hash names one upstream commit and @deltic/translator ships the translator wasm for that SAME commit. deno.lock carries integrity, --frozen enforced. One version repo-wide is asserted by the pin gate (../justfile).", "imports": { - "@deltic/ct-runner": "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/ct-runner/src/mod.ts", - "@deltic/runtime/embedder": "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/embedder/mod.ts", - "@deltic/runtime/shim": "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/shim/mod.ts", - "@deltic/wasi-shims": "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/wasi-shims/src/mod.ts" + "@deltic/ct-runner": "jsr:@deltic/ct-runner@0.1.0-pre.ga67ee83", + "@deltic/runtime/embedder": "jsr:@deltic/runtime@0.1.0-pre.ga67ee83/embedder", + "@deltic/runtime/shim": "jsr:@deltic/runtime@0.1.0-pre.ga67ee83/shim", + "@deltic/wasi-shims": "jsr:@deltic/wasi-shims@0.1.0-pre.ga67ee83", + "@deltic/translator": "jsr:@deltic/translator@0.1.0-pre.ga67ee83" }, + "minimumDependencyAge": { "age": "P1D", "exclude": ["jsr:@deltic/*"] }, "tasks": { - "check": "deno check run.ts fetch-translator.ts" + "check": "deno check run.ts browser-bundle-entry.ts" } } diff --git a/conformance/driver-ct/deltic/deno.lock b/conformance/driver-ct/deltic/deno.lock index 0427d07..61b993e 100644 --- a/conformance/driver-ct/deltic/deno.lock +++ b/conformance/driver-ct/deltic/deno.lock @@ -1,69 +1,49 @@ { "version": "5", - "remote": { - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/ct-runner/src/context.ts": "366db52e3189260a7fd2fc2fdb90aea9bd6a3055d83c42acad082eb75565c634", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/ct-runner/src/import-analysis.ts": "64971e796ebccd98730ba2a0e78b599db38284f22b7976687fc4cad898703c32", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/ct-runner/src/mod.ts": "24a88cb8dda9c1d346a1809297cc5b2ab1c3a2d39c4914694c2ee5f76e9911db", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/ct-runner/src/run-suite.ts": "76d76ed7dfbeb7ce24410dfabadb8f1524fe6e1adb0428b7d361310168a44411", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/ct-runner/src/tags.ts": "d64136eb7e21e18e73cc255e052f59377d2be869f4929bf4fc6de026f3b74a0b", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/async_values.ts": "af1279d4e4db5b756268979aeff5b27c1cf6c0f021213655676ade90472f282b", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/context.ts": "b4b60891ef9d9e72b208636f6ba37f0b9b6962d307af6156ad3b5ad59a626902", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/flatten.ts": "6c980fe38d7adce349d5e028b819eb0ffbb92714f958c1d5daae8da3e7ed3889", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/float.ts": "0483e8c1aa8786eee4c6f6357fee6738555e4310650c474aba6cd811a80d7d36", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/handles.ts": "30510750261499f48a812bb8c349a8f88a3bb7239175e6f1d4e6d10c38571e5d", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/layout.ts": "8122141b39f4d8189c13d91fc1b37825ceead86988f879f3fa9351bbef96f8f2", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/lift.ts": "e4475a44a5618114f288025601b535bc04b97e9a37b3be21f51d3be092d419c8", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/load.ts": "c1d8ddb1b3b3c59afe30710a97ad6dd7ae1ecd59aa1d427a5eaf4552d3b1ea01", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/lower.ts": "916ef7476dc583783770f4c42de7a655350531b3763c81a92249cca96f5e4d80", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/memory.ts": "09728360d6413fb30a5a7bff1ba6abec1ac6474ff150d45f093b8ebe5e65cd51", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/mod.ts": "b79cf9e2bab2e837fee76fa61dc18bff66d941e08597f1b76de93811bd6d6008", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/store.ts": "97aaecfeb4dfbf5c3c132fb5eadf1f5677924936eee0c7fa75a266a00cd73634", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/strings.ts": "9589dda3857725792ae15ef6888449b48e973b9eb0f3058ed64e10bf4d39b793", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/trap.ts": "307d8b48806eeba30400b3d7db9370cee70a12298851c1c19053dd8ca0013e1c", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/types.ts": "d0392e8cdf2990a76c8a1f9b85795d3b7c19b8eb006c2b159b671d08c39b9535", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/cabi/values.ts": "9e6ddcc4192d05897b2cbea250db3fef0ad9bf6548ba87aff378ee14b7ab7022", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/embedder/casing.ts": "1e9083becfc08107c09015ce3db79c304b05c40085a3c899ea1c8ebe25fcd45f", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/embedder/errors.ts": "b0cac244526b92c052d165f2aee1d9492e5915a5a4cad114e1ab575ffe1587ba", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/embedder/imports.ts": "98cca003e4a1131c35854c91b458f109d6761a3e8f67c23730f7e9bc28bbad88", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/embedder/instantiate.ts": "2479c085a82adc20eb3e8e11832cad8daaa50992d383e8a38d73fbc7259f52e5", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/embedder/mod.ts": "0a4f42b8c569b528b4c3172c3394ad5f9ddafa33bcaf5eccd00e645e111da2b1", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/embedder/resources.ts": "d209e5f13545b9c0c095ac4e188b72370d97c9bd394ba7c8793ddd74f436b1ef", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/embedder/streams.ts": "4ef894a43da94b4cb01ee65798a108a8fb3f6b2dc6013c71881f63e0806df565", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/embedder/values.ts": "ed876f9103f4a4f34e8eb475934091156bee1447f5a029ea300644b8f3ee71eb", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/embedder/version.ts": "b1c589988e5fb88dce3a014846c9253399e286f12afb5fd92509c8d6090ad4bb", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/exec/boundary.ts": "8a162aefc3524ce1a72f294a95eadc92b66764de75bad84966301192a57ae92e", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/exec/executor.ts": "55044c381d842a9d0f17731d55b47b48023d3a9222806e4b0607b53615a1dc97", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/exec/host_streams.ts": "63f6b113806c401ae9895df82448da70a7745a97b6e2f04061fb5bc64e7d0acf", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/exec/mod.ts": "a46320977ece14342bcb72c9c9e36d65a1cd09d789591d0909d7d1185264010b", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/intrinsics/async_builtins.ts": "526795358da8908d54a483bb47eebc43e0a1ea59e69ece94d0c6890ad0fa8784", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/intrinsics/context.ts": "be93b23d127ff71d5c372781f89d1c3746c5d32a44e67ebbcd91f2b0f0807e93", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/intrinsics/errors.ts": "9d09fc1818b4dc98b238aa69008a9110d9d305b6a8e806604f3bd48fca1eebcb", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/intrinsics/fact_calls.ts": "aa0b0aef81b59cdcd8dc572c20e1f57a8f5592f75a0d5d666032851df9201229", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/intrinsics/mod.ts": "f9c095e561f5fbb51f70693b21f272f66241f2e8ff2e1a83cd4176bcd0104eb9", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/intrinsics/stream_builtins.ts": "bbc1e1ea0e4616026a46d790a68695aa70589a88b08a6275acdb525f0ab531ec", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/intrinsics/transcode.ts": "e3fcaeb7a60b6cbad999d9389d4bce59e305e6f54e035ba791f909e10d1f82c7", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/jspi/bridge.ts": "7cf3706d3bf34b503aea516a31918a8d930aba3dac7e94ec04caecd23fe6025e", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/jspi/mechanics.ts": "dc0fe4965b3ef8c0aff6674afd8bae2a38942ab934fa07fd2eb7db72b2462f17", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/jspi/mod.ts": "4d047b820b50c410ed946c62dc48286f8abe4787ce6ae5466cd0ae255d98943c", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/jspi/types.ts": "86929224733a764a148ac75a9d6b95d61ab4c8123a48fe956d998e97726a1432", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/plan/format.ts": "90e31bbc7137c2f80c0782e1431afb6f81827aab8d38dba1178b8761f1b3ea0a", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/plan/loader.ts": "107db77e724a7f74f161a5fd20e7110a6e6f182c46f18282eba650bc887dc876", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/shim/mod.ts": "34af2240dfd0be720def487db2db34eaad6ba9178003f20e2193d03a0632779b", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/shim/translator.ts": "7ea1a4101363ee62ddedb9d6c3f798fd6042886ef38ee13046ac3cdb9485bf24", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/task/mod.ts": "5decca8045dfd9743910e83d512258a7be3b0d0917954b8d9cdbac38e03f7dfb", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/task/scheduler.ts": "18a4404f620407bd867876115861ee0cf98f6f1ccd41c5f3c877ef90e429ef9c", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/task/streams.ts": "83b522a6393ba06fbdb87881bc6761f3fce9c03b85e9eda03d3befe7d2605a60", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/task/subtask.ts": "750b13a1318f62836bfd149f1b9144de5b017fd7a84adc8e2fb2151e63130fbc", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/task/thread.ts": "81fe38b37a1ec130803b478a24e428b19ee4e1ef8c0bae741395cd8d52751580", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/runtime/src/task/waitable.ts": "5e1fc092e3d8f1fb4429d6a91d8886b3e474aa9ac6254e7924fd896c4929e1f9", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/wasi-shims/src/cli.ts": "d1617e12dc2569f4ee107f8b92488797daf431d14b8a86a1ab10750a28757394", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/wasi-shims/src/clocks.ts": "05468a822b635408ce3a671b40fd06fd4448c220019f9449bf029ac1c7e59664", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/wasi-shims/src/filesystem.ts": "6dcead5346d78084c3923410e44875e678f3b58db0c2d59513339b428596ec25", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/wasi-shims/src/io.ts": "dfe270e5ad3388c02696e27a5c69c58a411759fe8c99416361b0ac10177366da", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/wasi-shims/src/mod.ts": "1748985cf851252e1755aafd9ebb9c7ae96003ec41322d9524a952062d2b8570", - "https://raw.githubusercontent.com/lann/deltic/pre-83fff30/wasi-shims/src/random.ts": "dc04d20de5399cc7fa8685a04ec954618e3994a374ef94535fff408a745425e2" + "specifiers": { + "jsr:@deltic/ct-runner@0.1.0-pre.ga67ee83": "0.1.0-pre.ga67ee83", + "jsr:@deltic/runtime@0.1.0-pre.ga67ee83": "0.1.0-pre.ga67ee83", + "jsr:@deltic/runtime@~0.1.0-pre.ga67ee83": "0.1.0-pre.ga67ee83", + "jsr:@deltic/translator@0.1.0-pre.ga67ee83": "0.1.0-pre.ga67ee83", + "jsr:@deltic/wasi-shims@0.1.0-pre.ga67ee83": "0.1.0-pre.ga67ee83", + "npm:playwright-core@1.62.1": "1.62.1" + }, + "jsr": { + "@deltic/ct-runner@0.1.0-pre.ga67ee83": { + "integrity": "d78e96eba54e53dabe7c1de5a67782aad755362824d741913ab4d36941ebfbcc", + "dependencies": [ + "jsr:@deltic/runtime@~0.1.0-pre.ga67ee83" + ] + }, + "@deltic/runtime@0.1.0-pre.ga67ee83": { + "integrity": "2a2b0949031747a2340dc186299e654ea9f361ae39ac6bd633019940682db4ed" + }, + "@deltic/translator@0.1.0-pre.ga67ee83": { + "integrity": "e4f1bb219e56b62262b0c9665e3f6646aa13883b2cfbb9d6306f69d19974d412", + "dependencies": [ + "jsr:@deltic/runtime@~0.1.0-pre.ga67ee83" + ] + }, + "@deltic/wasi-shims@0.1.0-pre.ga67ee83": { + "integrity": "a5754e65d50873e675695a51279989e22b3771e31f16a84a09feb15905c574a7", + "dependencies": [ + "jsr:@deltic/runtime@~0.1.0-pre.ga67ee83" + ] + } + }, + "npm": { + "playwright-core@1.62.1": { + "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", + "bin": true + } }, "workspace": { + "dependencies": [ + "jsr:@deltic/ct-runner@0.1.0-pre.ga67ee83", + "jsr:@deltic/runtime@0.1.0-pre.ga67ee83", + "jsr:@deltic/translator@0.1.0-pre.ga67ee83", + "jsr:@deltic/wasi-shims@0.1.0-pre.ga67ee83" + ], "packageJson": { "dependencies": [ "npm:playwright-core@1.62.1" diff --git a/conformance/driver-ct/deltic/extract-translator-wasm.py b/conformance/driver-ct/deltic/extract-translator-wasm.py new file mode 100644 index 0000000..258701e --- /dev/null +++ b/conformance/driver-ct/deltic/extract-translator-wasm.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +"""Extract the translator wasm from the lock-pinned @deltic/translator +module graph (`deno info --json`) into the browser-asset output dir. + +No network, no sha256 bookkeeping: JSR package integrity lives in +deno.lock; this only truncates the already-fetched, --frozen-verified +cache entry down to its module bytes (Deno's on-disk remote-cache file +carries a trailing "\n// denoCacheMetadata={...}" line after the wasm +body — see the truncation + sanity checks below). See ../justfile's +`_deltic-browser-build` recipe and README.md's "Pinning" section. + +Usage: extract-translator-wasm.py +""" +import json +import sys + + +def main() -> int: + info_path, out_path, expected_version = sys.argv[1], sys.argv[2], sys.argv[3] + graph = json.load(open(info_path)) + mods = [m for m in graph["modules"] if "/@deltic/" in m.get("specifier", "")] + bad = {m["specifier"] for m in mods if expected_version not in m["specifier"]} + if bad: + print(f"pin drift in translator graph: {bad}", file=sys.stderr) + return 1 + wasm = next( + (m for m in mods if m["specifier"].endswith("/translator_shim.wasm")), + None, + ) + if wasm is None: + print("no translator_shim.wasm module found in the graph", file=sys.stderr) + return 1 + + # WARNING, learned the hard way: Deno's on-disk remote-cache file is + # module bytes PLUS a trailing "\n// denoCacheMetadata={...}" line. + # A plain copy yields a CORRUPT wasm (WebAssembly.compile: "unexpected + # section "; wasm-tools: "section out of order" near EOF) — + # Deno's own ESM wasm-module import reads through the cache API + # (trailer stripped), which is why that path never noticed. Truncate + # to the byte size `deno info` reports, then sanity-check both ends. + data = open(wasm["local"], "rb").read() + size = wasm.get("size") + if size is None: + print("deno info did not report a size for the translator module", file=sys.stderr) + return 1 + body, rest = data[:size], data[size:] + if body[:4] != b"\0asm": + print("not wasm after truncation to the reported size", file=sys.stderr) + return 1 + if rest and not rest.startswith(b"\n// denoCacheMetadata="): + print("unexpected cache-file layout; refusing to copy", file=sys.stderr) + return 1 + with open(out_path, "wb") as f: + f.write(body) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/conformance/driver-ct/deltic/fetch-translator.ts b/conformance/driver-ct/deltic/fetch-translator.ts deleted file mode 100644 index 4abec1a..0000000 --- a/conformance/driver-ct/deltic/fetch-translator.ts +++ /dev/null @@ -1,109 +0,0 @@ -// Fetch (and cache) pinned deltic release assets. -// -// deltic is a runtime linker: components are translated by a wasm build of -// its translator, shipped as a release asset so consumers need no Rust -// toolchain; the browser leg additionally loads `deltic-embedder.mjs` (one -// platform-neutral ES module: embedder API + Translator + runner glue + -// wasi shims). This script downloads the selected asset once into -// target/deltic/, verifies it against the pinned sha256, and prints the -// cached path on stdout (the `conformance-ct::run-deltic*` recipes capture -// it). -// -// fetch-translator.ts [--asset translator|embedder] (default: translator) -// -// THE PIN lives here (TAG + per-asset sha256) and in the sibling -// deno.json's import-map URLs. `assertPinConsistency` fails loud if the -// two drift. Bumping: update TAG here and in deno.json, update the shas -// from the release's SHA256SUMS, delete deno.lock, and re-run -// `deno cache run.ts fetch-translator.ts` in this directory to -// regenerate it (commit the diff). - -const TAG = "pre-83fff30"; -const ASSETS: Record = { - translator: { - file: "deltic-translator-shim.wasm", - sha256: "6d02b363785593595a789d083cda0aebb1de790726718ccf543198354fa3870c", - }, - embedder: { - file: "deltic-embedder.mjs", - sha256: "b9ceb33c78abdaa4311f681c1388b14a3471f8a17ebd2dbf2dddd4a596df72c3", - }, -}; - -const HERE = new URL(".", import.meta.url); -const REPO_ROOT = new URL("../../../", HERE); -const CACHE_DIR = new URL(`target/deltic/${TAG}/`, REPO_ROOT); - -async function sha256Hex(bytes: Uint8Array): Promise { - const digest = await crypto.subtle.digest( - "SHA-256", - bytes as BufferSource, - ); - return Array.from(new Uint8Array(digest)) - .map((b) => b.toString(16).padStart(2, "0")) - .join(""); -} - -/** The one-pin-everywhere gate: every raw.githubusercontent URL in the - * sibling import map must reference TAG. */ -async function assertPinConsistency(): Promise { - const denoJson = await Deno.readTextFile(new URL("deno.json", HERE)); - const urls = denoJson.match(/https:\/\/raw\.githubusercontent\.com[^"]+/g) ?? []; - if (urls.length === 0) { - throw new Error("deno.json: no pinned deltic URLs found"); - } - for (const url of urls) { - if (!url.includes(`/lann/deltic/${TAG}/`)) { - throw new Error( - `pin drift: deno.json pins ${url}\nbut fetch-translator.ts pins ${TAG}`, - ); - } - } -} - -async function main() { - await assertPinConsistency(); - - const flag = Deno.args.indexOf("--asset"); - const name = flag === -1 ? "translator" : Deno.args[flag + 1]; - const asset = ASSETS[name]; - if (!asset) { - throw new Error( - `unknown asset ${JSON.stringify(name)}; expected one of: ${ - Object.keys(ASSETS).join(", ") - }`, - ); - } - const cached = new URL(asset.file, CACHE_DIR); - - try { - const bytes = await Deno.readFile(cached); - if (await sha256Hex(bytes) === asset.sha256) { - console.log(cached.pathname); - return; - } - console.error(`cached ${asset.file} has a stale digest; re-fetching`); - } catch { - // not cached yet - } - - const releaseUrl = - `https://github.com/lann/deltic/releases/download/${TAG}/${asset.file}`; - console.error(`fetching ${releaseUrl} …`); - const resp = await fetch(releaseUrl); - if (!resp.ok) { - throw new Error(`GET ${releaseUrl}: ${resp.status} ${resp.statusText}`); - } - const bytes = new Uint8Array(await resp.arrayBuffer()); - const got = await sha256Hex(bytes); - if (got !== asset.sha256) { - throw new Error( - `sha256 mismatch for ${asset.file}@${TAG}:\n want ${asset.sha256}\n got ${got}`, - ); - } - await Deno.mkdir(CACHE_DIR, { recursive: true }); - await Deno.writeFile(cached, bytes); - console.log(cached.pathname); -} - -await main(); diff --git a/conformance/driver-ct/deltic/run-browser.mjs b/conformance/driver-ct/deltic/run-browser.mjs index ec26a6a..7c201ac 100644 --- a/conformance/driver-ct/deltic/run-browser.mjs +++ b/conformance/driver-ct/deltic/run-browser.mjs @@ -15,9 +15,10 @@ // Gates in CI (the Actions runner image ships Chrome); locally it runs // under CONFORMANCE_BROWSER=1 (`just conformance-ct::all`) or directly // via `just conformance-ct::run-deltic-browser`. The justfile recipe -// fetches the sha256-pinned release assets first (fetch-translator.ts -// --asset translator|embedder), cached under target/deltic// and -// served to the page from the repository-root server. +// builds the two browser assets first (deno bundle for the embedder, +// deno info + copy for the translator wasm — both from the SAME pinned +// JSR graph as the Deno legs; see README.md's "Pinning" section), served to the +// page from the repository-root server. import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { parseArgs } from "node:util"; @@ -32,10 +33,10 @@ import { writeResultsFile } from "@polymorph/component-test-js/node-runner"; const DELTIC_DIR = dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = join(DELTIC_DIR, "..", "..", ".."); -// Must agree with fetch-translator.ts's TAG (assets are served from its -// cache directory). -const TAG = "pre-83fff30"; -const ASSETS = `/target/deltic/${TAG}`; +// Version-free: the lock (not a path segment) owns the deltic version now +// (see README.md's "Pinning" section). Built by the justfile's +// browser-asset recipes before this script runs. +const ASSETS = `/target/deltic-browser`; const CASE_TIMEOUT_MS = 60_000; const STALL_TIMEOUT_MS = 90_000; diff --git a/conformance/driver-ct/deltic/run.ts b/conformance/driver-ct/deltic/run.ts index 24747de..539cacf 100644 --- a/conformance/driver-ct/deltic/run.ts +++ b/conformance/driver-ct/deltic/run.ts @@ -24,13 +24,17 @@ // // deno run --allow-read=../../.. --allow-write=../results \ // --config deno.json --frozen run.ts --suite suite-plain \ -// --missing delegated-signer --target deltic-deno \ -// --translator +// --missing delegated-signer --target deltic-deno +// +// The translator is the packaged @deltic/translator asset, loaded +// through the module graph (no net grant, no read grant for a fetched +// wasm) — see README.md's "Pinning" section. import { Translator } from "@deltic/runtime/shim"; import type { ComponentArtifacts } from "@deltic/runtime/embedder"; import { runSuite } from "@deltic/ct-runner"; import { wasiShims } from "@deltic/wasi-shims"; +import { defaultTranslator } from "@deltic/translator"; const ROOT = new URL("../../../", import.meta.url); const RESULTS = new URL("../results/", import.meta.url); @@ -57,7 +61,11 @@ interface Cli { target: string; suiteName: string; missing: string[]; - translator: string; + // Optional: an explicit translator shim wasm path, for callers that + // source their own build (e.g. a local dev override). Defaults to the + // packaged @deltic/translator asset (defaultTranslator()); see + // README.md's "Pinning" section. + translator?: string; } function parseCli(argv: string[]): Cli { @@ -89,10 +97,10 @@ function parseCli(argv: string[]): Cli { throw new Error(`unknown argument ${argv[i]}`); } } - if (!suite || !target || !translator) { + if (!suite || !target) { console.error( "usage: run.ts --suite --target " + - "--translator [--missing f1,f2] [--suite-name name]", + "[--missing f1,f2] [--suite-name name] [--translator ]", ); Deno.exit(2); } @@ -104,9 +112,9 @@ async function main() { const componentBytes = await Deno.readFile( new URL(`target/conformance/${cli.suite}.wasm`, ROOT), ); - const translator = await Translator.create( - await Deno.readFile(cli.translator), - ); + const translator = cli.translator + ? await Translator.create(await Deno.readFile(cli.translator)) + : await defaultTranslator(); const { plan, adapters } = translator.translate(componentBytes); const artifacts: ComponentArtifacts = { plan, componentBytes, adapters }; diff --git a/conformance/driver-ct/justfile b/conformance/driver-ct/justfile index ed2e038..10f426d 100644 --- a/conformance/driver-ct/justfile +++ b/conformance/driver-ct/justfile @@ -86,33 +86,42 @@ run-delegated: build _ct-tools --suite-artifact {{guest}} \ --target composed-delegated --jsonl > {{results}}/composed-delegated.jsonl +# The one-version-everywhere gate: every jsr:@deltic/* import across +# every deno.json in the repo must pin the same version (replaces the +# retired fetch-based translator script's pin-consistency check). Runs +# at the top of every deltic recipe below so drift fails loud immediately. +_deltic-pin-check: + #!/usr/bin/env bash + set -euo pipefail + cd {{root}} + files=$(find . -name deno.json -not -path '*/node_modules/*') + v=$(grep -ho 'jsr:@deltic/[a-z-]*@[^/"]*' $files | sed 's/.*@//' | sort -u) + n=$(printf '%s\n' "$v" | sed '/^$/d' | wc -l) + [ "$n" = 1 ] || { echo "deltic pin drift: $v" >&2; exit 1; } + # The composed artifact runtime-linked under deltic on stock Deno — # no transpile step, no generated tree, no engine flag (callback ABI). # The pin and the module-graph lock live in deltic/ (see its README). -run-deltic: build +# The translator is the packaged @deltic/translator asset, resolved +# through the module graph (no net grant, no fetched-asset read grant). +run-deltic: _deltic-pin-check build #!/usr/bin/env bash set -euo pipefail cd {{root}}/conformance/driver-ct/deltic - translator=$(deno run --allow-read=. --allow-write=../../../target/deltic \ - --allow-net=github.com,objects.githubusercontent.com,release-assets.githubusercontent.com \ - fetch-translator.ts) - deno run --allow-read=../../..,"$translator" --allow-write=../results \ + deno run --allow-read=../../.. --allow-write=../results \ --config deno.json --frozen run.ts \ --suite suite-plain --missing delegated-signer \ - --target deltic-deno --translator "$translator" + --target deltic-deno # The composed-delegated artifact under deltic on stock Deno. -run-deltic-delegated: build +run-deltic-delegated: _deltic-pin-check build #!/usr/bin/env bash set -euo pipefail cd {{root}}/conformance/driver-ct/deltic - translator=$(deno run --allow-read=. --allow-write=../../../target/deltic \ - --allow-net=github.com,objects.githubusercontent.com,release-assets.githubusercontent.com \ - fetch-translator.ts) - deno run --allow-read=../../..,"$translator" --allow-write=../results \ + deno run --allow-read=../../.. --allow-write=../results \ --config deno.json --frozen run.ts \ --suite suite-delegated \ - --target deltic-deno-delegated --translator "$translator" + --target deltic-deno-delegated # The deltic browser driver's npm tree (the upstream page driver + # playwright-core; no transpiler). @@ -124,19 +133,31 @@ _deltic-browser-prepared: build npm ci --no-audit --no-fund fi +# The two repo-built browser assets, from the SAME pinned JSR graph as +# the Deno legs (no sha256 bookkeeping — the lock owns integrity). +# Version-free output dir: the lock (not a path segment) owns the +# deltic version now (see deltic/README.md, "Pinning"). +_deltic-browser-build: _deltic-pin-check _deltic-browser-prepared + #!/usr/bin/env bash + set -euo pipefail + cd {{root}}/conformance/driver-ct/deltic + out=../../../target/deltic-browser + mkdir -p "$out" + deno bundle --config deno.json --frozen --platform browser \ + -o "$out/deltic-embedder.mjs" browser-bundle-entry.ts + info=$(mktemp) + trap 'rm -f "$info"' EXIT + deno info --json --config deno.json --frozen @deltic/translator > "$info" + pin=$(grep -o 'jsr:@deltic/runtime@[^/"]*' deno.json | head -1 | sed 's/.*@//') + python3 extract-translator-wasm.py "$info" "$out/deltic-translator-shim.wasm" "$pin" + # Both composed artifacts runtime-linked inside headless Chromium: the -# upstream deltic worker loads the pinned embedder bundle and links the -# suite in the browser — no transpile step, no generated tree. -run-deltic-browser: _deltic-browser-prepared +# upstream deltic worker loads the repo-built embedder bundle and links +# the suite in the browser — no transpile step, no generated tree. +run-deltic-browser: _deltic-browser-build #!/usr/bin/env bash set -euo pipefail cd {{root}}/conformance/driver-ct/deltic - deno run --allow-read=. --allow-write=../../../target/deltic \ - --allow-net=github.com,objects.githubusercontent.com,release-assets.githubusercontent.com \ - fetch-translator.ts --asset translator >/dev/null - deno run --allow-read=. --allow-write=../../../target/deltic \ - --allow-net=github.com,objects.githubusercontent.com,release-assets.githubusercontent.com \ - fetch-translator.ts --asset embedder >/dev/null node run-browser.mjs # Runs the deltic browser leg under CI or CONFORMANCE_BROWSER=1; diff --git a/conformance/driver-ct/targets.toml b/conformance/driver-ct/targets.toml index dcfff36..667f50d 100644 --- a/conformance/driver-ct/targets.toml +++ b/conformance/driver-ct/targets.toml @@ -3,7 +3,7 @@ # the algorithm profile: the wasmtime rows run under the generic # component-test host runner (the composed artifact imports only wasi # and test-context), and the deltic rows runtime-link the same -# artifacts under the release-pinned deltic runtime — on stock Deno +# artifacts under the JSR-pinned deltic runtime — on stock Deno # (driver-ct/deltic/run.ts) and inside headless Chromium # (driver-ct/deltic/run-browser.mjs). #