From e0b1e7cf54d6cb5cad36e0b9ca86ff4759c660c3 Mon Sep 17 00:00:00 2001 From: sneak Date: Mon, 6 Jul 2026 21:14:03 +0200 Subject: [PATCH] Restore TODO.md and move TODO content out of README (#58) Reviewed-on: https://git.eeqj.de/sneak/webhooker/pulls/58 Co-authored-by: sneak Co-committed-by: sneak --- README.md | 90 +------------------------------------------------------ TODO.md | 75 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 89 deletions(-) create mode 100644 TODO.md diff --git a/README.md b/README.md index 4012491..06a2e18 100644 --- a/README.md +++ b/README.md @@ -893,95 +893,7 @@ linted, tested, and compiled. ## TODO -### Completed: Code Quality (Phase 1 of MVP) -- [x] Rename Processor → Webhook, Webhook → Entrypoint in code - ([#12](https://git.eeqj.de/sneak/webhooker/issues/12)) -- [x] Embed templates via `//go:embed` - ([#7](https://git.eeqj.de/sneak/webhooker/issues/7)) -- [x] Use `slog.LevelVar` for dynamic log level switching - ([#8](https://git.eeqj.de/sneak/webhooker/issues/8)) -- [x] Simplify configuration to prefer environment variables - ([#10](https://git.eeqj.de/sneak/webhooker/issues/10)) -- [x] Remove redundant `godotenv/autoload` import - ([#11](https://git.eeqj.de/sneak/webhooker/issues/11)) -- [x] Implement authentication middleware for protected routes - ([#9](https://git.eeqj.de/sneak/webhooker/issues/9)) -- [x] Replace Bootstrap with Tailwind CSS + Alpine.js - ([#4](https://git.eeqj.de/sneak/webhooker/issues/4)) - -### Completed: Core Webhook Engine (Phase 2 of MVP) -- [x] Implement webhook reception and event storage at `/webhook/{uuid}` -- [x] Build event processing and target delivery engine -- [x] Implement HTTP target type (fire-and-forget with max_retries=0, - retries with exponential backoff when max_retries>0) -- [x] Implement database target type (store events in per-webhook DB) -- [x] Implement log target type (console output) -- [x] Implement Slack target type (Slack/Mattermost incoming webhook - notifications with pretty-printed payloads) -- [x] Webhook management pages (list, create, edit, delete) -- [x] Webhook request log viewer with pagination -- [x] Entrypoint and target management UI - -### Completed: Per-Webhook Event Databases -- [x] Split into main application DB + per-webhook event DBs -- [x] Per-webhook database lifecycle management (create on webhook - creation, delete on webhook removal) -- [x] `WebhookDBManager` component with lazy connection pooling -- [x] Event-driven delivery engine (channel notifications + timer-based retries) -- [x] Self-contained delivery tasks: in the ≤16KB happy path, the engine - delivers without reading from any database — target config, event - headers, and body are all carried inline in the channel notification. - The engine only touches the DB to record results (success/failure). - Large bodies (≥16KB) are fetched from the per-webhook DB on demand. -- [x] Database target type marks delivery as immediately successful - (events are already in the per-webhook DB) -- [x] Parallel fan-out: all targets for an event are delivered via - the bounded worker pool (no goroutine-per-target) -- [x] Circuit breaker for HTTP targets with retries: tracks consecutive - failures per target, opens after 5 failures (30s cooldown), - half-open probe to test recovery - -### Completed: Security Hardening -- [x] Security headers middleware (HSTS, CSP, X-Frame-Options, - X-Content-Type-Options, Referrer-Policy, Permissions-Policy) - ([#34](https://git.eeqj.de/sneak/webhooker/issues/34)) -- [x] Session regeneration on login to prevent session fixation - ([#38](https://git.eeqj.de/sneak/webhooker/issues/38)) -- [x] Request body size limits on form endpoints - ([#39](https://git.eeqj.de/sneak/webhooker/issues/39)) - -### Remaining: Core Features -- [ ] Per-webhook rate limiting in the receiver handler -- [ ] Webhook signature verification (GitHub, Stripe formats) -- [x] CSRF protection for forms - ([#35](https://git.eeqj.de/sneak/webhooker/issues/35)) -- [x] SSRF prevention for HTTP delivery targets - ([#36](https://git.eeqj.de/sneak/webhooker/issues/36)) -- [x] Login rate limiting (per-IP brute-force protection) - ([#37](https://git.eeqj.de/sneak/webhooker/issues/37)) -- [ ] Session expiration and "remember me" -- [ ] Password change/reset flow -- [ ] API key authentication for programmatic access -- [ ] Manual event redelivery -- [ ] Analytics dashboard (success rates, response times) -- [ ] Delivery status and retry management UI - -### Remaining: Event Maintenance -- [ ] Automatic event retention cleanup based on `retention_days` - -### Remaining: REST API -- [ ] RESTful CRUD for webhooks, entrypoints, targets -- [ ] Event viewing and filtering endpoints -- [ ] Event redelivery endpoint -- [ ] OpenAPI specification - -### Future -- [ ] Email delivery target type -- [ ] SNS, S3, Slack delivery targets -- [ ] Data transformations (e.g., webhook-to-Slack message formatting) -- [ ] JSONL file delivery with periodic S3 upload -- [ ] Webhook event search and filtering -- [ ] Multi-user with role-based access +See [TODO.md](TODO.md). ## License diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..690b26b --- /dev/null +++ b/TODO.md @@ -0,0 +1,75 @@ +# 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 + +# Status + +pre-1.0. No git tags exist. main (afe88c6) is a working webhook proxy +with auth, CSRF/SSRF protections, login rate limiting, Slack target, +policy compliance (#6), and pinned lint tooling (#55). 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 + +Implement automatic event retention cleanup based on retention_days: a +periodic maintenance job that deletes Events, Deliveries, and +DeliveryResults older than the parent webhook's retention_days from each +per-webhook event database. The field exists on the Webhook model and +the README promises the behavior, but nothing enforces it, so event +databases currently grow without bound. + +# Completed Steps + +- 2026-03-25 pin golangci-lint Docker image for linting (#55) +- 2026-03-18 CSRF middleware detects TLS per-request, fixing login over + plain HTTP and behind reverse proxies (#54) +- 2026-03-17 root path redirects based on auth state (#52) +- 2026-03-17 CSRF protection, SSRF prevention for HTTP delivery targets + with DNS rebinding defense, and per-IP login rate limiting (#42) +- 2026-03-17 Slack target type for incoming webhook notifications (#47) +- 2026-03-17 Dockerfile absolute paths and static linking (#49); + absolute dev DATA_DIR default and clarified env docs (#46) +- 2026-03-05 security headers middleware, session regeneration on + login, request body size limits (#41) +- 2026-03-04 tests for delivery, middleware, and session packages + (#32); removed globals.Buildarch (#31) +- 2026-03-04 1.0 MVP merge: Webhook/Entrypoint/Target rename, core + delivery engine with bounded worker pool and circuit breaker, + parallel fan-out, per-webhook event databases, management UI (#16) +- 2026-03-01 repo brought to REPO_POLICIES standards; TODO.md folded + into README (#6) + +# Future Steps + +- Manual event redelivery from the web UI (replay is a core promised + capability in the README rationale) +- Delivery status and retry management UI +- 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 +- API key authentication for programmatic access (APIKey model exists; + Bearer token middleware does not) +- REST API v1 + - CRUD for webhooks, entrypoints, targets + - event viewing and filtering endpoints + - event redelivery endpoint + - OpenAPI specification +- Analytics dashboard: success rates, response times, volume +- Session expiration tuning and a remember-me option +- Password change and reset flow +- Later, nice to have + - email delivery target type + - SNS and S3 delivery targets + - data transformations (e.g. webhook to Slack message formatting) + - JSONL file delivery with periodic S3 upload + - webhook event search and filtering + - multi-user with role-based access control