Skip to content

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.

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 Unsafe block 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.
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))

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.

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)

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)

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.

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.

  • 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.
  • 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.