Atex.DID.Document (atex v0.9.1)

View Source

Struct and schema for a DID document.

Covers the subset of DID document fields used by AT Protocol, including support for parsing the verificationMethod and service arrays into typed sub-structs.

Sub-structs

Parsing

Use new/1 to parse a raw map (as returned by a DID resolution response). The function accepts camelCase keys as returned by the wire protocol, validates the document structure via Peri, and converts public keys into JOSE.JWK structs.

Serialisation

Use to_json/1 to produce a camelCase map suitable for JSON encoding. Public keys are always emitted in the canonical Multikey / publicKeyMultibase format, regardless of the format used when the document was originally parsed.

ATProto-specific helpers

Summary

Functions

Returns the AT Protocol handle claimed by this DID document, or nil if none is present.

Returns the atproto signing key from the DID document as a JOSE.JWK, or nil.

Returns the PDS service endpoint URL from the DID document, or nil if not found.

Parses and validates a raw DID document map into a typed t() struct.

Serialises a t() struct to a camelCase map suitable for JSON encoding.

Validates that a DID document meets the minimum requirements for AT Protocol.

Types

t()

@type t() :: %Atex.DID.Document{
  "@context": [String.t()],
  also_known_as: [String.t()] | nil,
  authentication: [String.t() | Atex.DID.Document.VerificationMethod.t()] | nil,
  controller: (String.t() | [String.t()]) | nil,
  id: String.t(),
  service: [Atex.DID.Document.Service.t()] | nil,
  verification_method: [Atex.DID.Document.VerificationMethod.t()] | nil
}

Functions

get_atproto_handle(doc)

@spec get_atproto_handle(t()) :: String.t() | nil

Returns the AT Protocol handle claimed by this DID document, or nil if none is present.

The handle is found in the alsoKnownAs array as a URI with the at:// scheme followed by the handle hostname. Per the atproto specification, only the first syntactically valid handle in the list is returned.

Note

A handle returned here is only a claim. To confirm it, validate bidirectionally by resolving the handle to a DID and checking it matches. See Atex.IdentityResolver.Handle.resolve/2.

get_atproto_signing_key(doc)

@spec get_atproto_signing_key(t()) :: JOSE.JWK.t() | nil

Returns the atproto signing key from the DID document as a JOSE.JWK, or nil.

Finds the first verificationMethod entry whose id ends with #atproto. The public key is returned as a JOSE.JWK struct directly, since key decoding (including legacy formats) is performed at parse time in new/1.

get_pds_endpoint(doc)

@spec get_pds_endpoint(t()) :: String.t() | nil

Returns the PDS service endpoint URL from the DID document, or nil if not found.

Looks for a service entry with id ending #atproto_pds and type "AtprotoPersonalDataServer".

get_schema(atom)

new(map)

@spec new(map()) :: {:ok, t()} | {:error, Peri.Error.t()}

Parses and validates a raw DID document map into a typed t() struct.

Accepts the camelCase wire format as returned by DID resolution endpoints. verificationMethod and service entries are parsed into their respective sub-structs. Public keys are normalised to JOSE.JWK regardless of the wire encoding used.

Returns {:ok, t()} on success, or {:error, Peri.Error.t()} on validation failure.

Examples

iex> Atex.DID.Document.new(%{
...>   "@context" => ["https://www.w3.org/ns/did/v1"],
...>   "id" => "did:plc:abc123",
...>   "verificationMethod" => [],
...>   "service" => []
...> })
{:ok, %Atex.DID.Document{id: "did:plc:abc123", ...}}

schema(data)

schema!(data)

to_json(doc)

@spec to_json(t()) :: map()

Serialises a t() struct to a camelCase map suitable for JSON encoding.

Public keys in verificationMethod are always emitted in the canonical Multikey format with publicKeyMultibase.

Examples

iex> {:ok, doc} = Atex.DID.Document.new(%{
...>   "@context" => ["https://www.w3.org/ns/did/v1"],
...>   "id" => "did:plc:abc123"
...> })
iex> json = Atex.DID.Document.to_json(doc)
iex> json["id"]
"did:plc:abc123"

validate_for_atproto(doc, did)

@spec validate_for_atproto(t(), String.t()) ::
  :ok | {:error, :id_mismatch | :no_signing_key | :invalid_pds}

Validates that a DID document meets the minimum requirements for AT Protocol.

Checks:

  • The document id matches the expected DID.
  • A valid atproto signing key exists (verificationMethod entry with id ending #atproto and controller matching the DID).
  • A valid PDS service entry exists (service entry with id ending #atproto_pds, type "AtprotoPersonalDataServer", and a valid HTTPS or HTTP endpoint URL).

Returns :ok or one of {:error, :id_mismatch}, {:error, :no_signing_key}, {:error, :invalid_pds}.