Portable Runtime & Execution
Arcana’s compile-time guarantees are paired with a runtime-side sandbox: even bypassed compile-time assumptions meet a second boundary at execution. From one Arcana source, the toolchain emits to WebAssembly (the canonical target), web (HTMX-style islands + a TypeScript backend), iOS Swift, and Android Kotlin.
This is the pillar that makes Arcana’s safety story defense-in-depth — compile-time enforcement and runtime sandboxing, both checking the same effect contract.
WebAssembly as the compilation target
Section titled “WebAssembly as the compilation target”Arcana compiles to WebAssembly. WASM is the canonical compilation target for the language for three reasons:
- Portability. WASM runs on any host that embeds a WASM runtime — server (Wasmtime, Spin), browser, mobile, edge. The same compiled artifact is consumable across deployment targets without re-emission.
- A second safety boundary. WASM’s own sandbox model — explicit capability imports, no ambient I/O, deterministic execution semantics — is a structural complement to Arcana’s compile-time enforcement. If a compile-time assumption is bypassed somehow (an
Unsafeblock doing something the type system couldn’t see), the runtime sandbox still constrains what the binary can actually do at execution time. - AI-target ergonomics. WASM’s bounded resource model and explicit imports make AI-generated programs easier to audit at deployment — there’s no hidden global state for the program to depend on, and the capability surface is enumerated at the boundary rather than implied.
Server-side runtime: custom wasmtime host shim today, Spin as recommended target shape
Section titled “Server-side runtime: custom wasmtime host shim today, Spin as recommended target shape”For server-side execution, the shipped implementation is a custom Wasmtime-based host shim (arcana-runtime for the wasmtime + SQLite embedding core; arcana-serve for the HTTP shim that exposes WASM exports). Spin — a Wasmtime-based WASM runtime designed for small, stateless services with explicit capability declarations — is the recommended deployment target shape for the same Arcana-emitted WASM modules, because Spin’s capability model aligns with Arcana’s deployment contract (capabilities declared at the boundary, not implied by ambient state). At present, Spin is design intent for deployment; the shipped runtime integration is the custom wasmtime shim.
What this gives the safety story in practice:
Below is search_posts from tests/rpc-fixtures/blog.arcana — verified canonical, single {Database} effect. The compile-time effect row IS the runtime capability budget: the sandbox grants exactly the declared effects, no more.
;; pub fn search_posts(query: String) -> {Database} Int(dc-fn :fn (fn-decl :body (block :stmts () :expr (ex-call :args ( (arg-positional :expr (ex-lit :value (lit-string :value "SELECT id, title, body, published FROM posts WHERE title LIKE ?"))) (arg-positional :expr (ex-ident :name "query"))) :fn (ex-ident :name "db_query"))) :contracts () :effects (Database) :name "search_posts" :params ( (param :modifier none :name "query" :type (ty-named :path "String"))) :ret (ty-named :path "Int") :tparams () :vis pub))pub fn search_posts(query: String) -> {Database} Int { db_query("SELECT id, title, body, published FROM posts WHERE title LIKE ?", query)}Compile-time: the declared {Database} effect is the contract — the body may read or write the database, nothing else. Run-time (Wasmtime / Spin sandbox): the deployed component is granted exactly Database capability; anything else attempted at runtime (file system, environment vars, network egress, process spawn) the host runtime refuses. The compile-time check and the runtime sandbox enforce the same contract — once at build time, once at execution time.
{Database} can be parameterized as Database(local) (SQLite, synchronous), Database(server) (Postgres, async — requires await), or Database(synced) (local + server with background sync) at v0.7+. The example above uses the unparameterized form; the parameterized variants compose the same way in the effect row.
Honestly named: the host-shim layer is Rust
Section titled “Honestly named: the host-shim layer is Rust”The piece that sits between a deployed Arcana WASM module and the host process — arcana-runtime (the wasmtime + SQLite embedding core) and arcana-serve (the HTTP shim that exposes WASM exports over POST /_rpc/v1/{fn}) — is written in Rust. Customer-facing surface remains the Arcana program and the Wasmtime/Spin sandbox; the Rust crates are the host-integration implementation. See Honest Scope for the full per-mechanism status.
Multi-target codegen: web + native mobile
Section titled “Multi-target codegen: web + native mobile”The same Arcana source compiles to multiple frontend / mobile targets:
- Web: HTMX-style islands + a TypeScript backend. The compiler emits the client-side islands and the server-side handlers from one source.
- iOS: Swift output, integrated with platform UI primitives.
- Android: Kotlin output, integrated with platform UI primitives.
Two verified fixtures from the Arcana repo demonstrate the multi-target shape. First, a page handler — dc-page :name "Home" :route "/users/:id" from tests/v175-c2/fixtures/dc-page.arcana:
;; v1.7.5 C2 fixture: dc-page declaration lowering.(dc-page :body (block :stmts () :expr (ex-lit :value (lit-int :value "0"))) :name "Home" :params ( (param :modifier none :name "id" :type (ty-named :path "Int"))) :route "/users/:id" :vis pub)pub page Home(id: Int) at "/users/:id" { 0}A dc-page carries a route, a parameter list, a body, and a return type. The compile-time codegen produces the per-target route handler from this single declaration — HTMX-style island + TypeScript handler for web; SwiftUI view + action handler for iOS; Jetpack Compose composable + action handler for Android.
Second, a reusable component — dc-component :name "Greeting" from tests/v175-c2/fixtures/dc-component.arcana:
;; v1.7.5 C2 fixture: dc-component declaration lowering.(dc-component :body (block :stmts () :expr (ex-ident :name "label")) :name "Greeting" :params ( (param :modifier none :name "label" :type (ty-named :path "String"))) :tparams () :vis pub)pub component Greeting(label: String) { label}A dc-component is a reusable UI primitive that the codegen emits as platform-native UI for each target. The custom UI primitive admission-controlled discipline (must implement all platforms or none) prevents single-target “drift” from showing up at deploy time as a missing platform.
Cross-platform UI primitives are declared once. The codegen layer translates to each target’s native idioms (SwiftUI on iOS, Jetpack Compose on Android, HTMX/web on browser). A custom UI primitive must implement all platforms — an admission-controlled discipline that prevents single-target “drift” from showing up at deploy time as a missing platform.
Honest scope on the multi-target story
Section titled “Honest scope on the multi-target story”Codegen output is production-quality for current targets. WebAssembly compilation is verified end-to-end; mobile codegen (iOS Swift, Android Kotlin) closed its last emitter bugs in the most recent sub-version line. If you are generating code into Arcana for these targets, the codegen output is reliable.
Verification-harness parity — the equal-rigor verification of every codegen target through the self-hosted compiler — is the in-progress piece. See Self-Hosting & Determinism for the journey framing; the short version is that codegen output works today, while the equal-verification path across targets is the migration in progress.
This distinction matters because “multi-target codegen is in progress” can be misread as “the output might be wrong.” The output is checked today; what’s still being equalized is the path by which it’s checked across targets.
On the roadmap
Section titled “On the roadmap”- RPC cross-boundary type safety. When client-side islands talk to server-side handlers, the types should flow across the boundary so a mismatched payload is a compile error, not a runtime mystery. The current implementation provides HTTP+JSON RPC with marshal-in-guest per-endpoint wrappers; type-safety propagation across the full client/server boundary is a later-release item.
- WASM Component Model integration. Newer WASM standards (component model, interface types) land in successive sub-versions as the WASM ecosystem stabilizes them.
- Additional runtime targets beyond Spin (other Wasmtime-compatible hosts, edge-compute runtimes) — supported in principle today; canonically tested against Spin first.
What this pillar gives every other pillar
Section titled “What this pillar gives every other pillar”- Compile-Time Safety’s compile-time guarantees are paired with this pillar’s runtime-side guarantees — defense-in-depth at execution time as well as at build time.
- Effect Contracts & Capability Discipline carries through to deployment: the same admission-controlled effect vocabulary that the compiler checks is what the Spin sandbox enforces at execution time, via the deploy-artifact’s capability manifest.
- Self-Hosting & Determinism is the journey underlying this pillar — the compiler that emits these targets is itself self-hosted, and its evolution is honestly documented.