# TODO — migadu_counters State as of 2026-11-09. Review findings refer to `review/README.md`; the proof tests live in `review/_proof_tests/` and should become regression tests as each item is fixed (round 1 and items 7–8 are mapped at the end of `review/_proof_tests/README.md`). ## Done - Review round 1: #1–#6 (queue + 202, lenient validation + IDN, token logins, INCR with per-key results and master re-read, CDB parse cache, mandatory token / port 5555), plus `contrib/pull-domains.sh` and `counterctl --in/--out`. - #7 plus-addressing counts against the mailbox (`domains.Mailbox`). - #8 malformed CDB row is "not hosted" + warning (`domains.ErrMalformed`). ## Review round 2 — done 2026-11-09 #9-#17 fixed, plus the new findings from the 2026-11-09 review: repeat notifications after a lost Redis reply, pool timeouts treated as unknown outcomes, login suffix in the counting log, no retry of rejected transactions, `/counters` punycode, counter day taken from arrival time, CDB corruption checks, context deadlines on Redis sockets, example config path and placeholders, non-zero exit on a failed drain. Also added: the 80% early warning (`warn_percent`, `warn_*_url`) and per-counter notification markers. ## Open - [ ] **Persistent / recoverable counting on Redis outage** (deferred from round 1, #4). A Redis stall longer than a few seconds fills the queue and new requests are dropped (503, `dropped_total`). Decide whether drop-and-alert is acceptable before building anything. - [ ] **Exempt `mail_from` on `/in`.** An outside sender using `MAIL FROM:` avoids the recipient's incoming count, unless mizu rejects such senders inbound (not confirmed). Matches the old Lua rule; decide whether to keep it. - [ ] **Test gap.** Watcher tests can occasionally pass on a stale signal: make them wait for the specific reload they triggered. ## Outside this repo (deployment prerequisites) - [ ] **mailqueuer client**: `[counters]` section and a fire-and-forget POST `/in`|`/out` per recipient inside the publish loop of `mailqueuer/internal/handler/ingest.go` (after a successful publish; `/out` when `X-Auth-User` is set). Reply is `202 {"accepted":true}`; counted values only in the counting log and `GET /counters`. - [ ] **Ansible role** in `ansible-freebsd3`, cloned from `roles/rcptd`: user/group, `config.toml.j2` (`auth_token` is mandatory, port 5555), rc.d script under `daemon(8)`, newsyslog entries for `app.log`, `counting.log`, `pull.log`, templated `contrib/pull-domains.sh` + `contrib/migadu_counters-pull.cron` (see `contrib/README.md`), agent host key acceptance, firewall: mailqueuer hosts → :5555, service → Sentinel :26379/:6379 and admin.migadu.com:443. - [ ] **migadu_web** `/api/limits` `D` branch (domain level); until then `notify.domain_url` stays empty. - [ ] **migadu_web3 branch `limit-warning-notifications`**: review the warning email wording, merge and deploy, then set `warn_org_url` and `warn_address_url`. Until then warnings stay off. - [ ] **Firewall / monitoring**: `admin_addr` now defaults to localhost; set it explicitly if `/metrics` or `/health` are scraped from another host. - [ ] **Limits re-tuning**: outgoing is counted per recipient (Lua counted per message), so existing `*/o` limits are stricter. Review before relying on `outgoing_limit_exceeded!`. - [ ] **Retire stats-merger's quota module** once this service is the source (only fernrohr reads it). - [ ] **Dependencies**: `golang.org/x/net` is pinned to v0.43.0 because the offline module cache had it; run `go get -u golang.org/x/net && go mod tidy` with network access.