From 58ccb73ccb67114036f1efb93c24bf9768e01295 Mon Sep 17 00:00:00 2001 From: sneak Date: Sun, 25 Oct 2026 02:24:03 +0000 Subject: [PATCH] Rewrite TODO.md sentence by sentence Rewritten from scratch against the code on next; the sections and their contents are kept. Model: fable-5-1 --- TODO.md | 92 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/TODO.md b/TODO.md index 6929c87..5eda813 100644 --- a/TODO.md +++ b/TODO.md @@ -1,72 +1,74 @@ # Workflow -One issue per unit of work, one branch and one PR per issue: +One issue per unit of work, and 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` +- make sure a tracked issue exists with a definition of done +- branch from `next`, never from `main` +- do the work, then open a PR with base `next`, never `main` +- pass an independent review +- the repository manager, the role that merges every PR, then squash-merges it + 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. +`next` is the branch for the next milestone. It must stay green and mergeable +into `main` at all times. A milestone's work reaches `main` through one PR from +`next`. Cutting a release from `main` is a separate step after that. -The tracker (https://git.eeqj.de/sneak/webhooker/issues) is the record of what -is done and what is under way. This file keeps no list of either. +The tracker (https://git.eeqj.de/sneak/webhooker/issues) records what is done +and what is under way. This file keeps no list of either. # Status What is still open for 1.0.0 is in its milestone -(https://git.eeqj.de/sneak/webhooker/milestone/9). `v1.0.0` is not tagged, and -only @sneak tags it. +(https://git.eeqj.de/sneak/webhooker/milestone/9). `v1.0.0` is not tagged. Only +@sneak tags it. -Delivery is at-least-once by design, not by accident: a send whose result row -does not land is attempted again, so a receiver can see a duplicate. That is -deliberate — the alternative is a silent lost delivery — and the README says so -under Rationale. It is not a defect to re-file. +Delivery is at least once by design. When webhooker cannot record the outcome of +a delivery, it sends that delivery again. The target can then receive the same +event twice. The alternative is a lost delivery that nothing reports. The README +says so under How it works. Such a duplicate is not a defect to re-file. # Next Step @sneak runs webhooker in limited production, then tags `v1.0.0`. Merging `next` -into `main` is a separate act from tagging and waits on neither of those: `next` -is kept mergeable at all times, which is the point of the branch. +into `main` is a separate act. It waits on neither the production run nor the +tag. `next` is kept mergeable at all times; that is the point of the branch. # Future Steps -- Per-webhook rate limits, set in the web UI and enforced in the receiver - handler, on top of the receiver's existing limits, which `RECEIVER_RATE_LIMIT` - sets for the whole server (see Rate Limiting in the README) -- API key authentication for programmatic access (the `APIKey` model exists, but - nothing creates a key and no middleware checks one) -- REST API v1 - - CRUD for webhooks, entrypoints, targets +- Per-webhook rate limits, set in the web UI and enforced at the entrypoint. + Today `RECEIVER_RATE_LIMIT` is the only setting. It is how many requests per + minute one client address may send to one entrypoint. The same address is also + capped at ten times that across all entrypoints together. +- API key authentication for programmatic access. The `APIKey` model and its + `api_keys` table exist. Nothing creates a key and nothing checks one. +- REST API v1. `/api/v1` is mounted with no routes today. + - CRUD for webhooks, entrypoints and targets - event viewing and filtering endpoints - event redelivery endpoint - OpenAPI specification - Analytics in the web UI: response times summarised per webhook or per target, - and figures for all webhooks together. The webhook page already shows event, - delivery and failure counts and failure percentages, the target list counts - each target's deliveries, the event log and each event's page show every - attempt's duration, and `/metrics` carries server-wide counts and delivery - durations -- A remember-me option at login. Every session already survives a browser - restart: it lasts up to 7 days, and ends sooner after `SESSION_IDLE_TIMEOUT` - (default 24 hours) without activity -- 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) + and figures for all webhooks together. Today the webhook page shows event, + delivery and failure counts and failure percentages. The target list counts + each target's deliveries. The event log shows every attempt's duration. + `/metrics` carries server-wide counts and delivery durations. +- A remember-me option at login. Today every session survives a browser restart. + It lasts up to 7 days. It ends sooner after `SESSION_IDLE_TIMEOUT` (default 24 + hours) without use. +- Password reset over the web for a forgotten password. Today a signed-in user + can change their password. A lost password is reset 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 - - data transformations (e.g. a configurable Slack message format; the Slack - target sends one fixed format today) - - JSONL file delivery with periodic S3 upload (the `database` target already - archives events to SQLite files, rotated hourly, daily or monthly if set, - and the webhook page offers them as one gzipped JSON download) + - data transformations, such as a configurable Slack message format. The + Slack target sends one fixed format today. + - JSONL file delivery with periodic S3 upload. Today the `database` target + archives events to SQLite files. A target can rotate those files hourly, + daily or monthly. The webhook page offers them as one gzipped JSON + download. - webhook event search, and filtering beyond the event log's failed and pending views - - multi-user with role-based access control (each webhook already belongs to - one account, but there is only the account made at first boot and no way - to add another) + - multi-user with role-based access control. Today each webhook belongs to + one account. Only the account made at first boot exists. There is no way + to add another.