Exosphere.ATProto.Identity.DID.PLC (Exosphere v0.6.0)

Copy Markdown View Source

DID:PLC resolution and operation submission.

DID:PLC is Bluesky's novel DID method with key rotation and recovery support. DIDs are resolved via the PLC directory at https://plc.directory.

Reads live here; the write side is split across three modules:

Examples

iex> Exosphere.ATProto.Identity.DID.PLC.resolve("did:plc:z72i7hdynmk6r22z27h6tvur")
{:ok, %Document{...}}

Creating an identity — the DID falls out of the signed genesis operation rather than being allocated:

{:ok, op} = Operation.new(rotation_keys: [key], also_known_as: ["at://alice.example.com"])
{:ok, signed} = Signer.sign(op, private_key, :secp256k1)
{:ok, did} = Signer.derive_did(signed)
{:ok, ^did} = PLC.submit(did, signed)

Summary

Functions

Get the audit log for a did:plc.

Get the current PLC data (internal representation) for a did:plc.

The CID of the current head of a DID's operation log.

Resolve a did:plc to its DID Document.

Submit a signed operation to the directory (POST /:did).

Fetch and validate a DID's full audit log.

Types

resolve_opts()

@type resolve_opts() :: [
  timeout: pos_integer(),
  plc_directory: String.t(),
  http_client: module()
]

submit_opts()

@type submit_opts() :: [
  timeout: pos_integer(),
  plc_directory: String.t(),
  http_client: module(),
  max_attempts: pos_integer(),
  backoff_ms: pos_integer()
]

Functions

get_audit_log(did, opts \\ [])

@spec get_audit_log(String.t(), resolve_opts()) :: {:ok, [map()]} | {:error, term()}

Get the audit log for a did:plc.

Returns the full history of operations for the DID.

get_data(did, opts \\ [])

@spec get_data(String.t(), resolve_opts()) :: {:ok, map()} | {:error, term()}

Get the current PLC data (internal representation) for a did:plc.

This returns the PLC-specific data format, not the DID Document.

head(did, opts \\ [])

@spec head(String.t(), resolve_opts()) :: {:ok, String.t()} | {:error, term()}

The CID of the current head of a DID's operation log.

This is what a new operation's prev must point at. Fetch it rather than reusing a locally cached value: an operation chained from a stale head is a fork, not an update, and the directory will judge it as one.

resolve(did, opts \\ [])

@spec resolve(String.t(), resolve_opts()) ::
  {:ok, Exosphere.ATProto.Identity.Document.t()} | {:error, term()}

Resolve a did:plc to its DID Document.

Options

  • :timeout - HTTP request timeout in milliseconds (default: 10_000)
  • :plc_directory - PLC directory URL (default: "https://plc.directory")
  • :http_client - HTTP client module implementing HTTP.Behaviour (default: Exosphere.ATProto.HTTP; useful for testing)

submit(did, op, opts \\ [])

@spec submit(
  String.t(),
  Exosphere.ATProto.Identity.DID.PLC.Operation.t(),
  submit_opts()
) ::
  {:ok, String.t()} | {:error, term()}

Submit a signed operation to the directory (POST /:did).

Retries on transport failures and 5xx responses with linear backoff. A 4xx is not retried — the directory has judged the operation invalid, and resending it unchanged cannot help. The exception is 429: it comes from infrastructure rate limiting (the directory's own limits answer 400), not a judgment on the operation, so it retries like a 5xx.

Note that the directory rate-limits per DID — 10 operations an hour, 30 a day, 100 a week — and retries count against those limits.

Submission is idempotent at the directory: resubmitting an operation the directory already holds is accepted rather than duplicated, so a retry after an ambiguous timeout is safe.

Options

  • :max_attempts - total attempts including the first (default: 3)
  • :backoff_ms - base backoff, multiplied by attempt number (default: 500)
  • :timeout, :plc_directory, :http_client - as resolve/2

verify_audit_log(did, opts \\ [])

@spec verify_audit_log(String.t(), resolve_opts()) :: :ok | {:error, term()}

Fetch and validate a DID's full audit log.

Verifies every signature, the chain, nullification and the 72-hour recovery window, and cross-checks the computed nullification against the flags the directory reported.