The README states the rule that the webhook UUID in the URL is the credential, as a rule rather than a remark (#301).
The data directory's permission mode has one owner: the startup code that creates the directory also sets its mode, and nothing else touches it (#288).
The target forms and the README say that max_retries is the total number of delivery attempts, not retries on top of a first try; wording only, delivery behaviour unchanged (#316).
Nothing on the branch changes configuration, storage format or deployment steps. No action is needed to deploy it beyond a normal image rebuild.
Further units for the milestone land here one squashed commit each after an independent review; this body is updated as they do. The 1.0 tag waits on your production run and is separate from merging this branch.
Model: fable-5-1
Milestone branch `next` for 1.0.0 (https://git.eeqj.de/sneak/webhooker/milestone/9), mergeable to `main` at every moment.
On the branch since `main` (1.0.0b1):
- The README states the rule that the webhook UUID in the URL is the credential, as a rule rather than a remark (https://git.eeqj.de/sneak/webhooker/issues/301).
- The data directory's permission mode has one owner: the startup code that creates the directory also sets its mode, and nothing else touches it (https://git.eeqj.de/sneak/webhooker/issues/288).
- The target forms and the README say that `max_retries` is the total number of delivery attempts, not retries on top of a first try; wording only, delivery behaviour unchanged (https://git.eeqj.de/sneak/webhooker/issues/316).
Nothing on the branch changes configuration, storage format or deployment steps. No action is needed to deploy it beyond a normal image rebuild.
Further units for the milestone land here one squashed commit each after an independent review; this body is updated as they do. The 1.0 tag waits on your production run and is separate from merging this branch.
Model: fable-5-1
clawbot
self-assigned this 2026-09-21 14:56:25 +02:00
Closes #301. Docs-only apart from one test comment; no behaviour change.
The receiver has authenticated on the entrypoint UUID alone since inbound signature verification was removed in #279. The README described that as the current state. It did not say it is the decision, which leaves a future contributor free to propose HMAC as an improvement rather than as a reversal.
What changed:
- `## The entrypoint URL is the authentication secret` now states the rule: the v4 UUID at `/webhook/{uuid}` is the credential and the only one; no shared secret, HMAC signature, bearer token or second factor will be added, including as defence in depth. It names the removal that settled it, and it says explicitly that signature headers a sender sends anyway are stored and forwarded but never checked — the previous text left that ambiguous.
- The same section carries the two consequences an operator has to act on: the URL is a capability, so keep it out of logs, tickets and screenshots; and rotation means minting a new entrypoint, not changing a key.
- It also handles the case the rule will next be argued from: a sender that only supports signed payloads to a well-known URL is a constraint on that integration, to be raised on its own terms, not grounds to reintroduce shared secrets.
- The rule is reachable without scrolling 1,100 lines: a pointer in the intro, a new first bullet under Authentication (which previously listed the web UI, the API and `/metrics` and said nothing about the receiver at all), and a sharpened bullet under Security.
Stale language found and corrected: one, in `internal/delivery/redirect_test.go`. Its comment justified same-origin header retention partly by "the inbound signature the receiver verifies" — in this repo's vocabulary "the receiver" is `/webhook/{uuid}`, which verifies nothing. The endpoint that verifies it is the delivery target's, and the comment now says so.
Two places that read like stale signing language were checked and left alone as accurate: `internal/delivery/redirect.go` and `internal/server/sentry.go` describe signature headers senders put on the receiver route, which do arrive and are forwarded — neither claims webhooker checks them.
`REPO_POLICIES.md` was deliberately not touched. It is the cross-project policy document synced from `sneak/prompts` and carries `last_modified` front matter for that purpose, so a webhooker-specific carve-out does not belong in it. Worth knowing: its hardening section ends "if a standard security hardening measure exists for HTTP services and is not listed here, it is still expected. When in doubt, harden" — that is the sentence a future HMAC proposal will cite, and only the README now answers it.
`TODO.md` is untouched per its own Workflow section (issue branches do not touch it).
Co-authored-by: sneak <sneak@sneak.berlin>
Reviewed-on: #302
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
Two packages each declared the 0o750 mode for DATA_DIR and both created the directory. internal/datadir now exports DirPerm as the single definition, and internal/database uses it in both places it creates the directory. The value is unchanged, so existing deployments see no permission change. datadir owns it because guarding and creating DATA_DIR is that package's whole purpose and it imports nothing that would form a cycle.
Model: opus-4-8 (implementation and review); fable-5-1 (merge)
The help text under the field on both target forms and the max_retries rows in the README now say the number is the total number of delivery attempts: 0 is a single attempt with no retries and no circuit breaker, and N is N attempts in total. The delivery code already worked this way; only the wording was wrong, so an operator wanting one try plus two retries would have entered 2 instead of 3. A UI copy test renders both forms and pins the wording. Delivery behaviour is unchanged.
Model: opus-4-8 (implementation); fable-5-1 (merge)
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.
Milestone branch
nextfor 1.0.0 (https://git.eeqj.de/sneak/webhooker/milestone/9), mergeable tomainat every moment.On the branch since
main(1.0.0b1):max_retriesis the total number of delivery attempts, not retries on top of a first try; wording only, delivery behaviour unchanged (#316).Nothing on the branch changes configuration, storage format or deployment steps. No action is needed to deploy it beyond a normal image rebuild.
Further units for the milestone land here one squashed commit each after an independent review; this body is updated as they do. The 1.0 tag waits on your production run and is separate from merging this branch.
Model: fable-5-1
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.