Restore TODO.md and move TODO content out of README (#58)
All checks were successful
check / check (push) Successful in 4s
All checks were successful
check / check (push) Successful in 4s
Reviewed-on: #58 Co-authored-by: sneak <sneak@sneak.berlin> Co-committed-by: sneak <sneak@sneak.berlin>
This commit was merged in pull request #58.
This commit is contained in:
90
README.md
90
README.md
@@ -893,95 +893,7 @@ linted, tested, and compiled.
|
|||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
### Completed: Code Quality (Phase 1 of MVP)
|
See [TODO.md](TODO.md).
|
||||||
- [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
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
75
TODO.md
Normal file
75
TODO.md
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user