Skip to content

ADR 0014 phase 3: wasi:http, octosense:host, compile at install, Pulley, Windows - #451

Merged
ymote merged 10 commits into
mainfrom
feat/wasm-components-net
Oct 10, 2026
Merged

ymote merged 10 commits into
mainfrom
feat/wasm-components-net

Conversation

@ymote

@ymote ymote commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

ADR 0014 phase 3, including phase 2 from #445. Phase 1 (#436) is merged, and this PR now targets main. App Hub #188 is merged through #190; this branch pins its exact commit 371f51aeb6ba90e9a214c5ddb6ccfc40a2e2a339, which admits wasi:http and octosense:host. Shared-component loading (phase 4) is separate.

What it adds

  • wasi:http (crates/wasm-host/src/component/net.rs).
    • A component's outgoing requests reach any host. Under the ruling of 8 October 2026 (Remove the per-app Splash runtime gates (ruling of 8 Oct 2026): tracking #450), an app's network declarations (net, network.hosts) are shown at install and not enforced while it runs.
    • What the runtime still owes the call: a request waits outside the guest, where the epoch check cannot end it, so its connect, first-byte and between-bytes timeouts are clamped to the call's deadline.
    • A component that imports wasi:http gets the 10 s network deadline instead of 2 s, and wasm.describe says "network": true for it.
    • The branch's history shows the rule tightening and then dropping: first the app's hosts, then public HTTPS hosts only, then any host. Only the last commit's rule is in the final diff.
  • octosense:host (component/host.rs, wit/octosense-host.wit).
    • request(service, args) reaches the host services the app is granted, dispatched on the UI thread as the app's script's host.request is.
    • It never opens a sheet or prompts, and wasm.* is refused.
  • Compile at install (Runtime::precompile, wasm_service::warm). An installed or updated app's functions are compiled into the disk cache in the background, so its first call skips Cranelift.
  • Pulley. Wasmtime's interpreter runs on OpenHarmony and in tests (feature pulley). It is not on iOS, which stays out of this ("no iOS for now").
  • Windows. The service builds there, and .github/workflows/wasm-windows.yml runs the runtime's tests.
  • Docs. docs/wasm.md (English and Chinese) and ADR 0014 (English and Chinese) are updated.

Checks (macOS)

  • cargo test --locked -p octosense-wasm-host: component 13, guest 7, runtime 14 and unit tests 1, all pass. That includes http_reaches_any_host, a_request_that_never_answers_ends_at_the_deadline and the clamp test.
  • OCTOSENSE_WASM_PULLEY=1 cargo test --locked -p octosense-wasm-host --features pulley: pass.
  • From phone/: cargo test --locked --features mobile-apps -p octosense-shell wasm_service::tests: 9 passed. That includes a_components_requests_reach_any_host, where an app with neither net nor hosts reaches a local server as 127.0.0.1 and as localhost.
  • Home's OpenHarmony release build compiled with the service (earlier on this branch).

Not verified

Any device. A Windows run outside CI. A real app installed through App Hub with these imports.

🤖 Generated with Claude Code

ymote and others added 10 commits October 9, 2026 16:15
…orage quota

The shell's wasm service loads components from fns/ beside modules, keeps
one instance per component between calls, gives it the app's storage
folder by the engines' rules, and charges what each write adds against
what is left of the app's quota (wasm-host component/files.rs). Writes run
on the worker thread. Typed JSON accepts a one-item positional array.
Measurements, docs (en, zh-CN) and tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
App Hub #186 admits WebAssembly components when the manifest requires
wasm-components-v1, validates their imports (only the WASI packages a host
scopes to the app) and tells reviewers what each reaches. With the store
on it, a component shipped as a system app goes through admission, and the
new service test calls it as the app's script would: typed JSON, the
instance's state from one request to the next, no folder without storage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Components may import wasi:http (wasmtime-wasi-http 49.0.2, p2, rustls
with ring as the shell's). Requests go only to the app's network.hosts
under net, by a script's rule (exact host, any case, any port), and over
HTTPS except to this device. A request's timeouts are clamped to the
call's deadline, which is 10 s for a component that may reach the network.
Refused requests are logged with the reason. Tests: a fetch component
against a local server, a server that never answers, the service's hosts
from the admitted manifest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rvices

