Tracking issue for porting the Rust runtime and host runtime SDKs from the truapi_next prototype (~/github/truapi_next, branch develop) into this repo.
Scope
In scope: Rust runtime (truapi-server, truapi-platform, uniffi-bindgen-cli), Rust dispatcher codegen, JS host runtime packages (@parity/host-{shared,web,electron}), native host SDK shells (host-libs/{android,ios}).
Out of scope:
- API / struct model changes — the current
truapi crate is canonical (everything merged into v01; future v02 is deferred).
demos/ from truapi_next — hosts will be added as submodules later (like hosts/dotli/).
@novasamatech/host-api postMessage compat path.
- The host_logic API renames in
truapi_next (navigate_to→open_url, merging device_permission+remote_permission, dropping feature_supported). Current v01 callback shapes stay.
Cross-cutting rules
truapi-platform and truapi-server import types only from truapi::versioned::*.
host_logic/permissions operates on versioned permission enums and relies on new Display impls (Phase 2).
- Keep current v01 callback split:
device_permission + remote_permission stay separate; feature_supported and navigate_to keep their current names.
Source of truth
Prototype lives at ~/github/truapi_next (paritytech/truapi-next or local-only; treat as reference). Key crates to port:
rust/crates/truapi-codegen/src/rust_dispatcher.rs
rust/crates/truapi-platform/ (~200 LOC, 1 file)
rust/crates/truapi-server/ (~8.6 k LOC across core.rs, dispatcher.rs, frame.rs, transport.rs, subscription.rs, runtime.rs, chain_runtime.rs, host_logic/{dotns,features,permissions,session}.rs, smoldot_provider/, ws_bridge.rs, native.rs, wasm.rs, debug_log.rs, generated/)
rust/crates/uniffi-bindgen-cli/
host-libs/js/{shared,web,electron}/
host-libs/android/, host-libs/ios/TrUAPIHost/
Plan
Phase 1 — truapi-codegen: emit Rust dispatcher
- Port
rust_dispatcher.rs into the modular ts/-style layout under truapi-codegen/src/rust/.
- Add
--rust-output PATH → emits <path>/dispatcher.rs + <path>/wire_table.rs.
- Wire into
scripts/codegen.sh and Makefile so codegen emits TS + host-TS + Rust in one run.
Phase 2 — truapi crate: Display impls only
Additive only. No struct/module changes.
impl Display on versioned::permissions::HostDevicePermissionRequest + per-version inner(s)
impl Display on versioned::permissions::HostRemotePermissionRequest + per-version inner(s)
Phase 3 — New crate truapi-platform
rust/crates/truapi-platform/:
- Traits:
Storage, Navigation, Notifications, Permissions (two callbacks: device_permission, remote_permission), ChainProvider, JsonRpcConnection, Accounts, Signing, StatementStore, Preimage, Features.
Platform super-trait composing all.
- Re-export only
truapi::versioned.
Phase 4 — New crate truapi-server (vertical slices)
4a. frame.rs, transport.rs, dispatcher.rs, minimal core.rs (TrUApiCore::new(host)); snapshot tests for ProtocolMessage encoding.
4b. subscription.rs — start/stop/interrupt/receive lifecycle; 4-id reservation matches codegen.
4c. runtime.rs (PlatformRuntimeHost<P: Platform>) + host_logic/:
mod.rs
dotns.rs (keeps current navigate_to callback name)
permissions.rs (versioned types + Display, two callbacks)
features.rs (keeps feature_supported callback as-is)
session.rs — SessionState (wired into wasm.rs in 4e)
4d. chain_runtime.rs (RuntimeChainProvider, UnavailableChainProvider, chainHead-v1 SM); smoldot_provider/* (feature smoldot).
4e. ws_bridge.rs (feature ws-bridge); native.rs (UniFFI: NativeTrUApiCore, HostCallbacks); wasm.rs (wasm-bindgen + setActiveSession/clearActiveSession); debug_log.rs.
4f. Codegen output committed (or .gitignore-d like the TS output) at truapi-server/src/generated/{dispatcher.rs,wire_table.rs}.
Phase 5 — New crate uniffi-bindgen-cli
Trivial wrapper around uniffi::uniffi_bindgen_main(). make uniffi regenerates Kotlin/Swift into host-libs/{android,ios}.
Phase 6 — Host runtime SDKs
Rust → JS
New top-level host-libs/ dir (mirrors truapi_next layout) with three published packages:
-
host-libs/js/shared/ → @parity/host-shared
dispatcher.ts, runtime.ts, worker-runtime.ts, node-runtime.ts, worker-protocol.ts, types.ts
- Depends on
@parity/truapi-host
- Ships pre-built WASM under
dist/wasm/{web,node}/ (committed via CI build step)
-
host-libs/js/web/ → @parity/host-web
create-iframe-host.ts, create-worker-host-runtime.ts
- Depends on
@parity/host-shared
- No novasama compat shim
-
host-libs/js/electron/ → @parity/host-electron
- Preload bridge
- Depends on
@parity/host-shared
Rust → Native (port now)
host-libs/android/ — Kotlin shell + build.gradle.kts
host-libs/ios/TrUAPIHost/ — Swift Package + TrUAPIHost.swift
Both wrap UniFFI bindings emitted from truapi-server. Regenerated via make uniffi.
Phase 7 — Tooling & docs
Makefile: make wasm (cargo wasm32 build for truapi-server + copy into host-libs/js/shared/dist/wasm/), make uniffi, extend make build / make check.
docs/design/dotli-architecture-change.md + docs/design/dotli-rust-core-proposal.md ported from truapi_next/.claude/.
scripts/: port validate-wasm-host.mjs, validate-generated-client.mjs. Drop android/ios validators.
README.md / CLAUDE.md: document new crates + 3 new JS packages + 2 native SDKs.
- CI: extend
.github/workflows/ to build wasm and commit to release branches; mirror @parity/truapi release setup for the new packages.
Notable commits in truapi_next to mine for reference
(picked by likely-still-relevant signal)
Codegen the Rust dispatcher
Move PlatformRuntimeHost stubs into trait defaults
Add localhost WebSocket bridge for Android/iOS WebView hosts
Unify iOS + Android host callbacks into single 'native' Rust module
Scaffold host_logic module tree in truapi-server
Add host_logic::dotns; rename navigate_to to open_url (port the dotns parsing, not the rename)
add host_logic::permissions; replace device/remote_permission with prompt_permission (port the batching/persistence, not the merged callback)
add From/TryFrom between HostStatement and sp_statement_store::Statement
drop feature_supported callback; core owns genesis-hash list (skip the drop; keep callback)
regenerate uniffi bindings; shrink iOS/Android/web demo callbacks
Run the truapi-server wasm core in a Web Worker
Add SessionState + wasm setActiveSession/clearActiveSession
Tracking issue for porting the Rust runtime and host runtime SDKs from the
truapi_nextprototype (~/github/truapi_next, branchdevelop) into this repo.Scope
In scope: Rust runtime (
truapi-server,truapi-platform,uniffi-bindgen-cli), Rust dispatcher codegen, JS host runtime packages (@parity/host-{shared,web,electron}), native host SDK shells (host-libs/{android,ios}).Out of scope:
truapicrate is canonical (everything merged into v01; future v02 is deferred).demos/fromtruapi_next— hosts will be added as submodules later (likehosts/dotli/).@novasamatech/host-apipostMessage compat path.truapi_next(navigate_to→open_url, mergingdevice_permission+remote_permission, droppingfeature_supported). Current v01 callback shapes stay.Cross-cutting rules
truapi-platformandtruapi-serverimport types only fromtruapi::versioned::*.host_logic/permissionsoperates on versioned permission enums and relies on newDisplayimpls (Phase 2).device_permission+remote_permissionstay separate;feature_supportedandnavigate_tokeep their current names.Source of truth
Prototype lives at
~/github/truapi_next(paritytech/truapi-next or local-only; treat as reference). Key crates to port:rust/crates/truapi-codegen/src/rust_dispatcher.rsrust/crates/truapi-platform/(~200 LOC, 1 file)rust/crates/truapi-server/(~8.6 k LOC acrosscore.rs,dispatcher.rs,frame.rs,transport.rs,subscription.rs,runtime.rs,chain_runtime.rs,host_logic/{dotns,features,permissions,session}.rs,smoldot_provider/,ws_bridge.rs,native.rs,wasm.rs,debug_log.rs,generated/)rust/crates/uniffi-bindgen-cli/host-libs/js/{shared,web,electron}/host-libs/android/,host-libs/ios/TrUAPIHost/Plan
Phase 1 —
truapi-codegen: emit Rust dispatcherrust_dispatcher.rsinto the modularts/-style layout undertruapi-codegen/src/rust/.--rust-output PATH→ emits<path>/dispatcher.rs+<path>/wire_table.rs.scripts/codegen.shandMakefileso codegen emits TS + host-TS + Rust in one run.Phase 2 —
truapicrate:Displayimpls onlyAdditive only. No struct/module changes.
impl Displayonversioned::permissions::HostDevicePermissionRequest+ per-version inner(s)impl Displayonversioned::permissions::HostRemotePermissionRequest+ per-version inner(s)Phase 3 — New crate
truapi-platformrust/crates/truapi-platform/:Storage,Navigation,Notifications,Permissions(two callbacks:device_permission,remote_permission),ChainProvider,JsonRpcConnection,Accounts,Signing,StatementStore,Preimage,Features.Platformsuper-trait composing all.truapi::versioned.Phase 4 — New crate
truapi-server(vertical slices)4a.
frame.rs,transport.rs,dispatcher.rs, minimalcore.rs(TrUApiCore::new(host)); snapshot tests for ProtocolMessage encoding.4b.
subscription.rs— start/stop/interrupt/receive lifecycle; 4-id reservation matches codegen.4c.
runtime.rs(PlatformRuntimeHost<P: Platform>) +host_logic/:mod.rsdotns.rs(keeps currentnavigate_tocallback name)permissions.rs(versioned types + Display, two callbacks)features.rs(keepsfeature_supportedcallback as-is)session.rs— SessionState (wired intowasm.rsin 4e)4d.
chain_runtime.rs(RuntimeChainProvider,UnavailableChainProvider, chainHead-v1 SM);smoldot_provider/*(featuresmoldot).4e.
ws_bridge.rs(featurews-bridge);native.rs(UniFFI:NativeTrUApiCore,HostCallbacks);wasm.rs(wasm-bindgen +setActiveSession/clearActiveSession);debug_log.rs.4f. Codegen output committed (or
.gitignore-d like the TS output) attruapi-server/src/generated/{dispatcher.rs,wire_table.rs}.Phase 5 — New crate
uniffi-bindgen-cliTrivial wrapper around
uniffi::uniffi_bindgen_main().make uniffiregenerates Kotlin/Swift intohost-libs/{android,ios}.Phase 6 — Host runtime SDKs
Rust → JS
New top-level
host-libs/dir (mirrorstruapi_nextlayout) with three published packages:host-libs/js/shared/→@parity/host-shareddispatcher.ts,runtime.ts,worker-runtime.ts,node-runtime.ts,worker-protocol.ts,types.ts@parity/truapi-hostdist/wasm/{web,node}/(committed via CI build step)host-libs/js/web/→@parity/host-webcreate-iframe-host.ts,create-worker-host-runtime.ts@parity/host-sharedhost-libs/js/electron/→@parity/host-electron@parity/host-sharedRust → Native (port now)
host-libs/android/— Kotlin shell +build.gradle.ktshost-libs/ios/TrUAPIHost/— Swift Package +TrUAPIHost.swiftBoth wrap UniFFI bindings emitted from
truapi-server. Regenerated viamake uniffi.Phase 7 — Tooling & docs
Makefile:make wasm(cargo wasm32 build fortruapi-server+ copy intohost-libs/js/shared/dist/wasm/),make uniffi, extendmake build/make check.docs/design/dotli-architecture-change.md+docs/design/dotli-rust-core-proposal.mdported fromtruapi_next/.claude/.scripts/: portvalidate-wasm-host.mjs,validate-generated-client.mjs. Drop android/ios validators.README.md/CLAUDE.md: document new crates + 3 new JS packages + 2 native SDKs..github/workflows/to build wasm and commit to release branches; mirror@parity/truapirelease setup for the new packages.Notable commits in
truapi_nextto mine for reference(picked by likely-still-relevant signal)
Codegen the Rust dispatcherMove PlatformRuntimeHost stubs into trait defaultsAdd localhost WebSocket bridge for Android/iOS WebView hostsUnify iOS + Android host callbacks into single 'native' Rust moduleScaffold host_logic module tree in truapi-serverAdd host_logic::dotns; rename navigate_to to open_url(port the dotns parsing, not the rename)add host_logic::permissions; replace device/remote_permission with prompt_permission(port the batching/persistence, not the merged callback)add From/TryFrom between HostStatement and sp_statement_store::Statementdrop feature_supported callback; core owns genesis-hash list(skip the drop; keep callback)regenerate uniffi bindings; shrink iOS/Android/web demo callbacksRun the truapi-server wasm core in a Web WorkerAdd SessionState + wasm setActiveSession/clearActiveSession