Skip to content

Appliance vs A22 placement: should @polymorph/iroh own its @polyengine/runtime pin, or take the embedder from the application? #100

Description

@lannbot

The shape today

@polymorph/iroh is the appliance: the package instantiates its own packaged component. host-polyengine/src/harness.ts imports instantiate from @polyengine/runtime/embedder, and the published deno.json maps that bare specifier to jsr:@polyengine/runtime@^0.5.1/embedder. That was the explicit packaging ruling of #81 — "the endpoint component + the harness, consumable out of the box (newEndpointInstance()bindEndpoint())" — and #90 reaffirmed it post-A22 ("host-polyengine stays an instantiating application by design").

What A22 says, and where the tension is

polyengine A22 (contracts/embedder-api.md, "The host-ABI surface and its version"):

  • Host modules MUST NOT import @polyengine/runtime; the embedder surface was stripped to machinery "only an instantiating application uses".
  • Placement of runtime concerns — "like runtime selection itself — [stays] with the deploying application."

@polymorph/iroh is not a host module (it provides no import fragments to someone else's instantiation), so the MUST NOT does not bind it by letter. But it is a published package whose manifest names a runtime specifier, which pre-empts exactly the selection A22 assigns to the deploying application.

Consumer evidence

  • polyvisor's demo/deno.json records the failure mode concretely: at webrtc-datachannels 0.4.0, that sibling's polyengine-impl/deno.json named @polyengine/runtime@^0.4.0; Deno consulted the package's own config for the bare specifier and the app graph carried a second [email protected] beside the app's exact-pinned 0.5.1 — "the exact duplication this block exists to prevent." The sibling going A22-clean at its 0.5.0 was the fix. A published @polymorph/iroh JS surface in an embedding app's graph is the same hazard, latent: caret-vs-exact-pin skew duplicates rather than unifies.
  • The one real external consumer (polyvisor) does not use the appliance at all. It consumes the component bytes (engine/tools/fetch-endpoint-wasm.ts calls loadArtifacts() and discards the translation — paying a translator run and pulling the whole dependency graph because the package has no bytes-only door) and embeds its own composite under its own runtime pin. release-assets: attach iroh_endpoint.wasm + SHA256SUMS to releases #94's release assets (iroh_endpoint.wasm + SHA256SUMS) now serve that consumer properly.

So today nobody is bitten: the appliance's known consumers are leaf applications (this repo's exam), and the composer takes wasm, not JS. The question is what the package should promise before a consumer that embeds its own components alongside the appliance appears.

Options

a. Status quo, documented: the appliance is for leaf applications; a graph that loads its own embedder next to @polymorph/iroh owns the version-intersection problem. Cheapest; keeps the ^0.5.1 runtime floor (A23: the endpoint's dial timeouts drop in-flight import futures; polyengine#239) enforced by constraint.

b. Application-supplied embedder — A22's own placement pattern (the same move it makes for stream writers): the package goes protocol-only; newEndpointInstance() takes the embedder (or an instantiate capability) from the caller. Runtime selection returns to the deploying application; the A23 floor demotes from constraint to documentation plus a runtime check (the copy registry carries runtimeVersion). Breaking → minor bump under the caret-honest regime.

c. Split: a protocol-only parts surface (component bytes + import-fragment assembly) beside the appliance, in one package or two. The bytes-only door also fixes the loadArtifacts() extraction wart independently of the embedder question (though release assets may have mooted that consumer).

Whichever way this lands, it decides what the next minor release claims — recording it here per the divergence-with-no-artifact rule.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions