ADR-008: WASM Component Model for Future Plugins
Status: Proposed (Roadmap) Date: 2026-01-15
Context
As SiliconGhetto matures, we want to support third-party plugins and mods — custom components, systems, and behaviors that extend a game without modifying its core code. The WASM Component Model provides a standardized way to compose independently-built WASM modules with well-defined interfaces.
Options Considered
1. WASM Component Model (chosen for future)
- W3C standard for composable WASM modules
- WIT (WebAssembly Interface Types) defines typed interfaces between components
- Strong sandboxing — components cannot access each other’s memory
- Language-agnostic — plugins can be written in any language that compiles to WASM
2. Dynamic linking (WASM shared modules)
- Share memory between modules
- No standardized interface types
- Security concerns — shared memory allows data leaks between modules
- Limited browser support
3. Scripting language (Lua, JavaScript)
- Familiar to game modders
- Performance overhead from interpretation
- Adds a language runtime to the WASM binary
- Type safety depends on the scripting language
4. Static plugin compilation
- Plugins compiled into the main binary
- No runtime overhead
- Requires recompilation for any plugin change
- Not suitable for user-generated content
Decision
Plan for the WASM Component Model as the plugin/mod system, targeting implementation in v0.5+. Current engine design should avoid patterns that would prevent future component model adoption (e.g., don’t rely on shared linear memory between modules).
Consequences
Positive
- Plugins are fully sandboxed — a buggy plugin cannot crash the engine
- WIT interfaces provide type-safe boundaries
- Plugins can be written in Rust, C, AssemblyScript, or any language with WASM Component Model support
- Hot-reloading plugins becomes possible (swap one component, keep others)
- Security model aligns with platform goals (untrusted game code)
Negative
- WASM Component Model is not yet fully supported in browsers
- Performance overhead from component boundaries (copying data across interfaces)
- WIT interface design requires careful upfront planning
- Toolchain is still maturing (wit-bindgen, wasm-tools)
Mitigations
- This is a future feature — browser support will improve by the time we implement
- Design WIT interfaces to minimize cross-boundary data transfer
- Start with a small plugin surface (custom systems, component definitions)
- Follow the specification’s progress and prototype when browser support lands
Proposed Plugin Interface (Sketch)
// plugin.wit
interface sg-plugin {
record vec2 { x: f32, y: f32 }
record entity-id { index: u32, generation: u32 }
// Called once when the plugin loads
init: func()
// Called each fixed update tick
update: func(dt: f32)
// Query entity positions (engine provides data)
get-position: func(entity: entity-id) -> option<vec2>
set-position: func(entity: entity-id, pos: vec2)
}