Skip to content

feat(infra): per-event configurable notification thresholds (#6) - #18

Merged
Metbcy merged 1 commit into
mainfrom
feat/notification-thresholds
Jun 3, 2026
Merged

feat(infra): per-event configurable notification thresholds (#6)#18
Metbcy merged 1 commit into
mainfrom
feat/notification-thresholds

Conversation

@Metbcy

@Metbcy Metbcy commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Summary

Implements #6: per-event configurable notification thresholds.

The pre-#6 dispatcher had three hard-coded rules: notify on scan.complete only when findings_count > 0, always on scan.failed, always on scanner.failed. This PR replaces those with a per-event minimum severity threshold that admins can change at runtime.

What's new

Backend

  • Migration 007_add_notification_settings.py creates notification_settings (event_type PK, min_severity, updated_at). No rows are seeded; defaults live in code so existing deployments are no-ops.
  • Severity ladder: info < low < medium < high < critical.
  • Defaults that match current behavior:
    • scan.complete: medium
    • scan.failed: info (always fires)
    • scanner.failed: info (always fires)
  • New helpers in database.py: get_notification_settings, get_notification_threshold, upsert_notification_threshold, NOTIFICATION_THRESHOLD_DEFAULTS.
  • New api/settings.py router: GET/PATCH /api/v1/settings/notifications (admin scope; legacy alias mounted via the existing versioning helper).
  • _create_notification_for_event now consults the per-event threshold. scan.complete's effective severity is the highest finding severity in the run; the publish site in _run_scan was extended to pass max_severity. Failure events synthesize as critical so any threshold up to and including critical still fires.
  • Backward compatibility: legacy publish sites and tests that omit max_severity are treated as worst-case so behavior matches the pre-feat(infra): per-finding configurable notification thresholds #6 hard-coded rules.

Frontend

  • /settings/notifications page in the keys/webhooks pattern: one card per event with a severity select and a Save button.
  • Sidebar nav entry "Notification rules".

Tests

  • 15 new tests cover defaults, GET/PATCH, validation, threshold-suppress and threshold-fire paths, the clean-scan no-notify path, and backward compat for all three event types.
  • Local: cd backend && ruff check . && ruff format --check . && python -m pytest tests/ -x -q — 948 passed, 2 skipped (pre-existing semgrep + weasyprint env-only failures excluded; same as main).
  • Frontend pnpm build clean. pnpm lint adds 1 error to the 21 pre-existing baseline using the same void load() pattern other settings pages use.

Adds a notification_settings table (migration 007) with one row per
event type holding a configurable minimum severity threshold. Defaults
are applied in code so upgrades are no-ops:

- scan.complete: medium (approximates the prior any-finding rule)
- scan.failed: info (always notify)
- scanner.failed: info (always notify)

The dispatcher now consults the threshold before persisting an in-app
notification. Failure events are synthesized at critical severity so
threshold up to and including critical fires; clean scans never
notify regardless of threshold.

Adds GET/PATCH /api/v1/settings/notifications (admin scope) and a
matching /settings/notifications page in the dashboard.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Metbcy
Metbcy force-pushed the feat/notification-thresholds branch from 0779c21 to a30c9d9 Compare June 3, 2026 15:14
@Metbcy
Metbcy merged commit e5177a7 into main Jun 3, 2026
2 checks passed
@Metbcy
Metbcy deleted the feat/notification-thresholds branch June 3, 2026 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant