diff --git a/Cargo.lock b/Cargo.lock index e596461..d95a312 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2586,7 +2586,7 @@ dependencies = [ [[package]] name = "iroh-endpoint-core" -version = "0.0.1" +version = "0.1.0" dependencies = [ "blake3", "hex", diff --git a/README.md b/README.md index 9d56bd7..57d293c 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,14 @@ Status: **proposal**. This README records the design research and the rulings it produced; open questions are tracked in the [issues](../../issues). +## Releases + +Everything here is **unstable** (0.x), but [releases](../../releases) are +**caret-honest**: within a minor line they stay backward-compatible, and +anything breaking bumps the minor. Consumption is pinned at a release's +commit — sibling checkouts and vendored WIT at pinned release commits, +the release-pinned deltic/JSR graph — and bumped deliberately. + ## What iroh is, layer by layer Iroh's stack, per its own documentation, is a set of small layers with a diff --git a/core/Cargo.toml b/core/Cargo.toml index 7549005..d42a2ea 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iroh-endpoint-core" -version = "0.0.1" +version = "0.1.0" edition.workspace = true publish.workspace = true description = "Shared endpoint core: the webcrypto-held identity, RPK TLS configs over the polymorph:tls profile, and relay wire framing" diff --git a/experiments/iroh-relay-ws/host/deno.json b/experiments/iroh-relay-ws/host/deno.json index e4f9566..2055ccc 100644 --- a/experiments/iroh-relay-ws/host/deno.json +++ b/experiments/iroh-relay-ws/host/deno.json @@ -1,5 +1,5 @@ { - "//": "MODULE-IDENTITY CONSTRAINT: deltic's wasi-shims and the sibling deltic host modules (.deps/{websocket,webrtc}) import @deltic/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. deltic arrives as exactly-pinned JSR prereleases (0.1.0-pre.g names one upstream commit; @deltic/translator ships the translator wasm for the SAME commit); the version matches host-deltic/deno.json by repo convention (exam-deltic asserts it; see host-deltic/README.md, 'The pin'). minimumDependencyAge keeps Deno's default supply-chain gate for everything else while letting same-day @deltic prereleases resolve. The npm mappings serve the webrtc module's bare specifiers under Deno; a browser build 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: deltic's wasi package and the sibling deltic host modules (.deps/{websocket,webrtc}) import @deltic/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. deltic arrives as exact-pinned JSR releases (caret-honest upstream: within a minor line releases stay compatible, breaking bumps the minor; per-commit `-pre.g` prereleases exist between releases — pin exactly; @deltic/translator ships the translator wasm for the SAME commit); the version matches host-deltic/deno.json by repo convention (exam-deltic asserts it; see host-deltic/README.md, 'The pin'). minimumDependencyAge keeps Deno's default supply-chain gate for everything else while letting same-day @deltic publishes resolve. The npm mappings serve the webrtc module's bare specifiers under Deno; a browser build 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", @@ -9,10 +9,11 @@ "lib": ["dom", "dom.iterable", "dom.asynciterable", "deno.ns"] }, "imports": { - "@deltic/runtime/embedder": "jsr:@deltic/runtime@0.1.0-pre.ga2f84a5/embedder", - "@deltic/runtime/shim": "jsr:@deltic/runtime@0.1.0-pre.ga2f84a5/shim", - "@deltic/translator": "jsr:@deltic/translator@0.1.0-pre.ga2f84a5", - "@deltic/wasi-shims": "jsr:@deltic/wasi-shims@0.1.0-pre.ga2f84a5", + "@deltic/runtime/embedder": "jsr:@deltic/runtime@0.1.0/embedder", + "@deltic/runtime/shim": "jsr:@deltic/runtime@0.1.0/shim", + "@deltic/translator": "jsr:@deltic/translator@0.1.0", + "@deltic/wasi": "jsr:@deltic/wasi@0.1.0", + "@deltic/wasi/io": "jsr:@deltic/wasi@0.1.0/io", "node-datachannel": "npm:node-datachannel@0.32.3", "node-datachannel/polyfill": "npm:node-datachannel@0.32.3/polyfill", "werift": "npm:werift@0.22.2" diff --git a/experiments/iroh-relay-ws/host/deno.lock b/experiments/iroh-relay-ws/host/deno.lock index fc68d31..6dccdd8 100644 --- a/experiments/iroh-relay-ws/host/deno.lock +++ b/experiments/iroh-relay-ws/host/deno.lock @@ -2,10 +2,10 @@ "version": "5", "specifiers": { "jsr:@deltic/protocol@0.2": "0.2.0", - "jsr:@deltic/runtime@0.1.0-pre.ga2f84a5": "0.1.0-pre.ga2f84a5", - "jsr:@deltic/runtime@~0.1.0-pre.ga2f84a5": "0.1.0-pre.ga2f84a5", - "jsr:@deltic/translator@0.1.0-pre.ga2f84a5": "0.1.0-pre.ga2f84a5", - "jsr:@deltic/wasi-shims@0.1.0-pre.ga2f84a5": "0.1.0-pre.ga2f84a5", + "jsr:@deltic/runtime@0.1": "0.1.0", + "jsr:@deltic/runtime@0.1.0": "0.1.0", + "jsr:@deltic/translator@0.1.0": "0.1.0", + "jsr:@deltic/wasi@0.1.0": "0.1.0", "npm:node-datachannel@0.32.3": "0.32.3", "npm:playwright@^1.62.1": "1.62.1", "npm:werift@0.22.2": "0.22.2" @@ -14,23 +14,23 @@ "@deltic/protocol@0.2.0": { "integrity": "028be6a3623c5e910598aa7a199209b85e8931ae484ac7f6638d610ddb0e19fa" }, - "@deltic/runtime@0.1.0-pre.ga2f84a5": { - "integrity": "c9abb811d0c814c819924e92d57eed5f68b7bad35593edc5dcf3fc656022f4e1", + "@deltic/runtime@0.1.0": { + "integrity": "8d3f52f1a336a2dd9aed28a5c34fd281612a2f55a1582b159be614dd678593b3", "dependencies": [ "jsr:@deltic/protocol" ] }, - "@deltic/translator@0.1.0-pre.ga2f84a5": { - "integrity": "7e286b0cbacc26d144c4cad17f7ccae647cf5b71a48f986448e89f52204046b9", + "@deltic/translator@0.1.0": { + "integrity": "c447f27a90d7637dd3d5709f3f25378ded0f4b985bedc890c3f6a8cb9ff1eb9f", "dependencies": [ - "jsr:@deltic/runtime@~0.1.0-pre.ga2f84a5" + "jsr:@deltic/runtime@0.1" ] }, - "@deltic/wasi-shims@0.1.0-pre.ga2f84a5": { - "integrity": "92bb3f82371b1e356734e6d173fa7c38eeadf5f4cdf5c58393d2a3b7287c1b0b", + "@deltic/wasi@0.1.0": { + "integrity": "c35a19d139d684dafeca8ba200230a3eb1154627c80db298ae1393e3af938d68", "dependencies": [ "jsr:@deltic/protocol", - "jsr:@deltic/runtime@~0.1.0-pre.ga2f84a5" + "jsr:@deltic/runtime@0.1" ] } }, @@ -621,9 +621,9 @@ }, "workspace": { "dependencies": [ - "jsr:@deltic/runtime@0.1.0-pre.ga2f84a5", - "jsr:@deltic/translator@0.1.0-pre.ga2f84a5", - "jsr:@deltic/wasi-shims@0.1.0-pre.ga2f84a5", + "jsr:@deltic/runtime@0.1.0", + "jsr:@deltic/translator@0.1.0", + "jsr:@deltic/wasi@0.1.0", "npm:node-datachannel@0.32.3", "npm:werift@0.22.2" ], diff --git a/experiments/iroh-relay-ws/host/harness.ts b/experiments/iroh-relay-ws/host/harness.ts index f19aa7f..b0062c7 100644 --- a/experiments/iroh-relay-ws/host/harness.ts +++ b/experiments/iroh-relay-ws/host/harness.ts @@ -6,7 +6,7 @@ // globals only. // // MODULE-IDENTITY CONSTRAINT (host-deltic/README.md "Module identity"): -// deltic's wasi-shims and this package import `@deltic/runtime/embedder` +// deltic's wasi package and this package import `@deltic/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 @@ -15,7 +15,8 @@ import type { ComponentArtifacts } from "@deltic/runtime/embedder"; import { artifactsFromEnvelope, instantiate } from "@deltic/runtime/embedder"; import type { Translator } from "@deltic/runtime/shim"; -import { OutputStream, wasiShims } from "@deltic/wasi-shims"; +import { wasi } from "@deltic/wasi"; +import { OutputStream } from "@deltic/wasi/io"; import { syntheticNetImports } from "./sockets.ts"; /** Reconstitute build-time-translated artifacts (embedder-api A4). */ @@ -49,7 +50,7 @@ export interface GuestOptions { } /** - * The full import record for the spike guests: deltic's wasi-shims + * The full import record for the spike guests: deltic's wasi() * baseline (whose A5 parking kernel serves poll/clock suspension), the * synthetic network fragment (sockets.ts), and stdio routed to the * console line-buffered. @@ -58,7 +59,7 @@ export function guestImports(options: GuestOptions): Record { const stdout = new OutputStream(lineSink("guest-out", console.log)); const stderr = new OutputStream(lineSink("guest-err", console.error)); return { - ...wasiShims({ cli: { args: options.args, env: options.env } }), + ...wasi({ cli: { args: options.args, env: options.env } }), ...syntheticNetImports(), "wasi:cli/stdout@0.2": { getStdout: (): OutputStream => stdout }, "wasi:cli/stderr@0.2": { getStderr: (): OutputStream => stderr }, @@ -71,7 +72,7 @@ export function guestImports(options: GuestOptions): Record { * `artifacts` is anything `instantiate` accepts (embedder-api A3): the * translated `ComponentArtifacts`, or `{ componentBytes, translator }` * with `@deltic/translator`'s instance for in-process translation. jspi - * mode is selected by wasi-shims' own `suspending()` markers (the A5 + * mode is selected by the wasi package's own `suspending()` markers (the A5 * kernel); no explicit option is needed. */ export async function runGuest( diff --git a/experiments/iroh-relay-ws/host/sockets.ts b/experiments/iroh-relay-ws/host/sockets.ts index b18c6ad..04caa0d 100644 --- a/experiments/iroh-relay-ws/host/sockets.ts +++ b/experiments/iroh-relay-ws/host/sockets.ts @@ -7,7 +7,7 @@ // to host-side bridges by well-known port (bridge.ts, webrtc-bridge.ts) // or by full synthetic destination address (the issue #26 overlay). // -// Parking is deltic's, not this module's: wasi-shims' kernel (embedder-api +// Parking is deltic's, not this module's: the wasi package's kernel (embedder-api // A5) serves `wasi:io/poll` and the clock subscriptions with real // suspension, and its `Pollable` is publicly constructible as the interop // seam — this module only mints `new Pollable(ready, wait)` over its @@ -23,7 +23,7 @@ // browsers. import { ComponentException } from "@deltic/runtime/embedder"; -import { Pollable } from "@deltic/wasi-shims"; +import { Pollable } from "@deltic/wasi/io"; // --------------------------------------------------------------------------- // instrumentation @@ -330,7 +330,7 @@ export class ResolveAddressStream { /** * The synthetic-network provider fragment (track keys), spread next to - * deltic's `wasiShims(...)`, whose A5 kernel serves `wasi:io/poll` and + * deltic's `wasi(...)`, whose A5 kernel serves `wasi:io/poll` and * the clock subscriptions these sockets' pollables park under. */ export function syntheticNetImports(): Record { diff --git a/host-deltic/deno.json b/host-deltic/deno.json index cde2646..59afd76 100644 --- a/host-deltic/deno.json +++ b/host-deltic/deno.json @@ -1,14 +1,15 @@ { - "//": "MODULE-IDENTITY CONSTRAINT: deltic's wasi-shims and the sibling deltic host modules (.deps/{websocket,webrtc,webcrypto}) import @deltic/runtime/embedder by bare specifier internally; this file maps that specifier ONCE for the whole module graph, so `instanceof ComponentException` holds across every boundary. deltic arrives as exactly-pinned JSR prereleases (0.1.0-pre.g names one upstream commit; @deltic/translator ships the translator wasm for the SAME commit, so the plan-format coupling is self-consistent per graph); deno.lock carries integrity, enforced with --frozen. The version matches experiments/iroh-relay-ws/host/deno.json by repo convention (see README.md, 'The pin'; exam-deltic asserts it). minimumDependencyAge keeps Deno's default supply-chain gate for everything else while letting same-day @deltic prereleases resolve. The npm mappings serve the webrtc module's bare specifiers, which resolve against this config as the entry import map.", + "//": "MODULE-IDENTITY CONSTRAINT: deltic's wasi package and the sibling deltic host modules (.deps/{websocket,webrtc,webcrypto}) import @deltic/runtime/embedder by bare specifier internally; this file maps that specifier ONCE for the whole module graph, so `instanceof ComponentException` holds across every boundary. deltic arrives as exact-pinned JSR releases (caret-honest upstream: within a minor line releases stay compatible, breaking bumps the minor; per-commit `-pre.g` prereleases exist between releases — pin exactly; @deltic/translator ships the translator wasm for the SAME commit, so the plan-format coupling is self-consistent per graph); deno.lock carries integrity, enforced with --frozen. The version matches experiments/iroh-relay-ws/host/deno.json by repo convention (see README.md, 'The pin'; exam-deltic asserts it). minimumDependencyAge keeps Deno's default supply-chain gate for everything else while letting same-day @deltic publishes resolve. The npm mappings serve the webrtc module's bare specifiers, which resolve against this config as the entry import map.", "nodeModulesDir": "auto", "minimumDependencyAge": { "age": "P1D", "exclude": ["jsr:@deltic/*"] }, "imports": { - "@deltic/runtime/embedder": "jsr:@deltic/runtime@0.1.0-pre.ga2f84a5/embedder", - "@deltic/translator": "jsr:@deltic/translator@0.1.0-pre.ga2f84a5", - "@deltic/wasi-shims": "jsr:@deltic/wasi-shims@0.1.0-pre.ga2f84a5", + "@deltic/runtime/embedder": "jsr:@deltic/runtime@0.1.0/embedder", + "@deltic/translator": "jsr:@deltic/translator@0.1.0", + "@deltic/wasi": "jsr:@deltic/wasi@0.1.0", + "@deltic/wasi/io": "jsr:@deltic/wasi@0.1.0/io", "@polymorph/webcrypto-deltic": "../.deps/webcrypto/js/deltic/src/mod.ts", "node-datachannel": "npm:node-datachannel@0.32.3", "node-datachannel/polyfill": "npm:node-datachannel@0.32.3/polyfill", diff --git a/host-deltic/deno.lock b/host-deltic/deno.lock index cc41b4f..0c92ad3 100644 --- a/host-deltic/deno.lock +++ b/host-deltic/deno.lock @@ -2,10 +2,10 @@ "version": "5", "specifiers": { "jsr:@deltic/protocol@0.2": "0.2.0", - "jsr:@deltic/runtime@0.1.0-pre.ga2f84a5": "0.1.0-pre.ga2f84a5", - "jsr:@deltic/runtime@~0.1.0-pre.ga2f84a5": "0.1.0-pre.ga2f84a5", - "jsr:@deltic/translator@0.1.0-pre.ga2f84a5": "0.1.0-pre.ga2f84a5", - "jsr:@deltic/wasi-shims@0.1.0-pre.ga2f84a5": "0.1.0-pre.ga2f84a5", + "jsr:@deltic/runtime@0.1": "0.1.0", + "jsr:@deltic/runtime@0.1.0": "0.1.0", + "jsr:@deltic/translator@0.1.0": "0.1.0", + "jsr:@deltic/wasi@0.1.0": "0.1.0", "npm:node-datachannel@0.32.3": "0.32.3", "npm:werift@0.22.2": "0.22.2" }, @@ -13,23 +13,23 @@ "@deltic/protocol@0.2.0": { "integrity": "028be6a3623c5e910598aa7a199209b85e8931ae484ac7f6638d610ddb0e19fa" }, - "@deltic/runtime@0.1.0-pre.ga2f84a5": { - "integrity": "c9abb811d0c814c819924e92d57eed5f68b7bad35593edc5dcf3fc656022f4e1", + "@deltic/runtime@0.1.0": { + "integrity": "8d3f52f1a336a2dd9aed28a5c34fd281612a2f55a1582b159be614dd678593b3", "dependencies": [ "jsr:@deltic/protocol" ] }, - "@deltic/translator@0.1.0-pre.ga2f84a5": { - "integrity": "7e286b0cbacc26d144c4cad17f7ccae647cf5b71a48f986448e89f52204046b9", + "@deltic/translator@0.1.0": { + "integrity": "c447f27a90d7637dd3d5709f3f25378ded0f4b985bedc890c3f6a8cb9ff1eb9f", "dependencies": [ - "jsr:@deltic/runtime@~0.1.0-pre.ga2f84a5" + "jsr:@deltic/runtime@0.1" ] }, - "@deltic/wasi-shims@0.1.0-pre.ga2f84a5": { - "integrity": "92bb3f82371b1e356734e6d173fa7c38eeadf5f4cdf5c58393d2a3b7287c1b0b", + "@deltic/wasi@0.1.0": { + "integrity": "c35a19d139d684dafeca8ba200230a3eb1154627c80db298ae1393e3af938d68", "dependencies": [ "jsr:@deltic/protocol", - "jsr:@deltic/runtime@~0.1.0-pre.ga2f84a5" + "jsr:@deltic/runtime@0.1" ] } }, @@ -601,16 +601,16 @@ }, "workspace": { "dependencies": [ - "jsr:@deltic/runtime@0.1.0-pre.ga2f84a5", - "jsr:@deltic/translator@0.1.0-pre.ga2f84a5", - "jsr:@deltic/wasi-shims@0.1.0-pre.ga2f84a5", + "jsr:@deltic/runtime@0.1.0", + "jsr:@deltic/translator@0.1.0", + "jsr:@deltic/wasi@0.1.0", "npm:node-datachannel@0.32.3", "npm:werift@0.22.2" ], "links": { - "jsr:@polymorph/webcrypto-deltic@0.0.0": { + "jsr:@polymorph/webcrypto-deltic@0.1.0": { "dependencies": [ - "jsr:@deltic/runtime@0.1.0-pre.ga2f84a5" + "jsr:@deltic/runtime@0.1.0" ] } } diff --git a/host-deltic/src/harness.ts b/host-deltic/src/harness.ts index 1feec89..5c32e6b 100644 --- a/host-deltic/src/harness.ts +++ b/host-deltic/src/harness.ts @@ -6,7 +6,7 @@ // `iroh.Endpoint.bind(...)` driving shape over `instantiate` + the deltic // embedder facade. // -// MODULE-IDENTITY CONSTRAINT: deltic's wasi-shims and the sibling host +// MODULE-IDENTITY CONSTRAINT: deltic's wasi package and the sibling host // modules import `@deltic/runtime/embedder` by bare specifier internally; // this package's `deno.json` maps that specifier ONCE for the whole module // graph, so there is exactly one `ComponentException`/`Stream` module @@ -15,7 +15,7 @@ import { defaultTranslator } from "@deltic/translator"; import type { ComponentArtifacts } from "@deltic/runtime/embedder"; import { instantiate, ComponentException } from "@deltic/runtime/embedder"; -import { wasiShims } from "@deltic/wasi-shims"; +import { wasi } from "@deltic/wasi"; import { webcryptoImports } from "@polymorph/webcrypto-deltic"; import { websocketImports } from "../../.deps/websocket/js/deltic/websocket.ts"; import { webrtcImports } from "../../.deps/webrtc/deltic-impl/src/webrtc.ts"; @@ -112,7 +112,7 @@ export async function newEndpointInstance( options: EndpointInstanceOptions, ): Promise { const artifacts = await loadArtifacts(); - const shims = wasiShims({ + const shims = wasi({ cli: { args: [`iroh-endpoint-${options.label}`], env: { ...options.env }, diff --git a/host-deltic/src/sockets.ts b/host-deltic/src/sockets.ts index 696d791..1327668 100644 --- a/host-deltic/src/sockets.ts +++ b/host-deltic/src/sockets.ts @@ -23,7 +23,7 @@ // socket. Scenario 1 asserts exactly that. // // A direct-path leg (real UDP over `Deno.listenDatagram`) is the natural -// extension once deltic's wasi-shims grow p3 `wasi:sockets` providers +// extension once deltic's wasi package grows p3 `wasi:sockets` providers // (lann/deltic#4); this file is where that provider would be wired. import { ComponentException } from "@deltic/runtime/embedder"; diff --git a/scripts/setup.sh b/scripts/setup.sh index 79357d0..b799275 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -16,15 +16,15 @@ JUST_VERSION="${JUST_VERSION:-1.54.0}" WAC_VERSION="${WAC_VERSION:-0.10.1}" WEBRTC_REPO=https://github.com/polymorph-components/polymorph-webrtc-datachannels.git -WEBRTC_PIN=aa9460c674e9f9a5d3227291333a60ecd5bcd988 +WEBRTC_PIN=003aaef572ad2ec847718e326aa4f08879bcf685 WEBCRYPTO_REPO=https://github.com/polymorph-components/polymorph-webcrypto.git -WEBCRYPTO_PIN=662586ad873469c2329a0a73986adef8d5e3c908 +WEBCRYPTO_PIN=5bb3d483f30e78b0b029bdedb500956710234c1b WEBSOCKET_REPO=https://github.com/polymorph-components/polymorph-websocket.git -WEBSOCKET_PIN=9808bdb5d3f62d5212e2e91c9645d2f6cdda9e74 +WEBSOCKET_PIN=9bf9e92bb40937724d92a96e357a26c2b715a6dd IROH_REPO=https://github.com/n0-computer/iroh.git IROH_PIN=816dd70c056b813dcb5cbfb6a9a15e12d04b72b1 # v1.0.3 TLS_REPO=https://github.com/polymorph-components/polymorph-tls.git -TLS_PIN=e43cad46625b049c1037cc734114457e1ae2cac1 +TLS_PIN=2f7a203a711b585439ed679aa3fa4e274284eb33 log() { printf '\n==> %s\n' "$1"; } diff --git a/wit/deps/polymorph-webcrypto/README.md b/wit/deps/polymorph-webcrypto/README.md index 1b279ea..9403592 100644 --- a/wit/deps/polymorph-webcrypto/README.md +++ b/wit/deps/polymorph-webcrypto/README.md @@ -204,12 +204,20 @@ pair, which is a behavioral change for the producing implementation but never a type change. **`extension(extension-error)` carries named conditions outside the closed -set.** The closed cases are the conditions the *generic kinds'* contracts -name — universal across operation families; `extension` carries algorithm- -and feature-specific conditions, identified by the (`origin`, `name`) pair -and defined by the interface that produces them (the first is -`sha1-checked`'s `("polymorph:webcrypto", "collision-detected")`). The record's -fields have two fixed roles: +set — all of them, from here on.** The closed set is frozen: it is the set +of conditions the package's contracts named when the `error` variant was +designed — a historical artifact, not a tier of generality — and it never +grows again, because a new closed case is a semver-major change (the +variant sits in return position, where variant growth has no compatible +path). Every named condition since, kind-level and algorithm-level alike, +is an extension pair under `"polymorph:webcrypto"`, identified by the +(`origin`, `name`) pair and defined by the interface whose contract says +when it occurs — `sha1-checked`'s `("polymorph:webcrypto", +"collision-detected")`, `public-encryption`'s kind-level +`("polymorph:webcrypto", "message-too-long")`. One boundary is absolute: +failed verification reports `authentication-failed` and nothing else +(above), so no extension condition may ever carry a verification verdict. +The record's fields have two fixed roles: - the (`origin`, `name`) **pair** is the condition's only branchable identity; @@ -231,7 +239,11 @@ an opaque namespace owned by the defining party (by convention its package name; this package defines all of its conditions under `"polymorph:webcrypto"`). Third-party providers mint conditions under their own `origin`. SDKs expose constants for known pairs, and the conformance -suites pin exact pairs cross-implementation. +suites pin exact pairs cross-implementation. The pairs this package +defines are recorded in +[`extension-conditions.json`](extension-conditions.json): the +authoritative spelling, which the SDK constants and the implementations' +mapping tables are gated against. **Verification returns `result<_, error>`, not `bool`.** An ignored boolean fails open; a dropped `result` does not.