send_webhook_email() only returned False on a network exception — a
webhook that responded with a non-2xx status (bad URL, wrong API key,
misconfigured Power Automate flow) was still reported as delivered. Now
checks response.ok and returns False on rejection too.
send_password_setup_email() also never checked the return value at all,
so the admin's 'Send Email' action (including resending a password-reset
email after the user already set their password) always showed success
even when nothing was actually sent. Now raises a clear error instead.
- All webhook emails now render as branded HTML (dark header, inline base64
Aegis logo, card layout, CTA-button links) instead of plain text.
- Wired the 7 remaining notification-preference keys that had no trigger:
stale coverage alerts, campaign-activated assignment emails, generic
test-state-change steps (execution started / blue evaluating / in review),
all-team-validation broadcasts on every lead vote, webhook delivery
failures (3rd consecutive failure), new user registration, and background
job errors (APScheduler global error listener).
- New notify_roles_by_email() helper for role-scoped, preference-gated,
actor-excludable broadcasts.
- Fixed apscheduler.events stubbing gaps in several test files' sys.modules
fakes that broke full-suite collection after adding the APScheduler
error-listener import.
- Renamed the password-setup webhook (email_webhook.*, /system/email-webhook-config)
and made it the single transport for all notification emails.
- New webhook_email_service.py shared by password_setup_service and
notification_service.
- Wired test validated/rejected, campaign completed, and new-MITRE-technique
notifications through the webhook (previously dead SMTP code, never triggered).
- Added POST /system/email-webhook-test to send a real test email.
- Hid the Email/SMTP settings tab from the UI (SMTP code kept intact, unused).
- Redact email_webhook.api_key on config export.
- A lead opening a test with a pending procedure suggestion awaiting
their review now gets a blocking popup (approve/reject only) instead
of discovering it later in a separate queue.
- Users can be granted more than one role via extra_roles; only one is
ever active at a time (no permission mixing) and a top-bar switcher
lets the user swap which one, taking effect immediately since role
is read fresh from the DB on every request.
- The password-setup/reset webhook now posts the agreed Power Automate
contract ({to, subject, body} with the platform's standard greeting
and signature template) and supports an admin-configured API key
sent as an x-api-key header.
Admins now create users with a name + email (no password) and role;
a Send Email action (per-user, also reusable for resets) issues a
one-time token and POSTs it to an admin-configurable webhook URL —
intended for a Power Automate flow that delivers the actual email.
The old admin-sets-the-password flow is kept server-side
(LegacyUserCreateWithPassword) but no longer wired into the UI.
Every user-facing surface (top bar, sidebar, user management, audit
log, assignee pickers, dispute notifications) now shows full_name
instead of username, falling back to username when unset.
Also fixes long attack_procedure/expected_detection/suggested_text
text overflowing its container in the template review panels and
Red/Blue team fields (missing break-words on whitespace-pre-wrap
blocks).