A component may import octosense:host/services@0.1.0 (wit/octosense-host.wit):
request(service, args) -> result<string, string>. The runtime knows no
services; the shell's wasm service gives each instance its app's: the
families its admitted manifest grants (a system app's own namespace too),
dispatched on the UI thread (host_tools::pump) as its script's host.request
would be, but never with a sheet or a prompt, so only the methods a
background surface may call. wasm.* is refused (the app's worker is busy
with the call). The call's deadline bounds the wait.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…st call

When App Hub completes an install or an update, the shell compiles the
app's admitted fns/*.wasm (modules and components) into the disk cache in
the background (wasm_service::warm, Runtime::precompile): one app at a
time, on a thread of its own, never in a worker's place, and only with the
wasm grant. The first call then loads from the cache instead of waiting for
Cranelift (ADR 0011 measured about 0.4 s for a 433 KiB module on a mid-range
phone).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Windows, docs

Pulley, Wasmtime's interpreter, runs app functions where an app may not
generate code: wasm-host's pulley feature, on by itself for iOS and
OpenHarmony, selected elsewhere with OCTOSENSE_WASM_PULLEY for tests
(phone.yml runs the runtime's tests in it too; about 32 times Cranelift's
code). The wasm service now runs on OpenHarmony (Home's OpenHarmony
release build compiled with it; no device run) and on Windows, whose new
wasm-windows.yml runs the runtime's tests and compiles the shell with the
service on windows-2022. iOS stays out until a build with it is compiled.
A full disk is ENOSPC on Unix and StorageFull elsewhere. Docs (en, zh-CN):
the components' network and host services, compiling at install, the
platforms, the tests; ADR 0014's phase 3 status and the Pulley figures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A component's wasi:http no longer reaches the device itself, even when the
app lists localhost or 127.0.0.1: an app that lists one would otherwise
reach every local service (the shell's remote control, a developer's
servers), over plain HTTP too. Loopback, private, link-local and similar
addresses, localhost, single-label and .local/.lan/.internal names are
refused, as makepad's public_https_host refuses them. Grants::http_local
lets tests and a developer's runs use a local server; the shell never sets
it (its own tests do). Scripts still allow a listed loopback host; that is
reported, not changed here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ruling of 8 October 2026 removes the per-app runtime gates: an app's
network declarations (net, network.hosts) are shown at install and not
enforced while it runs, and the OS and the host's API surface are the
boundary. A component's wasi:http therefore reaches any host, and the
public-HTTPS rule of the previous commit goes with the host list.

What stays: a request's timeouts are clamped to the call's deadline, and
a component that imports wasi:http gets the network deadline (decided by
its imports now, not by a grant). wasm.describe says "network": true for
such a component instead of listing hosts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ymote
ymote changed the base branch from feat/wasm-components-service to main October 10, 2026 01:35
@ymote
ymote marked this pull request as ready for review October 10, 2026 01:35
@ymote

ymote commented Oct 10, 2026

Copy link
Copy Markdown
Contributor Author

Local CI passed on 40a5dea (tools/ci-local.sh --only all --linux-host --offload, 21m48s, Darwin arm64; the ubuntu jobs and the macOS jobs' portable steps (their macOS steps ran here) on the Linux build host, Linux x86_64).

GitHub would run for this PR: desktop.yml, phone.yml, apps.yml. Merged on this local pass (macOS runner queue); GitHub CI runs on the merge commit on main.

Job Step Result Time
ci-local / drift The local mapping fits the workflows PASS -
desktop.yml / desktop Prepare the pinned framework sources PASS 1s
desktop.yml / desktop Compile the desktop with the shared runtime PASS 9m01s
desktop.yml / desktop Desktop tools and scripts PASS 15s
desktop.yml / desktop (linux) Prepare the pinned framework sources PASS 1s
desktop.yml / desktop (linux) One copy of every shell source PASS -
desktop.yml / desktop (linux) One Makepad, App Hub, octos and Rinx in the locked graph PASS 3s
desktop.yml / desktop (linux) The native apps' generated places match native-apps.json PASS 0s
desktop.yml / native-host-api Prepare the pinned framework sources PASS 1s
desktop.yml / native-host-api Build the native acceptance host and pinned Hub CLI PASS 8m07s
desktop.yml / native-host-api Signed app tool calls a real OS permission API PASS 4s
phone.yml / home Prepare pinned sources and the reviewed runtime patch PASS 1s
phone.yml / home Validate launcher icons and Apple asset catalogs PASS 3s
phone.yml / home (linux) Prepare pinned sources and the reviewed runtime patch PASS 0s
phone.yml / home (linux) Verify the single runtime graph PASS 2s
phone.yml / home (linux) The native apps' generated places match native-apps.json PASS 0s
phone.yml / home (linux) The pinned octos revision PASS -
phone.yml / home (linux) Build octos (unless cached) PASS -
phone.yml / home (linux) Build Home, App Hub admission and runtime policy tests PASS 5m05s
phone.yml / home (linux) Test Home, App Hub admission and runtime policy PASS 45s
phone.yml / home (linux) Two-lane scenario (real kernel, scripted model) PASS 28s
phone.yml / home (linux) Build opt-in AppCard tests PASS 4m05s
phone.yml / home (linux) Test opt-in AppCard PASS 1s
phone.yml / home (linux) Build craft-engine relay and system-chat tests PASS 3m07s
phone.yml / home (linux) Test craft-engine relay and system chat PASS 5s
phone.yml / home (linux) Build linked Terminal tests PASS 2m31s
phone.yml / home (linux) Test linked Terminal PASS 1s
phone.yml / home (linux) Build Wasm and runtime policy tests PASS 2m16s
phone.yml / home (linux) Test Wasm and runtime policy PASS 10s
phone.yml / home Compile Home and its bundled modules PASS 4m16s
apps.yml / services (linux) python3 tools/setup.py PASS 0s
apps.yml / services (linux) Shared system app interface PASS 0s
apps.yml / services (linux) Kernel service PASS 17s
apps.yml / services (linux) App peers PASS 30s
apps.yml / services (linux) AI providers config PASS 4s
apps.yml / services (linux) Connected provider protocols and Linux host adapter PASS 1m05s
apps.yml / services (linux) L0 in-card chat (sys.chat, host side) PASS 11s
apps.yml / services (linux) System toolbox (workflow templates) PASS 1m42s
apps.yml / kernel-security (linux) python3 tools/setup.py PASS 0s
apps.yml / kernel-security (linux) The pinned octos revision PASS -
apps.yml / kernel-security (linux) Build octos (unless cached) PASS -
apps.yml / kernel-security (linux) Real-kernel tests PASS 34s
apps.yml / apps (linux) python3 tools/setup.py PASS 0s
apps.yml / apps (linux) Host services (Mail, AI providers, News) PASS 2m22s
apps.yml / apps (linux) Connected accounts and Rinx editor PASS 1m47s
apps.yml / apps (linux) Shell AI services (crates/ai-host) PASS 3m07s
apps.yml / apps (linux) AppCard runtime setup safeguards PASS 0s
apps.yml / apps (linux) AppCard clippy (own crates; shared runtime compiles) PASS 33s
apps.yml / apps (linux) AppCard transport and store PASS 8s
apps.yml / apps (linux) One Makepad, App Hub, octos and Rinx in the locked graph PASS 2s
rom.yml / product (linux) python3 -m unittest discover -s tests -v SKIPPED (!) -
rom.yml / product (linux) Check generated Agent Binder client SKIPPED (!) -
rom.yml / product (linux) bash -n scripts/stage-forks.sh scripts/publish-release.sh scripts/apply-to-tree.sh scripts/build-rom.sh PASS -
rom.yml / web-installer (linux) npm ci --ignore-scripts --no-audit --no-fund SKIPPED (!) -
rom.yml / web-installer (linux) npm test SKIPPED (!) -
rom.yml / web-installer (linux) npx playwright install --with-deps chromium SKIPPED (!) -
rom.yml / web-installer (linux) npm run test:browser SKIPPED (!) -
rom.yml / web-installer (linux) python3 -m unittest discover -s tests -p test_installer_manifest.py -v SKIPPED (!) -
rom.yml / web-installer (linux) bash -n scripts/release.sh SKIPPED (!) -
linux-host / sandbox (linux) python3 tools/setup.py PASS 0s
linux-host / sandbox (linux) Process sandbox on Linux (Landlock, seccomp) PASS 2m01s

Skipped (these did NOT pass; (!) marks a skip that blocks tools/ci-local-merge.sh):

  • rom.yml / product (linux): python3 -m unittest discover -s tests -v: javac -version does not work here: install a JDK (17 or newer) and put its bin/ on PATH or set JAVA_HOME
  • rom.yml / product (linux): Check generated Agent Binder client: needs build-tools/35.0.0/aidl, platforms/android-35/framework.aidl in the Android SDK (no Android SDK found): install the SDK packages 'build-tools;35.0.0' and 'platforms;android-35' (sdkmanager) and set ANDROID_HOME
  • rom.yml / web-installer (linux): npm ci --ignore-scripts --no-audit --no-fund: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): npm test: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): npx playwright install --with-deps chromium: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): npm run test:browser: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): python3 -m unittest discover -s tests -p test_installer_manifest.py -v: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): bash -n scripts/release.sh: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH

Notes:

  • GitHub runs Python 3.12; this run used Python 3.9.6
  • GitHub runs Python 3.12; the Linux host used Python 3.14.4

Native GitHub acceptance passed on the same head: embedded-browser.yml.

@ymote
ymote merged commit 80b2769 into main Oct 10, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant