Persistent allowlist of peer public keys this node will talk to.
PeerNet's whole security model rests on this list. A peer is "trusted" iff their Ed25519 public key (32 bytes) appears here. Untrusted peers are rejected at handshake time — they cannot complete the Noise XX exchange, so the connection is closed before any application-level message is exchanged.
Pairing flow: out-of-band exchange of public keys (e.g. via QR code), then
both sides call add/3 with the other's pubkey.
Pubkey format
All pubkeys are 32-byte binaries. Anything else is rejected with
{:error, :invalid_pubkey}. This shape check is the entire input
validation — no parsing, no decoding, no Base64. If a caller has a hex or
Base64 representation, decode it first.
Persistence
The trust list is written to data_dir/trust.bin after every change. The
file format is intentionally simple (a list of %{pubkey, label, added_at}
maps serialized via :erlang.term_to_binary/2 with :safe decoding) so
it can be inspected and recovered without this module.
Process model
Implemented as a GenServer so multiple callers can read and write
concurrently without races. The list is held in memory; persistence is a
side-effect of mutations, not the source of truth at runtime.
Examples
iex> uniq = "#{:os.system_time(:nanosecond)}_#{System.unique_integer([:positive])}"
iex> dir = Path.join(System.tmp_dir!(), "peer_net_doctest_#{uniq}")
iex> name = :"trust_doctest_#{uniq}"
iex> {:ok, pid} = PeerNet.Trust.start_link(data_dir: dir, name: name)
iex> PeerNet.Trust.list(pid)
[]
iex> :ok = PeerNet.Trust.add(pid, <<1::256>>, label: "test")
iex> PeerNet.Trust.trusted?(pid, <<1::256>>)
true
Summary
Functions
Add pubkey to the trust list.
Returns a specification to start this module under a supervisor.
Return all trusted peer entries.
Remove pubkey from the trust list. No-op if it wasn't present.
Start the trust process.
True iff pubkey (a 32-byte binary) is in the trust list.
Types
@type entry() :: %{ pubkey: <<_::256>>, label: String.t() | nil, added_at: DateTime.t() }
An entry in the trust list.
pubkey: the peer's Ed25519 public key (32 bytes).label: optional human-readable name for UI display.added_at: when this peer was first added, for the trust UI.
Functions
@spec add(GenServer.server(), binary(), keyword()) :: :ok | {:error, :invalid_pubkey}
Add pubkey to the trust list.
Options:
:label— optional human-readable name shown in trust UI.
Returns :ok whether the pubkey was newly added or already present
(idempotent). Returns {:error, :invalid_pubkey} if pubkey isn't a
32-byte binary.
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec list(GenServer.server()) :: [entry()]
Return all trusted peer entries.
@spec remove(GenServer.server(), binary()) :: :ok
Remove pubkey from the trust list. No-op if it wasn't present.
@spec start_link(keyword()) :: GenServer.on_start()
Start the trust process.
Options:
:data_dir(required) — directory under whichtrust.binwill be read and written.:name(optional) — process registration name.
@spec trusted?(GenServer.server(), term()) :: boolean()
True iff pubkey (a 32-byte binary) is in the trust list.
Returns false (not an error) for any non-32-byte input — this lets call sites screen unknown peers without a guard.