Postgres-backed AttestoPhoenix.ClientIdMetadata.Cache for clustered
deployments - CIMD (draft-ietf-oauth-client-id-metadata-document-01, IETF
OAuth WG).
CIMD lets a client identify itself with no prior registration by using an
HTTPS URL as its client_id; the authorization server dereferences that URL
and validates the returned document. Caching the validated document keeps
every authorization request from reaching out to the network. The default
per-node AttestoPhoenix.ClientIdMetadata.Cache.ETS would re-fetch on each
node and offers no coherence; this store persists each entry so a document
fetched on one node is served from every node and the outbound fetch fan-out
is bounded under load. It is the cache default for exactly the same reason the
code/refresh/nonce/replay/PAR stores default to Ecto.
Only a validated document is ever written (the caller stores after
Attesto.ClientIdMetadata.validate_document/2 succeeds, with an expires_at
derived from the response's freshness directives clamped to the configured
bounds); the draft (§6) and RFC 9111 forbid caching errors or malformed
documents, so this store never validates and never sees an unaccepted
document.
Behaviour callbacks
get/1resolves a live (unexpired) cached document WITHOUT consuming it. Expiry is re-checked on read (expires_at > now), so an unswept expired row is a:miss, never a stale hit.put/3upserts the validated metadata and its expiry. A re-fetched document legitimately supersedes a stale one, so a conflictingurlreplaces the existing row'smetadataandexpires_atrather than failing - the freshest fetch wins.
Expired rows are reclaimed by AttestoPhoenix.Store.Sweeper, but sweeping is
housekeeping only: get/1 already refuses an expired row.
The repository module is supplied by the host application (:repo under the
:attesto_phoenix app) and read at call time; a cache with no backing
repository fails closed rather than silently no-opping.
Summary
Functions
Resolves a live cached document for a CIMD client_id URL.
Caches validated metadata for a CIMD client_id URL until expires_at.
Functions
Resolves a live cached document for a CIMD client_id URL.
Returns {:ok, metadata} when a row exists and has not expired, or :miss
when it is absent or expired. metadata is round-tripped through jsonb, so
the caller reads back the same string-keyed map it stored. Freshness is
enforced on read (expires_at > now); resolution does not consume the entry,
so it serves every request until it expires or is replaced.
@spec put(String.t(), map(), DateTime.t()) :: :ok
Caches validated metadata for a CIMD client_id URL until expires_at.
metadata is the validated, string-keyed map; it is round-tripped through
jsonb. The url is the primary key, so a re-fetch upserts the single row:
on conflict the stored metadata and expires_at are replaced with the
freshly fetched values (the freshest accepted document wins), rather than
raising or keeping a stale entry.