Alex Dunmow ad6d87bf06 feat(ninja): plugin build/verify → .bnp packer + ABI riders (WO-WZ-009)
`ninja plugin build` compiles a plugin to reactor-mode wasip1 wasm (Go >= 1.24
enforced), extracts manifest.pb by driving one HOOK_DESCRIBE over wazero with
failing host stubs, and packs a tar.zst .bnp (plugin.wasm, plugin.mod,
manifest.pb + migrations/schemas/assets/web-dist when present) with a summary
table. A describe-time capability call (e.g. db.* from Register) fails with an
actionable error naming the offending method. `ninja plugin verify` re-runs the
CMS reader's layout/name/abi/path-safety/size checks standalone (deliberate
duplication of cms backend/plugin/bnp/reader.go; kept in lockstep by WO-WZ-010).

ABI riders (additive; buf breaking clean):
- ABI_ERROR_CODE_TX_EXPIRED enum value + bnwasm guest mapping to a new
  bnwasm.ErrTxExpired sentinel (retryable tx expiry, distinct from real faults);
  the cms dbexec side adopts the emit separately.
- PluginManifest.data_dir bool + a first-class `data_dir` key on the plugin.mod
  parser (so writeMod's struct round-trip can't drop it); `plugin build` stamps
  it from plugin.mod into the manifest.

Docs: wasm-abi.md gains a Building & packing section, the error-code table row,
the manifest data_dir mapping, and the plugin.mod reference. Tests: CLI e2e
builds the WZ-002 fixture → verify + manifest block keys; a capfixture proves
the actionable describe-time error; verify rejects each malformed class;
bnwasm TX_EXPIRED classification.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 18:34:17 +08:00

39 lines
1.2 KiB
Go

// Package main is a NEGATIVE build fixture: its Register hook reaches a host
// capability (a db.* call) at describe time, which is illegal — DESCRIBE runs
// with no live host. `ninja plugin build` must surface an actionable error
// naming the offending call rather than hanging or crashing.
package main
import (
"context"
"database/sql"
"fmt"
// Registers the "bnwasm" database/sql driver (its init runs sql.Register).
_ "git.dev.alexdunmow.com/block/core/plugin/wasmguest/bnwasm"
"git.dev.alexdunmow.com/block/core/blocks"
"git.dev.alexdunmow.com/block/core/plugin"
"git.dev.alexdunmow.com/block/core/templates"
)
var Registration = plugin.PluginRegistration{
Name: "capfixture",
Version: "0.0.1",
Register: func(_ templates.TemplateRegistry, _ blocks.BlockRegistry) error {
// Illegal describe-time capability use: query the host DB from
// Register. Over the packer's failing host stub this returns an error
// naming "db.query".
db, err := sql.Open("bnwasm", "")
if err != nil {
return err
}
defer func() { _ = db.Close() }()
var n int
if err := db.QueryRowContext(context.Background(), "SELECT 1").Scan(&n); err != nil {
return fmt.Errorf("describe-time db probe: %w", err)
}
return nil
},
}