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
17 changes: 9 additions & 8 deletions experiments/iroh-relay-ws/host/deno.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"//": "MODULE-IDENTITY CONSTRAINT: polyengine's wasi package and the sibling @polymorph host modules (JSR) import @polyengine/runtime/embedder by bare specifier internally; this file maps that specifier ONCE for the whole module graph, so `instanceof ComponentException` holds across every boundary. This is the ONE deno config for all three experiments (iroh-relay-ws, iroh-blobs, ping-demo): the others pass --config pointing here. polyengine arrives as exact-pinned JSR releases (caret-honest upstream: within a minor line releases stay compatible, breaking bumps the minor; per-commit `<next>-pre.g<hash>` prereleases exist between releases — pin exactly; @polyengine/translator ships the translator wasm for the SAME commit); the version matches host-polyengine/deno.json by repo convention (exam-polyengine asserts it; see host-polyengine/README.md, 'The pin'). The @polymorph packages are exact-pinned the same way. minimumDependencyAge keeps Deno's default supply-chain gate for everything else while letting same-day @polyengine/@polymorph publishes resolve. The webrtc module's npm dependencies (node-datachannel, werift) arrive through @polymorph/webrtc-datachannels' own manifest; a browser build externalizes them and resolves the RTCPeerConnection global instead. compilerOptions.lib carries dom next to deno.ns so the browser entries (browser-entry.ts, ping-demo's demo.ts/overlay.ts) type-check in the same graph as the Deno drivers.",
"//": "MODULE-IDENTITY CONSTRAINT: this application config loads @polyengine/runtime/embedder ONCE for the whole experiment graph (iroh-relay-ws, iroh-blobs, ping-demo), so `instanceof`-checked embedder handles hold across every boundary here by construction. As of A22 (polyengine 0.5.0), @polyengine/wasi is protocol-only internally and the @polymorph sibling packages (@polymorph/{websocket,webrtc-datachannels}) now depend only on @polyengine/protocol — neither couples to @polyengine/runtime, so they no longer bear on embedder identity; only this config's own two @polyengine/runtime import lines (embedder, shim) do, and mapping them once here is what keeps that true. This is the ONE deno config for all three experiments: the others pass --config pointing here. polyengine's lockstep family (runtime, translator, wasi) arrives as exact-pinned JSR releases (caret-honest upstream: within a minor line releases stay compatible, breaking bumps the minor; per-commit `<next>-pre.g<hash>` prereleases exist between releases — pin exactly; @polyengine/translator ships the translator wasm for the SAME commit); @polyengine/protocol is versioned independently (the A22 host-ABI vocabulary line) and is also exact-pinned here. The runtime family's version matches host-polyengine/deno.json by repo convention (exam-polyengine asserts it; see host-polyengine/README.md, 'The pin'). The @polymorph packages are exact-pinned the same way. minimumDependencyAge keeps Deno's default supply-chain gate for everything else while letting same-day @polyengine/@polymorph publishes resolve. The webrtc module's npm dependencies (node-datachannel, werift) arrive through @polymorph/webrtc-datachannels' own manifest; a browser build externalizes them and resolves the RTCPeerConnection global instead. compilerOptions.lib carries dom next to deno.ns so the browser entries (browser-entry.ts, ping-demo's demo.ts/overlay.ts) type-check in the same graph as the Deno drivers.",
"nodeModulesDir": "auto",
"minimumDependencyAge": {
"age": "P1D",
Expand All @@ -9,13 +9,14 @@
"lib": ["dom", "dom.iterable", "dom.asynciterable", "deno.ns"]
},
"imports": {
"@polyengine/runtime/embedder": "jsr:@polyengine/runtime@0.4.0/embedder",
"@polyengine/runtime/shim": "jsr:@polyengine/runtime@0.4.0/shim",
"@polyengine/translator": "jsr:@polyengine/translator@0.4.0",
"@polyengine/wasi": "jsr:@polyengine/wasi@0.4.0",
"@polyengine/wasi/io": "jsr:@polyengine/wasi@0.4.0/io",
"@polymorph/webrtc-datachannels": "jsr:@polymorph/webrtc-datachannels@0.4.0",
"@polymorph/websocket": "jsr:@polymorph/websocket@0.4.0"
"@polyengine/runtime/embedder": "jsr:@polyengine/runtime@0.5.0/embedder",
"@polyengine/runtime/shim": "jsr:@polyengine/runtime@0.5.0/shim",
"@polyengine/protocol": "jsr:@polyengine/protocol@0.2.2",
"@polyengine/translator": "jsr:@polyengine/translator@0.5.0",
"@polyengine/wasi": "jsr:@polyengine/wasi@0.5.0",
"@polyengine/wasi/io": "jsr:@polyengine/wasi@0.5.0/io",
"@polymorph/webrtc-datachannels": "jsr:@polymorph/webrtc-datachannels@0.5.0",
"@polymorph/websocket": "jsr:@polymorph/websocket@0.5.0"
},
"tasks": {
"check": "deno check ."
Expand Down
61 changes: 31 additions & 30 deletions experiments/iroh-relay-ws/host/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 experiments/iroh-relay-ws/host/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// `ComponentException<{kind, value?}>` payloads (the sibling host modules
// throw these).

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

export function describeErr(err: unknown): string {
if (err instanceof ComponentException) {
Expand Down
12 changes: 7 additions & 5 deletions experiments/iroh-relay-ws/host/harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
// globals only.
//
// MODULE-IDENTITY CONSTRAINT (host-polyengine/README.md "Module identity"):
// polyengine's wasi package and this package import `@polyengine/runtime/embedder`
// by bare specifier; the `deno.json` next to this file maps that
// specifier once for the whole module graph, so there is exactly one
// `ComponentException` module instance and `instanceof` holds across every
// boundary — including the branded errors sockets.ts throws.
// this application config maps `@polyengine/runtime/embedder` ONCE for the
// whole experiment module graph, so there is exactly one embedder instance
// and stateful handles (component instantiation, streams minted through it)
// stay portable across every boundary here. `ComponentException` and other
// vocabulary (thrown by sockets.ts) come from `@polyengine/protocol`
// instead (A22) — its copies are brand-checked, not `instanceof`-checked,
// so they don't depend on this constraint.

import type { ComponentArtifacts } from "@polyengine/runtime/embedder";
import { artifactsFromEnvelope, instantiate } from "@polyengine/runtime/embedder";
Expand Down
2 changes: 1 addition & 1 deletion experiments/iroh-relay-ws/host/sockets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
// Environment-portable: standard globals only; works under Deno and in
// browsers.

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

// ---------------------------------------------------------------------------
Expand Down
42 changes: 26 additions & 16 deletions host-polyengine/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ guest's and is latent on every host.
## The pin

polyengine and the sibling host modules arrive from JSR under caret
constraints on one minor line (`jsr:@polyengine/*@^0.4.0`,
`jsr:@polymorph/*@^0.4.0`); `deno.lock` pins the resolved versions and
constraints on one minor line: the `@polyengine/{runtime,translator,wasi}@^0.5.0`
lockstep family, plus `@polyengine/protocol@^0.2.2` (versioned independently
of the lockstep family — the A22 host-ABI vocabulary line) and
`jsr:@polymorph/*@^0.5.0`. `deno.lock` pins the resolved versions and
carries integrity, enforced with `--frozen`. `@polyengine/translator` ships
the translator wasm for the same commit as the runtime, so the
plan-format coupling between runtime and translator is self-consistent
Expand All @@ -65,7 +67,8 @@ no fetch step. `minimumDependencyAge` exempts `jsr:@polyengine/*` and
same-day releases resolve; everything else keeps the default.
`experiments/iroh-relay-ws/host/deno.json` (the upstream-iroh spikes'
shared config) exact-pins the same polyengine packages; the `exam-polyengine`
recipe asserts both `deno.lock`s resolve to one polyengine version.
recipe asserts both `deno.lock`s resolve to one `@polyengine/runtime`
version and one `@polyengine/protocol` version.

To bump: adjust the constraints (a new minor line) or just delete the
`deno.lock` files (within the line), re-run `just polyengine-setup` and
Expand All @@ -75,16 +78,23 @@ diff.

## Module identity

polyengine's wasi package and the sibling host modules import
`@polyengine/runtime/embedder` by bare specifier internally, each resolved
through its own package manifest. Identity rests on every manifest in
the graph carrying a constraint the resolver can satisfy with ONE
`@polyengine/runtime` version, so it dedupes to one
`ComponentException`/`Stream` module instance — caret constraints on
one minor line guarantee that; an exact pin outside every other
manifest's range (or a raw-URL embedder module) splits the graph, and
`instanceof ComponentException` silently stops holding across that
boundary. Two gates in `just exam-polyengine` keep it true: the lock check
(this repo's `deno.lock`s resolve to one polyengine version) and
`scripts/polyengine-identity-gate.ts` (the RESOLVED run-endpoint graph
carries exactly one `@polyengine/runtime` and no raw URLs).
This package instantiates the packaged endpoint component, so it still
loads `@polyengine/runtime/embedder` by bare specifier, resolved through
its own `deno.json`. As of A22 (polyengine 0.5.0), `@polyengine/wasi` is
protocol-only internally and the sibling host modules
(`@polymorph/{webcrypto,websocket,webrtc-datachannels}@^0.5.0`) depend
only on `@polyengine/protocol` — neither couples to `@polyengine/runtime`
at all, so they no longer contribute to embedder identity. The remaining
true constraint: any consumer graph that loads the embedder in more than
one config (this package does; the `experiments/iroh-relay-ws/host`
config does too, for the upstream-iroh spikes) must still resolve to ONE
`@polyengine/runtime` version — a component instantiated under one
embedder copy is refused by another (stateful handles are not portable
across runtime copies). `@polyengine/protocol` copies are harmless by
construction: its error classes and handle-vocabulary types are brand-
checked, not `instanceof`-checked, across copies. Two gates in
`just exam-polyengine` keep this true: the lock check (this repo's
`deno.lock`s resolve to one `@polyengine/runtime` version and one
`@polyengine/protocol` version) and `scripts/polyengine-identity-gate.ts`
(the RESOLVED run-endpoint graph carries exactly one
`@polyengine/runtime` and no raw URLs).
17 changes: 9 additions & 8 deletions host-polyengine/deno.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
{
"name": "@polymorph/iroh",
"version": "0.4.0",
"version": "0.5.0",
"license": "Apache-2.0",
"exports": { ".": "./src/mod.ts" },
"//": "MODULE-IDENTITY CONSTRAINT: polyengine's wasi package and the sibling @polymorph host modules import @polyengine/runtime/embedder by bare specifier internally. Every dependency constraint here is a caret range on one minor line (published-package convention, polyengine's own precedent), so a consumer's resolver dedupes the whole family onto ONE @polyengine/runtime module instance and `instanceof ComponentException` holds across every boundary; deno.lock carries integrity, --frozen enforced in the repo. The exam gate (justfile: exam-polyengine) asserts the repo's deno.locks resolve to one @polyengine version and pipes the resolved graph through scripts/polyengine-identity-gate.ts (one runtime module, no raw URLs). src/endpoint_component.ts is GENERATED by `just build-components` (gitignored; the publish workflow regenerates it) — the packaged endpoint component, base64 in the module graph. minimumDependencyAge keeps Deno's default supply-chain gate for everything else while letting same-day @polyengine/@polymorph publishes resolve.",
"//": "MODULE-IDENTITY CONSTRAINT: this package instantiates the packaged endpoint component, so it still loads @polyengine/runtime/embedder — every consumer's resolver must still resolve exactly ONE @polyengine/runtime version for stateful-handle interop (a component instantiated under one embedder copy is refused by another). @polyengine/wasi@0.5.0 is protocol-only internally (A22) and the sibling @polymorph host modules (@polymorph/{webcrypto,websocket,webrtc-datachannels}@0.5.0) depend only on @polyengine/protocol — neither couples to @polyengine/runtime at all, so they no longer contribute to that constraint; @polyengine/protocol copies are harmless by construction (A22, contracts/embedder-api.md). Every dependency constraint here is a caret range on one minor line (published-package convention, polyengine's own precedent); deno.lock carries integrity, --frozen enforced in the repo. The exam gate (justfile: exam-polyengine) asserts the repo's deno.locks resolve to one @polyengine/runtime version and one @polyengine/protocol version, and pipes the resolved graph through scripts/polyengine-identity-gate.ts (one runtime module, no raw URLs). src/endpoint_component.ts is GENERATED by `just build-components` (gitignored; the publish workflow regenerates it) — the packaged endpoint component, base64 in the module graph. minimumDependencyAge keeps Deno's default supply-chain gate for everything else while letting same-day @polyengine/@polymorph publishes resolve.",
"nodeModulesDir": "auto",
"minimumDependencyAge": {
"age": "P1D",
"exclude": ["jsr:@polyengine/*", "jsr:@polymorph/*"]
},
"imports": {
"@polyengine/runtime/embedder": "jsr:@polyengine/runtime@^0.4.0/embedder",
"@polyengine/translator": "jsr:@polyengine/translator@^0.4.0",
"@polyengine/wasi": "jsr:@polyengine/wasi@^0.4.0",
"@polymorph/webcrypto": "jsr:@polymorph/webcrypto@^0.4.0",
"@polymorph/websocket": "jsr:@polymorph/websocket@^0.4.0",
"@polymorph/webrtc-datachannels": "jsr:@polymorph/webrtc-datachannels@^0.4.0"
"@polyengine/runtime/embedder": "jsr:@polyengine/runtime@^0.5.0/embedder",
"@polyengine/protocol": "jsr:@polyengine/protocol@^0.2.2",
"@polyengine/translator": "jsr:@polyengine/translator@^0.5.0",
"@polyengine/wasi": "jsr:@polyengine/wasi@^0.5.0",
"@polymorph/webcrypto": "jsr:@polymorph/webcrypto@^0.5.0",
"@polymorph/websocket": "jsr:@polymorph/websocket@^0.5.0",
"@polymorph/webrtc-datachannels": "jsr:@polymorph/webrtc-datachannels@^0.5.0"
},
"publish": {
"exclude": ["src/run-endpoint.ts", "src/scenario.ts", "src/repo.ts", "!src/endpoint_component.ts"]
Expand Down
Loading
Loading