-- DMARC aggregate (rua) report ingestion.
--
-- WHY: DMARC aggregate reports (RFC 7489) are the authoritative, cross-operator
-- view of who is sending mail AS us (header_from = performancewest.net / its
-- subdomains) and whether that mail passes SPF + DKIM alignment. Every major
-- receiver (Google, Yahoo, Comcast, Cox, Bell, Mimecast, Cisco ESA, GMX, mail.com,
-- ...) emails one zipped/gzipped XML per day to rua=mailto:dmarc@performancewest.net.
-- Reading them by hand is hopeless (dozens/day). This turns them into queryable
-- per-source-IP / per-domain SPF+DKIM+DMARC pass-fail trends so we can SEE:
--   * our own senders (.94 bulk / .107 hcout / .71 transactional / .15 relay) all
--     passing alignment (DKIM d=send. selector send, d=root selector mail) -- the
--     deliverability fixes this session were exactly about this; and
--   * any UNKNOWN IP sending as us that fails -- i.e. spoofing or a forgotten relay,
--     which is reputation poison under p=reject.
--
-- Populated by scripts/dmarc_report_parser.py (IMAP fetch dmarc@ -> unzip -> parse
-- XML -> upsert). Idempotent: each report is keyed by (org_name, report_id) and
-- re-parsing the same report is a no-op (ON CONFLICT DO NOTHING).

-- One row per aggregate report (the <report_metadata> + <policy_published>).
CREATE TABLE IF NOT EXISTS dmarc_report (
    id              BIGSERIAL PRIMARY KEY,
    org_name        TEXT        NOT NULL,           -- reporting operator (google.com, yahoo.com, ...)
    org_email       TEXT,                           -- contact email from the report
    report_id       TEXT        NOT NULL,           -- operator's unique report id
    date_begin      TIMESTAMPTZ,                    -- report window start (from epoch)
    date_end        TIMESTAMPTZ,                    -- report window end
    policy_domain   TEXT,                           -- <policy_published><domain>
    policy_p        TEXT,                           -- published policy: none|quarantine|reject
    policy_sp       TEXT,                           -- subdomain policy
    policy_adkim    TEXT,                           -- DKIM alignment mode r|s
    policy_aspf     TEXT,                           -- SPF alignment mode r|s
    policy_pct      INTEGER,                        -- % of mail policy applies to
    received_at     TIMESTAMPTZ NOT NULL DEFAULT now(),
    UNIQUE (org_name, report_id)
);

-- One row per <record> inside a report (a distinct source_ip + auth result combo).
CREATE TABLE IF NOT EXISTS dmarc_record (
    id              BIGSERIAL PRIMARY KEY,
    report_id       BIGINT      NOT NULL REFERENCES dmarc_report(id) ON DELETE CASCADE,
    source_ip       TEXT        NOT NULL,           -- the IP that sent the mail
    msg_count       INTEGER     NOT NULL DEFAULT 0, -- messages from this IP in the window
    disposition     TEXT,                           -- DMARC disposition applied: none|quarantine|reject
    dkim_aligned    TEXT,                           -- policy_evaluated/dkim: pass|fail
    spf_aligned     TEXT,                           -- policy_evaluated/spf:  pass|fail
    dmarc_pass      BOOLEAN,                         -- derived: dkim_aligned=pass OR spf_aligned=pass
    header_from     TEXT,                           -- identifiers/header_from
    envelope_from   TEXT,                           -- identifiers/envelope_from
    dkim_domain     TEXT,                           -- auth_results/dkim/domain
    dkim_selector   TEXT,                           -- auth_results/dkim/selector
    dkim_result     TEXT,                           -- auth_results/dkim/result (raw)
    spf_domain      TEXT,                           -- auth_results/spf/domain
    spf_result      TEXT                            -- auth_results/spf/result (raw)
);

CREATE INDEX IF NOT EXISTS idx_dmarc_report_window   ON dmarc_report (date_begin);
CREATE INDEX IF NOT EXISTS idx_dmarc_report_org      ON dmarc_report (org_name);
CREATE INDEX IF NOT EXISTS idx_dmarc_record_report   ON dmarc_record (report_id);
CREATE INDEX IF NOT EXISTS idx_dmarc_record_ip       ON dmarc_record (source_ip);
CREATE INDEX IF NOT EXISTS idx_dmarc_record_fail     ON dmarc_record (dmarc_pass) WHERE dmarc_pass = false;

COMMENT ON TABLE  dmarc_report IS
  'DMARC aggregate (rua) report headers. One row per operator report, keyed (org_name, report_id). Populated by scripts/dmarc_report_parser.py.';
COMMENT ON TABLE  dmarc_record IS
  'Per-source-IP rows inside each DMARC aggregate report: SPF/DKIM alignment + raw auth results. dmarc_pass = dkim_aligned=pass OR spf_aligned=pass.';
