Issue 4: an SMTP add-on for e-mail notifications.
- SmtpSetup modal: server (host/port/encryption/user/pass), from/to, and
individual toggles for the events you want mailed — device offline, low
battery, automation messages. "Send test e-mail" button. Config stored
encrypted on the addon row; a runtime mailer is built from it (no .env edits).
- NotificationService: notify(event, …) sends only if SMTP is set up AND that
event is enabled; send() for the test.
- Triggers: automation "notify" actions e-mail (when enabled);
notifications:sweep (every 5 min) e-mails on NEW device-offline / low-battery
with per-condition dedup + battery hysteresis, so it's one mail per event.
6 tests (gating, per-event toggle, config persist + password-keep, sweep dedup).
Suite 82 green, 12/12 tabs clean; card + modal browser-verified.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codex R15 flagged two P1 correctness bugs in AutomationEngine:
- Conditions were never evaluated — a trigger→condition→action rule ran its
actions unconditionally. Now every stored condition must match current
entity state (AND) before actions run; a false condition does NOT touch the
cooldown clock, so the rule stays armed for its next legitimate trigger.
- Cooldown was read-check-then-save, so concurrent queue workers on a burst of
state changes could all pass the check and each fire. Now claimed with a
single conditional UPDATE — exactly one worker wins the race (H5).
+3 tests (condition true/false, cooldown-not-armed-on-failed-condition).
AutomationTest 9 green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>