From 67ce7978c4fcf8d950f6cf9e275aed5da587816f Mon Sep 17 00:00:00 2001 From: sneak Date: Wed, 12 Aug 2026 10:20:20 +0000 Subject: [PATCH] Update TODO.md for the completed 1.0.0 milestone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Records the trusted-proxy gating (#88), the hop cap (#124) and the bounded scan (#133), and corrects the Workflow section, which still described branching from main and committing TODO.md alongside the work — both contradicted by the branch-per-issue-onto-next model and by the decision on #112 that issue branches leave this file alone. --- TODO.md | 59 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/TODO.md b/TODO.md index 7900d62..8b1ee6d 100644 --- a/TODO.md +++ b/TODO.md @@ -1,31 +1,62 @@ # Workflow -* branch (from `main`) -* do the work in Next Step -* move Next Step to the top of Completed Steps -* move the top item of Future Steps into Next Step -* commit (`TODO.md` changes in the same commit as the work) -* merge to `main` if the branch is not protected, otherwise open a PR -* push +One issue per unit of work, one branch and one PR per issue: + +* ensure a tracked issue exists with a definition of done +* branch from `next` (never from `main`) +* do the work; open a PR based on `next` (never on `main`) +* pass an independent review, then the manager squash-merges into `next` +* push; nothing stays local-only + +`next` is the branch for the next milestone and must stay green and +mergeable to `main` without notice. One `next` -> `main` PR accumulates +the milestone; releases are cut from `main` separately. + +Issue branches do NOT touch this file — the manager maintains it on +`next`. Every branch editing `TODO.md` conflicts with every other +(#112). # Status -pre-1.0. No git tags exist. main (4f5ecb1) is a working webhook proxy +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). 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. +(#55), and fail-loud configuration parsing (#80). + +`next` (9bfd033) holds the completed 1.0.0 milestone: every issue in it +is closed, and it is verified green by cache-defeated container runs +rather than by the CI badge, which can pass without executing anything +(#119). 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 -Manual event redelivery from the web UI (replay is a core promised -capability in the README rationale). +Tag 1.0.0 from `main` once the milestone PR merges, then repair the CI +gate (#119) before the next cycle's work lands — a gate that can report +success without running is the one thing every other guarantee here +rests on. # Completed Steps +- 2026-08-12 Bound the `X-Forwarded-For` scan's allocation to the hop + cap: the reverse walk cuts entries with `strings.LastIndexByte` + instead of joining and splitting, so a 1 MB header allocates 16 bytes + rather than 1.6 MB per request on the unauthenticated receiver. + Semantics proven unchanged by differential testing against the + previous implementation (#133) +- 2026-08-12 Cap the `X-Forwarded-For` hop walk at 64 entries, so an + attacker-supplied chain cannot burn unbounded CPU in the rate-limit + key function; running off the end falls back to the peer address + (#124) +- 2026-08-12 Gate forwarded-header trust behind a `TRUSTED_PROXIES` CIDR + list: all three rate limiters key on the connection's own address + unless the direct peer is a configured proxy, in which case + `X-Forwarded-For` is walked right to left for the first non-proxy hop. + Default trusts nothing, and a set-but-unparseable value aborts + startup. Before this, any client could mint a fresh bucket or drain + another's by rotating a spoofed header (#88) - 2026-08-11 Web UI cleanup: nav terminology unified on Webhooks, the Profile settings placeholder removed, a progressive-enhancement copy button for the entrypoint URL, and retention form copy that states the