English | 简体中文
WebAssembly turns up in four places in OctoSense. One is designed to run an
app's own code: an app's own functions, which standard builds run on macOS,
Windows, Linux, Android and OpenHarmony, with limited support. The plug-ins of two engines,
photocraft behind photo and vectorcraft behind vector, are closed: both
services refuse every plug-in command. The other two are a makepad internal and a browser build that does not compile.
For each, this page says whose module runs, what it can reach, which builds
have it and how it was checked. This page describes the current source tree.
Desktop 0.1.0-rc.2 and Home 0.1.0-beta.2 contain ADR 0011 core modules.
ADR 0014 shared components and the declaration-only changes below passed
final-source acceptance at 8b09e05d on macOS and OnePlus 6.
Desktop RC5 at 83d356c2 (11 October 2026) is
the first release in which a component's HTTPS request works (#471:
RC4 panicked while choosing a TLS provider on the first wasi:http
request) and the first with the native charts an app can require through
charts.d3@1 (charts). On it, Repo Radar became
the first component app installed from the official public catalog: its
public-store acceptance passed 93 native checks covering
live GitHub requests from the component, native charts and
component-owned state across a restart. Desktop RC6 keeps all of
this and adds sockets. Desktop RC4
at 9266b008 brought the component runtime; its archive evidence
records the actual package, signing and acceptance boundaries.
The isolated phone fixtures did not update installed Home.
Source, test and release status are separate.
See capabilities and execution boundaries.
| Where | Whose module | Runtime | Builds | State |
|---|---|---|---|---|
An app's own functions: the wasm service (ADR 0011) |
The admitted app's fns/*.wasm or its exact shared-component pins |
Wasmtime 49, compiled by Cranelift (crates/wasm-host); components get WASI 0.2 from wasmtime-wasi |
Every standard desktop and Home build on macOS, Windows, Linux, Android and OpenHarmony (feature wasm-functions; on OpenHarmony in Pulley, Wasmtime's interpreter); none for iOS |
Core modules shipped in desktop rc.2 and Home beta.2. Desktop RC4 includes components and shared components; archive/source evidence is recorded below. Isolated OnePlus 6 fixtures did not upgrade Home |
Engine plug-ins: photocraft behind photo, vectorcraft behind vector (ADR 0013) |
None: both services refuse every plugin.* command (#398, #405) |
wasmi 2, an interpreter | Linked into every build with App Hub | Closed: no caller can install or run a plug-in |
| Splash's math compiler (makepad) | Generated by makepad from Splash code | makepad-stitch, an interpreter | Linked into every build | Not used: OctoSense links nothing that calls it |
| The shell in a browser | The shell itself, built for wasm32-unknown-unknown |
The browser | None | Does not build |
ADR 0011 (Accepted, with limited support) lets an app ship Rust functions compiled to WebAssembly in its bundle, and the shell runs them for that app only. They are for light computing beside a script: parsing, ranking, scheduling, diffing, a format conversion. Splash's compute kernels stay the answer for numeric work.
A module is core WebAssembly at fns/<name>.wasm, at most 8 per bundle, with
no WASI. A file there may instead be a component, which has
both.
- It exports
memory,octo_alloc(len) -> ptrandocto_free(ptr, len). - Every other export of type
(i32, i32) -> i64is a function: it takes its input at(ptr, len)and returns(out_ptr << 32) | out_len. The output starts with a status byte,0for success and1for an error, whose text follows. - Its only import may be
octo.log(ptr, len). A module that imports anything else is refused when it loads. - It has one memory and at most one table.
The guest crate
apps/wasmlab/guest/octosense-guest
writes all of this: export! for fn(&[u8]) -> Result<Vec<u8>, String>,
export_json! for serde types, and log. Build the crate as a cdylib for
wasm32-unknown-unknown. Builds for wasm32-wasip1 and wasm-bindgen output
import functions the shell does not provide, so they do not load; a build for
wasm32-wasip2 is a component, the other kind it runs.
App developers start from App Flow's
Run your own Rust code.
ADR 0014 (Accepted; desktop implementation released in RC4, with working component HTTPS since RC5) adds a second
kind of fns/<name>.wasm: a WebAssembly component, built from an ordinary
Rust crate with cargo build --target wasm32-wasip2. The service tells the
two kinds apart by the file's preamble, and a bundle may carry both.
- No glue. Every function the component exports is
wasm.<function>, named in snake_case:save-htmliswasm.save_html, and either spelling is accepted. Arguments are an object keyed by parameter name, an array in parameter order or, for one parameter, the value itself. A record comes back as an object, an enum as its name,list<u8>as base64 and aresult<T, E>as its value or the request's error.wasm.functionslists every export with its WIT signature; a function that takes or returns a resource is listed as skipped, with the reason. - State. Each component's instance lives on in the app's worker between calls, so it can keep a parsed document or a cache. A trap or the deadline spends it and the next call gets a new one; an update, a changed grant, a withdrawal, the last owning app isolate closing, or the worker's exit (a minute without calls) ends it.
- What it reaches. Clocks and random numbers. Its stdout and stderr become
the app's log lines, and it gets no environment, arguments or stdin. A
component that imports anything beyond
wasi:cli,wasi:clocks,wasi:filesystem,wasi:http,wasi:io,wasi:random,wasi:socketsandoctosense:hostis refused when it loads. - Files. The app's available storage folder, the one its script's
fs.*sees, is the component's/. Account-scoped apps need their active account. Nothing else on the device is visible. Missing storage or a signed-out account leaves no preopen; omitting thestoragedeclaration does not. - The storage quota. A call may add what is left of the app's quota when
the call starts. A write past it fails inside the component:
ftruncatereports a full disk, and an ordinary write an I/O error, because wasi-libc reports any failed stream write as one. The request's error then ends with "a write was refused: the storage budget is used up". Rewriting, truncating and deleting give bytes back, so a component can free space. - The network. Its
wasi:httprequests andwasi:socketsTCP, UDP and DNS operations reach the network as the device can: an app's network declarations (net,network.hosts) are shown when it is installed and not enforced while it runs. The ruling of 8 October 2026 removed the per-app runtime gates; the OS and the host's API surface are the boundary. The pinned Splash runtime also no longer enforces the manifest host list. A component that importswasi:httporwasi:socketsgets 10 s a call instead of 2 s. HTTP timeouts and blocking socket/stream/poll waits end with the call; cancellation is observed at most every 10 ms while waiting in the host. TCP bind/listen/accept and UDP bind/send/receive are supported. Privileged raw IP sockets (SOCK_RAW) are not part of this API. An app shares a 32-handle budget for live TCP/UDP sockets and DNS lookup streams across its components. Each component has at most 512 host resources, including streams and pollables. Closing a handle refunds its slot; a trap or cancellation immediately drops the instance's resources. A cancelled DNS waiter stops promptly. An OS resolver operation already running may finish in the background; it retains its budget slot until then. At most eight native resolvers run across the process, with no waiting queue. - Host services. Through
octosense:host(crates/wasm-host/wit/octosense-host.wit),request(service, args)uses the admitted app's identity, dispatched on the UI thread. Declaration lists do not gate the call. Each service still checks its account, consent, review and resource boundaries. A component never gains a sheet, prompt or trusted user input, so only methods a background surface may call are available.wasm.*is refused, since the app's worker is busy with the call, and the call's deadline bounds the wait.
Socket compatibility: desktop RC6
includes TCP, UDP and DNS support on macOS, Windows and Linux. Desktop RC5
rejects socket imports. This desktop release does not update Android Home.
Socket bundles must keep host-api-v1 and wasm-components-v1 in
requires and declare host_api.required: {"wasm.sockets": 1}. The SDK adds
this automatically when it detects socket imports, and App Hub verifies it
for bundled and shared components. wasm.sockets is a runtime compatibility
marker, not a callable JSON method or permission. Older hosts can still read
the catalog and report this individual app as incompatible. Rust crates must
still build for wasm32-wasip2; native TLS backends, process creation and
threads do not become portable just because sockets work. Rust's WASI UDP
set_read_timeout is unsupported; use nonblocking receive with a deadline,
or rely on the host call deadline.
ADR 0014 records what this costs. On an M-series Mac, the 313 KiB test component compiles in about 40 ms and loads from the cache in about 4 ms; its Markdown function runs about 2.6 times slower than native Rust, close to the same code as a module. In Pulley it runs about 32 times slower than that.
An app can also call a component that App Hub publishes on its own (App Hub
ADR 0003, OctoSense ADR 0014 phase 4). The manifest pins it under
components by alias, id, exact version and BLAKE3 digest, and requires
wasm-shared-components-v1. The wasm service loads each pinned component
beside the app's fns/ and routes its functions as wasm.<alias>.<function>:
with {"as": "md", "id": "org.example.markdown", …}, wasm.md.to_html calls
the component's to-html. The app gets an instance of its own, under its own
account and storage boundaries, as for a component in its fns/. It may carry no fns/ at all and
call only shared components. wasm.functions lists their functions with the
alias, and names the component each comes from ("shared": {"alias", "id", "version", "blake3"}).
The service asks App Hub for the files on every load
(octosense_appstore::components::resolved_in). A system app's are in its
bundle at components/<blake3>.wasm. An installed app's are in the shared,
read-only store at <apps root>/.components/<blake3>.wasm. Each is checked
against the verified catalog, which must still offer it at that version, and
against its digest. Nothing is fetched there: App Hub's installers fetch an
app's components before the app itself. A missing, changed or withdrawn
component stops the app's launch.
wasm_service::tests::a_pinned_shared_component_answers_as_alias_and_function
is a focused test with a stand-in resolver. The separate
real GitHub acceptance
uses actual publisher attestations and an admin-attested private dry-run
catalog, then installs two apps through the real Store and calls their shared
components through Splash tools. Both macOS and OnePlus 6 passed 28/28 native
assertions in the earlier c5f0c5c1 run; their drivers passed 12/12 and 13/13
checks respectively. At final source 8b09e05d, the full macOS desktop passed
11/11 App Hub/component rehearsal checks, and OnePlus 6 again passed 28/28 native
assertions plus 13/13 driver checks. Final evidence
keeps those runs separate. The public catalog and installed Home were unchanged.
The Mac rehearsal used a development binary, not a released archive; neither
run used a live model.
- A store app. App Hub's current gate (app contract 1.11) admits up to
8
.wasmfiles atfns/<name>.wasm(name[a-z0-9_-], at most 64 characters). It distinguishes core modules from components and checks component imports and required ABIs. It verifies exact shared-component versions, digests and publishing proofs. Omittingwasm,storageornetis not an admission refusal. Keep those declarations accurate for store disclosure; the runtime still validates code when it loads. The rules are in App Hub's publishing reference (thefunctionsfinding, required ABIs andwasmusage disclosure). - A system app. It is packed into the shell like any other, by digest,
from the packaging's system-app list.
desktop/system-apps-wasm-lab.jsonandphone/system-apps-wasm-lab.jsonare the standard lists pluswasmlab.
The wasm host service (crates/shell/src/wasm_service.rs) is in every
standard desktop and Home build on macOS, Windows, Linux, Android and
OpenHarmony: the shell's wasm-functions feature, on by default in both
packages (wasm-lab is its former name). iOS leaves the runtime out. A build
without the service answers no service answers "wasm" on this device.
It answers two kinds of request:
wasm.functions: the functions the app's modules export, how each module loaded (compiled, or from the cache, and how long it took) and how each function has run.wasm.<function>: one call. For a module, a string argument goes in as its text and anything else as JSON; JSON output comes back as data, anything else as{"text": …}. A component's arguments and result are typed (Components). The function's own error, a trap or the deadline is the request's error.
The code always comes from the calling app's own admitted, digest-checked bundle, never from an argument, and no app reaches another app's functions. The service rechecks bundle admission and app/profile identity before loading or executing code. Capability declarations do not authorize execution.
Every call to a module gets a fresh instance: memory, globals, tables and log
lines from one call never reach the next, including after a success or the
function's own error. A component keeps one instance between calls instead
(Components). Only compiled code is reused, in the app's worker and in a disk
cache (wasm-cache in the host directory, keyed by the module's SHA-256 and
the engine's compatibility hash). The service checks admission again before a
call runs and before its answer is delivered. An update, a changed grant or a
signed withdrawal discards the answer and the compiled code. Compiling cannot
be interrupted, but an expired or cancelled request never goes on to run.
| Limit | Value |
|---|---|
| One call, start function included | 2 s; 10 s with HTTP/socket imports (checked every 10 ms) |
| Linear memory | 256 MiB |
| Table elements | 16,384 |
| Wasm stack | 512 KiB |
| Live sockets and DNS lookup streams | 32 per app, shared across components |
| Host resource table | 512 entries per component |
| Native DNS work | 8 resolvers per process; slots retained until native completion |
| Module | 8 MiB |
| Input or output of one call | 16 MiB in the runtime; 8 MiB of serialized input in the service |
| Log | 64 lines a call, 1 KiB each |
| Modules per app | 8 |
| Apps running functions at once | 4 workers, one per app |
| Queued requests | 4 per app |
| Buffered input, all apps | 32 MiB |
| One request, queueing and loading included | 10 s |
| An idle worker | exits after 5 s, or after 60 s while it holds a component's instance |
A full queue or no free worker fails the request at once instead of making it wait.
When App Hub installs or updates an app, the shell compiles its functions into
the cache in the background (wasm_service::warm): one app at a time, on a
thread of its own, from the admitted bundle. When that work has finished and
the cache is promptly readable, the app's first call uses the compiled code.
Cache reads wait at most 50 ms, with at most two readers in flight per process.
A slow or unavailable cache falls back to compiling the verified source without
rewriting that cache entry. The request deadline remains 10 s; source compilation
still takes time. See the runtime cache notes.
An app's tools.json may map a tool to one of its functions with
"host_method": "wasm.<function>". The tool must be offered by its app; a
wasm declaration is not an execution grant. Unlike
shared host methods it has no minimum risk and needs no
"private_data": true: a module sees only the arguments it is given, and a
component also its own app's folder, as the app's script does. Neither
reaches shared data. Wasm Lab maps wasmlab.find_slots, wasmlab.rank and wasmlab.diff
to wasm.find_slots, wasm.fuzzy_rank and wasm.text_diff, all read.
| Platform | State |
|---|---|
| macOS | Runs. Validated in a hidden desktop shell (ADR 0011). Wasmtime catches traps with Mach exception ports, not signals. |
| Linux | Runs. The runtime and service tests pass on x86_64, with traps caught by signals, and Wasm Lab ran in a headless desktop (8 October 2026). |
| Android | Runs in Home's default build. Needs libc 0.2.190 or later, which crates/wasm-host requires: with 0.2.189 every trap ended the process. Validated on a Redmi Note 12 (ADR 0011) and by the phone acceptance on a OnePlus 6. The runtime adds about 7.5 MiB of code; compiling a 433 KiB module takes about 0.4 s on a Snapdragon 685, and loading it from the cache 5–11 ms. |
| Windows | Included (ADR 0014). Windows CI at a8e170d4 passed 42/42 runtime tests and checked the shell with the service; see the RC4 source distinction. A desktop GUI run on Windows is unverified. |
| iOS | Not included and not planned for now (ADR 0014). No iOS build with the service has been compiled. |
| OpenHarmony | Included, in Pulley, Wasmtime's interpreter, until OpenHarmony's code-generation policy is known: Cranelift compiles to Pulley's bytecode and nothing runs as native code. Home's OpenHarmony release build compiled with the service (9 October 2026, cargo-makepad makepad ohos … deveco -p octosense-home --release); no device has run it (unverified). Pulley is about 32 times slower than Cranelift (ADR 0014). |
ADR 0011 records earlier cache-open measurements on a managed Mac. The full desktop rehearsal also observed file-open stalls lasting about 10 s; its stack sample identifies the file-open wait, not its cause. The bounded cache reader prevents this optional cache wait from consuming the whole request deadline.
Wasm Lab (os.wasmlab, apps/wasmlab/) is the system app that shows the
service. It is a demo: standard builds do not ship it. Its functions
(apps/wasmlab/guest/functions) are Markdown to HTML (pulldown-cmark), free
slots around busy times, fuzzy ranking (strsim), a line diff (similar), and
rogue, which loops forever, allocates without end, panics or recurses
without end on request. Its screen calls each one through host.request and
shows what came back, the round trip and wasm.functions.
Build a desktop with it, then start it with Wasm Lab open, hidden and driven
over the remote control surface (/help lists the routes; end with /quit):
OCTOSENSE_SYSTEM_APPS=$PWD/desktop/system-apps-wasm-lab.json cargo build --locked -p octosense
MAKEPAD_HIDE_WINDOWS=1 target/debug/octosense --remote=47631 --test-action launch-wasmlabOn the Linux build host (8 October 2026; a default debug build, hidden, under a headless Weston), the module compiled in 98 ms on first use and loaded from the cache in 4 ms after that, also after a restart. Each misbehaving mode ended in an error and the shell kept running: the endless loop at its deadline after 2,039 ms, endless allocation at the memory cap after 340 ms, and the panic and runaway recursion after 37 ms each, as the script timed them.
When it opens, Wasm Lab makes its four calls first and asks for
wasm.functions once they have answered: the service queues at most four
requests per app. wasm.functions counts calls since the app's worker
started; a worker exits after five idle seconds, and the counts start again
with the next one.
The checked-in module rebuilds byte for byte: with rustc 1.97.1,
apps/wasmlab/guest/build.sh writes the same bundle/fns/wasmlab.wasm
(SHA-256 f4a69c32…). It needs the target once:
rustup target add wasm32-unknown-unknown.
cargo test --locked -p octosense-wasm-host
cd phone && cargo test --locked --features mobile-apps -p octosense-shell wasm_service::testscrates/wasm-host/tests/runtime.rsruns a hand-written guest: input and output, guest errors, the deadline, the memory, table and stack caps, traps, the import rule, per-instance state, threads, the size limit, the cache and its concurrent writers, cancellation.crates/wasm-host/tests/guest.rsruns Wasm Lab's module and compares every function with the same Rust run natively, then everyroguemode.crates/wasm-host/tests/component.rsruns four components built fromcrates/wasm-host/tests/component-guest: an unmodified crate (pulldown-cmark) called with JSON, records and snake_case names, state kept on one instance, clocks, randomness and bytes, files only in the app folder (also read-only), the storage budget, the deadline and the memory cap;fetch, whosewasi:httpreaches a local server without a manifest host allowlist, and whose request to a server that never answers ends at the deadline;hostcall, which calls host services through the embedder; and a component importing ordinary sockets.crates/wasm-host/tests/component_sockets.rsruns real TCP/UDP echo, localhost DNS, listener/accept, shared socket limits, close/refund cycles, blocked-read cancellation and UDP deadlines. Unit tests also cover stalled stream destruction and abandoned native resolver work.- The service tests cover the tool mapping, bounded input, a fresh instance per call, revocation after an update, a grant change or a withdrawal, cancellation and the queue bounds, and the app's own functions answering its tools and its script. For a component they cover typed calls, its instance's state, the app's storage folder and its quota, an app without available storage area, a component shipped as a system app through App Hub's admission, network calls without a manifest allowlist, host calls under the app's identity and service boundaries, and an installed app's first call loading from the cache.
cargo run --release -p octosense-wasm-host --example measure_componentprints a component's timings against a module and native Rust.OCTOSENSE_WASM_PULLEY=1 cargo test --locked -p octosense-wasm-host --features pulleyruns the same tests in Pulley, as OpenHarmony runs them;phone.ymlruns it too.
The test components rebuild byte for byte: with rustc 1.97.1,
crates/wasm-host/tests/component-guest/build.sh writes the same
notes.component.wasm (SHA-256 963c965b…), netprobe.component.wasm
(faf1cb5d…), fetch.component.wasm (6eaf6ac8…) and
hostcall.component.wasm (d39f2a8e…). It needs the target once:
rustup target add wasm32-wasip2.
phone.yml runs the first command, and the service's tests as part of Home's
(mobile-apps includes wasm-functions); tools/ci-local.sh --linux-host --offload runs both on the Linux build host. Every CI build of the desktop
and Home includes the service, and tools/check-shell-graph.sh checks that
its runtime is linked exactly on macOS, Linux and Android.
crates/wasm-host/examples/wasm_call.rs calls one function of a .wasm
file with the same runtime and limits as the wasm service, with no shell
and no device. Run from this repository:
cargo run -q -p octosense-wasm-host --example wasm_call -- \
crates/wasm-host/tests/fixtures/notes.component.wasm to-html '"# Hi"'It prints "<h1>Hi</h1>\n". For a component, the arguments are the JSON a
script passes to wasm.<function>: a bare value for one parameter, an object
by name, or an array in order. The answer prints as JSON, and a record prints
as an object. For a core module, the arguments are the function's input as
text: wasm_call apps/wasmlab/bundle/fns/wasmlab.wasm md_to_html '# Hello *core*'
prints <h1>Hello <em>core</em></h1>.
--storage DIR gives a component DIR as its app's storage folder. Its
wasi:http requests go out as in the shell. Its octosense:host calls fail
with no host services in wasm_call: <service> needs a shell. Each call runs
in a fresh instance, where the shell keeps a component's instance between
calls.
tools/fixtures/wasm-phone-lab
holds a synthetic signed store app, org.octosense.samples.wasmprobe, whose
module (state.wasm, from state.wat) remembers its last input if its
instance is ever reused. crates/wasm-phone-smoke packages it in a test APK
that installs it through the normal signed store and calls it through a real
script tool, and tools/test-wasm-phone.py drives that on an assigned
device. Its receipt
records 22 of 22 checks passed on a OnePlus 6 with Android 15, including a
fresh instance after a success, a guest error, a trap and the deadline. Its
source, e67ce63e, records the service and runtime tested at that time. A live
model, performance and a release APK were not part of it. state.wasm
rebuilds byte for byte with the fixture README's encode_phone_fixture
command.
- A Home release with ADR 0014 components and declaration-only behavior. Desktop RC4 includes them; the isolated phone acceptance did not upgrade Home beta.2, which ships core modules only.
- CPU fairness between apps, and a bound on the disk cache, which nothing evicts.
- Compiling system apps' functions ahead: an installed app's are compiled at install, a system app's at its first call.
- OpenHarmony component execution on a device (unverified); Android shared-component execution passed on the OnePlus 6.
- Shared-component publication in the official public catalog. The private, genuinely attested dry-run catalog passed the development-host and final Mac RC4 archive flows; its synthetic entries were not added to the public catalog.
- Bytes are slow through JSON: a 1 MiB
list<u8>costs about 18 ms there and back, as base64.
Two engines of ADR 0013 host their own WebAssembly plug-ins, in wasmi, a pure-Rust interpreter, each in a registry that belongs to the process, not to a call:
- photocraft, the raster engine behind the
photoservice (apps/photo/host-service): filter plug-ins with no imports, 32 MiB per module, 512 MiB of memory per instance, 50 million instructions per call and 60 s per run. - vectorcraft, the vector engine behind the
vectorservice (apps/vector/host-service): object filters and live effects with no imports, a fuel budget, a memory cap and a fresh instance per run.
effectcraft, behind effect, has WebAssembly plug-ins too, behind an optional
feature; OctoSense does not link its plug-in crate. vectorcraft's desktop UI
crate has a second install command, ui.installPlugin; OctoSense does not
link that crate either.
Closed since #398. photo.run refuses every plugin.* command before the
engine sees it, and photo.commands leaves them out. Before #398 a caller
could install a plug-in from base64 data; it went into photocraft's
process-wide registry, outlived the call and served every later caller, under
limits far above the wasm service's. A scratch program that calls the
service as a script's host.request does showed both, on the Linux build host
(8 October 2026). Before #398, os.photos installed photocraft's example
plug-in, the next call listed it, and another system app, os.notes, ran it
on a document. With #398, each of those calls was refused. Since the
command doors (#418, ADR 0013) the refusal is the allowlist gate's, which
classes every plugin.* id code:
photo.run: `plugin.install` is classed code: it installs or runs code, or runs other commands, so the door never runs it.
Closed in vector by #405. vector.run refused files, documents, the
app.* group and path-like arguments, but not plugin.*, and vectorcraft's
engine installs a plug-in from base64 dataBase64. The same scratch program
showed it on main before #405: os.notes installed vectorcraft's example
plug-in, the next call listed it, another system app (os.maps) saw it, and
vector.commands offered plugin.install. Now vector.run refuses every
plugin.* id before the engine sees it (since #418 by the allowlist gate:
vector.run: `plugin.install` is classed code: it installs or runs code, or runs other commands, so the door never runs it),
and vector.commands leaves them out. An effect plug-in named to a built-in
effect command (effect.apply {effect: "plugin.<id>"}) is refused too.
Both engines still link wasmi, and both services answer system apps (os.*)
only.
The UI thread. The photo service, like the other engine services, does
its work inside the request. App Hub dispatches a script's host.request on
the UI thread, and calls the service while it holds the lock on the service
registry (services::dispatch). So a long photo.run holds up the UI and
every other app's requests until it returns
(#399).
makepad's script engine can compile a pure-math Splash function, such as a
signed distance field, into a WebAssembly module it generates itself, and run
it in makepad-stitch, its own interpreter, as the reference that matches the
Splash interpreter bit for bit
(.sources/makepad/platform/script/src/math_aot/). No app supplies that
module. In OctoSense only makepad's CSG library would call it, and OctoSense
does not link that library, so the code is present and unused. ADR 0011
measured stitch for apps' functions (2,942 CoreMark against Wasmtime's
44,534) and did not choose it.
makepad's compute kernels also have a WebAssembly backend, but it runs only
when makepad itself is compiled for wasm32 (a browser). Native builds use
their native backends.
The shell keeps the wasm32 paths of makepad's window manager, its "web
superbuild": no child processes (crates/shell/src/host.rs), every native app
hosted in process (tools/native_apps.py gives each app a wasm hosting of
module or none in crates/shell/src/native_apps.rs, and refuses
process there), and in-process service links for the assistant
(crates/shell/src/pane_links.rs). App Hub reports such a host's platform as
web.
No build, CI job or release produces it, and it does not compile. This check on the browser target fails:
cargo check --locked --keep-going --target wasm32-unknown-unknown -p octosense-shell --no-default-featuresgetrandom 0.2 and 0.3, uuid, fs2, ring and aws-lc-sys fail to build for that
target. Even without default features the shell links octosense-ai-host and
App Hub's crates, which bring in most of them (credential encryption, sigstore
verification, TLS, file locking); the shell's own uuid lacks a randomness
source there. Treat these paths as unmaintained.
- ADR 0011: the decision, the runtimes measured and the phone measurements.
- ADR 0012: host API discovery adds no WebAssembly loading.
- ADR 0013: the engines behind
photoand the other craft services. - App Hub's publishing reference:
wasmusage disclosure, required ABIs, thefunctionsfinding andwasm.<function>tools. Current 1.11 policy does not require a matching capability-family declaration to admit or execute a public call.