# `Mailglass.SupplyChain.AcceptedAdvisories`
[🔗](https://github.com/szTheory/mailglass/blob/v2.7.0/lib/mailglass/supply_chain/accepted_advisories.ex#L1)

The single source of truth for advisories `mailglass` deliberately allows
past `mix hex.audit` / `mix deps.audit` gates because no upstream fix exists
yet. Both `mix mailglass.publish.check` (publish gate) and
`mix mailglass.audit` (CI gate, `dev/mix/tasks/mailglass.audit.ex`) read this
module exclusively — there is no second copy of the allowlist anywhere in
the repo.

Each entry carries `:id` (the primary EEF-CVE id reported by `hex.audit`),
`:aliases` (any GHSA ids the same advisory is known by in the
mirego/elixir-security-advisories DB that `mix deps.audit` reads),
`:package`, `:severity`, `:reason`, `:accepted_on`, and `:recheck_by`.
Matching against a finding is exact `:id`-or-`:aliases`-member equality
against ONE entry — never fuzzy, prefix, or cross-package.

## Expiry and staleness

`expired_entries/1` flags any entry whose `:recheck_by` date has passed
(strictly after — an entry due today does not yet block). `unused_entries/1`
flags any entry that matched no current `hex.audit` finding across all three
scanned Mix projects, so a suppression that is no longer needed cannot
silently age forever. Both checks are local and deterministic — they never
depend on OSV's unreliable `fixed`-event data.

## Known limitation

`unused_entries/1`'s "used" signal comes only from `matched_hex_audit_ids/1`,
which is populated only by `--kind hex` runs of `mix mailglass.audit`. A
future allowlist entry that is detectable ONLY by `mix deps.audit` (e.g. a
GHSA-only id absent from the EEF-CVE database) would therefore be
perpetually reported "unused" by every `--kind hex` run, pressuring a
maintainer to delete a legitimately-needed suppression. This fails loud, not
silent, so it does not reintroduce VULN-06's silent-aging defect for the two
entries this phase ships (both EEF-CVE-keyed and hex.audit-native). It is
nonetheless a real constraint on who may add future entries: if such an
entry is ever needed, widen the "used" signal to also aggregate `--kind
deps` matches — that widening is deliberately not built speculatively here.

# `entry`

```elixir
@type entry() :: %{
  id: String.t(),
  aliases: [String.t()],
  package: String.t(),
  severity: String.t(),
  reason: String.t(),
  accepted_on: Date.t(),
  recheck_by: Date.t()
}
```

# `entries`

```elixir
@spec entries() :: [entry()]
```

Returns the full accepted-advisory allowlist.

# `expired_entries`

```elixir
@spec expired_entries(Date.t()) :: [entry()]
```

Entries whose `:recheck_by` date has strictly passed as of `today`
(`Date.compare(today, recheck_by) == :gt`) — an entry due today does not
yet block; it blocks starting the day after.

# `unused_entries`

```elixir
@spec unused_entries(MapSet.t(String.t())) :: [entry()]
```

Entries whose `:id` is absent from `matched_ids` — the aggregate of
`matched_hex_audit_ids/1` across every directory scanned by a single
`--kind hex` run of `mix mailglass.audit`. An entry counts as "used" if it
matched a finding in ANY scanned directory.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
