Plugin Pre-Flight Checklist#
Use this checklist to audit a plugin before declaring it ready. Each item is a hard pass / fail.
File layout#
- Plugin file is
<name>.wasminplugins/. - Optional
<name>.manifestis in the same directory as the.wasm. - Plugin filename (without extension) and the manifest’s
namefield match. The host does not enforce this today, but matching them is good hygiene.
Hooks#
- Plugin exports at least one of the three currently-invoked hooks:
hook_before_save,hook_after_create,hook_after_publish. - Plugin does not rely on
hook_on_plugin_loadedorhook_before_delete. Both are defined in the host but not currently invoked. Plugins that only export one of these will load but never fire. - Each hook’s result is a JSON object containing (at most)
customFieldsfor mutation. The host reads onlycustomFieldsback; other fields in the result are ignored. -
__hook_result_lenis exported only if the result length differs from the input length. The export is optional; the host usesinputLenas the result length when the export is missing.
Manifest#
-
nameis set and non-empty. -
versionis set and non-empty. -
capabilities.httpis set to a list of URL patterns if the plugin useshttp_getorhttp_post. -
capabilities.databaseis set to a list ofread|write:content|media|userspermissions if the plugin usesdb_queryordb_exec. - URL patterns use trailing
*only (no regex, no?). - URL patterns are ordered so the most specific match comes first (the first match wins).
Host function calls#
- If the plugin uses
http_getorhttp_post, the manifest’shttppatterns cover the actual URLs the plugin will request. - If the plugin uses
db_queryordb_exec, the manifest’sdatabasepermissions cover the actual table names in the queries (and the actual operation:db_queryis alwaysread,db_execis alwayswrite). - Every SQL query is a single explicit
SELECT/INSERT/UPDATE/DELETEstatement. No CTEs, no subqueries, no comments, no quoted identifiers, no multi-statement queries. - The plugin reads each host function’s result from offset
4096before invoking the next host function. All four data host functions share the same result offset.
Build#
- Compiled with
tinygo build -target=wasi(Go),cargo build --target wasm32-wasip1(Rust), orclang --target=wasm32-wasi(C/C++). - Compiled
.wasmis well under 64 MB (typical TinyGo plugin: < 1 MB). - For Go plugins that use host functions, the
//go:wasmimportblock fromreferences/host-function-imports.go.txtis copied into the plugin’smain.go.
Deployment#
- Lesstruct was restarted after the last
plugins/change (unlessDEV_MODE=trueis set; in that case, the watcher picks up new.wasmfiles automatically). - The
.wasmis the top-level file inplugins/. Subdirectories are not watched.
Smoke test#
- Run the smoke test from
SKILL.mdStep 8 and confirm the relevant hook fires and anycustomFieldsmodification is reflected in the saved item. - For host function calls, check the Lesstruct log for
“blocked” messages. If the call was permitted, no log line is
produced (audit logging is partial); use
log_infofrom the plugin to record what it did.
Documentation#
- A
plugins/<name>.READMErecords the Lesstruct version the plugin was authored against, the hooks it uses, and the capabilities declared in the manifest.