MailglassInbound.Internal.Doctor (MailglassInbound v0.2.0)

Copy Markdown View Source

DNS-free pre-deploy config check runner for mix mailglass.inbound.doctor (IOPS-01, MIME-03). All checks are pure reflection — no DB, no DNS, no network — so the doctor is fast, offline, and CI-friendly (D-49-06).

run/1 returns %{summary: %{pass, warn, fail, cannot_diagnose}, findings: [...]} with the locked finding shape %{check, status, title, observed, remediation, evidence} (D-49-05). The CLI shell maps the summary to the three-state exit code.

Checks (all DNS-free)

  • router configured + compiles (absent -> a :cannot_diagnose marker the task maps to exit 2);
  • >= 1 route defined;
  • each route's mailbox is compiled + function_exported?(mod, :process, 1);
  • provider signing keys are PRESENT (reads the same :mailglass_inbound config the plug reads — NEVER verifies a signature; the finding text says so);
  • MIME backend availability + version via Mailglass.OptionalDeps.GenSmtp (MIME-03, no bare optional-dep reference);
  • route-conflict detection REUSING MailglassInbound.Router.Matcher.matches_route?/2 (D-49-07): structural subsumption (broad-before-narrow) -> :fail, witness-probe shadow -> :fail, regex-vs-regex overlap -> :warn. Conflict findings name router.ex:LINE via Route.:source (D-49-08).

Summary

Functions

Run all DNS-free checks against the configured (or opt-supplied) router.

Types

finding()

@type finding() :: %{
  check: atom(),
  status: status(),
  title: String.t(),
  observed: String.t(),
  remediation: String.t(),
  evidence: map()
}

result()

@type result() :: %{summary: map(), findings: [finding()]}

status()

@type status() :: :pass | :warn | :fail

Functions

run(opts \\ [])

@spec run(keyword()) :: result()

Run all DNS-free checks against the configured (or opt-supplied) router.

Options:

  • :router — the router module to reflect. Defaults to Application.get_env(:mailglass_inbound, :router). When nil/absent the result carries a :cannot_diagnose finding (drives exit 2).