feat(admin): surface email-ingress / IMAP-poll / retention-sweep health on /admin/settings (LC-207-OBSERVABILITY) #281
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/lc-207-observability-ingress-sweep-imap"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #278 (LC-207-OBSERVABILITY). Three background subsystems had a
tracinglog line as their sole operator-facing diagnostic. This persists runtime status for each and surfaces it read-only on the existing/admin/settingspage, mirroring the LC-207 bridge-avatar diagnostic precedent, so an operator can self-serve "is ingress alive / why didn't my email post? / did the destructive sweep run?" without container-log access.What lands
IMAP poll health (
O3).spawn_email_pollwrites asettings.dbsingleton (imap_poll_status, migrationsettings/0008) every tick: last poll, last success, consecutive-failure counter, last error, and last-tick fetched/posted/dropped. A failure increments the counter and preserves the last-success time; a success resets both and clears the error.Email-ingress drops (
O1). The three drop sites inpoll_once(FETCH-fail, oversize, per-message drop) record to achat.dblog (email_ingress_drops, migrationchat/0058): structuredDropReason, the IMAP UID, and a bounded (200-char) non-body diagnosticdetailonly. It never stores the message body, subject, or any correspondent address. Rows are swept at 30 days by the hourly orphan sweeper alongside the dedup table. The page shows a by-reason summary (last 24h) plus the most recent 20 drops.Retention sweep (
O2).spawn_message_retention_sweeperrecords every completed tick (including zero-delete) to achat.dbsingleton (retention_sweep_status, migrationchat/0059): last run, last/total messages deleted, run count, last error. Failures record the error without advancinglast_run_at(a failed tick is not a completed run). The page shows enabled/disabled (theLETS_CHAT_RETENTION_SWEEP_ENABLEDgate) plus the run snapshot, so an operator who enabled the destructive sweep can confirm it ran and how much it deleted.Notes
#[cfg(feature = "standalone")]/admin/settingsroute, so saas is unaffected. i18n keys added toen+es.[operator-action]: this is additive observability with no new env var, config, or required operator step.Validation
just testandjust test-saasgreen.just checkclean: server standalone + saas clippy (-D warnings,--all-targets), desktop compile,cargo fmt --check. New tests:db_observability_status(round-trips for all three modules - failure-counter climb + recovery, drop recent/counts/sweep/truncation, run accumulation + error-without-run) androutes_admin_observability(standalone-gated render: seeded health + drops appear, placeholders when empty, retention disabled-hint names the env var).migration_enclaveshand-rolled chat array updated for the two new chat migrations (CLAUDE.md category-2 drift).🤖 Generated with Claude Code