Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Plugin Release Acceptance

A first-party plugin is accepted for a release when an operator can install it by name on a published zeroclaw binary, with no Rust toolchain on the machine, and can show that the plugin, not a built-in feature, does the work. This page is the runbook for that proof and the template for its evidence. It uses the Discord channel plugin as the worked example. For another package, substitute its name, its alias, its required keys, and its destinations.

One run proves one package version on one published build of the host. It says nothing about other targets, other host versions, or behavior under load.

When to run it

Run it after the release is published and the package version is in the registry, once for each package version the release claims to support. Run it again when either side changes: a new package version, or a host release that changes the plugin interface.

Before you start

  • The artifact. A published zeroclaw CLI archive for a 64-bit target whose plugin host compiles .wasm components. Check it first with Release artifact verification. An x86_64 Linux archive in a fresh container is the simplest place to show that no toolchain was involved.
  • A clean machine. No Rust toolchain and no configuration left over from an earlier run.
  • Platform test accounts. For Discord, a dedicated bot application in a small test server, never a production bot, with the Message Content Intent on and the bot invited (see the Discord quickstart), plus a second Discord account for the tester. Plan to reset the bot token when the run is over.
  • A model provider. Any configured provider works. A scripted local provider makes the agent’s replies repeatable.
  • An evidence file. Copy the evidence template and fill it in as you go.

Enter the bot token only at the masked zeroclaw config set prompt. Never put it in a file, on a command line, in shell history, in a screenshot, or in the evidence.

1. Record the environment

command -v cargo rustc || echo "no Rust toolchain"
sha256sum zeroclaw-<target>.tar.gz
zeroclaw --version
zeroclaw plugin search discord

Record the archive name and digest, the version string, and the registry entry the install resolves: its name, version, archive URL, and sha256.

2. Install by name and bind an instance

zeroclaw plugin install discord --channel-alias acceptance --egress declared
zeroclaw config set plugins.entries.zpi1_WyJkaXNjb3JkIiwiY2hhbm5lbCIsImFjY2VwdGFuY2UiXQ.config.bot_token
zeroclaw config set plugins.enabled true
zeroclaw plugin info discord

The install prints the binding and the hosts it granted. plugin info must report that the package loads on this host and that the instance key above exists. Then, by hand:

  • add plugin.acceptance to one enabled agent’s channels;
  • add a peer group with channel = "plugin.acceptance" whose external_peers holds the tester’s numeric Discord user ID.

The Discord page shows both. Configure no [channels.discord.<alias>] table anywhere, then start the daemon. Keep a copy of config.toml for the evidence; its secrets stay encrypted.

3. Exercise the plugin

Work through the template in order and record what you observe, including anything unexpected. The log records named below are in the daemon’s structured log, which the dashboard’s Logs page and GET /api/logs read (see Observability). Use synthetic message text throughout.

Evidence template

ClaimActionEvidenceResult
Installed by name with no toolchainSteps 1 and 2command -v output, install output, registry entry, archive digest
Loads on this hostzeroclaw plugin info discordIts load verdict
Inbound goes through the pluginThe tester sends a messageA channel inbound message record with zeroclaw.channel = plugin.acceptance
Outbound goes through the pluginThe agent repliesA reply delivered record for plugin.acceptance; a redacted screenshot of the reply
The built-in channel handled nothingRead the startup output and /healthThe channel list shows plugin.acceptance and no discord.*; /health lists channel:plugin.acceptance and no channel:discord.*; the config copy has no [channels.discord] table
Negative controlSet channels.plugin.acceptance.enabled to false, restart, send a messageNo inbound record and no reply; set it back to true and restart again before the next row
ReconnectCut the machine’s network for at least two minutes, then restore itThe next message is answered; note whether the plugin resumed its session or started a new one
ShutdownStop the daemonThe process exits cleanly; note how long the bot takes to show offline
Denied destinationRemove *.discord.gg from the instance’s egress_hosts, restartThe gateway does not connect, the bot stays offline, and nothing arrives inbound. A host that logs refused WebSocket connections also writes a plugin_egress_denied record with transport = websocket, the refused host, and a remedy command; v0.8.6 writes none
Grant restoredPut *.discord.gg back and apply it to the running daemon with POST /admin/reload from the same machine (see Remote daemon reload), without a full restart. Saving the change, with zeroclaw config set or by editing config.toml, does not reach the running daemon on its ownThe bot reconnects; note how long it took
Denied senderSend from an account outside the peer groupA plugin_channel_sender_denied record and no reply
Missing platform permissionRemove the bot’s Send Messages permission in one channel and message it thereA send failure in the log, the daemon still running, no reconnect loop
Invalid tokenSet a syntactically valid invalid or revoked token through the masked config set prompt, then restartThe plugin reports Discord’s authentication refusal and backs off; no reconnect loop in the log over five minutes. A malformed token rejected locally by configure() does not exercise platform authentication or backoff
Trust policy holdsSet plugins.security.signature_mode to strict without trusting the package’s publisher key, restartThe daemon skips the package and logs the signature refusal; plugin.acceptance does not start. The CLI reports the refused package as Plugin discord not found or No plugins installed, so read the daemon log for the reason. Restore the previous mode

Redact before posting

The channel inbound message and reply delivered records carry the message text and the sender’s user ID. Before posting anything:

  • replace user, server, and channel IDs with placeholders;
  • keep only synthetic message text;
  • replace every enc2: value in the config copy with <encrypted>;
  • crop screenshots to the messages under test.

The token never appears in the evidence, redacted or not.

Post the evidence

Post on the tracking issue for the release: the artifact name and digest, the zeroclaw --version output, the registry entry and package version, the exact commands from steps 1 and 2, the filled-in table, and links to the pull requests that changed the package or the host since the last accepted run.

Clean up

  1. Stop the daemon and run zeroclaw plugin remove discord. Removal keeps the instance’s [[plugins.entries]] row and its [channels.plugin.acceptance] binding and prints both; delete them.
  2. Reset the bot token in the Discord Developer Portal, so the token used in the run stops working.