Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 29 additions & 12 deletions conformance/driver-ct/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,44 @@ composed := root + "/target/conformance-composed-ct.wasm"
conformance-browser-enabled := if env('GITHUB_ACTIONS', '') == 'true' { '1' } else if env('CONFORMANCE_BROWSER', '') == '1' { '1' } else { '' }
conformance-firefox-enabled := if env('CONFORMANCE_FIREFOX', '') == '1' { '1' } else { '' }

# The one-VERSION-everywhere pin gate, replacing the old
# assertPinConsistency script: every resolved `@polyengine/*` package (except
# @polyengine/protocol, which is versioned independently) across BOTH
# deno.lock files (this directory's and js/polyengine's) must resolve to the
# exact same version — js/polyengine's published manifest carries a caret
# range, so the specifier string no longer pins identity; the resolved
# lockfile version is what module identity actually needs. Wired into the
# The pin gate for the A22 two-line world: `@polyengine/runtime` (the
# lockstep engine line, resolved only where an application loads the
# embedder — this directory's deno.lock) and `@polyengine/protocol` (the
# independent host-ABI line, resolved everywhere) must each converge on
# exactly one version repo-wide, and the published host module
# (js/polyengine) must couple to the engine through protocol alone — it
# MUST resolve no `@polyengine/runtime` at all. Wired into the
# conformance CI job (.github/justfile's conformance-checks) as the
# fail-loud point.
polyengine-pin-check:
#!/usr/bin/env bash
set -euo pipefail
v=$(jq -r '.jsr | keys[]' \
runtime_v=$(jq -r '.jsr | keys[]' \
{{root}}/js/polyengine/deno.lock polyengine/deno.lock \
| grep '^@polyengine/' | grep -v '^@polyengine/protocol@' \
| grep '^@polyengine/runtime@' \
| sed 's/.*@//' | sort -u)
if [ "$(printf '%s\n' "$v" | wc -l)" != 1 ]; then
echo "polyengine pin drift: $v" >&2
if [ -n "$runtime_v" ] && [ "$(printf '%s\n' "$runtime_v" | wc -l)" != 1 ]; then
echo "polyengine runtime pin drift: $runtime_v" >&2
exit 1
fi
echo "polyengine pin OK: $v"
protocol_v=$(jq -r '.jsr | keys[]' \
{{root}}/js/polyengine/deno.lock polyengine/deno.lock \
| grep '^@polyengine/protocol@' \
| sed 's/.*@//' | sort -u)
if [ "$(printf '%s\n' "$protocol_v" | wc -l)" != 1 ]; then
echo "polyengine protocol pin drift: $protocol_v" >&2
exit 1
fi
if jq -r '.imports | keys[]' {{root}}/js/polyengine/deno.json | grep -q '^@polyengine/runtime'; then
echo "js/polyengine (published host module) must not resolve @polyengine/runtime" >&2
exit 1
fi
if jq -e '.jsr | keys[] | select(startswith("@polyengine/runtime@"))' {{root}}/js/polyengine/deno.lock >/dev/null 2>&1; then
echo "js/polyengine (published host module) must not resolve @polyengine/runtime" >&2
exit 1
fi
echo "polyengine pin OK: runtime ${runtime_v:-<unresolved>}, protocol $protocol_v"


# The JS runner core's one-version gate: every npm tree consuming
# @jsr/polymorph__test (jsr:@polymorph/test through JSR's npm-compat
Expand Down
13 changes: 7 additions & 6 deletions conformance/driver-ct/polyengine/deno.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"//": "MODULE-IDENTITY CONSTRAINT: polyengine's wasi module imports @polyengine/runtime/embedder by bare specifier internally. The @polyengine/runtime/embedder entry here must map to the IDENTICAL exact-pinned JSR version as ../../../js/polyengine/deno.json's entry, or the embedder module loads twice and `instanceof ComponentException` stops holding across the module boundary. polyengine ships as exact-pinned JSR releases (caret-honest upstream: within a minor line releases stay compatible, breaking bumps the minor; between releases, per-commit `<next>-pre.g<hash>` prereleases exist — pin exactly); deno.lock carries integrity, --frozen enforced; the pin gate (just conformance-ct::polyengine-pin-check) asserts one @polyengine version repo-wide.",
"//": "MODULE IDENTITY (A22): applications that load the embedder in more than one config must still resolve ONE runtime version — stateful handles minted by one copy are refused by another. The @polyengine/runtime/embedder entry here must map to the same exact-pinned JSR version everywhere this config's process loads the embedder (polyengine ships as exact-pinned JSR releases; caret-honest upstreamwithin a minor line releases stay compatible, breaking bumps the minor; between releases, per-commit `<next>-pre.g<hash>` prereleases exist — pin exactly). Published host modules (../../../js/polyengine) now couple only to @polyengine/protocol, whose copies are harmless by construction, so this constraint no longer spans that config. deno.lock carries integrity, --frozen enforced; the pin gate (just conformance-ct::polyengine-pin-check) asserts one @polyengine/runtime version where resolved and one @polyengine/protocol version repo-wide.",
"imports": {
"@polyengine/ct-runner": "jsr:@polyengine/ct-runner@0.4.0",
"@polyengine/runtime/embedder": "jsr:@polyengine/runtime@0.4.0/embedder",
"@polyengine/runtime/shim": "jsr:@polyengine/runtime@0.4.0/shim",
"@polyengine/wasi": "jsr:@polyengine/wasi@0.4.0",
"@polyengine/translator": "jsr:@polyengine/translator@0.4.0",
"@polyengine/ct-runner": "jsr:@polyengine/ct-runner@0.5.0",
"@polyengine/runtime/embedder": "jsr:@polyengine/runtime@0.5.0/embedder",
"@polyengine/runtime/shim": "jsr:@polyengine/runtime@0.5.0/shim",
"@polyengine/wasi": "jsr:@polyengine/wasi@0.5.0",
"@polyengine/translator": "jsr:@polyengine/translator@0.5.0",
"@polyengine/protocol": "jsr:@polyengine/protocol@0.2.2",
"@polymorph/test/polyengine-worker-main": "jsr:@polymorph/test@0.2.1/polyengine-worker-main"
},
"minimumDependencyAge": { "age": "P1D", "exclude": ["jsr:@polyengine/*", "jsr:@polymorph/*"] },
Expand Down
52 changes: 27 additions & 25 deletions conformance/driver-ct/polyengine/deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 5 additions & 6 deletions conformance/driver-ct/polyengine/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,11 @@
// green — per the KAT asymmetry above. When debugging any such run,
// `--fresh-cases` restores per-case containment.
//
// MODULE-IDENTITY CONSTRAINT: polyengine's wasi module imports
// `@polyengine/runtime/embedder` by bare specifier internally; this leg's
// `deno.json` AND `js/polyengine/deno.json` must map that specifier to the
// IDENTICAL exact-pinned JSR version, or the embedder module loads twice
// and `instanceof ComponentException` stops holding across the module boundary.
// `just conformance-ct::polyengine-pin-check` gates that.
// MODULE-IDENTITY CONSTRAINT: this leg loads the embedder from
// `deno.json`'s exact-pinned `@polyengine/runtime/embedder` entry.
// Stateful handles minted by one runtime copy are refused by another, so
// any other place this process loads the embedder must resolve the same
// version. `just conformance-ct::polyengine-pin-check` gates that.

import { Translator } from "@polyengine/runtime/shim";
import type { ComponentArtifacts } from "@polyengine/runtime/embedder";
Expand Down
15 changes: 7 additions & 8 deletions js/polyengine/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,13 @@ browser-hosted embedding should call `setRsaPrivateKeyPolicy("decline")`

## Module identity

`deno.json`'s `@polyengine/runtime/embedder` import maps to the exact same
pinned JSR version as
[`conformance/driver-ct/polyengine/deno.json`](../../conformance/driver-ct/polyengine/deno.json).
polyengine's `wasi-shims` module imports that specifier by bare name
internally; if the two configs ever disagreed, the embedder module would
load twice and `instanceof ComponentException` would stop holding across the
boundary. Keep both import maps' version identical for that one entry —
`just conformance-ct::polyengine-pin-check` gates that.
This module depends only on `@polyengine/protocol` (never
`@polyengine/runtime`, per the A22 host-module rule): the protocol's brand
and handle vocabulary is designed to be robust to duplicate copies, so
there is no module-identity constraint to keep in sync here.
`just conformance-ct::polyengine-pin-check` gates one `@polyengine/protocol`
version repo-wide and that this package's dependency graph carries no
`@polyengine/runtime` specifier.

## Unit tests

Expand Down
6 changes: 3 additions & 3 deletions js/polyengine/deno.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"name": "@polymorph/webcrypto",
"version": "0.4.0",
"version": "0.5.0",
"license": "Apache-2.0",
"exports": "./src/mod.ts",
"//": "MODULE-IDENTITY CONSTRAINT: polyengine's wasi module imports @polyengine/runtime/embedder by bare specifier internally. This file's @polyengine/runtime/embedder entry is a caret range (published-package convention: consumers resolve one shared @polyengine/runtime across their dependency graph); conformance/driver-ct/polyengine/deno.json (repo-internal, not published) exact-pins the same package for its own module-identity needs. The pin gate (just conformance-ct::polyengine-pin-check) asserts the two deno.locks resolve to one @polyengine/runtime version repo-wide.",
"//": "MODULE-IDENTITY CONSTRAINT (A22): this package couples only to @polyengine/protocol, whose copies are harmless by construction (the protocol's brand/handle vocabulary is designed to be robust to duplication), so there is no module-identity constraint to state here. This file's @polyengine/protocol entry is a caret range (published-package convention: consumers resolve one shared @polyengine/protocol across their dependency graph); conformance/driver-ct/polyengine/deno.json (repo-internal, not published) exact-pins the same package. The pin gate (just conformance-ct::polyengine-pin-check) asserts one @polyengine/protocol version repo-wide, one @polyengine/runtime version across the configs that resolve it, and that this package's lockfile carries no @polyengine/runtime specifier.",
"imports": {
"@polyengine/runtime/embedder": "jsr:@polyengine/runtime@^0.4.0/embedder"
"@polyengine/protocol": "jsr:@polyengine/protocol@^0.2.2"
},
"minimumDependencyAge": { "age": "P1D", "exclude": ["jsr:@polyengine/*"] },
"publish": {
Expand Down
15 changes: 4 additions & 11 deletions js/polyengine/deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion js/polyengine/src/aead.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
type WrapInput as WrapInputT,
WrapInput,
} from "./wrapping.ts";
import type { Stream } from "@polyengine/runtime/embedder";
import type { Stream } from "@polyengine/protocol";
import { MINT, requireMint } from "./internal.ts";

const subtle = globalThis.crypto.subtle;
Expand Down
2 changes: 1 addition & 1 deletion js/polyengine/src/cipher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
} from "./platform.ts";
import { type DeriveInput, deriveKeyFrom } from "./derivation.ts";
import { consumeUnwrapInput, consumeWrapInput, UnwrapInput, WrapInput } from "./wrapping.ts";
import type { Stream } from "@polyengine/runtime/embedder";
import type { Stream } from "@polyengine/protocol";
import { MINT, requireMint } from "./internal.ts";

