Skip to main content

WASM Extension System — Decision Matrix

ARCHIVE — This document is historical reference only. It may contain outdated information. See docs/status.md for current project state.

Date: 2026-02-16 (updated 2026-02-20: iOS JIT constraint + wasmer + BaseMorphRuntime concept) Purpose: Quick reference for technical decisions


Runtime Comparison (Python)

Featurewasmtime-py ✅wasmer-pythonwasm3-py
Performance88% native (JIT)80% native (JIT)65% native (interpreter)
Cold Start5-15ms5-15ms<5ms
Warm Start<1ms (cached)<1ms (cached)<1ms
Security TestingRigorous (Bytecode Alliance)ModerateGood
WASI Support0.2 + 0.3 (async)0.2Limited
Component ModelFull supportPartialNone
Memory Overhead10-50MB18MB10MB
Binary Size~10MB~8MB~64KB
EcosystemBytecode AllianceWasmer Inc.Independent
Use CaseProductionCloud/edgeEmbedded/IoT
RecommendationUSECloud onlyMobile fallback

Verdict: wasmtime-py for Morphee Python backend. Best security, performance, and WASI support.


Runtime Comparison (Rust — Tauri)

Critical iOS constraint: iOS prohibits JIT compilation (App Store Review Guidelines §2.5.2). wasmtime's JIT mode is completely blocked on iOS. wasmer 5.0 with Wasmi interpreter is the correct choice for iOS.

Featurewasmer 5.0+ ✅wasmtimewasm3
Desktop performance80-88% native (Cranelift JIT)88% native (JIT)65% native
iOS performance50-60% native (Wasmi interpreter)❌ JIT blocked by Apple65% native
Android performance80-88% native (Cranelift JIT)88% native65% native
Unified API✅ One crate, pluggable backend❌ No iOS path❌ Different API
Async Support✅ Yes✅ Tokio integration❌ Sync only
WASI ImplementationCustomTokio + cap-stdLimited
Component ModelPartialFirst-classNone
Industry UsageDocker Desktop, WasmEdgeShopify, Cloudflare, FastlyEmbedded systems
Binary Size~12MB~15MB~200KB
iOS App Store✅ Approved❌ JIT rejected✅ Approved
RecommendationUSE❌ iOS blocked🔲 Future option

Verdict: wasmer 5.0 for all Tauri Rust targets. Single crate, pluggable backend (Cranelift on desktop/Android, Wasmi on iOS). wasm3 tracked as future ultra-minimal option.

Platform Summary

PlatformBackendSpeed
macOS / Windows / Linuxwasmer Cranelift JIT80-88% native
Androidwasmer Cranelift JIT80-88% native
iOSwasmer Wasmi interpreter50-60% native
iOS (future option)wasm365% native, sync-only

Performance Benchmarks (2026)

MetricWasmtimeWasmerwasm3
Fibonacci (1000)88% native speed80% native65% native
Cold Start5-15ms5-15ms<5ms
Memory (idle)10-50MB18MB10MB
Compilation5-15ms (cache this!)5-15msInstant (interpreter)
Instantiation<1ms<1ms<1ms

Source: wasmRuntime.com 2026 Benchmarks


WASI Version Comparison

FeatureWASI 0.1 (Legacy)WASI 0.2WASI 0.3 (Feb 2026) ✅
Filesystem✅ Yes✅ Yes✅ Yes
Networking❌ No✅ TCP/UDP✅ TCP/UDP + HTTP
Async/Await❌ No⚠️ Experimental✅ Native support
Resource Types❌ No⚠️ Basic✅ Borrow/own semantics
Zero-Copy I/O❌ No⚠️ Limited✅ High-performance streaming
Component Model❌ No⚠️ Experimental✅ Integrated

Verdict: Use WASI 0.3 (releasing Feb 2026). Async support is critical for HTTP extensions.


Security Comparison

Security FeatureWASMJavaScript (iframe)Native Plugin
Memory Safety✅ Guaranteed⚠️ Runtime errors❌ Unsafe
Sandboxing✅ True sandbox⚠️ Can be escaped❌ Full access
Permission Model✅ Capability-based⚠️ Web APIs❌ OS-level
Code Signing✅ Easy (hash binary)⚠️ Subresource integrity⚠️ Code signing
Audit Trail✅ All imports logged⚠️ Limited❌ Opaque
Resource Limits✅ Memory/CPU enforceable⚠️ Hard to enforce❌ OS-level only

Verdict: WASM provides true sandboxing impossible with JS or native plugins.


Developer Experience

LanguageToolchainSDK MaturityBinary SizeRecommendation
Rustcargo + wasm32-wasi✅ Excellent~200KB (optimized)PRIMARY
AssemblyScriptasc✅ Good~100KB✅ Secondary
JavaScriptJavy⚠️ Experimental~500KB (includes runtime)⚠️ Future
GoTinyGo✅ Good~300KB✅ Alternative
C/C++clang + wasi-sdk✅ Mature~150KB✅ Alternative
Pythonpy2wasm⚠️ Experimental~5MB (includes CPython)❌ Not recommended

Verdict: Rust for primary SDK, AssemblyScript for TypeScript developers.


Distribution Methods

MethodProsConsRecommendation
OCI RegistryVersioned, signed, CDN, immutableRequires registry infraUSE
GitHub ReleasesSimple, freeNo versioning API, manual signing⚠️ Fallback
NPMFamiliar to JS devsNot designed for binaries❌ No
Direct DownloadSimpleNo versioning, no signing❌ No

Verdict: OCI Registry (GitHub Container Registry) for production distribution.


Real-World Architecture Comparison

PlatformExtension TypeRuntimeSecurityKey Learning
VS CodeWASM + TS bindingsQuickJS in WASMSandboxUse SharedArrayBuffer for sync API
FigmaQuickJS in WASMBrowser WASMDouble sandboxWASM-in-WASM = extreme isolation
ShopifyRust → WASMWasmtime (server)NaN-boxed I/OModule linking reduces size
CloudflareAny → WASMV8 isolatesStreaming compileOptimize for size (<1MB limit)
MorpheeRust → WASMwasmtime-py + wasmer 5.0Capability-basedSame binary on Python + Rust; wasmer solves iOS JIT ban

Permission Model Design

Option A: Coarse-Grained (Simple)

permissions:
- network
- storage
- tasks

Pros: Easy for users to understand Cons: Extensions get more access than needed

Option B: Fine-Grained (Secure) ✅

permissions:
- http:read # GET/HEAD only
- http:write # POST/PUT/DELETE
- vault:read # Read secrets
- vault:write # Write secrets
- event:emit # Emit events
- data:write # Create/update tasks

Pros: Principle of least privilege Cons: More complex permission dialog

Verdict: Fine-grained (Option B). Security > simplicity for extension system.


Binary Size Optimization

StepSizeReduction
Debug build2.5MBBaseline
Release build (--release)500KB80% smaller
Strip symbols (wasm-strip)400KB84% smaller
Optimize (wasm-opt -Oz)200KB92% smaller
Gzip compression80KB97% smaller

Recommended Build Command:

cargo build --target wasm32-wasi --release
wasm-strip target/wasm32-wasi/release/extension.wasm
wasm-opt -Oz target/wasm32-wasi/release/extension.wasm -o extension.wasm

Module Caching Strategy

Without Caching (Slow)

# Every request: compile module (5-15ms)
module = Module.from_file(engine, "extension.wasm")
instance = Instance(store, module, [])

Cost: 5-15ms per request

With Caching (Fast) ✅

# Once at startup: compile and serialize
module = Module.from_file(engine, "extension.wasm")
compiled_bytes = module.serialize()

# Every request: deserialize (instant)
module = Module.deserialize(engine, compiled_bytes)
instance = Instance(store, module, [])

Cost: <1ms per request (15x faster)

Verdict: Always cache compiled modules. Serialize to disk or memory.


Resource Limit Recommendations

ResourceLimitRationale
Memory128-256MBEnough for HTTP/JSON processing
CPU Time30-60 secondsPrevent infinite loops
HTTP Requests100-500/minRate limiting
File Size10MBPrevent disk exhaustion
Network Bandwidth100MB/minPrevent abuse

Per-Extension Tuning: High-volume extensions (e.g., email sync) get higher limits via manifest.


Code Signing Requirements

AlgorithmHashSignatureKey Size
RSA-PSSSHA-256PSS padding2048-bit
RSA-PKCS1SHA-256PKCS#1 padding2048-bit
ECDSASHA-256P-256 curve256-bit

Verdict: RSA-PSS with SHA-256 (industry standard, widely supported).

Verification Flow:

  1. Hash WASM binary (SHA-256)
  2. Verify signature with developer's public key
  3. Check developer key against trusted registry
  4. Reject if signature invalid or key revoked

