···11defmodule Atex.IdentityResolver do
22+ @moduledoc """
33+ Resolves AT Protocol identifiers (DIDs and handles) to `Atex.IdentityResolver.Identity` structs.
44+55+ Resolution results are cached in `Atex.IdentityResolver.Cache` (ETS) to avoid
66+ repeated network calls. Handle resolution strategy is compile-time configurable:
77+88+ config :atex, handle_resolver_strategy: :dns_first # default: :dns_first
99+1010+ ## Examples
1111+1212+ {:ok, identity} = Atex.IdentityResolver.resolve("user.bsky.social")
1313+ {:ok, identity} = Atex.IdentityResolver.resolve("did:plc:abc123")
1414+1515+ """
1616+217 alias Atex.IdentityResolver.{Cache, DID, Handle, Identity}
318 alias Atex.DID.Document, as: DIDDocument
419···722823 # TODO: simplify errors
9242525+ @doc """
2626+ Resolve a DID or handle to an `Atex.IdentityResolver.Identity` struct.
2727+2828+ For a DID, resolves the DID document and optionally cross-checks the handle
2929+ declared in it. For a handle, resolves to a DID via DNS or HTTP, then fetches
3030+ and validates the DID document.
3131+3232+ Results are cached. Pass `skip_cache: true` to force a fresh resolution.
3333+3434+ ## Parameters
3535+3636+ - `identifier` - A DID string (e.g., `"did:plc:abc123"`) or a handle (e.g., `"user.bsky.social"`)
3737+ - `opts` - Keyword options:
3838+ - `:skip_cache` - If `true`, bypass the cache (default: `false`)
3939+4040+ ## Returns
4141+4242+ - `{:ok, identity}` - Successfully resolved identity
4343+ - `{:error, :handle_mismatch}` - Handle in DID document does not match resolved handle
4444+ - `{:error, reason}` - Resolution or network failure
4545+ """
1046 @spec resolve(String.t(), list(options())) :: {:ok, Identity.t()} | {:error, any()}
1147 def resolve(identifier, opts \\ []) do
1248 opts = Keyword.validate!(opts, skip_cache: false)