Skip to content

Support TrUAPI statement signing review - #128

Draft
pgherveou wants to merge 67 commits into
mainfrom
codex/truapi-headless-host-compat-pr77
Draft

Support TrUAPI statement signing review#128
pgherveou wants to merge 67 commits into
mainfrom
codex/truapi-headless-host-compat-pr77

Conversation

@pgherveou

@pgherveou pgherveou commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #77.

Summary

  • render StatementStoreProductSign confirmations with signer and statement details
  • support the review shape before it is present in the published host package types
  • raise the Workbox precache file limit so the local TrUAPI WASM can be included

Test plan

  • focused UI tests: 20 passed
  • clean build against published @parity/truapi-host 0.2.1
  • make e2e-dotli from the TrUAPI integration checkout

E2E result

The dotli build, initial pairing, host sign-out, signer reconnect, resource allocation, and Statement Store authorized proof all passed. The diagnosis completed with 41 success and 23 failed; one failure was unexpected: Signing/create_transaction received a statement_submit noAllowance rejection. The two expected legacy-account signing failures and twenty intentionally unsupported methods account for the other failures.

pgherveou added 30 commits July 15, 2026 11:03
Replace the Nova host-container, auth, and signing path with the worker-backed Rust core. Keep dotli responsible only for browser policy, persistence, UI, and physical chain transports.
Notification grants do not alter iframe Permissions Policy. Reloading disposed the in-flight Rust request before its response reached the product.
The pending-message flush drops send failures silently, matching the
pre-port behavior. Surfacing them as JSON-RPC errors moves to a
follow-up PR with test coverage.
…follow-up

Keep @polkadot-api/signer and @polkadot-labs/hdkd{,-helpers} declared
(unused since before the port) and limit rpc-chain tests to the new
core gateway provider surface. Removing the dead deps and adding
coverage for pre-existing chain checks moves to a follow-up PR.
Keep the base panel top offset and suffix-based terminator matching
(minus the removed host-papp events). The offset correction, the
exact-match terminator set, and the @dotli/config dependency
declaration move to a follow-up PR.
Prompts always reach the modal, matching the pre-port behavior. The
sliding-window limiter returns in a follow-up PR together with the
denied-path semantics and a test that trips the window.
AllowanceKeys persist as plain hex through the same path as every
other core storage key. The at-rest cipher moves to a follow-up PR
where the scheme (per-write nonce, plain-hex read fallback) can get a
focused security review.
The bridge emits only the first_inbound/first_outbound lifecycle
events. The per-frame TrUAPI tap that feeds the debug panel timeline
returns in a follow-up PR; the panel's truapi event handling stays in
place and receives no events until then.
… follow-up

Login failures fall back to the raw reason except for the base
OriginPersonProviderError mapping, and the permissions popover renders
last-write-wins without a staleness guard or unavailable-state hint.
The failure-message pack and popover hardening move to a follow-up PR.
…i-host 0.1.0

The published packages replace the temporary personal-scope npm
aliases used while the port was in review.
bun run link:truapi replaces the two installed TrUAPI npm packages with
symlinks to a sibling TrUAPI checkout, and bun run unlink:truapi runs a
forced frozen install to restore the declared packages. Package
resolution is validated after linking so local E2E cannot silently
exercise a stale npm build. The parent truapi repo's make e2e-dotli
target depends on this script via make dotli-link.
getActiveGatewayChains and its doc comment match the pre-port source;
only the core gateway set is new.
Nova exposes synthetic follow ids to legacy products, while the Rust core requires the subscription wire request id. Translate only at the legacy window boundary so existing product-sdk apps keep working without weakening core validation.
All OpenUrl requests are normalized and scheme-validated by the Rust core before they reach this browser callback, so duplicating that policy in TypeScript would create a second allowlist that can drift.

Add the noopener window feature to every routing branch instead. This prevents an allowed destination from retaining window.opener access to the dotli host while preserving the existing dot-domain, localhost, and external URL routing behavior.

Cover all three branches with a regression test that verifies each new tab is opened with noopener.
Changing a permission dispatched a synchronous permission-changed event whose listener started rendering the open popover, then the dropdown success path started a second render directly. Both asynchronous renders appended their rows after the same clear, doubling every entry.

Remove only the redundant success-path render and keep the catch-path render for recovery. The permission event remains the single successful refresh trigger for both device and non-device permissions.

Add a regression test that changes a dropdown and asserts the popover still contains exactly one row per permission.
The topbar login promise previously listened only for response frames. If the core provider closed during pairing, no response could arrive and the pending promise retained its message subscription indefinitely.

Subscribe to provider close events and reject with the transport error. Centralize settlement and cleanup so message responses, malformed frames, send failures, and provider closure all unsubscribe both listeners exactly once.

The cleanup also handles the provider contract where an already-closed provider invokes the close callback during subscription. Add a regression test that closes a pending provider and verifies rejection plus listener cleanup.
The confirmation adapter already rendered and resolved the newer review variants, but its suite exercised only legacy payload signing and omitted transaction creation and the dedicated preimage flow.

