2 Commits

Author SHA1 Message Date
a83e8fe654 Record the completed 1.0.0 milestone in TODO.md (#249)
All checks were successful
check / check (push) Successful in 7s
2026-08-20 11:16:51 +02:00
687405993e Harden operator-set target headers (closes #233) (#242)
All checks were successful
check / check (push) Successful in 2m58s
2026-08-20 10:54:43 +02:00

113
TODO.md
View File

@@ -18,68 +18,52 @@ Issue branches do NOT touch this file — the manager maintains it on
# Status # Status
pre-1.0. No git tags exist. `main` (4f5ecb1) is a working webhook proxy 1.0.0 is complete: 55 closed, 0 open. `next` (6874059) is 62 commits
with auth, CSRF/SSRF protections, login rate limiting, Slack target, ahead of `main` and a strict fast-forward. No git tags exist yet.
event retention (#63), the database archiving target (#43), the admin
password change flow (#65), policy compliance (#6), pinned lint tooling
(#55), and fail-loud configuration parsing (#80).
`next` is green — verified both by CI and by cache-defeated container The bar was not "the milestone is empty" but "sneak can deploy this and
runs (`docker build --no-cache-filter=lint --no-cache-filter=builder`) — use it in low-volume production". Every gap the deployability audit
but the **1.0.0 milestone is no longer complete**. It was reopened on named against that bar is now closed:
2026-08-20 by a code-level deployability audit that ran the service end
to end (verdict:
https://git.eeqj.de/sneak/webhooker/issues/33#issuecomment-66686).
The bar for 1.0 is not "the milestone is empty" but "sneak can deploy - `DATA_DIR` locking, so two instances cannot both deliver
this and use it in low-volume production". The audit found the gap (https://git.eeqj.de/sneak/webhooker/issues/201)
between those two: two instances on one `DATA_DIR` both deliver - shutdown on listener failure, rather than a live non-serving process
(reproduced), a failed listen leaves a live non-serving process that (https://git.eeqj.de/sneak/webhooker/issues/200)
restart policies never fire on, there is no inbound authentication of - inbound signature verification
any kind, delivery failures render as a bare word with no status code or (https://git.eeqj.de/sneak/webhooker/issues/67)
error, a terminally failed delivery can never be replayed, the SSRF - per-attempt delivery detail in the event log
blocklist has no escape hatch so the proxy cannot forward to your own (https://git.eeqj.de/sneak/webhooker/issues/202)
network at all, and target credentials leak into the per-webhook event - replay of a terminally failed delivery
databases. (https://git.eeqj.de/sneak/webhooker/issues/203)
- `ALLOWED_EGRESS_CIDRS`, an allowlist escape hatch for the SSRF guard
(https://git.eeqj.de/sneak/webhooker/issues/204)
- the three credential exposures
(https://git.eeqj.de/sneak/webhooker/issues/205,
https://git.eeqj.de/sneak/webhooker/issues/206,
https://git.eeqj.de/sneak/webhooker/issues/207)
One caveat on reading a green check, narrower than it used to be. A One caveat on reading a green check: a docs-only commit deliberately
docs-only commit deliberately replays from the layer cache (#119), so a replays from the layer cache
green status on such a commit evidences a replay rather than an executed (https://git.eeqj.de/sneak/webhooker/issues/119), so a green status on
run; a code commit invalidates the `COPY` layer and genuinely executes. such a commit evidences a replay rather than an executed run. A code
Superseded runs are no longer the hazard they were: before #152 they commit invalidates the `COPY` layer and genuinely executes.
were recorded as `skipped` and rolled up green, and before #119 a warm
layer cache let the gate report success without executing anything,
replaying the previous build's console log so the lie looked like a real
run. Both are fixed. Note: `TODO.md` was deliberately
deleted from this repo in f9a9569 (2026-03-01, #6); its content was
folded into the README TODO section, which this draft reconstructs as
of 2026-07-06.
# Next Step # Next Step
Clear the reopened 1.0.0 milestone. The milestone PR Merge the milestone PR (https://git.eeqj.de/sneak/webhooker/pulls/111)
(https://git.eeqj.de/sneak/webhooker/pulls/111) is held: it carries a and tag `v1.0.0`. It is `merge-ready` and assigned to sneak; nothing
`WIP: ` prefix, no labels and is assigned to `clawbot`, and it stays else gates it.
that way until the milestone is empty. Correctness first — the
duplicate-delivery lock and the listen-failure shutdown — then the
operability gaps that make the service usable in production, then the
three credential exposures.
Three items belong to the owner, none of them blocking. #150 was decided Post-1.0 follow-ups are open, none blocking the tag:
by the manager rather than left to stall the queue and is flagged on the https://git.eeqj.de/sneak/webhooker/issues/245,
issue for reversal if that call was wrong. #112 (whether `Completed https://git.eeqj.de/sneak/webhooker/issues/246,
Steps` should exist at all, given it once conflicted on every unit) is https://git.eeqj.de/sneak/webhooker/issues/247 and
unanswered; the provisional ruling in force is that issue branches do https://git.eeqj.de/sneak/webhooker/issues/248. Also still open and
not touch this file. #198 records that `make test` is past the org 20s unmilestoned: https://git.eeqj.de/sneak/webhooker/issues/193 (a design
target — 46s of test execution inside a 62.8s CI layer — and turns on question, not a defect), https://git.eeqj.de/sneak/webhooker/issues/198
which quantity the 60s hard cap governs; it is scoped as the improvement (`make test` is past the org 20s target) and
bug the 20-60s band requires, and should be milestoned instead if the https://git.eeqj.de/sneak/webhooker/issues/212 (encrypting target config
cap is read as covering the whole invocation. at rest).
After the tag, the largest open cluster is the unmilestoned follow-up
backlog these units generated: #183, #184, #185, #190, #191, #193, #198,
#211 and #212 (encrypting target config at rest, split out of the
credential-leak fix because it needs a key-rotation and re-wrap story).
# Completed Steps # Completed Steps
@@ -308,14 +292,16 @@ credential-leak fix because it needs a key-rotation and re-wrap story).
# Future Steps # Future Steps
- Manual event redelivery from the web UI — the "Replay" capability the - Delivery status and retry management UI. Replay of a terminally
README describes as planned. No redelivery code exists anywhere in the failed delivery and per-attempt detail already landed
tree; events are stored in full, which is all it would be built on (https://git.eeqj.de/sneak/webhooker/issues/203,
- Delivery status and retry management UI https://git.eeqj.de/sneak/webhooker/issues/202)
- Per-webhook rate limiting in the receiver handler (per-webhook config - Per-webhook rate limiting in the receiver handler (per-webhook config
plus handler enforcement; global limits must not apply to receiver plus handler enforcement; global limits must not apply to receiver
endpoints) endpoints)
- Webhook signature verification for GitHub and Stripe HMAC formats - Stripe HMAC signature verification. The GitHub and GitLab schemes
landed with inbound verification
(https://git.eeqj.de/sneak/webhooker/issues/67)
- API key authentication for programmatic access (APIKey model exists; - API key authentication for programmatic access (APIKey model exists;
Bearer token middleware does not) Bearer token middleware does not)
- REST API v1 - REST API v1
@@ -325,9 +311,10 @@ credential-leak fix because it needs a key-rotation and re-wrap story).
- OpenAPI specification - OpenAPI specification
- Analytics dashboard: success rates, response times, volume - Analytics dashboard: success rates, response times, volume
- A remember-me option at login - A remember-me option at login
- Password reset flow for a forgotten password. The authenticated - Password reset flow for a forgotten password over the web. The
password *change* flow already landed on `main` (#65); reset does not authenticated password *change* flow already landed, and a lost
exist password is recoverable from the console with `webhooker resetpw`
(https://git.eeqj.de/sneak/webhooker/issues/208)
- Later, nice to have - Later, nice to have
- email delivery target type - email delivery target type
- SNS and S3 delivery targets - SNS and S3 delivery targets