# Testing a command without a second Signal account Signal never delivers an account its own sends. The bot cannot type `!kot` at itself, so until now every command was verified one of two weak ways: by asking a human to type it, or by rebuilding the object graph in a scratch script. The first proves nothing about the path between the websocket and the handler; the second is not the wiring that runs in production. `POST /_selftest` injects a real envelope frame into the **live** dispatcher. Everything downstream of the socket read is the code that actually serves the group: envelope parsing, the scoping gate, the tally, trigger resolution, the cooldown decorator and the real REST transport. Only the socket read is skipped. ## Using it Name the groups it may post into -- in `.env`, because the service reads it: ``` SELFTEST_GROUPS=testbot,catbot,finaltestbot ``` Then: ```sh scripts/selftest.sh testbot '!papież' 3 ``` `SELFTEST_INTERVAL` (default 11s) spaces the calls past the per-user cooldown; the self-test is always the same author, so a tighter loop just exercises the cooldown instead of the command. ## What it will not do It **posts for real**, into a real group. Two things keep that from becoming a way to make the bot say anything anywhere: - The endpoint lives on the same loopback bind as `/healthz`, never a public one. - `SELFTEST_GROUPS` is **empty by default**, and any group not named in it is refused with 403. So a fresh checkout cannot post into the production group even by accident. ## Why the author matters The reply quotes whoever asked, and `quote_author` has to be somebody Signal can resolve -- a made-up uuid comes back as `The user ... is not registered` and the whole send fails. `resolve_group` therefore attributes the message to a real member of the target group who is not the bot.