SafeRPC transports Erlang external term format (ETF) frames over a packet-oriented transport. The default transport is a Unix domain socket.

Term shapes

SafeRPC currently uses four protocol terms.

Call request:

{:safe_rpc, 1, id, cap, :call, op, payload, meta}

Cast request:

{:safe_rpc, 1, id, cap, :cast, op, payload, meta}

Cancel request:

{:safe_rpc_cancel, 1, id}

Reply:

{:safe_rpc_reply, 1, id, result}

Each term is encoded with :erlang.term_to_binary/1 and decoded with :erlang.binary_to_term(binary, [:safe]).

Fields

  • id correlates requests and replies.
  • cap is an optional capability token checked on the server.
  • kind is :call or :cast.
  • op is the application operation. use SafeRPC services use {Module, function}.
  • payload is the request term.
  • meta is a map of per-request metadata.
  • result is normally {:ok, term} or {:error, reason}, but SafeRPC does not enforce an application result schema.

Built-in operations

SafeRPC reserves two operation atoms:

:safe_rpc_describe
:safe_rpc_atoms

:safe_rpc_describe returns a native descriptor for tooling on compatible code paths.

:safe_rpc_atoms returns the service atom vocabulary as strings so independent clients can prepare their VM for safe ETF decoding.

Both operations go through normal server-side capability and authorizer checks.

Safe decoding

SafeRPC does not use unsafe binary_to_term/1 for protocol frames. Safe decoding rejects unknown atoms, remote references that would create atoms indirectly, and unsafe external function references.

For atom-rich cross-release replies, use SafeRPC.prepare/2 before the call. See Atom vocabularies and safe ETF.

Versioning

The protocol term version is currently 1. Unknown or malformed request/reply terms are rejected by the protocol decoder.