Add product-account payload and transaction assertions so account formatting and transaction fields are locked down. Add both allow and cancel cases for preimage submission to verify that the dedicated modal maps user intent to the boolean host response.

This intentionally changes tests only: the existing production behavior satisfies the review request once these untested branches are covered.
The legacy window transport accepted inbound frames based only on Window identity and sent outbound frames with a wildcard target. The iframe keeps its real origin because its sandbox includes allow-same-origin; credentialless mode does not make that origin opaque.

Require the resolved product origin for inbound provider frames, use it as the outbound postMessage target, and enforce it on the initial modern-versus-legacy probe before replaying the first frame. This closes the wildcard path without changing the legacy Nova wire compatibility layer.

Add coverage for the exact outbound target and for rejecting both wrong-origin and wrong-source inbound messages.
Preimage lookup trusted non-empty bytes returned by both the IPFS gateway and Bitswap and cached them under the requested key. A faulty or hostile backend could therefore poison the process-wide cache and serve mismatched bytes to later subscribers.

Recompute the requested Blake2b-256 content hash with the existing content verification utility before either cache write. Verification failures follow the existing backend-error stream path and never populate the cache.

Cover successful verified caching and corrupt responses from both backend modes. The corruption cases subscribe twice to prove that rejected bytes are fetched again rather than retained.
Link one TrUAPI client across dotli and the product so local runs exercise the same runtime end to end. Surface authentication progress while pairing finalizes.
pgherveou and others added 22 commits July 23, 2026 10:32
…ermissions popover

Map slot-exhaustion, rejected-transaction, and JSON-RPC registration
failures to actionable copy with the raw reason as a detail line, and
guard the async permissions popover against stale renders with an
unavailable-state fallback.
Wrap each core provider so every inbound/outbound wire frame is
decoded and emitted on the dotli debug bus when the panel is
listening, restoring per-frame protocol traffic in the timeline.
AllowanceKeys slots are AES-GCM encrypted before hitting localStorage.
Known issues to resolve before merge: derive a random per-write nonce
(the current fixed nonce is obfuscation, not encryption) and accept
the plain-hex format written before this change as a read fallback.
Prompt-driven host callbacks share a 20-per-10s sliding window so a
hostile product cannot flood the host with modal prompts.
Align the docked panel with the 56px topbar iframe, close system flows
by exact layer:event names so setup_ready no longer false-matches the
ready suffix, and declare the @dotli/config dependency that
chain-registry already imports.
Remove @polkadot-api/signer and @polkadot-labs/hdkd{,-helpers}, which
nothing in the resolver imports, and cover isChainSupported and the
pre-existing rpc-chain provider behavior with unit tests.
Failed sends flushed after chainConnect resolve to JSON-RPC error
responses, matching the direct send path, so polkadot-api's client
sees the failure instead of hanging.
Backend read failures no longer push a terminal error into the
preimage lookup subscription, so the stream keeps polling and slow
Bulletin/IPFS propagation surfaces as a late result instead of a
permanent failure. Gateway mode logs that sandbox bitswap is
unavailable rather than advertising the Bulletin chain.
Ref-count upstream tokens shared by local sessions and buffer
subscription events that arrive before their token response. Broker
transport hardening kept separate from the Rust host migration.
origin/main gained the squash-merge of #70, whose tree is identical to
commit 1edd74e already in this branch's history; -s ours records the
merge without changing the tree.
@github-actions

Copy link
Copy Markdown
Contributor

⚡ Performance Report

⚠️ No baseline found on main. This PR's results are recorded but cannot be compared.
Merge to main to establish a baseline.

@github-actions

Copy link
Copy Markdown
Contributor

Bundle Size Report

Chunks over 500 KB:

File Raw Brotli Gzip
host/assets/paseo.smol-DboPaEh1.json 1.84 MB 941.7 KB 1019.4 KB
host/assets/paseo-people-next.smol.json 3.36 MB 1.68 MB 1.82 MB
host/assets/previewnet.smol.json 1.88 MB 181.4 KB 353.0 KB
host/assets/smoldot.js 2.98 MB 2.21 MB (-1 B) 2.22 MB (+12 B)
host/assets/smoldot_worker.js 2.95 MB 2.21 MB 2.21 MB
host/assets/wasm/web/truapi_server_bg.wasm 1.97 MB (+13.8 KB) 623.3 KB (+6.0 KB) 818.7 KB (+6.0 KB)
Total 15.92 MB (+34.4 KB) 8.12 MB (+11.8 KB) (-49%) 8.75 MB (+12.5 KB)
All files
File Raw Brotli Gzip
host/.well-known/apple-app-site-association 738 B 738 B 738 B
host/.well-known/assetlinks.json 1.3 KB 317 B 391 B
host/assets/bridge.js 75.4 KB (+3.7 KB) 20.4 KB (+816 B) 23.4 KB (+888 B)
host/assets/browser.js 22.9 KB 7.6 KB (+1 B) 8.6 KB (-1 B)
host/assets/client.js 100.1 KB (-12 B) 29.4 KB (+3 B) 32.5 KB (+14 B)
host/assets/dist.js 30.3 KB (-8.7 KB) 10.5 KB (-2.4 KB) 11.7 KB (-2.9 KB)
host/assets/dotli-debug-bus.js 710 B (+64 B) 710 B (+64 B) 710 B (+64 B)
host/assets/get-sync-provider.js 2.8 KB 1.1 KB (+1 B) 1.2 KB
host/assets/hex.js 154 B (+1 B) 154 B (+1 B) 154 B (+1 B)
host/assets/index.js 156.3 KB (+19.3 KB) 43.1 KB (+5.7 KB) 50.5 KB (+6.7 KB)
host/assets/index.css 44.8 KB 7.1 KB 7.9 KB
host/assets/manifest.js 22.5 KB (+2 B) 7.2 KB (-7 B) 7.9 KB (-16 B)
host/assets/panel.js 72.6 KB (+91 B) 19.7 KB (+31 B) 22.3 KB (+11 B)
host/assets/paseo.smol-DboPaEh1.json 1.84 MB 941.7 KB 1019.4 KB
host/assets/paseo-people-next.smol.json 3.36 MB 1.68 MB 1.82 MB
host/assets/paseo.smol.json 25.4 KB 4.9 KB 5.6 KB
host/assets/previewnet.smol.json 1.88 MB 181.4 KB 353.0 KB
host/assets/resolve.js 128 B 128 B 128 B
host/assets/rpc-resolve.js 2.4 KB 1.0 KB (+13 B) 1.2 KB (+4 B)
host/assets/shared-mode.js 1.8 KB 753 B (+3 B) 850 B (-1 B)
host/assets/smoldot.js 2.98 MB 2.21 MB (-1 B) 2.22 MB (+12 B)
host/assets/smoldot_worker.js 2.95 MB 2.21 MB 2.21 MB
host/assets/src.js 1.8 KB 855 B (-2 B) 945 B (-1 B)
host/assets/styles.css 15.1 KB 3.2 KB 3.8 KB
host/assets/wasm/web/README.md 10.9 KB 10.9 KB 10.9 KB
host/assets/wasm/web/package.json 371 B 371 B 371 B
host/assets/wasm/web/truapi_server.d.ts 6.9 KB 6.9 KB 6.9 KB
host/assets/wasm/web/truapi_server.js 35.6 KB 6.3 KB (+5 B) 7.2 KB (+3 B)
host/assets/wasm/web/truapi_server_bg.wasm 1.97 MB (+13.8 KB) 623.3 KB (+6.0 KB) 818.7 KB (+6.0 KB)
host/assets/wasm/web/truapi_server_bg.wasm.d.ts 2.5 KB 2.5 KB 2.5 KB
host/assets/web.js 13.2 KB 3.6 KB (-3 B) 4.0 KB (+1 B)
host/assets/worker-runtime.js 6.3 KB (+6.2 KB) 1.6 KB (+1.5 KB) 1.8 KB (+1.7 KB)
host/assets/worker-runtime.js 106 B 106 B 106 B
host/assets/ws.js 23.1 KB (-1 B) 7.5 KB (-1 B) 8.2 KB (+3 B)
host/dotli.png 11.5 KB 11.5 KB 11.5 KB
host/favicon.svg 1.8 KB 1.8 KB 1.8 KB
host/host-sw.js 2.7 KB 1.1 KB (-13 B) 1.2 KB (+1 B)
host/icon-192.png 12.5 KB 12.5 KB 12.5 KB
host/icon-512.png 42.8 KB 42.8 KB 42.8 KB
host/index.html 19.9 KB 4.4 KB (-3 B) 5.4 KB (-4 B)
host/manifest.webmanifest 441 B 441 B 441 B
host/workbox.js 14.8 KB 4.6 KB 5.1 KB
sandbox/app-sw.js 9.6 KB 3.1 KB (-3 B) 3.5 KB (+1 B)
sandbox/assets/bitswap-bridge.js 840 B 840 B 840 B
sandbox/assets/fetch.js 3.4 KB 1.2 KB (+1 B) 1.4 KB (+1 B)
sandbox/assets/index.js 118.0 KB 33.7 KB (+8 B) 39.6 KB
sandbox/assets/index.css 44.8 KB 7.1 KB 7.9 KB
sandbox/favicon.svg 1.8 KB 1.8 KB 1.8 KB
sandbox/index.html 1.7 KB 581 B (-3 B) 787 B
Total 15.92 MB (+34.4 KB) 8.12 MB (+11.8 KB) (-49%) 8.75 MB (+12.5 KB)

Commit: 9b9cfa7

@github-actions

Copy link
Copy Markdown
Contributor

E2E Product suite failed on 7fb26bcb1a64726f8e465fae2ad29e0ffeb80b9c — 41 passed, 4 failed, 17 skipped.

Failed tests:

  • Bulletin Allowance
  • All Allowances
  • As a product user, I can create an authorized statement proof
  • Sign Raw Message

Logs: https://github.com/paritytech/dotli-community/actions/runs/30353820813
Artifacts: e2e-product-results (uploaded above) — open the failed test's trace.zip with npx playwright show-trace.

Base automatically changed from codex/dotli-rust-port-follow-ups to main July 28, 2026 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants