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)
| Feature | wasmtime-py ✅ | wasmer-python | wasm3-py |
|---|---|---|---|
| Performance | 88% native (JIT) | 80% native (JIT) | 65% native (interpreter) |
| Cold Start | 5-15ms | 5-15ms | <5ms |
| Warm Start | <1ms (cached) | <1ms (cached) | <1ms |
| Security Testing | Rigorous (Bytecode Alliance) | Moderate | Good |
| WASI Support | 0.2 + 0.3 (async) | 0.2 | Limited |
| Component Model | Full support | Partial | None |
| Memory Overhead | 10-50MB | 18MB | 10MB |
| Binary Size | ~10MB | ~8MB | ~64KB |
| Ecosystem | Bytecode Alliance | Wasmer Inc. | Independent |
| Use Case | Production | Cloud/edge | Embedded/IoT |
| Recommendation | ✅ USE | Cloud only | Mobile 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.wasmer5.0 with Wasmi interpreter is the correct choice for iOS.
| Feature | wasmer 5.0+ ✅ | wasmtime | wasm3 |
|---|---|---|---|
| Desktop performance | 80-88% native (Cranelift JIT) | 88% native (JIT) | 65% native |
| iOS performance | 50-60% native (Wasmi interpreter) | ❌ JIT blocked by Apple | 65% native |
| Android performance | 80-88% native (Cranelift JIT) | 88% native | 65% native |
| Unified API | ✅ One crate, pluggable backend | ❌ No iOS path | ❌ Different API |
| Async Support | ✅ Yes | ✅ Tokio integration | ❌ Sync only |
| WASI Implementation | Custom | Tokio + cap-std | Limited |
| Component Model | Partial | First-class | None |
| Industry Usage | Docker Desktop, WasmEdge | Shopify, Cloudflare, Fastly | Embedded systems |
| Binary Size | ~12MB | ~15MB | ~200KB |
| iOS App Store | ✅ Approved | ❌ JIT rejected | ✅ Approved |
| Recommendation | ✅ USE | ❌ 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
| Platform | Backend | Speed |
|---|---|---|
| macOS / Windows / Linux | wasmer Cranelift JIT | 80-88% native |
| Android | wasmer Cranelift JIT | 80-88% native |
| iOS | wasmer Wasmi interpreter | 50-60% native |
| iOS (future option) | wasm3 | 65% native, sync-only |
Performance Benchmarks (2026)
| Metric | Wasmtime | Wasmer | wasm3 |
|---|---|---|---|
| Fibonacci (1000) | 88% native speed | 80% native | 65% native |
| Cold Start | 5-15ms | 5-15ms | <5ms |
| Memory (idle) | 10-50MB | 18MB | 10MB |
| Compilation | 5-15ms (cache this!) | 5-15ms | Instant (interpreter) |
| Instantiation | <1ms | <1ms | <1ms |
Source: wasmRuntime.com 2026 Benchmarks
WASI Version Comparison
| Feature | WASI 0.1 (Legacy) | WASI 0.2 | WASI 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 Feature | WASM | JavaScript (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
| Language | Toolchain | SDK Maturity | Binary Size | Recommendation |
|---|---|---|---|---|
| Rust | cargo + wasm32-wasi | ✅ Excellent | ~200KB (optimized) | ✅ PRIMARY |
| AssemblyScript | asc | ✅ Good | ~100KB | ✅ Secondary |
| JavaScript | Javy | ⚠️ Experimental | ~500KB (includes runtime) | ⚠️ Future |
| Go | TinyGo | ✅ Good | ~300KB | ✅ Alternative |
| C/C++ | clang + wasi-sdk | ✅ Mature | ~150KB | ✅ Alternative |
| Python | py2wasm | ⚠️ Experimental | ~5MB (includes CPython) | ❌ Not recommended |
Verdict: Rust for primary SDK, AssemblyScript for TypeScript developers.
Distribution Methods
| Method | Pros | Cons | Recommendation |
|---|---|---|---|
| OCI Registry | Versioned, signed, CDN, immutable | Requires registry infra | ✅ USE |
| GitHub Releases | Simple, free | No versioning API, manual signing | ⚠️ Fallback |
| NPM | Familiar to JS devs | Not designed for binaries | ❌ No |
| Direct Download | Simple | No versioning, no signing | ❌ No |
Verdict: OCI Registry (GitHub Container Registry) for production distribution.
Real-World Architecture Comparison
| Platform | Extension Type | Runtime | Security | Key Learning |
|---|---|---|---|---|
| VS Code | WASM + TS bindings | QuickJS in WASM | Sandbox | Use SharedArrayBuffer for sync API |
| Figma | QuickJS in WASM | Browser WASM | Double sandbox | WASM-in-WASM = extreme isolation |
| Shopify | Rust → WASM | Wasmtime (server) | NaN-boxed I/O | Module linking reduces size |
| Cloudflare | Any → WASM | V8 isolates | Streaming compile | Optimize for size (<1MB limit) |
| Morphee | Rust → WASM | wasmtime-py + wasmer 5.0 | Capability-based | Same 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
| Step | Size | Reduction |
|---|---|---|
| Debug build | 2.5MB | Baseline |
Release build (--release) | 500KB | 80% smaller |
Strip symbols (wasm-strip) | 400KB | 84% smaller |
Optimize (wasm-opt -Oz) | 200KB | 92% smaller |
| Gzip compression | 80KB | 97% 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
| Resource | Limit | Rationale |
|---|---|---|
| Memory | 128-256MB | Enough for HTTP/JSON processing |
| CPU Time | 30-60 seconds | Prevent infinite loops |
| HTTP Requests | 100-500/min | Rate limiting |
| File Size | 10MB | Prevent disk exhaustion |
| Network Bandwidth | 100MB/min | Prevent abuse |
Per-Extension Tuning: High-volume extensions (e.g., email sync) get higher limits via manifest.
Code Signing Requirements
| Algorithm | Hash | Signature | Key Size |
|---|---|---|---|
| RSA-PSS ✅ | SHA-256 | PSS padding | 2048-bit |
| RSA-PKCS1 | SHA-256 | PKCS#1 padding | 2048-bit |
| ECDSA | SHA-256 | P-256 curve | 256-bit |
Verdict: RSA-PSS with SHA-256 (industry standard, widely supported).
Verification Flow:
- Hash WASM binary (SHA-256)
- Verify signature with developer's public key
- Check developer key against trusted registry
- Reject if signature invalid or key revoked
Async Support Comparison
| WASM Runtime | Async Model | Integration | iOS compatible |
|---|---|---|---|
| wasmtime-py | ✅ Native (WASI 0.3) | Python asyncio | N/A (server-side) |
| wasmer (Rust) | ✅ Yes | Tokio compatible | ✅ Yes (Wasmi mode) |
| wasmtime (Rust) | ✅ Native (WASI 0.3) | Tokio | ❌ JIT blocked |
| wasm3 | ❌ Sync only | Blocking | ✅ 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)
| Approach | Development Cost | Runtime Cost | Maintenance Cost |
|---|---|---|---|
| WASM Extensions | High (new system) | Low (efficient) | Low (sandboxed) |
| JS Extensions | Medium (iframe) | Medium (overhead) | High (security issues) |
| Native Plugins | Low (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)
| Integration | Complexity | Estimated Time | Priority |
|---|---|---|---|
| JIRA | Medium | 1 week | High (reference impl) |
| Slack | Medium | 1 week | High (popular) |
| Gmail | High (OAuth) | 2 weeks | Medium |
| Calendar | High (OAuth) | 2 weeks | Medium |
| GitHub | Medium | 1 week | High (dev tool) |
| Notion | Medium | 1 week | High (productivity) |
| Linear | Low | 3 days | Medium |
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:
| Runtime | Technology | Use Case |
|---|---|---|
| WasmRuntime | wasmer 5.0 (Cranelift/Wasmi) | Backend extensions: JIRA, GitHub, Notion, Slack... |
| JSRuntime | Browser/Tauri webview JS | Canvas components, dynamic UI, frontend integrations |
| PythonRuntime | (future) sandboxed Python | Dynamic 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
- Use wasmtime-py for Python backend (best security, WASI 0.3, unchanged)
- Use wasmer 5.0 for Tauri Rust (unified API — Cranelift desktop/Android, Wasmi iOS)
- Use WASI 0.3 (async support, component model)
- Cache compiled modules (15x performance improvement)
- Fine-grained permissions (security > simplicity)
- Sign all extensions (code signing mandatory)
- OCI registry distribution (versioning, immutability)
- Rust SDK first (best toolchain, smallest binaries)
- Resource limits (memory, CPU, rate limiting)
- Audit logging (all extension actions logged)
- AOT compilation (production performance)
❌ DON'T
- Don't use JavaScript extensions (sandboxing inadequate)
- Don't skip code signing (security critical)
- Don't trust extension manifests (verify binaries)
- Don't allow unlimited resources (abuse prevention)
- Don't expose raw database access (use safe APIs)
- Don't log secrets (vault keys, tokens)
- Don't auto-update MAJOR versions (breaking changes)
- Don't skip WASI (capability-based security essential)
- Don't use coarse permissions (principle of least privilege)
- 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
- Full Research: 2026-02-16-wasm-extension-research.md
- Quick Reference: WASM_QUICK_REFERENCE.md
- Implementation Plan: WASM_IMPLEMENTATION_NEXT_STEPS.md
- Roadmap: ROADMAP.md (Phase 3l archived, see current V1.2 WASM Extension layer)