Single-node ETS implementation of Attesto.RefreshStore.
Tokens live in an ETS table owned by a GenServer. The security-
critical rotate/4 transition is serialised through the owning process.
It validates the parent/child pair and performs one list-form ETS insert of
the post-parent and child, so direct readers cannot observe an intermediate
state. insert/1 and revoke_family/1 go through the same process, so all
family mutations are ordered.
This is a per-node store. A multi-node deployment MUST back
Attesto.RefreshStore with a shared store whose complete rotate/4
transaction is atomic across nodes and serialized against family
revocation, or reuse detection only holds per node.
Start options: :sweep_interval_ms (default 60_000). The sweeper
deletes tokens past their expiry; consumed parents may be retained until
their persisted retry deadline so replay is still detected, but that
retention never permits a retry after the parent's expiry. Plaintext
successor retry data is redacted after its :retry_until deadline.
Revoked-family markers are retained for the lifetime of the store, as
required by the sticky-revocation contract, including after all token rows
have expired.
children = [Attesto.RefreshStore.ETS]
Summary
Functions
@spec reset() :: :ok
Clear every entry. Test-facing.
@spec start_link(keyword()) :: GenServer.on_start()