Introductionâ
Dynamic plugins are LinaPro's runtime-extensible plugin form. They compile plugins into .wasm artifacts that can be uploaded, installed, enabled, disabled, uninstalled, and explicitly upgraded at runtime â without recompiling the core framework.
Dynamic plugins run inside a WASM sandbox. They cannot directly access the core framework filesystem, network, or database; all core framework capability access must go through pluginbridge and hostServices authorization.
When to Useâ
| Scenario | Description |
|---|---|
| Runtime hot-loading | Upload a .wasm artifact and it enters the plugin governance flow immediately |
| Temporary capability validation | Quickly bring up a proof-of-concept feature; convert to a source plugin after validation |
| Commercial plugin distribution | Distribute only binary artifacts without exposing source code |
| Controlled external integration | Network, storage, and data access are all governed through authorization snapshots |
Long-term core business capabilities should still prefer source plugins. Dynamic plugins are better suited for hot-loading and scenarios with stronger isolation requirements.
What Is WebAssembly?â
WebAssembly (abbreviated WASM) is a stack-based virtual machine binary instruction format standardized by the W3C. Originally designed for the browser, it is now widely used in server-side, edge computing, and plugin system scenarios.
-
Cross-platform:
WASMmodules are platform-agnostic binaries. The same.wasmartifact runs onLinux,macOS,Windows, and acrossx86andARMinstruction sets without recompilation. -
Secure sandbox:
WASMruns in a strictly isolated sandbox. By default, it cannot access the core framework filesystem, network, memory, or system calls. Every core framework capability must be explicitly authorized through an interface, fundamentally limiting the blast radius of malicious code or vulnerabilities. -
Near-native performance:
WASMuses a compact binary format that can be JIT-compiled to native machine code at runtime, achieving near-native execution efficiency while maintaining sandbox isolation. -
Hot-loading support:
WASMmodules can be dynamically loaded and unloaded at runtime without restarting the core framework process. This provides a natural hot-update capability for plugin systems â new versions can go live or roll back without affecting overall system operation. -
Multi-language ecosystem: Mainstream languages including
Go,Rust,C/C++, andAssemblyScriptcan all compile toWASM. Plugin developers are not locked into a single tech stack.LinaProcurrently usesGoas the primary plugin development language, extending the sandbox and core framework service communication contract based onWASI(WebAssembly System Interface).
Runtime Modelâ
The core framework completes authentication, authorization, and tenant context handling before passing a request snapshot into the WASM instance. Dynamic plugins see a structured request envelope â not a raw core framework internal object.
Directory Structureâ
Dynamic plugin source directories follow the same layout as source plugins, with an additional main.go as the WASM entry point:
apps/lina-plugins/<plugin-id>/
âââ main.go # WASM export function entry
âââ plugin.yaml
âââ plugin_embed.go
âââ backend/
â âââ api/ # API DTOs and route contracts
â âââ internal/
â â âââ controller/ # HTTP controllers
â â âââ service/ # Business service layer
â â âââ dao/ # gf gen dao generated
â â âââ model/ # do/entity models
â âââ plugin.go # Plugin registration entry
âââ frontend/
â âââ pages/ # Plugin pages
âââ manifest/
â âââ sql/ # Installation and upgrade SQL
â â âââ mock-data/ # Demo data, optional
â â âââ uninstall/ # Uninstall SQL
â âââ i18n/ # Plugin language packs
âââ README.md
WASM Entry Pointâ
Dynamic plugins must export functions defined by the core framework contract. Here is an official example:
var guestRuntime = pluginbridge.NewGuestRuntime(dynamicbackend.HandleRequest)
//go:wasmexport lina_dynamic_route_alloc
func linaDynamicRouteAlloc(size uint32) uint32 {
return guestRuntime.Alloc(size)
}
//go:wasmexport lina_dynamic_route_execute
func linaDynamicRouteExecute(size uint32) uint64 {
responsePointer, responseLength, err := guestRuntime.Execute(size)
if err != nil {
fallback, _ := pluginbridge.EncodeResponseEnvelope(
pluginbridge.NewInternalErrorResponse(err.Error()),
)
responsePointer, responseLength, _ = guestRuntime.ExposeResponseBuffer(fallback)
}
return uint64(responsePointer)<<32 | uint64(responseLength)
}
//go:wasmexport lina_host_call_alloc
func linaHostCallAlloc(size uint32) uint32 {
return guestRuntime.HostCallAlloc(size)
}
func main() {}
Business routing is typically delegated to pluginbridge.MustNewGuestControllerRouteDispatcher, which dispatches requests to controller methods.
hostServices Authorizationâ
Dynamic plugins must declare the core framework services, methods, and resource scopes they need in plugin.yaml. When a plugin is installed or enabled, the core framework writes the authorization into a release snapshot. At runtime, any unauthorized call is rejected.
| Service | Typical Capabilities |
|---|---|
runtime | Log writing, plugin status, time, UUID, node info |
data | Database read/write constrained by table scope and tenant filtering |
storage | File read/write within the plugin's namespace |
network | External HTTP requests constrained by target address |
cache | Cluster-aware cache read/write |
lock | Distributed lock acquisition, renewal, and release |
cron | Built-in task registration for dynamic plugins |
config | Plugin configuration reading |
notify | Core framework notification capability |
Example:
hostServices:
- service: runtime
methods: [log.write, info.now, info.node]
- service: data
methods: [list, get, create, update, delete]
resources:
tables:
- plugin_demo_dynamic_record
- service: network
methods: [request]
resources:
- url: https://api.example.com
Building Dynamic Pluginsâ
Dynamic plugins use the standard Go toolchain compiled to the wasip1/wasm target. The project provides make commands to simplify the build process:
make wasm
make wasm p=plugin-demo-dynamic
Build artifacts are output to temp/output/<plugin-id>.wasm and include the plugin manifest, route contracts, and necessary embedded resources.
Installation, Enablement, and Upgradeâ
The runtime flow for dynamic plugins:
- Build the
.wasmartifact. - Upload the dynamic plugin package in the admin workspace's Extension Center.
- The core framework validates the
WASMfile header, custom sections, embedded manifest,ABIversion, and resources. - The administrator confirms
hostServicesauthorization. - The installation
SQLis executed and governance records are written. - Once enabled, the core framework loads the
WASMsandbox and projects routes, menus, and resources.
When a higher version is uploaded, the core framework does not immediately switch the active version. Instead, it marks the plugin as pending_upgrade. The administrator previews the diff in the plugin management page and explicitly executes the runtime upgrade. If the upgrade fails, the previous active version is retained and failure diagnostics are recorded for retry after fixing.
Key Differences from Source Pluginsâ
| Dimension | Source Plugin | WASM Dynamic Plugin |
|---|---|---|
| Delivery | Source code compiled with the core framework | .wasm runtime artifact |
| Hot-loading | Requires new core framework deployment | Supports runtime upload and enablement |
| Performance | Native Go performance | Sandbox and bridge overhead |
| Core framework capability access | pluginhost stable contract | hostServices authorized bridge |
| Isolation strength | Namespace isolation | WASM sandbox isolation |
| Debugging | Standard Go debug toolchain | More reliant on logs and bridge diagnostics |
| Best for | Long-term business modules | Commercial distribution, hot-loading, temporary extensions |
Best Practicesâ
- Only request the
hostServicesmethods and resource scopes you actually need. - Use the plugin
IDnamespace for database tables to avoid conflicts with the core framework or other plugins. - Be explicit about target addresses for outbound network access; avoid broad authorization.
- Prepare rollback-friendly, idempotent upgrade
SQLfor runtime upgrades. - Promote long-running, high-frequency business logic to source plugins; use dynamic plugins for hot-loading and isolation scenarios.