Validated configuration accessor for the :mailglass_inbound app env (D-49-02).
Mirrors the style of Mailglass.Config (NimbleOptions @schema declared
before @moduledoc, validate_at_boot!/0) but reads the :mailglass_inbound
app env, never core Mailglass.Config. Adding inbound keys to core would invert
the package dependency — core reads :mailglass only and cannot validate config
for a package it does not depend on (boundary law, D-49-02).
Configuration
config :mailglass_inbound,
retention: [
records_days: 90,
evidence_days: 90,
execution_runs_days: 90,
replay_runs_days: 30
],
rate_limit: [
tenant: [capacity: 1000, per_minute: 1000],
sender_domain: [capacity: 200, per_minute: 200],
recipient: [capacity: 500, per_minute: 500]
]:infinity on any retention class disables that window. Only the knobs the
runtime actually reads are shipped — no speculative per-tenant override maps
(honest-surface, D-49-03).
Schema
:retention(keyword/0) - Retention windows (in days) per inbound table class.:infinityon a class disables that window. Defaults: records 90, evidence 90, execution_runs 90, replay_runs 30.The windows must respect the FK lineage so the child-first prune never trips an
on_delete: :nothingforeign key (CR-02):replay_runsrows reference bothrecordsandevidence, andevidencereferencesrecords. So a parent must outlive every child that references it —evidence_days >= max(execution_runs_days, replay_runs_days)andrecords_days >= evidence_days.retention/0CLAMPS any configured override up to satisfy this invariant rather than letting prune crash on an FK violation.The default value is
[].:records_days- The default value is90.:evidence_days- The default value is90.:execution_runs_days- The default value is90.:replay_runs_days- The default value is30.
:rate_limit(keyword/0) - Post-verify ingress rate-limit buckets. Three buckets evaluated fail-fast in order tenant -> recipient -> sender_domain. Each bucket has acapacity(token-bucket BURST size) and aper_minuteSUSTAINED refill rate. Following the coreMailglass.RateLimiterconvention, the defaults setper_minute == capacity, so "N/min" is literally the sustained throughput: the bucket refills its full capacity each minute. Defaults: tenant 1000/min, recipient 500/min, sender_domain 200/min. The default value is[].:tenant(keyword/0) - The default value is[capacity: 1000, per_minute: 1000].:capacity(non_neg_integer/0) - Required.:per_minute(non_neg_integer/0) - Required.
:sender_domain(keyword/0) - The default value is[capacity: 200, per_minute: 200].:capacity(non_neg_integer/0) - Required.:per_minute(non_neg_integer/0) - Required.
:recipient(keyword/0) - The default value is[capacity: 500, per_minute: 500].:capacity(non_neg_integer/0) - Required.:per_minute(non_neg_integer/0) - Required.
Summary
Functions
Returns the validated rate-limit buckets as a keyword list with every bucket present (defaults merged over any configured overrides).
Returns the validated retention windows as a keyword list with every class present (defaults merged over any configured overrides), CLAMPED to satisfy the FK-lineage invariant (CR-02).
Validate the :mailglass_inbound retention + rate_limit config at boot.
Functions
@spec rate_limit() :: keyword()
Returns the validated rate-limit buckets as a keyword list with every bucket present (defaults merged over any configured overrides).
@spec retention() :: keyword()
Returns the validated retention windows as a keyword list with every class present (defaults merged over any configured overrides), CLAMPED to satisfy the FK-lineage invariant (CR-02).
The inbound prune deletes child-first against on_delete: :nothing FKs, so a
parent window can never be shorter than a child that references it. This
accessor enforces:
evidence_days >= max(execution_runs_days, replay_runs_days)— evidence is referenced by both:freshand:replayruns.records_days >= evidence_days— records are referenced by evidence (and by runs, butevidence_daysalready dominates the run windows).
A configured override that would invert the lineage is silently clamped UP to
the smallest safe value rather than allowed to crash the sweep on a
foreign_key_violation. :infinity (window disabled) is treated as the
maximum, so an :infinity child forces its parents to :infinity too.
@spec validate_at_boot!() :: :ok
Validate the :mailglass_inbound retention + rate_limit config at boot.
Returns :ok. Raises NimbleOptions.ValidationError if the configured shape
is invalid (e.g. a negative retention value, a non-:infinity atom on a
retention class, or a negative bucket capacity).
Intended to be called from the host application's boot path (it is not called automatically — the inbound package does not own the host's app env).