Developing Built-in Plugins
Weave v0.1 supports only built-in plugins that are compiled, tested, and upgraded with the product release. There is no third-party marketplace, independent install/uninstall, version selection, artifact upload, WebAssembly (WASM), native subprocess, sandbox, or microservice runtime.
This boundary is intentional: the current priority is fast and reliable platform and agent releases. Agent capabilities that need an independent lifecycle may later use a project-specific worker protocol built with the Pi SDK, not the generic plugin runtime. That worker protocol is a Weave proposal, not a Pi SDK interface.
Runtime model
| Location | Form | Registration | Release unit |
|---|---|---|---|
| Backend | In-process Go implementing pluginsdk.BackendPlugin | internal/backend/plugins/catalog/ | weave |
| Device | In-process Go implementing agentplugin.AgentPlugin | internal/agent/plugins/catalog/ | weave-agent |
The lifecycle is fixed:
compile-time catalog → Init → Start → Health → Stop (reverse order)Registration order is startup order. An Init or Start failure is logged and isolated while the remaining built-ins continue.
Backend plugin
Implement a package under internal/backend/plugins/{plugin-id}/:
type Plugin struct {
host pluginsdk.HostAPI
}
func New() *Plugin { return &Plugin{} }
func (p *Plugin) Manifest() pluginsdk.PluginManifest {
return pluginsdk.PluginManifest{
ID: "example",
Version: "1.0.0",
Description: "Example builtin module",
Bus: &pluginsdk.BusCapability{
Topics: []string{"evt.plugin.example.*"},
},
Capabilities: []pluginsdk.Capability{
"bus.subscribe.evt.plugin.example.*",
},
}
}
func (p *Plugin) Init(ctx context.Context, host pluginsdk.HostAPI) error {
p.host = host
return nil
}
func (p *Plugin) Start(context.Context) error { return nil }
func (p *Plugin) Stop(context.Context) error { return nil }
func (p *Plugin) Health() pluginsdk.HealthReport {
return pluginsdk.HealthReport{Healthy: true}
}PluginManifest contains only fields consumed by the platform:
- identity:
ID,Version, andDescription - HostAPI declarations:
HTTP,Bus,Metrics, andDB - control plane:
Permissions,ConfigSchema, andSurfaces - config targeting:
ApplyScopesandDefaultApplyTarget - security capabilities:
Capabilities - optional device-local port:
UIPort
It has no runtime tier, artifact location, dependency graph, or resource-budget declaration.
HostAPI boundary
A backend plugin uses platform services only through pluginsdk.HostAPI:
HTTP(): register routes under/api/v1/plugins/{plugin-id}/Bus(): publish and subscribe to declared topicsMetrics(): register plugin-namespaced metricsDB(): run plugin migrations and queriesStore(): use plugin-ID-namespaced key-value (KV) statePluginConfig(),Shadow(),Secrets(), andAuditor()HTTPClient(tenantID): make outbound requests checked against host capabilities
Register HTTP routes in Init, before the server starts listening. Put bus subscriptions and background work in Start.
Database and tenant isolation
Declaring DB requests database access; the composition root must also list the plugin ID as a trusted built-in.
Row-Level Security (RLS) protects tenant tables. Always access them through:
db := host.DB().WithTenant(tenantID)The implementation uses transaction-local SET LOCAL app.tenant_id. Never use SET SESSION, and never import bun from a plugin.
HTTP and role-based access control (RBAC)
Declare routes and permissions in the manifest:
HTTP: &pluginsdk.HTTPCapability{Routes: []pluginsdk.RouteDecl{
{
Pattern: "/items/{id}",
Method: "GET",
Subresource: "item",
Action: "read",
},
}},
Permissions: []pluginsdk.PluginPermissionDecl{
{
Subresource: "item",
Action: "read",
Description: "Read example items",
DefaultRoles: []string{"viewer", "operator", "tenant_admin"},
},
},Register the route in Init:
host.HTTP().Handle("GET /items/{id}", "item", "read", handler)The RBAC resource is {plugin-id}/{subresource}. The manager seeds manifest permissions idempotently at boot.
Registration and tests
Add backend constructors only to internal/backend/plugins/catalog/catalog.go. Add device constructors only to internal/agent/plugins/catalog/catalog.go. Do not import concrete plugins from cmd/weave or cmd/weave-agent.
At minimum, run:
go test ./internal/backend/plugin/... ./internal/backend/plugins/...
go test ./internal/agent/plugin/... ./internal/agent/plugins/...
go test ./...If Protobuf changes, also run make proto and make web-proto.