fix(reaper): deliver pre-reap warnings for real — and never fake a delivery
The §18 warning path had no delivery channel at all: no Warner implementation existed, `felis reaper` passed nil, and maybeWarn still stamped warned_3d_at/ warned_1d_at and counted `warned=N`. So every owned server was silently reaped 15 days after its last join with no notice, and the operator's only feedback said warnings were sent. Two changes close that: - Honest stamps: warned_* now records a DELIVERED notice. A nil Warner logs `warning suppressed — no warner wired` and does NOT stamp; a delivery error logs and retries on the next daily run (bounded by the warning window). The stamps are no longer burned by notices nobody received. - A real channel: mail.SendNotice (the second and last message shape the mail package sends) plus a mailWarner that resolves the owner's VERIFIED email and mails the notice through the configured [smtp] relay. `felis reaper` wires it when [smtp] is set (same password_ref convention as felis-api) and prints exactly what happens when it is not. Plumbing so the in-cluster CronJob can actually reach the relay: the reaper pod gets the optional FELIS_SMTP_PASSWORD env (same Secret as felis-api), and the "configure email" screen now refreshes the minecraft-namespace mirrors of felis-smtp AND felis-config (a secretKeyRef is namespace-local, and the config mirror is what carries [smtp] into the reaper's own config). `felis setup`'s replica list gains felis-smtp for fresh installs. Tests: the delivered/retried/suppressed matrix in internal/reaper (the old "stamp advances on failure" contract is deliberately replaced), the notice message shape, the warner's resolve/send/failure paths, and the CronJob's optional-secret env. docs/troubleshooting.md §10 now states the real semantics.
This commit is contained in:
12 files changed
+375
-27
No files matched your search
@@ -504,6 +504,29 @@ So a missing backup never results in a deleted world. [GO-TESTED:
|
||||
- CRD missing → logs `reaper: CRD missing, skipping`, skipped.
|
||||
- Idle `≤ 15d` → not yet eligible.
|
||||
|
||||
### Pre-reap warnings (the `warn_before` offsets)
|
||||
|
||||
An OWNED server inside a warning window gets an email notice (`3d`/`1d` before
|
||||
the deadline, `warn_before` from `[archive]`) to the owner's **verified** email —
|
||||
the same `[smtp]` relay felis-api uses. The `warned_3d_at` / `warned_1d_at`
|
||||
stamps record a **delivered** notice:
|
||||
|
||||
- No `[smtp]` configured (or owner has no verified address): the run logs
|
||||
`reaper: warning suppressed — no warner wired` / a delivery error and does
|
||||
NOT stamp. Nothing is falsely recorded as sent, and the day SMTP is
|
||||
configured the pending warning can still go out.
|
||||
- Delivery failure (relay down): logged and retried on the next daily run —
|
||||
bounded by the warning window, since the reap removes the candidate anyway.
|
||||
- `warned=` in the run output counts DELIVERED notices, not attempts.
|
||||
|
||||
The reaper runs in the minecraft namespace and reads the **mirrors** of
|
||||
`felis-smtp` and `felis-config` there (a `secretKeyRef` is namespace-local). The
|
||||
installed `felis setup`'s "configure email" screen refreshes both mirrors when it
|
||||
applies, so configuring SMTP after install is enough; a manual edit of the
|
||||
control-namespace Secret alone is not. [GO-TESTED: the delivered/retried/
|
||||
suppressed matrix in `internal/reaper`; live-drilled end to end against a local
|
||||
SMTP sink.]
|
||||
|
||||
### Genuine false-delete risk vectors
|
||||
|
||||
- **Stale `last_active_at`.** The keep-alive is `RecordJoin`, called from the
|
||||
|
||||
Reference in new issue
Block a user