Async Support Comparison

WASM RuntimeAsync ModelIntegrationiOS compatible
wasmtime-py✅ Native (WASI 0.3)Python asyncioN/A (server-side)
wasmer (Rust)✅ YesTokio compatible✅ Yes (Wasmi mode)
wasmtime (Rust)✅ Native (WASI 0.3)Tokio❌ JIT blocked
wasm3❌ Sync onlyBlocking✅ Yes

Why Async Matters: Extensions make HTTP requests, database queries, etc. Blocking execution = poor performance.

Verdict: wasmtime-py for Python backend (WASI 0.3 async), wasmer for Tauri Rust (async-compatible, iOS-safe).


Cost Comparison (Estimated)

ApproachDevelopment CostRuntime CostMaintenance Cost
WASM ExtensionsHigh (new system)Low (efficient)Low (sandboxed)
JS ExtensionsMedium (iframe)Medium (overhead)High (security issues)
Native PluginsLow (existing APIs)Low (native)Very High (security, compatibility)

Verdict: WASM has higher upfront cost, lower long-term cost (security, performance, portability).


Migration Path (Existing Python Integrations → WASM)

IntegrationComplexityEstimated TimePriority
JIRAMedium1 weekHigh (reference impl)
SlackMedium1 weekHigh (popular)
GmailHigh (OAuth)2 weeksMedium
CalendarHigh (OAuth)2 weeksMedium
GitHubMedium1 weekHigh (dev tool)
NotionMedium1 weekHigh (productivity)
LinearLow3 daysMedium

Strategy: Start with JIRA (reference implementation), then Slack (most popular), then others.


Runtime Architecture (BaseMorphRuntime)

The WASM system introduces a BaseMorphRuntime abstraction — execution runtimes that back dynamic Integrations:

RuntimeTechnologyUse Case
WasmRuntimewasmer 5.0 (Cranelift/Wasmi)Backend extensions: JIRA, GitHub, Notion, Slack...
JSRuntimeBrowser/Tauri webview JSCanvas components, dynamic UI, frontend integrations
PythonRuntime(future) sandboxed PythonDynamic Python scripts at runtime

All runtimes expose the same BaseInterface contract to InterfaceManager — installed extensions are indistinguishable from built-in Python integrations from the orchestrator's perspective.


Final Recommendations

✅ DO

  1. Use wasmtime-py for Python backend (best security, WASI 0.3, unchanged)
  2. Use wasmer 5.0 for Tauri Rust (unified API — Cranelift desktop/Android, Wasmi iOS)
  3. Use WASI 0.3 (async support, component model)
  4. Cache compiled modules (15x performance improvement)
  5. Fine-grained permissions (security > simplicity)
  6. Sign all extensions (code signing mandatory)
  7. OCI registry distribution (versioning, immutability)
  8. Rust SDK first (best toolchain, smallest binaries)
  9. Resource limits (memory, CPU, rate limiting)
  10. Audit logging (all extension actions logged)
  11. AOT compilation (production performance)

❌ DON'T

  1. Don't use JavaScript extensions (sandboxing inadequate)
  2. Don't skip code signing (security critical)
  3. Don't trust extension manifests (verify binaries)
  4. Don't allow unlimited resources (abuse prevention)
  5. Don't expose raw database access (use safe APIs)
  6. Don't log secrets (vault keys, tokens)
  7. Don't auto-update MAJOR versions (breaking changes)
  8. Don't skip WASI (capability-based security essential)
  9. Don't use coarse permissions (principle of least privilege)
  10. Don't forget binary optimization (wasm-opt -Oz)

Key Metrics to Track

Performance:

  • Extension compilation time (target: <15ms)
  • Extension instantiation time (target: <1ms)
  • Extension execution time (target: <100ms for simple actions)
  • Memory usage per extension (target: <128MB)

Security:

  • Permission violations (target: 0)
  • Resource limit traps (log, don't crash)
  • Unsigned extension attempts (target: 0 allowed)
  • Audit log completeness (target: 100%)

Developer Experience:

  • Time to first extension (target: <30 min)
  • SDK documentation coverage (target: 100%)
  • Example extension count (target: 10+)
  • Developer support response time (target: <24h)

Adoption:

  • Extensions in marketplace (target: 50+ in 6 months)
  • Active users with extensions (target: 50% within 1 year)
  • Average extensions per user (target: 3-5)
  • Extension install success rate (target: >95%)

References