A DIDComm v2 message.
Fields
id— unique message identifier (UUID v4)type— DIDComm message type URIfrom— sender DIDto— list of recipient DIDsthread_id— correlates messages in a thread (thid)parent_thread_id— links to a parent thread (pthid)body— message payload (arbitrary map)attachments— list ofLayr8.Attachmentstructs (DIDComm v2 attachments), ornilwhen the header could not be read; see belowattachments_unread— why theattachmentsheader was not read,nilwhen it wastrace_context— the DIDCommtrace_contextheader, see belowcontext— inbound-only metadata from the cloud-node
trace_context
A W3C trace context carried in the top-level trace_context plaintext
header, as a map with the W3C header names as string keys:
%{"traceparent" => "00-…", "tracestate" => "…"} ("tracestate" is
optional). That shape is a ready-made text-map carrier for an OpenTelemetry
propagator. nil means the message carried none, or carried a value this SDK
could not read (see read_trace_context/1). The SDK carries the value and
does not validate the traceparent format; the node does.
A handler's {:reply, msg} and the problem report for a failed handler copy
the request's trace_context unchanged when the reply does not set its own.
attachments has three states, not two
| the message carried | attachments | attachments_unread |
|---|---|---|
no attachments header | [] | nil |
| a header this SDK read | the attachments | nil |
| a header it could not read | nil | why |
Returning [] for a header nobody could read would report "this message
carried no attachments", which is a measurement that was never taken.
The message itself is parsed either way. An authorization denial must not
disappear because a hint travelling beside it was malformed — being refused
and being ignored are different events, and a caller waiting on
Layr8.Client.request/4 sees the difference as a denial versus a timeout.
Wire Format (outbound)
{
"id": "...",
"type": "...",
"from": "...",
"to": [...],
"thid": "...",
"pthid": "...",
"body": {...},
"attachments": [...],
"trace_context": {"traceparent": "...", "tracestate": "..."}
}Wire Format (inbound, from cloud-node)
{
"context": {"recipient": "...", "authorized": true, "sender_credentials": [...]},
"plaintext": {"id": "...", "type": "...", "from": "...", "to": [...], "body": {...}, "thid": "...", "pthid": "..."}
}
Summary
Functions
Generate a new unique message ID (UUID v4).
Serializes a Layr8.Message into a DIDComm JSON envelope map.
Parses an inbound cloud-node message envelope (with context + plaintext) into a Layr8.Message.
Reads a trace_context header value.
Types
@type t() :: %Layr8.Message{ attachments: [Layr8.Attachment.t()] | nil, attachments_unread: String.t() | nil, body: map() | nil, context: Layr8.Message.Context.t() | nil, from: String.t(), id: String.t(), parent_thread_id: String.t(), thread_id: String.t(), to: [String.t()], trace_context: trace_context() | nil, type: String.t() }
A W3C trace context: "traceparent" and, optionally, "tracestate".
Functions
@spec generate_id() :: String.t()
Generate a new unique message ID (UUID v4).
Serializes a Layr8.Message into a DIDComm JSON envelope map.
The result is suitable for encoding with Jason.encode!/1.
Example
msg = %Layr8.Message{id: "abc", type: "...", from: "did:ex:alice", to: ["did:ex:bob"], body: %{text: "hi"}}
Layr8.Message.marshal(msg)
# => %{"id" => "abc", "type" => "...", "from" => "did:ex:alice", "to" => ["did:ex:bob"], "body" => %{text: "hi"}}
Parses an inbound cloud-node message envelope (with context + plaintext) into a Layr8.Message.
Accepts a map (already JSON-decoded) or a JSON string.
Example
envelope = %{
"context" => %{"recipient" => "did:ex:bob", "authorized" => true, "sender_credentials" => []},
"plaintext" => %{"id" => "abc", "type" => "...", "from" => "did:ex:alice", "to" => ["did:ex:bob"], "body" => %{}}
}
Layr8.Message.parse(envelope)
@spec read_trace_context(term()) :: trace_context() | nil
Reads a trace_context header value.
Returns a map with only the string keys "traceparent" and (when it is a
string) "tracestate", or nil for anything that is not a map with a string
traceparent. Never raises: a malformed header must not cost the reader the
message. Other members are dropped and never forwarded. Atom keys
(%{traceparent: ...}) are accepted for values a caller builds.