POST /api/v1/chats/{id}/webhooks registers a URL on a chat: 201, or 200 with the existing webhook when the chat already has exactly that URL. GET lists the chat's webhooks in registration order, and DELETE /api/v1/chats/{id}/webhooks/{webhook_id} removes one with 204. Every id that GET /api/v1/chats does not list gets 404, through the lookup the messages endpoints use.
The webhooks are kept in webhooks.json in DATA_DIR. Each change writes a new file with os.CreateTemp, which creates it with mode 0600, syncs it and renames it over the old one, which is never opened for writing. bot.Run reads the file before starting the chat client, so a file that cannot be read stops startup as bad configuration does. Nothing is posted to a webhook yet; that is #7.
What the diff does not show:
Startup also refuses a file that is JSON but has no webhooks list ({}, null), or holds a webhook that registering could not have made, so a hand edit gone wrong stops the bot instead of being written over.
A crash between creating the temporary file and the rename leaves a file named webhooks.json. and digits beside it, which the bot ignores.
Disclosures:
Judgement call: reading a JSON body moved from the send handler into decodeBody, which both POST endpoints use; the send handler's answers are unchanged.
Judgement call: the write uses the standard library, not an atomic-write package.
Suppressed: gosec G304 on reading webhooks.json, and on two tests reading their own temporary files.
Model: opus-5-5
Implements https://git.eeqj.de/sneak/simplexcalc/issues/6.
`POST /api/v1/chats/{id}/webhooks` registers a URL on a chat: `201`, or `200` with the existing webhook when the chat already has exactly that URL. `GET` lists the chat's webhooks in registration order, and `DELETE /api/v1/chats/{id}/webhooks/{webhook_id}` removes one with `204`. Every id that `GET /api/v1/chats` does not list gets `404`, through the lookup the messages endpoints use.
The webhooks are kept in `webhooks.json` in `DATA_DIR`. Each change writes a new file with `os.CreateTemp`, which creates it with mode 0600, syncs it and renames it over the old one, which is never opened for writing. `bot.Run` reads the file before starting the chat client, so a file that cannot be read stops startup as bad configuration does. Nothing is posted to a webhook yet; that is https://git.eeqj.de/sneak/simplexcalc/issues/7.
What the diff does not show:
- Startup also refuses a file that is JSON but has no `webhooks` list (`{}`, `null`), or holds a webhook that registering could not have made, so a hand edit gone wrong stops the bot instead of being written over.
- A crash between creating the temporary file and the rename leaves a file named `webhooks.json.` and digits beside it, which the bot ignores.
Disclosures:
- Judgement call: reading a JSON body moved from the send handler into `decodeBody`, which both `POST` endpoints use; the send handler's answers are unchanged.
- Judgement call: the write uses the standard library, not an atomic-write package.
- Suppressed: gosec G304 on reading `webhooks.json`, and on two tests reading their own temporary files.
Model: opus-5-5
POST, GET and DELETE under /api/v1/chats/{id}/webhooks, for the chats
that GET /api/v1/chats lists. The webhooks are kept in
$DATA_DIR/webhooks.json, mode 0600, which each change replaces whole
through a temporary file in the same directory and a rename. bot.Run
reads the file before it starts the chat client: absent means none, and
a file that cannot be read aborts startup. Reading a JSON request body
moved into decodeBody, which the messages endpoint now shares. Nothing
is posted to a webhook yet.
Model: opus-5-5
PASS: registering, listing and removing webhooks, and keeping them across restarts, match #6 and reopen nothing the earlier API reviews settled.
Model: opus-5-5
PASS: registering, listing and removing webhooks, and keeping them across restarts, match https://git.eeqj.de/sneak/simplexcalc/issues/6 and reopen nothing the earlier API reviews settled.
Model: opus-5-5
clawbot
merged commit 397fc95149 into next2026-09-29 08:38:14 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Implements #6.
POST /api/v1/chats/{id}/webhooksregisters a URL on a chat:201, or200with the existing webhook when the chat already has exactly that URL.GETlists the chat's webhooks in registration order, andDELETE /api/v1/chats/{id}/webhooks/{webhook_id}removes one with204. Every id thatGET /api/v1/chatsdoes not list gets404, through the lookup the messages endpoints use.The webhooks are kept in
webhooks.jsoninDATA_DIR. Each change writes a new file withos.CreateTemp, which creates it with mode 0600, syncs it and renames it over the old one, which is never opened for writing.bot.Runreads the file before starting the chat client, so a file that cannot be read stops startup as bad configuration does. Nothing is posted to a webhook yet; that is #7.What the diff does not show:
webhookslist ({},null), or holds a webhook that registering could not have made, so a hand edit gone wrong stops the bot instead of being written over.webhooks.json.and digits beside it, which the bot ignores.Disclosures:
decodeBody, which bothPOSTendpoints use; the send handler's answers are unchanged.webhooks.json, and on two tests reading their own temporary files.Model: opus-5-5
POST, GET and DELETE under /api/v1/chats/{id}/webhooks, for the chats that GET /api/v1/chats lists. The webhooks are kept in $DATA_DIR/webhooks.json, mode 0600, which each change replaces whole through a temporary file in the same directory and a rename. bot.Run reads the file before it starts the chat client: absent means none, and a file that cannot be read aborts startup. Reading a JSON request body moved into decodeBody, which the messages endpoint now shares. Nothing is posted to a webhook yet. Model: opus-5-5PASS: registering, listing and removing webhooks, and keeping them across restarts, match #6 and reopen nothing the earlier API reviews settled.
Model: opus-5-5