4.6 KiB
Code Map
This map describes the implemented Python modules and their main responsibilities.
Application Entry Points
app/main.pycreates the FastAPI app, loads settings, configures logging, initializes the database, mounts static assets, starts the scheduler on startup, and defines HTML/API routes.app/cli.pyexposespython -m app.cli backlogfor backlog processing using the sameprocess_inbox()pipeline as the admin API.Dockerfilerunsuvicorn app.main:app --host 0.0.0.0 --port 8000.
Configuration and Auth
app/config.pydefines Pydantic models forapp,security,llm,inboxes,known_senders, andalerts.load_settings()readsDMARC_SENTINEL_CONFIGwhen set, otherwiseconfig/config.yml; missing runtime config is a startup error.validate_llm_environment()requires the configured OpenAI API key whenllm.providerisopenai, except whenDMARC_SENTINEL_ALLOW_NO_LLM_FOR_TESTS=true.app/auth.pyprotects dashboard/admin routes with Basic Auth when enabled and protects homepage API routes with bearer token auth when required.app/templates/settings.htmlrenders runtime settings and environment-variable presence as read-only information.
Persistence
app/db.pycreates a SQLAlchemy engine fromsettings.app.database_url, provides session helpers, and creates tables withBase.metadata.create_all().app/models.pydefines tables for inbox status, mail messages, parsed reports, records, auth results, alerts, daily stats, and stored LLM reports.- Duplicate report detection is based on the unique
Report.raw_xml_sha256field.
Ingestion Pipeline
The main ingestion path is implemented in app/message_processor.py:
process_inbox()opens an IMAP connection usingapp/imap_client.py.- It searches UIDs in either new-message mode or backlog mode.
- It stores or reuses a
MailMessagerow for each fetched message. is_candidate_message()checks recipients, subject text, and attachment hints.app/attachment_extractor.pyextracts.xml,.gz, and.zipreport payloads, rejects unsafe ZIP paths, skips nested archives inside ZIPs, and enforces the decompressed size limit.app/dmarc_parser.pyparses DMARC aggregate XML withdefusedxml.app/known_senders.pyclassifies each record using configured CIDR allowlists, DKIM domains, SPF domains, or aligned DKIM evidence.app/analyzer.pycreates or updates deterministic alerts.- Email notifications are sent through
app/alerts.pywhen configured and when a new alert is created or severity increases.
Deterministic Analysis
app/analyzer.py produces alerts from stored report records. Implemented alert paths include:
- unknown source failed both SPF and DKIM alignment;
- known sender DMARC failure;
- quarantine or reject disposition;
- first observed failing source;
- first observed passing but unclassified source;
- high SPF or DKIM alignment failure rate;
- sudden unknown failure spike;
- new reporter;
- first observed policy for a domain;
- missing expected reporter based on recent report history.
Open alerts are deduplicated by a fingerprint composed from domain, alert type, and key. Existing open alerts are updated rather than duplicated.
LLM Usage
app/llm.pywraps the OpenAI client for JSON-only alert explanations and daily/weekly summaries.- Alert existence and severity are deterministic in
app/analyzer.py; LLM output is stored as explanation fields on alerts or inLLMReportrows. - Fallback outputs are returned when LLM calls fail or validation fails.
- Config flags for raw XML and raw email are present in settings. The implemented LLM payloads use derived alert or summary facts.
Scheduler
app/scheduler.py starts an APScheduler BackgroundScheduler with these jobs:
poll: interval job usingsettings.app.poll_interval_minutes;daily: cron job at 07:00 insettings.app.timezone;weekly: cron job on Monday at 07:30 insettings.app.timezone.
Daily and weekly summary jobs aggregate stored data, call LLMClient, store LLMReport rows, and attempt digest email delivery through app/alerts.py.
HTTP and Template Surfaces
HTML routes in app/main.py render templates from app/templates/:
/: overview dashboard;/domains/{domain}: domain detail;/reports/{report_id}: report detail;/alerts: alert list and actions;/inboxes: inbox status and manual processing controls;/settings: read-only runtime configuration.
JSON routes include /health, homepage widget endpoints, domain/report/alert APIs, and admin processing endpoints. Authentication behavior is defined by route dependencies in app/main.py.