const subtle = globalThis.crypto.subtle;
Expand Down
2 changes: 1 addition & 1 deletion js/polyengine/src/digest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import { errUnsupported, platformCall } from "./errors.ts";
import { asBufferSource, collectByteStream } from "./util.ts";
import type { Stream } from "@polyengine/runtime/embedder";
import type { Stream } from "@polyengine/protocol";

const subtle = globalThis.crypto.subtle;

Expand Down
2 changes: 1 addition & 1 deletion js/polyengine/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// payload shape is `{ kind, value? }` with `value` absent for payloadless
// cases.

import { ComponentException } from "@polyengine/runtime/embedder";
import { ComponentException } from "@polyengine/protocol";

/** The `types.error` payload shape (the value-mapping table's variant row). */
export type WcErrorPayload =
Expand Down
2 changes: 1 addition & 1 deletion js/polyengine/src/mac.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { importPlatformKeyJwk, jwkKeyBytes, jwkMaterial, requireStrictBase64url
import { asBufferSource, unwrappedJwk, utf8Encode } from "./util.ts";
import { deriveKeyFrom, type DeriveInput } from "./derivation.ts";
import { consumeUnwrapInput, type UnwrapInput, WrapInput } from "./wrapping.ts";
import type { Stream } from "@polyengine/runtime/embedder";
import type { Stream } from "@polyengine/protocol";
import { collectByteStream } from "./util.ts";
import {
injectedKey,
Expand Down
2 changes: 1 addition & 1 deletion js/polyengine/src/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// port, `polymorph-components/polyengine ports/webcrypto/src/`, where it was developed and
// where its unit suite lives; the only edit on the way in is the import
// rewrite from polyengine-repo-relative paths
// (`../../../runtime/src/embedder/…`) to the pinned `@polyengine/runtime/embedder`
// (`../../../runtime/src/embedder/…`) to the pinned `@polyengine/protocol`
// specifier this repo's import maps resolve (see ../README.md). It is the
// polyengine-conventions sibling of [`js/jco/webcrypto.js`](../jco/webcrypto.js)
// — same behavioral reference host, `ComponentException` throws and typed `Stream<T>`
Expand Down
2 changes: 1 addition & 1 deletion js/polyengine/src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// authority for which verdict each is.

import { errInvalidKey, errNotExtractable, errUnsupported, platformCall } from "./errors.ts";
import { ComponentException } from "@polyengine/runtime/embedder";
import { ComponentException } from "@polyengine/protocol";
import { asBufferSource } from "./util.ts";

const subtle = globalThis.crypto.subtle;
Expand Down
2 changes: 1 addition & 1 deletion js/polyengine/src/signature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import { injectedKey, launderCryptoKey, MINT, requireKeyType, requireMint } from
// is inside a function body — so whichever module is entered first completes
// the other's evaluation before any call can occur.
import { rsassaInjectedAlgorithm } from "./rsaSignature.ts";
import type { Stream } from "@polyengine/runtime/embedder";
import type { Stream } from "@polyengine/protocol";

const subtle = globalThis.crypto.subtle;

Expand Down
2 changes: 1 addition & 1 deletion js/polyengine/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// not jco's async-iterable convention, so this collector is written
// directly against `Stream<number>.read`, no jco-shape tolerance needed.

import type { Stream } from "@polyengine/runtime/embedder";
import type { Stream } from "@polyengine/protocol";
import { errInvalidKey } from "./errors.ts";

/** Read a guest `stream<u8>` to completion, copying chunks into one buffer. */
Expand Down
2 changes: 1 addition & 1 deletion js/polyengine/tests/embedder_keys_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import {
VerifyingKey,
} from "../src/mod.ts";
import { arrayStream } from "./testStream.ts";
import { ComponentException } from "@polyengine/runtime/embedder";
import { ComponentException } from "@polyengine/protocol";

function kindOf(err: unknown): string {
return ((err as ComponentException).payload as { kind: string }).kind;
Expand Down
2 changes: 1 addition & 1 deletion js/polyengine/tests/families_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
AgreementKeyOptions,
} from "../src/mod.ts";
import { arrayStream } from "./testStream.ts";
import { ComponentException } from "@polyengine/runtime/embedder";
import { ComponentException } from "@polyengine/protocol";

// This file sits at js/polyengine/tests/, so the repo root is three levels up
// and the vector tree is in-repo — no absolute path, and no skip guard:
Expand Down
2 changes: 1 addition & 1 deletion js/polyengine/tests/testStream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// runtime's full stream/store machinery for unit tests (the exec-model
// integration test exercises the real `Stream<T>` handle end-to-end).

import type { Stream } from "@polyengine/runtime/embedder";
import type { Stream } from "@polyengine/protocol";

export function arrayStream(bytes: Uint8Array): Stream<number> {
let offset = 0;
Expand Down
Loading