Conversation
Implements the TrUAPI PeerTransport service in the browser over
WebTransport, directly to JAM validators, for PolkaVM apps whose App
manifest v2 declares capabilities.network.jam = { genesis }.
The grant is derived only from the resolved, verified manifest, covers
exactly that genesis, is execution-local and is closed when the app
stops, fails or relaunches. Trait-21 frames are answered by the local
session; every other frame, including the handshake reply the guest
sees, still comes from the authenticated host port. Without the
capability nothing changes. The in-app menu lists the grant and its
limits.
Vendors @parity/truapi and @parity/truapi-host 0.20.0 from
host-rust-core feat/pvm-peer-transport fc2df9d3 (#1010), the host layer
on top of #540; the web wasm keeps wasm-signing-host as before.
Picks up PeerTransport's move to wire trait 23 (clear of Contacts, Game and Profile).
Contributor
Bundle Size ReportWarning Bundle budget exceeded — not a blocker, but please confirm the regression is intentional.
Eager path (module entry + modulepreloaded chunks):
Chunks over 500 KB:
All files
Commit: 3e7a0d1 |
Contributor
⚡ Performance ReportCold StartOverall: 🟢 improved | p50: 11.30s → 8.22s (-27.3%) | p95: 14.48s → 10.15s (-29.9%) | Mann-Whitney: z=3.69 ✅ significant Phase breakdown
Warm StartOverall: 🔴 regressed | p50: 477ms → 6.34s (+1229.8%) | p95: 518ms → 6.64s (+1181.5%) | Mann-Whitney: z=4.40 ✅ significant Phase breakdown
Lukewarm Start (different site, same session)Overall: 🟠 uncertain | p50: 11.87s → 10.82s (-8.9%) | p95: 19.36s → 15.08s (-22.1%) | Mann-Whitney: z=1.50 not significant Phase breakdown
Commit: 3e7a0d1 | Outliers (>2x best) discarded before stats |
PeerTransport access is now RemotePermission::JamPeers { genesis }, a
runtime permission like ChainSubmit, instead of an App-manifest
capability. capabilities.network is no longer parsed and no grant is
derived from the manifest.
Every PolkaVM application gets an execution-local PeerTransport
session. Its first dial of a JAM network sends
permissions.request_remote_permission(JamPeers { genesis }) over the
authenticated host port with a random request id of the sandbox's own,
and the sandbox consumes the reply; the guest never sees it. The core
checks the product's stored decision, prompts while it is undetermined
and persists the answer per product and genesis. The session asks once
per genesis; a refusal answers NotGranted and opens no WebTransport. An
app that never dials is never asked. Frame routing reads the wire
header only.
The host prompt asks "Allow <product> to connect to JAM network
0x…… (read-only peer access, no accounts or signing)?" with Deny,
Always allow and Allow once. The in-app "Network access" menu lists the
networks granted to the running session.
Vendors @parity/truapi and @parity/truapi-host 0.20.0 from
host-rust-core feat/pvm-peer-transport 4f5a7504 (#1010).
Picks up the bounded 10 s dial (prompt included) and CANCEL handling in the browser PeerTransport session. The web wasm is byte-identical.
Follows paritytech/trinity-user-agents#1010 at 50284f97, which renames the TrUAPI service to JamPeerTransport because it is JAM-specific (JamPeers permission, jamnp-s ALPN, JAMNP-S identity and framing). Wire-identical: trait 23, methods 0..6, same SCALE layout, same JamPeers permission. The sandbox now imports @parity/truapi/jam-peer-transport (createJamPeerTransportSession, JamPeerTransportSession, JAM_PEER_TRANSPORT_*), and the vendored @parity/truapi and @parity/truapi-host are rebuilt from that commit.
replghost
added a commit
that referenced
this pull request
Sep 27, 2026
Brings in the JamPeerTransport rename (#290 at 8980057). Only vendor/ conflicted; it is rebuilt from paritytech/trinity-user-agents#1011 (feat/jam-peer-transport-on-seity) at c85c26b6, the --no-ff merge of the renamed #1010. Wire-identical: trait 23, methods 0..6, JamPeers.
…trait 111 Vendors @parity/truapi and @parity/truapi-host 0.21.0 from host-rust-core#1010 at 5bee953e1, where JamPeerTransport moved from wire trait 23 to 111. The runtime already routes by the vendored JAM_PEER_TRANSPORT_DIAL.trait, so only the comment changes here.
replghost
added a commit
that referenced
this pull request
Sep 28, 2026
Vendors @parity/truapi and @parity/truapi-host 0.21.0 from host-rust-core#1011 at 0e0729546 (Seity #1001 plus #1010, where JamPeerTransport moved from wire trait 23 to 111).
# Conflicts: # vendor/truapi-host.lock.json
Pins both the stock serial-0 and the distinct-serial PolkaJAM WebTransport certificate per validity period, so Firefox reaches every validator that runs jam-explore's polkajam-webtransport-serial.patch and stock validators keep working.
replghost
added a commit
that referenced
this pull request
Sep 29, 2026
…seity # Conflicts: # vendor/truapi-host.lock.json # vendor/truapi-host/dist/wasm/web/truapi_server_bg.wasm # vendor/truapi-host/dist/wasm/web/truapi_server_bg.wasm.br # vendor/truapi-host/dist/wasm/web/truapi_server_bg.wasm.gz
Integrate 30336a7 source ancestry and unified 0.23 documentation. Retain this branch's feature-specific vendor SDK and lock unchanged pending a matching host #1010 rebuild; generated artifacts are not refreshed by this source merge.
replghost
added a commit
that referenced
this pull request
Sep 29, 2026
Integrate refreshed #290 source ancestry while retaining the JAM/Seity branch's feature-specific vendor SDK and lock unchanged. A matching host #1011 rebuild must replace artifacts and provenance before publication; this is source integration only.
# Conflicts: # vendor/truapi-host.lock.json # vendor/truapi-host/dist/wasm/testing/truapi_server_bg.wasm # vendor/truapi-host/dist/wasm/web/truapi_server_bg.wasm
This was referenced Oct 2, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Current repair qualification — 2026-10-02
19a9c5aeb0f0f6ef33151ca66da3bb147efa5936. Prior main baseline:f4012c50c3400d1186c332ad2ae50298cefd153d.ab46811b1e02469119a94706d7b4a01c9fc57839(peer). Complete matching SDK/host packages remain 0.23.0; no mixed or hand-patched Wasm bundle. Generated client bytes are unchanged. Production:wasm-signing-host; separate testing bundle:wasm-signing-host,test-host.5efd803fff8452ecb1fbc9d23e58a28298d1ec256e7cf66b55ea567b67703077dist/generated/client.js5fe2e73ed9f9210045a1ad456e29632cff8fa3acbb2cc2054f8774a6633f57a51a99b8c8ab0f9e22ccc24d78273cc2c42d621e368fc31587f93699dc999a8a36b80462f2f938ccb3aaef6035bb2dccd71159588cc9d8a887f00450c558bc111356b0027e01fc1d08bb547a4489bbc08ef778f913eea08f68d56f79d114657a91Native correction and causal limits
Bulletin mortal signatures now anchor to a finalized checkpoint, while nonce/runtime state comes from the freshest available signing snapshot. A checkpoint at least 64 blocks behind is rejected before broadcast. Regression coverage verifies the actual signature with a newer nonce and older finalized checkpoint, and the expiry boundary. Existing transaction retries/deadlines are unchanged; no chain error is suppressed. The affected test fixture uses
parking_lot::Mutex.The former Seity
Extrinsic marked as invalidrun used noncanonical best-block anchors, but retained evidence lacks the signed bytes and typed pool reason. Fork-sensitive mortality was a real correctness hazard; it is not claimed as the conclusively proved cause of that historical failure. Prior hosted Factory/Genesis timeout causes also remain unproved. No broker/readiness workaround, prewarming, extra retry, or timeout increase was added.Final exact-head hosted checks
Real-runtime local verification
All six consumers passed configured build, typecheck and lint. The later README-only formatting correction passed targeted Prettier checks and did not change runtime source or canonical native package bytes. Original full Wallet→Chat→Seity test sequences, without test retries, added waits, or prewarming:
0a24db4aa189adad7b93f9ff508c7949e39196ee301a235ba13248ef4281e9e3d859919fb6cfbe06d3dc8a41807c36b8bcdf001c47eccb9735305499Wallet's tested head is final. Chat and Seity tested heads precede documentation-only formatting merges; native/Wasm pins and runtime code are unchanged. Factory, Genesis-after-navigation and Submit passed on all three. These bounded passes do not establish the cause or elimination of the older hosted timeouts. Prior SharedWorker lifecycle, Chat/profile, Peer and JAM runtime proofs remain historical at their recorded heads; they were not all rerun on these artifacts.
Final hosted retest: failures remain
error; it is not evidence of a chain rejection. Retained traces include People-chain/local development sockets but do not expose the Asset Hub gateway WebSocket exchange, so these new failures do not establish an upstream or broker cause.paseo-bulletin-next-ipfs.polkadot.io. The zero-failure host-settings gate correctly failed.Doom: criterion corrected, backend matrix still unqualified
The user explicitly approved 35 FPS sustained over 30 seconds, with one frame of sampling-boundary tolerance:
frames + 1 >= elapsedMs * 35 / 1000. This replaces the instantaneousFPS >= 35sample; it is an acceptance-criterion change, not a runtime speedup. Runtime and displayed FPS are unchanged; raw samples are not rounded to force a pass. Update p95 <28.6ms, cold/warm first-frame limits <3,000/<1,000ms, audio and translation-cache checks remain. The revised official RPC benchmark passed once before the vendor replacement.The later isolated matrix used the rebuilt base pair at frontend
238ab5fa739788b2eb948ba1f807a1876edbacad, with fresh owned Chrome profiles and no concurrent builds/E2E:Distinct diagnostics found no presentation loss in a later instrumented 24-second shared-worker sample and observed a successful hidden RPC new-document reload. Neither diagnostic supersedes the failures or qualifies performance. No evidence-proved runtime fix, guest rebuild, speculative tuning, or further unchanged gate rerun was made. The original strict RPC failure and every new failure remain retained. Next causal capture must instrument the original early 30-second window and distinguish warm lifecycle states before proposing a runtime fix.
Retention and rollout boundary
Local verification used
paseo-next-v2, the pinned host-playground fixturef56294cea4430163bf16ec068844b1327441073c, and existing private QA identities. All three corrected sequences paired on their first existing setup attempt. A prior local launch failure and a misconfigured Previewnet-product run (34 passed, 20 skipped, 8 Chain/Contract failures) are retained separately, not presented as reproductions of the hosted Genesis timeout. Private traces/auth/signers were not published.The first repair heads also exposed a README formatting failure (corrected by documentation-only commits) and a PVM cache-unit-test 5,000ms timeout. No cache runtime/test change, limit increase, or causal claim was made for that isolated timeout. Older in-flight runs superseded by the formatting correction remain recorded as cancelled, not passed.
No PR merge, force push, deployment, environment approval, SDK/npm/product/guest publication, or rollback was performed by this repair. JAM remains JAM-TEST-INSTANCE, never JAM-PUBLIC-DEVNET. The user-owned
deploy: paseo.fyilabel is retained; repair-triggered deployment runs 36970790399 and 36971286469 were cancelled before deployment. The earlier rollout audit is retained below: an older workflow deployed56cea5d37577bf82684fb5c6b6e4ba81d2142938; this record does not claim live remained unchanged historically.Historical integration qualification (superseded; retained verbatim)
Current merged-main refresh and qualification — 2026-10-01
44ed4f830a2c8f86990e02fb061c802aa389b0bc; base:feat/pvm-wasm. Includes merged mainf4012c50c3400d1186c332ad2ae50298cefd153dand fix: protocol iframe and SharedWorker chains on the pool, and every chain client recovers from halts #313. No separate/unmerged fix: protocol iframe and SharedWorker chains on the pool, and every chain client recovers from halts #313 boundary remains.3cc0e5c44850a5f87606bf065a7603a17c342ed8, including native mainbda6ac518c8cc59319491b12e4e23b96777375fd. Complete canonical SDK/host artifact-generation pin:79cd7de8a7ccb4ef27e81ae158f6e7cf9aedffd6. Later native changes are tests/docs/iOS-only, not SDK/Wasm inputs; the generation pin intentionally differs from the latest source head.web-wasm-signing-hostwithouttest-host, with testing Wasm separate. No hand-edited generated declarations or mixed variants. No package publication.5efd803fff8452ecb1fbc9d23e58a28298d1ec256e7cf66b55ea567b67703077dist/generated/client.js(notdist/index.js)5fe2e73ed9f9210045a1ad456e29632cff8fa3acbb2cc2054f8774a6633f57a5a17d04963c096d859699e88f41c473e899a84fa90a5dc3f05ce2018f57752459cddf79e80de21e517b97ad2156611f09bb77c4c55016994384efb7bb593cbdb2Stack and hosted qualification
Wallet → PVM → Chat → Seity; PVM → Peer; JAM contains both Seity and Peer. All updates used fresh-fetch ancestry checks and ordinary pushes. User worktrees, metadata and canonical repositories were preserved.
70845db96bdd21409310daeff5e471b74ab5a1c9.351e5d73fab803a0fd2a4007ce2d2557aebaff05.bb9ad3d8921c63cf62c98b9029289f458b1a67a2.b03e83616857f4e4745d479776dde43cdfa6267a.44ed4f830a2c8f86990e02fb061c802aa389b0bc.dcdef40499119183aed82a39f784ef740d494341.Exact-head hosted results: functional 89 passed, 3 skipped; E2E 42 passed, 20 skipped; 3 passed in the cold-start suite. Tests run.
Performance Tests runs the cold-start suite, not the strict Doom matrix below. Existing thresholds, retries, deadlines and skips were not relaxed. Native current-head Core CI has 22 passed jobs and 2 path-filter skips; full iOS application CI is not claimed for the latest native heads.
Local and actual-runtime evidence
main-refresh-terminal-verified-pvm.json/ screenshot.main-refresh-pvm-transport.json/ screenshot.0x10c123f02eb6df4c01397d797a112055be691883baa2e82f83b618ed6ce45e46. No TLS bypass or new published guest. Evidence:main-refresh-peer-pvm-live.jsonand screenshots.Strict Doom matrix — retained failure
Fresh isolated visible headless Chromium profiles; cold cache miss, real compiler, nonzero audio, and 360 frame updates for each backend. Warm reload uses a new document in the owned iframe: cache hit and zero translation. Gates remain FPS ≥35, p95 <28.6ms, cold first frame <3000ms, warm first frame <1000ms.
Evidence:
main-refresh-isolated-doom-{rpc-gateway,smoldot-direct,smoldot-shared-worker}.jsonand screenshots. Earlier hidden-tab and concurrent-QA failures remain recorded; no clock/rounding/threshold change or failure-only rerun was used to erase them.Other retained limits
Extrinsic marked as invalid). One UI call caused the existing two native broadcast attempts; both validated then invalidated. No matching included Submit was found in the inspected canonical block range. [INFERENCE] Noncanonical mortality anchors may explain invalidation, but the exact cause is unproved without the unretained signed extrinsic bytes. Evidence:main-refresh-seity-submit-diagnosis.json. Passing hosted E2E does not erase this local failure.main-refresh-seity-factory-diagnosis.json. No added retries, deadline changes, or unsupported cause claim.Rollout boundary
Not an all-green rollout qualification. The refreshed heads were not deployed, and this qualification granted no environment approval. No PR merge, SDK/npm publication, or guest/product publication was performed. JAM remains JAM-TEST-INSTANCE. All three refresh-triggered JAM Deploy runs were cancelled before rollout; latest final-head cancellation. Other branches have no deployment labels.
The live environment changed during qualification: older Deploy run 36945647296, attempt 3 was approved under GitHub account
replghost, explicitly checked out baseline56cea5d37577bf82684fb5c6b6e4ba81d2142938, and recorded deployment success at 2026-10-02 01:19:01 UTC. Its later published-product smoke failed. The operator/client/session behind that account is unproven; this qualification granted no approval and performed no rollback. The observed live content hash changed from4a7caf047fb7f350c1833039b93ba634698a47c56f051b8c7fc0525d4c59a5c8to5882695ee20df5d24a6ed2feb9e997f176fe27ecf4eafe742fabb39eba92885f; these are content hashes, not Git SHAs, and their exact byte-level mapping to a source commit is unproven.Earlier deployment authorizations/results below are historical evidence, not approval to deploy this refreshed stack.
Historical integration qualification (superseded; retained verbatim)
Current-main integration qualification (2026-10-01)
bac980c18e45ffa714a6f9db65ec19b5103c277c. Includes main74bb603e518ace149a846124f6e7353aca198c57, propagated through feat(wallet): add an opt-in debug-only browser test wallet #238 → feat(polkavm): run App Manifest v2 runtimes in Dotli #185 → feat(chat): restore separate Chat authority integration above PolkaVM #255 → feat(profile): show product-referenced Seity profiles in a host drawer #287 and feat(polkavm): run App Manifest v2 runtimes in Dotli #185 → feat(polkavm): JamPeerTransport over WebTransport for JAM apps (layer atop #185) #290, then combined in chore(deploy): Seity layer + JamPeerTransport (#287 + #290) #291. All six heads are published by normal ancestry-guarded pushes; no history rewrite.908843385ba73ab15f513759be5b8694cba5b9d6; complete feature-specific artifacts, signing-only browser Wasm, and separate testing Wasm. Native base #540 CI and Peer #1010 CI are green. No npm or guest publication.117ef1eb2928a470e65e48c05b5bf22e8ab29c02(successful deployment and smoke, deployment ID6778272827). Hosted smoke passed 8/8 published products and 19/19 wallet-free capabilities. Independent fresh HTTPS Chromium sessions confirmed Build0.6.0 (117ef1e)and playable Doom with advancing frames/input/audio on smoldot-direct, RPC gateway, and an actual SharedWorker, with zero browser exceptions. All three screenshots and geometry checks show the 384 px frame meeting the 360 px debug panel without a gap. An actual retained productionc4a08e9session waited for consent, navigated exactly once after Reload, retained the URL plus localStorage/IndexedDB/product-cache markers, and resumed playable Doom on117ef1ewith an activated controlling worker, no waiting worker, and zero exceptions. This is an actual release upgrade, not a substituted worker-script test. Local JSON/screenshots are retained underdotli-community-worktrees/paseo-fixed-doom-*andpaseo-debug-fix-retained-*. No other environment was approved; no PR merge, force push, npm release, or on-chain guest publication.Earlier sections are historical implementation and qualification records.
Latest dependency refresh qualification (2026-09-30)
b3fa339f3ef733d42059844d690eeab095fe429a; normal merges and ancestry-guarded pushes only, no history rewrite.c73e072c96cff7d363af9a61e378ee22621e9f5b. Feature-specific 0.23.0 client/host/WASM artifacts remain unchanged; this source pin is intentionally not relabeled as the refreshed upstream branch head.Earlier implementation and qualification history follows; the versions and heads above describe this refresh.
Summary
Browser implementation of the TrUAPI
JamPeerTransportservice for PolkaVM apps, over WebTransport directly to JAM validators (no sidecar). Access is a runtime permission,RemotePermission::JamPeers { genesis }, not an App-manifest capability: manifests declare no TrUAPI services and there is no host-side allowlist.JamPeerTransportsession. Nothing is granted up front: the firstdialof a JAM network makes the sandbox sendpermissions.request_remote_permission(JamPeers { genesis })over the authenticated host port with a request id of its own. It consumes that reply itself; the guest never sees it.ChainSubmit. The session caches the answer for the execution, so six dials of one network prompt at most once; denied, dismissed or unsupported answersNotGrantedand opens no WebTransport. An app that never dials is never prompted. A dial answers within 10 s, prompt included, andCANCELwithdraws it; an answer given later is still remembered, so the app's next dial proceeds without asking again.@dotli/uipermission modal) reads: "Allow product to connect to JAM network 0x3539abcd… (read-only peer access, no accounts or signing)?", with the full genesis on hover, and offers Deny / Always allow / Allow once.send. Routing reads the wire header only.@parity/truapiand@parity/truapi-host0.23.0 from the matching host layer (lock records branch, revision and archive/wasm digests; web wasm built withwasm-signing-hostas before).JamPeerTransport(renamed fromPeerTransporttogether with host #1010) because it is JAM-specific:JamPeerspermission,jamnp-sALPN, JAMNP-S identity and framing. The rename is wire-identical: trait 23 at the time (now 111), methods 0..6 in the same order, the same SCALE layout and the sameJamPeerspermission. The sandbox imports@parity/truapi/jam-peer-transport.Stacking
A separate layer on top of #185, consuming the host layer paritytech/trinity-user-agents#1010 (on top of #540). It must not be merged before #185. It is combined with Seity in #291; #255 remains the separate Chat layer.
Security
This is the first outbound-network permission for PolkaVM apps on this host. It is user-granted per product and genesis, peer-identity-pinned (P-256 certificate hashes), default
NotGranted, capped at 8 connections, 16 streams per connection, 1 MiB messages and 4 MiB buffered per connection. It adds no HTTP, DNS, arbitrary-host, account, signing or storage authority; the app names the endpoints and received bytes are untrusted until it verifies them. The sandbox's permission request id carries 128 random bits, so the guest cannot forge or intercept its reply.Artifacts and qualification
Head:
ad5ec019e6bac494e8d72aed70cd240118c01f58.Matching client, host, and wallet WASM source:
c73e072c96cff7d363af9a61e378ee22621e9f5bin host-rust-core#1010. Exact archives, generated-client/WASM digests, and build features are recorded invendor/truapi-host.lock.json. Wallet WASM enableswasm-signing-host, nottest-host.Current-head checks pass, including unit, functional, and live E2E, type-checking, production builds, and full-history secret scanning. Deployment evidence is qualified separately in #291.
After pulling these local-file SDK dependencies, use
bun install --force --frozen-lockfileto replace Bun's cached packages.JamPeerTransport remains wire trait 111, methods 0..6; the sandbox routes through the generated SDK constant. The deployment's published-product smoke is not a claim of a new live JAM-validator transport trial.
Startup applies URL-selected protocol settings before wallet/debug hooks and drains shared-mode writes before iframe replacement or startup-triggered reload. Failure-only deployed smoke traces and screenshots are retained for three days.
Secret scanning retains the default rules and full-history scan. The public resolver mapping-slot vector is exempted only when both its exact value and test path match; a boundary smoke confirms changed values and the same value elsewhere remain detectable.
Experimental execution defaults
PolkaVM execution defaults on for test environments (
paseo.fyi,paseo.li, previews, and localhost) and off for productiondot.li. Settings → Experimental → PolkaVM apps explicitly overrides either default; existing saved opt-outs and opt-ins remain authoritative. This is an execution gate, not build-time exclusion of runtime assets or Firebase-controlled eligibility. Product permissions remain separate from the execution setting.Testnet product smoke exercises fresh visits without opting in; production
dot.listill uses the explicit Settings opt-in.