fix+feat: site mail log, phantom staging, sidebar status, ClamAV niceness - #91
Merged
Conversation
… niceness MAIL SENT BY THIS SITE — reported twice as "still doesn't work", and the cause was neither the wrapper nor the mail path. The wrapper writes JSON keys `from` and `to`; SiteEmailLogEntry declared `from_address` and `to_address` with no alias, so serde failed on EVERY line — and the reader parses with `filter_map(.. .ok())`, which turned each failure into a silently dropped record. The panel then said "No outbound mail captured yet" forever, however much mail the site sent. Aliases fix it for the jsonl already on disk; `#[serde(default)]` means one odd record loses a column instead of hiding every record around it. Three tests pin the wrapper's exact output, a missing field, and the unchanged wire format. PHANTOM STAGING. The staging card rendered unconditionally: "Open staging ↗" linked to a computed `staging.<domain>` that had never been provisioned, and "Push staging → production" offered to overwrite the live site from a source that did not exist. Both are now behind an existence check, so the card shows either the create form or the live actions, never both. ACME DIRECTORY was empty because nothing ever populated it — and worse, the key was writable while being read by nobody: issuance hardcodes the Let's Encrypt endpoints, so saving it wrote a value into agent.toml that reads as authoritative and changes nothing. A knob that lies is worse than no knob, so the field is gone from the form and the key is no longer accepted; the panel states the endpoint it actually uses. SIDEBAR STATUS. Monitoring, WordPress updates and Certificates now carry a dot: green when nothing needs attention, a red count when something does. One request feeds all three, so they cannot disagree with each other, and nothing is painted until a response arrives — a green dot nobody checked would be worse than no dot. CLAMAV NICENESS. clamscan is single-threaded but CPU-bound and will saturate a core for minutes, which on a small VPS is the difference between a site that responds and one that does not. Scans now run under `nice` (+ `ionice` best-effort, since starving nginx of disk is the other half of "the site went slow during a scan"). The default is a RECOMMENDATION derived from core count rather than 0 — one core gets 19, many cores get 5 — because a default of "no limit" means every box has the problem until someone goes looking for the switch. Overridable via `[integrity] scan_niceness`. Care packages: Edit is a button rather than a text link. It is the row's primary action and sat next to real buttons looking like a caption. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First tranche of the latest round. Each diagnosis below was verified against the code, then adversarially re-checked before anything was changed.
"Mail sent by this site" — reported twice as still broken
Neither the wrapper nor the mail path was at fault. The wrapper writes JSON keys
fromandto(site-mail-wrapper.sh:171);SiteEmailLogEntrydeclaredfrom_address/to_addresswith no alias. serde therefore failed on every line — and the reader parses withfilter_map(… .ok()), turning each failure into a silently dropped record. The panel said "No outbound mail captured yet" forever, however much mail went out.Fixed with
alias(so the RPC wire and templates keep the long names, and the jsonl already on every node stays readable) plus#[serde(default)], so one odd record loses a column instead of hiding every record around it. Three tests: the wrapper's exact output, a missing field, and the unchanged wire format.Phantom staging card
The card rendered unconditionally. "Open staging ↗" linked to a computed
staging.<domain>that had never been provisioned, and "Push staging → production" offered to overwrite the live site from a source that did not exist. Both are now behind an existence check.ACME directory was empty
Nothing ever populated it —
directory_url: String::new(), // not stored here. Worse, the key was writable but read by nobody: issuance hardcodes the Let's Encrypt endpoints, so saving it persisted a value intoagent.tomlthat reads as authoritative and changes nothing. A knob that lies is worse than no knob — the field is gone and the key is no longer accepted; the panel states the endpoint it actually uses.Sidebar status dots
Monitoring, WordPress updates and Certificates carry a dot: green when nothing needs attention, a red count when something does. One request feeds all three so they cannot disagree, and nothing is painted until a response arrives — a green dot nobody checked would be worse than no dot.
ClamAV niceness — with recommended defaults
clamscanis single-threaded but CPU-bound and will saturate a core for minutes; on a small VPS that's the difference between a site that responds and one that doesn't. Scans now run undernice, plusionicebest-effort (starving nginx of disk is the other half of "the site went slow during a scan").The default is a recommendation derived from core count, not 0 — 1 core → 19, 2-3 → 15, 4-7 → 10, 8+ → 5 — because a default of "no limit" means every box has the problem until someone goes looking for the switch. Override with
[integrity] scan_niceness.nicebeats a hard percentage cap here: it costs nothing on an idle box and yields instantly when a web request wants the CPU.Care packages
Edit is a button, not a text link — it's the row's primary action and sat next to real buttons looking like a caption.
Tests
cargo test --workspacegreen,cargo fmt --allclean.🤖 Generated with Claude Code