SafeRPC is a small BEAM-native RPC layer for explicit, capability-scoped APIs over safe Erlang external term format.

Use it when both sides are BEAM applications and you want ordinary Elixir/Erlang terms without exposing Erlang distribution or arbitrary remote MFA.

defmodule MyApp.AdminRPC do
  use SafeRPC, service: :my_app, version: "1"

  @rpc true
  @spec status(map(), map(), keyword()) :: {:ok, :ready}
  def status(_payload, _meta, _state), do: {:ok, :ready}
end

defmodule MyApp.AdminRPCServer do
  use SafeRPC.Adapter.Server, service: MyApp.AdminRPC
end
{:ok, server} = MyApp.AdminRPCServer.start_link(socket: "/tmp/my-app.sock")
{:ok, :ready} = SafeRPC.call("/tmp/my-app.sock", {MyApp.AdminRPC, :status})

What runs where

ConcernSideTime
use SafeRPC and @rpc collectionservice modulecompile time
atom vocabulary collection from RPC specs/bodies/optionsservice modulecompile time
socket listener and operation dispatchserver BEAMruntime
SafeRPC.call/4, cast/4, async/4client BEAMruntime
SafeRPC.prepare/2 atom preflightclient BEAM calling serverruntime before atom-rich calls
capability and authorizer checksserver BEAMruntime per request

Why not Erlang distribution?

Erlang distribution is designed for trusted clusters. Once nodes are connected, the trust boundary is broad. SafeRPC keeps the surface narrow: only operations explicitly marked with @rpc or explicitly implemented by an adapter service are callable.

Installation

def deps do
  [{:safe_rpc, "~> 0.1"}]
end

Guides

License

MIT