Compare commits
2 Commits
24af4b4200
...
next
| Author | SHA1 | Date | |
|---|---|---|---|
| a83e8fe654 | |||
| 687405993e |
113
TODO.md
113
TODO.md
@@ -18,68 +18,52 @@ Issue branches do NOT touch this file — the manager maintains it on
|
||||
|
||||
# Status
|
||||
|
||||
pre-1.0. No git tags exist. `main` (4f5ecb1) is a working webhook proxy
|
||||
with auth, CSRF/SSRF protections, login rate limiting, Slack target,
|
||||
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).
|
||||
1.0.0 is complete: 55 closed, 0 open. `next` (6874059) is 62 commits
|
||||
ahead of `main` and a strict fast-forward. No git tags exist yet.
|
||||
|
||||
`next` is green — verified both by CI and by cache-defeated container
|
||||
runs (`docker build --no-cache-filter=lint --no-cache-filter=builder`) —
|
||||
but the **1.0.0 milestone is no longer complete**. It was reopened on
|
||||
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 was not "the milestone is empty" but "sneak can deploy this and
|
||||
use it in low-volume production". Every gap the deployability audit
|
||||
named against that bar is now closed:
|
||||
|
||||
The bar for 1.0 is not "the milestone is empty" but "sneak can deploy
|
||||
this and use it in low-volume production". The audit found the gap
|
||||
between those two: two instances on one `DATA_DIR` both deliver
|
||||
(reproduced), a failed listen leaves a live non-serving process that
|
||||
restart policies never fire on, there is no inbound authentication of
|
||||
any kind, delivery failures render as a bare word with no status code or
|
||||
error, a terminally failed delivery can never be replayed, the SSRF
|
||||
blocklist has no escape hatch so the proxy cannot forward to your own
|
||||
network at all, and target credentials leak into the per-webhook event
|
||||
databases.
|
||||
- `DATA_DIR` locking, so two instances cannot both deliver
|
||||
(https://git.eeqj.de/sneak/webhooker/issues/201)
|
||||
- shutdown on listener failure, rather than a live non-serving process
|
||||
(https://git.eeqj.de/sneak/webhooker/issues/200)
|
||||
- inbound signature verification
|
||||
(https://git.eeqj.de/sneak/webhooker/issues/67)
|
||||
- per-attempt delivery detail in the event log
|
||||
(https://git.eeqj.de/sneak/webhooker/issues/202)
|
||||
- replay of a terminally failed delivery
|
||||
(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
|
||||
docs-only commit deliberately replays from the layer cache (#119), so a
|
||||
green status on such a commit evidences a replay rather than an executed
|
||||
run; a code commit invalidates the `COPY` layer and genuinely executes.
|
||||
Superseded runs are no longer the hazard they were: before #152 they
|
||||
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.
|
||||
One caveat on reading a green check: a docs-only commit deliberately
|
||||
replays from the layer cache
|
||||
(https://git.eeqj.de/sneak/webhooker/issues/119), so a green status on
|
||||
such a commit evidences a replay rather than an executed run. A code
|
||||
commit invalidates the `COPY` layer and genuinely executes.
|
||||
|
||||
# Next Step
|
||||
|
||||
Clear the reopened 1.0.0 milestone. The milestone PR
|
||||
(https://git.eeqj.de/sneak/webhooker/pulls/111) is held: it carries a
|
||||
`WIP: ` prefix, no labels and is assigned to `clawbot`, and it stays
|
||||
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.
|
||||
Merge the milestone PR (https://git.eeqj.de/sneak/webhooker/pulls/111)
|
||||
and tag `v1.0.0`. It is `merge-ready` and assigned to sneak; nothing
|
||||
else gates it.
|
||||
|
||||
Three items belong to the owner, none of them blocking. #150 was decided
|
||||
by the manager rather than left to stall the queue and is flagged on the
|
||||
issue for reversal if that call was wrong. #112 (whether `Completed
|
||||
Steps` should exist at all, given it once conflicted on every unit) is
|
||||
unanswered; the provisional ruling in force is that issue branches do
|
||||
not touch this file. #198 records that `make test` is past the org 20s
|
||||
target — 46s of test execution inside a 62.8s CI layer — and turns on
|
||||
which quantity the 60s hard cap governs; it is scoped as the improvement
|
||||
bug the 20-60s band requires, and should be milestoned instead if the
|
||||
cap is read as covering the whole invocation.
|
||||
|
||||
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).
|
||||
Post-1.0 follow-ups are open, none blocking the tag:
|
||||
https://git.eeqj.de/sneak/webhooker/issues/245,
|
||||
https://git.eeqj.de/sneak/webhooker/issues/246,
|
||||
https://git.eeqj.de/sneak/webhooker/issues/247 and
|
||||
https://git.eeqj.de/sneak/webhooker/issues/248. Also still open and
|
||||
unmilestoned: https://git.eeqj.de/sneak/webhooker/issues/193 (a design
|
||||
question, not a defect), https://git.eeqj.de/sneak/webhooker/issues/198
|
||||
(`make test` is past the org 20s target) and
|
||||
https://git.eeqj.de/sneak/webhooker/issues/212 (encrypting target config
|
||||
at rest).
|
||||
|
||||
# Completed Steps
|
||||
|
||||
@@ -308,14 +292,16 @@ credential-leak fix because it needs a key-rotation and re-wrap story).
|
||||
|
||||
# Future Steps
|
||||
|
||||
- Manual event redelivery from the web UI — the "Replay" capability the
|
||||
README describes as planned. No redelivery code exists anywhere in the
|
||||
tree; events are stored in full, which is all it would be built on
|
||||
- Delivery status and retry management UI
|
||||
- Delivery status and retry management UI. Replay of a terminally
|
||||
failed delivery and per-attempt detail already landed
|
||||
(https://git.eeqj.de/sneak/webhooker/issues/203,
|
||||
https://git.eeqj.de/sneak/webhooker/issues/202)
|
||||
- Per-webhook rate limiting in the receiver handler (per-webhook config
|
||||
plus handler enforcement; global limits must not apply to receiver
|
||||
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;
|
||||
Bearer token middleware does not)
|
||||
- REST API v1
|
||||
@@ -325,9 +311,10 @@ credential-leak fix because it needs a key-rotation and re-wrap story).
|
||||
- OpenAPI specification
|
||||
- Analytics dashboard: success rates, response times, volume
|
||||
- A remember-me option at login
|
||||
- Password reset flow for a forgotten password. The authenticated
|
||||
password *change* flow already landed on `main` (#65); reset does not
|
||||
exist
|
||||
- Password reset flow for a forgotten password over the web. The
|
||||
authenticated password *change* flow already landed, and a lost
|
||||
password is recoverable from the console with `webhooker resetpw`
|
||||
(https://git.eeqj.de/sneak/webhooker/issues/208)
|
||||
- Later, nice to have
|
||||
- email delivery target type
|
||||
- SNS and S3 delivery targets
|
||||
|
||||
Reference in New Issue
Block a user