2026-10-21 18:27:09 -06:00
|
|
|
"""The notification event types. One routing rule per type lives in `notification_rules`.
|
|
|
|
|
|
|
|
|
|
A security type cannot be opted out of on Account settings, and the Admin cannot exclude anyone from it either.
|
|
|
|
|
A department-scoped type carries the department of its packet, so it can go to that department's Supervisor group.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
class EventType:
|
|
|
|
|
key: str
|
|
|
|
|
label: str
|
|
|
|
|
description: str
|
|
|
|
|
security: bool = False
|
|
|
|
|
dept_scoped: bool = False
|
|
|
|
|
param: str | None = None # "hours" or "days"
|
|
|
|
|
param_default: int | None = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_TYPES = (
|
|
|
|
|
EventType(
|
|
|
|
|
"security_alert",
|
|
|
|
|
"Security alert",
|
|
|
|
|
"An account cooldown started, a PIN was disabled after five wrong tries, or a session ended after three"
|
|
|
|
|
" wrong unlock or signature PINs.",
|
|
|
|
|
security=True,
|
|
|
|
|
),
|
|
|
|
|
EventType(
|
|
|
|
|
"signin_burst",
|
|
|
|
|
"Sign-in burst",
|
|
|
|
|
"The per-address sign-in limit tripped, or many sign-ins failed across accounts in five minutes.",
|
|
|
|
|
security=True,
|
|
|
|
|
),
|
|
|
|
|
EventType(
|
|
|
|
|
"integrity_failure",
|
|
|
|
|
"Integrity check failure",
|
|
|
|
|
"The nightly integrity check found a broken seal, a changed or missing file, or a break in the audit chain.",
|
|
|
|
|
security=True,
|
|
|
|
|
),
|
|
|
|
|
EventType("feed_failed", "Feed run failed", "A VISUAL feed or drawing lookup run failed."),
|
|
|
|
|
EventType("feed_degraded", "Feed run degraded", "A VISUAL feed run finished with errors."),
|
|
|
|
|
EventType(
|
|
|
|
|
"drawing_failing",
|
|
|
|
|
"Drawing lookup failing",
|
|
|
|
|
"Drawing lookups in M-Files have failed for more than the set number of hours.",
|
|
|
|
|
param="hours",
|
|
|
|
|
param_default=24,
|
|
|
|
|
),
|
|
|
|
|
EventType(
|
|
|
|
|
"ad_reconcile_report",
|
|
|
|
|
"AD reconcile report",
|
|
|
|
|
"The nightly AD reconcile added or deactivated people, found extra groups, or flagged employee IDs.",
|
|
|
|
|
),
|
|
|
|
|
EventType("group_missing", "Group missing from the OU", "A mapped PS group is not in the PacketStation OU."),
|
|
|
|
|
EventType("backup_stale", "Backup failed or stale", "The newest database backup is missing, empty, old or failed."),
|
|
|
|
|
EventType(
|
|
|
|
|
"co_waiting",
|
|
|
|
|
"Change order waiting",
|
|
|
|
|
"A change order has waited for review for more than the set number of days.",
|
|
|
|
|
dept_scoped=True,
|
|
|
|
|
param="days",
|
|
|
|
|
param_default=3,
|
|
|
|
|
),
|
|
|
|
|
EventType(
|
|
|
|
|
"qc_reject",
|
|
|
|
|
"Hold-point or ITP reject",
|
|
|
|
|
"Q.C. rejected a packet, or an ITP line was rejected.",
|
|
|
|
|
dept_scoped=True,
|
|
|
|
|
),
|
|
|
|
|
EventType("version_deployed", "Version deployed", "The worker started on a new build."),
|
|
|
|
|
EventType("assets_quota", "Assets storage warning", "The assets storage passed its warning threshold."),
|
2026-10-30 17:50:04 -06:00
|
|
|
EventType(
|
|
|
|
|
"archive_failed",
|
|
|
|
|
"Archive copy failing",
|
|
|
|
|
"A filed packet could not be copied to the archive folder after three tries, or the archive folder check"
|
|
|
|
|
" failed.",
|
|
|
|
|
),
|
2026-10-21 18:27:09 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
EVENT_TYPES: dict[str, EventType] = {t.key: t for t in _TYPES}
|
|
|
|
|
SECURITY_TYPES: frozenset[str] = frozenset(t.key for t in _TYPES if t.security)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_known(event_type: str) -> bool:
|
|
|
|
|
return event_type in EVENT_TYPES
|