Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
2e834bd
feat(pvm): run framebuffer products through Wasm
replghost Aug 26, 2026
3ca785e
feat(pvm): enforce App manifest v2 identity
replghost Aug 26, 2026
d106b64
fix(pvm): support bounded CoreVM game hostcalls
replghost Aug 26, 2026
63d2f07
feat(pvm): support Tri2D and WebGPU Raster
replghost Aug 27, 2026
1a39648
fix(pvm): await smoldot app manifest resolution
replghost Aug 27, 2026
58c9ab6
perf(pvm): compile graphics profile guests
replghost Aug 27, 2026
97a1f66
fix(pvm): slice long hostcall sequences
replghost Aug 27, 2026
54dfdb4
refactor(pvm): consume neutral browser runtime
replghost Aug 28, 2026
faef286
chore(pvm): pin neutral runtime source
replghost Aug 28, 2026
4def2a0
refactor(pvm): share worker runtime core
replghost Aug 28, 2026
1457024
test(pvm): allow app-specific smoke inputs
replghost Aug 28, 2026
3efcb60
fix(pvm): consume Epoca input events
replghost Aug 28, 2026
5b8674b
style(pvm): format runtime adapter
replghost Aug 28, 2026
1cc021f
fix(pvm): vendor reviewed host runtime
replghost Aug 28, 2026
be48a71
fix(pvm): revendor Epoca input runtime
replghost Aug 28, 2026
68717c7
test(pvm): verify continuous Duke audio
replghost Aug 28, 2026
f1c2e68
chore(pvm): point runtime source at PR branch
replghost Aug 28, 2026
29bf23a
fix(pvm): retain launch contract across reloads
replghost Aug 29, 2026
57b36f7
fix(resolve): revalidate App v2 contenthashes
replghost Aug 29, 2026
ec5857c
refactor(pvm): consume host runtime bridge
replghost Aug 29, 2026
a45dcd4
feat(pvm): add forced interpreter launch mode
replghost Aug 29, 2026
4b6a133
fix(pvm): restore bridge-owned worker bytes
replghost Aug 29, 2026
4ee19da
fix(cache): store installed executable pairs atomically
replghost Aug 29, 2026
4e3e98c
fix(pvm): expose interpreter startup stages
replghost Aug 29, 2026
a349693
fix(pwa): recover incompatible host-sandbox builds
replghost Aug 29, 2026
ac1d0d4
fix(pvm): protect bridge-owned runtime assets
replghost Aug 29, 2026
d096a7f
feat(pvm): vendor runtime v0.1.1
replghost Aug 29, 2026
31bd6f9
fix(pvm): use browser clock for CoreVM guests
replghost Aug 29, 2026
9c2c8a9
fix(pvm): bound pointer-lock warp deltas
replghost Aug 29, 2026
b944be4
fix(pvm): reject pointer-lock jumps
replghost Aug 30, 2026
119d95b
fix(pvm): coalesce relative pointer backlog
replghost Aug 30, 2026
d265df2
fix(pvm): drop pointer-lock discontinuities
replghost Aug 30, 2026
37e7d50
fix(pvm): discard stale mouse backlog
replghost Aug 30, 2026
7ad7a97
fix(pvm): enable Safari CoreVM JIT
replghost Aug 30, 2026
cc3f4ae
feat(pvm): route baseline TrUAPI in sandbox
replghost Aug 30, 2026
ade4ffb
fix(pvm): negotiate canonical TrUAPI port
replghost Aug 30, 2026
8dfee3b
fix(pvm): restore bridge-owned runtime assets
replghost Aug 30, 2026
9a27b0d
style(pvm): format TrUAPI transport
replghost Aug 30, 2026
1195641
test(pvm): prove canonical TrUAPI roundtrip
replghost Aug 30, 2026
5ba1ffa
fix(pvm): update runtime to v0.1.4
replghost Aug 30, 2026
761aa1a
test(pvm): isolate live performance server
replghost Aug 30, 2026
1a8aa4d
fix(pvm): reconnect warm runtime cache
replghost Aug 30, 2026
082dbdf
fix(pvm): compact runtime metrics overlay
replghost Aug 30, 2026
ec2efd1
fix(pvm): explain unsupported app features
replghost Aug 31, 2026
41026af
fix(pvm): recover WebGPU apps across resize
replghost Aug 31, 2026
6da503d
fix(pvm): capture pointer for WebGPU games
replghost Aug 31, 2026
fa52dc1
chore(pvm): pin reviewed motion bridge
replghost Aug 31, 2026
6dc3417
style(pvm): format resize coverage
replghost Aug 31, 2026
e7a3593
feat(pvm): integrate MotionSample v1
replghost Aug 31, 2026
f3249ea
chore(pvm): pin merged GPU motion runtime
replghost Aug 31, 2026
5b13132
feat(pvm): require explicit relative pointer input
replghost Aug 31, 2026
f640003
test(pvm): separate capture from guest input
replghost Aug 31, 2026
d200b5b
test(pvm): retain relative pointer control label
replghost Aug 31, 2026
ddd43c2
Revert "test(pvm): retain relative pointer control label"
replghost Aug 31, 2026
8173197
Revert "test(pvm): separate capture from guest input"
replghost Aug 31, 2026
f270f1f
Revert "feat(pvm): require explicit relative pointer input"
replghost Aug 31, 2026
f00782c
Merge remote-tracking branch 'origin/main' into feat/pvm-wasm
replghost Sep 1, 2026
4ec7254
feat(pvm): deliver text IME focus and wheel input
replghost Sep 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ jobs:
- name: Install dependencies
run: bun install --frozen-lockfile

- name: Verify PVM bridge assets
run: bun run check:pvm-runtime

- name: Run tests
run: bunx --bun turbo run test

Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules/
bun.lock
tests/results/
docs/
apps/sandbox/public/pvm-runtime/
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Each product gets its own `<label>.app.paseo.li` origin, so versions of the same
1. **Resolves** `.dot` names via an in-browser [smoldot](https://github.com/paritytech/smoldot) light client connected to Asset Hub Paseo, querying dotNS contracts.
2. **Fetches** content from the [Bulletin Chain](https://github.com/paritytech/polkadot-bulletin-chain) via smoldot `bitswap_v1_get` JSON-RPC or an IPFS gateway.
3. **Renders** the content in a sandboxed iframe with the Rust-backed TrUAPI bridge, so loaded SPAs can request accounts, sign transactions, connect to chains, and use scoped storage.
4. **Runs** verified framebuffer PolkaVM products by translating `app.polkavm` to WebAssembly at load time inside a worker, with a bounded interpreter fallback.

```
host-playground.paseo.li
Expand Down Expand Up @@ -100,12 +101,31 @@ When a CID points to an IPFS directory (not a single file):
4. The iframe loads from `/dotli-app/index.html` — the SW intercepts all requests and serves files from the in-memory archive
5. Relative imports (`<script src="main.js">`, `<link href="styles.css">`) just work

## How PolkaVM apps work

An archive whose `manifest.json` declares `runtime.kind: "polkavm"` never
executes package-owned HTML. The sandbox instead creates a host-owned canvas,
loads the verified `app.polkavm` and immutable package assets, and translates
the program to WebAssembly inside a worker. Keyboard, pointer, framebuffer,
PCM-audio, asset, and save traffic stays on the bounded PolkaVM host ABI.

The initial profile supports Epoca framebuffer ABI version 1, including CoreVM
products such as `doom.paseo`. Tri2D, WebGPU, and TruAPI guest hostcalls fail
closed until their capability boundaries are implemented independently.

Translated Wasm bytes are cached in product-origin IndexedDB by the SHA-256 of
the PVM program and the pinned translator version. Warm launches skip PVM
instruction lowering; WebAssembly compilation remains browser-owned. If
translation or Wasm compilation fails, the same worker retries through the
bounded interpreter.

## Caching and verification

dotli uses a two-layer cache for fast repeat visits:
dotli uses three cache layers for fast repeat visits:

1. **CID cache** (IndexedDB) — maps `.dot` labels to their last-known CID
2. **Archive cache** (Service Worker) — stores fetched file maps keyed by domain; a cache hit additionally requires the stored CID (and content backend) to match
3. **PVM translation cache** (IndexedDB) — stores translated Wasm bytes keyed by translator version and PVM program digest

On repeat visits, content renders instantly from the cache while it is resolved in the background. The topbar shield shows how the current page was loaded:

Expand Down
10 changes: 6 additions & 4 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ alphabetically. Copyright and permission notices for each package are retained
in its distribution under `node_modules`.

GPL-family components (GPL-3.0 with the Classpath linking exception) are
compatible with this project's AGPL-3.0 outbound license. Build-time-only
tooling under weak-copyleft (MPL-2.0) or source-available (FSL-1.1-MIT) terms is
used to build the application and is not redistributed as part of it.
compatible with this project's AGPL-3.0 outbound license. The vendored Epoca
PolkaVM browser runtime remains under MPL-2.0, with its PolkaVM-derived portions
under Apache-2.0 OR MIT. Its complete notices and source provenance ship beside
the runtime. Build-time-only tooling under source-available FSL-1.1-MIT terms is
not redistributed as part of the application.

> Generated from the resolved dependency tree (595 distinct third-party
> packages). Platform-specific binary packages (for example
Expand Down Expand Up @@ -76,7 +78,7 @@ smoldot, verifiablejs

## MPL-2.0

lightningcss, lightningcss-darwin-arm64
Epoca PolkaVM browser runtime, lightningcss, lightningcss-darwin-arm64

## FSL-1.1-MIT

Expand Down
7 changes: 6 additions & 1 deletion apps/host/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
"scripts": {
"build": "tsc && bunx --bun vite build",
"build:prod": "tsc && bunx --bun vite build && bun ../../scripts/compress-dist.ts",
"test:functional": "playwright test --config=tests/functional/playwright.config.ts tests/functional/loading.spec.ts tests/functional/resolution.spec.ts tests/functional/navigation.spec.ts",
"test:functional": "playwright test --config=tests/functional/playwright.config.ts tests/functional/loading.spec.ts tests/functional/resolution.spec.ts tests/functional/navigation.spec.ts tests/functional/pvm.spec.ts",
"test:e2e": "playwright test --config=tests/e2e/playwright.config.ts",
"test:e2e:local": "E2E_PRODUCT_URL=${E2E_PRODUCT_URL:-http://localhost:5199} SIGNER_BOT_BASE_URL=${SIGNER_BOT_BASE_URL:-http://localhost:3737/} SIGNER_BOT_SVC_TOKEN=${SIGNER_BOT_SVC_TOKEN:-admin} SIGNER_BOT_NETWORK=${SIGNER_BOT_NETWORK:-paseo-next-v2} playwright test --config=tests/e2e/playwright.config.ts",
"test:perf": "PERF_RUNS=10 PERF_DOMAIN_A=explore PERF_DOMAIN_B=host-playground npx playwright test --config=tests/performance/playwright.config.ts tests/performance/cold-start.spec.ts",
"test:perf:base": "PERF_RUNS=20 PERF_SAVE_BASE=1 PERF_DOMAIN_A=explore PERF_DOMAIN_B=host-playground npx playwright test --config=tests/performance/playwright.config.ts tests/performance/cold-start.spec.ts",
"test:perf:compare": "bun tests/performance/compare.ts",
"test:pvm:doom": "playwright test --config=tests/performance/playwright.config.ts tests/performance/pvm-doom.spec.ts",
"test:perf:compare:md": "bun tests/performance/compare.ts --markdown",
"lint": "bunx eslint src/",
"typecheck": "tsc --noEmit"
Expand All @@ -21,10 +22,14 @@
"@dotli/eslint-config": "workspace:*",
"@dotli/typescript-config": "workspace:*",
"@playwright/test": "^1.59.1",
"@ipld/car": "^5.4.3",
"@ipld/dag-pb": "^4.1.5",
"playwright": "^1.59.1",
"@types/node": "^25.9.3",
"eslint": "^10.5.0",
"jsqr": "^1.4.0",
"ipfs-unixfs": "^13.0.0",
"multiformats": "^14.0.0",
"prettier": "^3.8.3",
"simple-statistics": "^7.9.0",
"typescript": "~6.0.3",
Expand Down
Loading
Loading