Add supervision tree
diff --git a/src/passage_local_ns.erl b/src/passage_local_ns.erl
new file mode 100644
index 0000000..a13461f
--- /dev/null
+++ b/src/passage_local_ns.erl
@@ -0,0 +1,12 @@
+-module(passage_local_ns).
+
+-export([child_spec/0]).
+-export([mailbox_name/1]).
+
+-spec child_spec() -> supervisor:child_spec().
+child_spec() ->
+    local:name_server_child_spec(?MODULE).
+
+-spec mailbox_name(jaegerl:tracer()) -> local:otp_name().
+mailbox_name(Tracer) ->
+    local:otp_name({?MODULE, {mailbox, Tracer}}).
diff --git a/src/passage_mailbox.erl b/src/passage_mailbox.erl
new file mode 100644
index 0000000..d5c257e
--- /dev/null
+++ b/src/passage_mailbox.erl
@@ -0,0 +1,49 @@
+-module(passage_mailbox).
+
+-behavior(gen_server).
+
+-export([start_link/1]).
+-export([post/1]).
+
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
+
+-define(STATE, ?MODULE).
+
+-record(?STATE,
+        {
+        }).
+
+-spec start_link(passage:tracer()) -> {ok, pid()} | {error, Reason :: term()}.
+start_link(Tracer) ->
+    gen_server:start_link(passage_local_ns:mailbox_name(Tracer), ?MODULE, [], []).
+
+-spec post(passage_span:span()) -> ok.
+post(Span) ->
+    Tracer = passage_span:get_tracer(Span),
+    gen_server:cast(passage_local_ns:mailbox_name(Tracer), {post, Span}).
+
+init([]) ->
+    State = #?STATE{},
+    {ok, State}.
+
+handle_call(_Request, _From, State) ->
+    {noreply, State}.
+
+handle_cast({post, Span}, State0) ->
+    State1 = handle_post(Span, State0),
+    {noreply, State1};
+handle_cast(_Request, State) ->
+    {noreply, State}.
+
+handle_info(_Info, State) ->
+    {noreply, State}.
+
+terminate(_Reason, _State) ->
+    ok.
+
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
+
+-spec handle_post(passage_span:span(), #?STATE{}) -> #?STATE{}.
+handle_post(Span, State) ->
+    error(unimplemented, [Span,State]).
diff --git a/src/passage_mailbox_sup.erl b/src/passage_mailbox_sup.erl
new file mode 100644
index 0000000..61bc041
--- /dev/null
+++ b/src/passage_mailbox_sup.erl
@@ -0,0 +1,24 @@
+-module(passage_mailbox_sup).
+
+-behaviour(supervisor).
+
+-export([start_child/1]).
+
+-export([start_link/0]).
+
+-export([init/1]).
+
+-spec start_child(passage:tracer()) -> {ok, pid()} | {error, Reason :: term()}.
+start_child(Tracer) ->
+    Child = #{
+      id      => Tracer,
+      start   => {passage_mailbox, start_link, [Tracer]},
+      restart => permanent
+     },
+    supervisor:start_child(?MODULE, Child).
+
+start_link() ->
+    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init([]) ->
+    {ok, {#{}, []}}.
diff --git a/src/passage_registry.erl b/src/passage_registry.erl
new file mode 100644
index 0000000..4ba0423
--- /dev/null
+++ b/src/passage_registry.erl
@@ -0,0 +1,54 @@
+-module(passage_registry).
+
+-behavior(gen_server).
+
+-export([start_link/0]).
+
+-export([get_default_tracer/0]).
+-export([get_sampler/1]).
+-export([get_tracer_module/1]). % TODO: get_tracer(?)
+
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
+
+-define(STATE, ?MODULE).
+
+-record(?STATE,
+        {
+          table :: ets:tab()
+        }).
+
+-spec start_link() -> {ok, pid()} | {error, Reason :: term()}.
+start_link() ->
+    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+-spec get_default_tracer() -> passage:tracer().
+get_default_tracer() ->
+    error(unimplemented).
+
+-spec get_sampler(passage:tracer()) -> passage_sampler:sampler().
+get_sampler(Tracer) ->
+    error(unimplemented, [Tracer]).
+
+-spec get_tracer_module(passage:tracer()) -> module().
+get_tracer_module(Tracer) ->
+    error(unimplemented, [Tracer]).
+
+init([]) ->
+    Table = ets:new(?MODULE, [named_table, protected, {read_concurrency, true}]),
+    State = #?STATE{table = Table},
+    {ok, State}.
+
+handle_call(_Request, _From, State) ->
+    {noreply, State}.
+
+handle_cast(_Request, State) ->
+    {noreply, State}.
+
+handle_info(_Info, State) ->
+    {noreply, State}.
+
+terminate(_Reason, _State) ->
+    ok.
+
+code_change(_OldVsn, State, _Extra) ->
+    {ok, State}.
diff --git a/src/passage_sup.erl b/src/passage_sup.erl
index a3a3e38..c8efb95 100644
--- a/src/passage_sup.erl
+++ b/src/passage_sup.erl
@@ -1,35 +1,24 @@
-%%%-------------------------------------------------------------------
-%% @doc trace top level supervisor.
-%% @end
-%%%-------------------------------------------------------------------
-
 -module(passage_sup).
 
 -behaviour(supervisor).
 
-%% API
 -export([start_link/0]).
 
-%% Supervisor callbacks
 -export([init/1]).
 
--define(SERVER, ?MODULE).
-
-%%====================================================================
-%% API functions
-%%====================================================================
-
 start_link() ->
-    supervisor:start_link({local, ?SERVER}, ?MODULE, []).
+    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
 
-%%====================================================================
-%% Supervisor callbacks
-%%====================================================================
-
-%% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules}
 init([]) ->
-    {ok, { {one_for_all, 0, 1}, []} }.
-
-%%====================================================================
-%% Internal functions
-%%====================================================================
+    Registry = #{
+      id      => passage_registry,
+      start   => {passage_registry, start_link, []},
+      restart => permanent
+     },
+    NameServer = passage_local_ns:child_spec(),
+    MailboxSup = #{
+      id    => passage_mailbox_sup,
+      start => {passage_mailbox_sup, start_link, []},
+      type  => supervisor
+     },
+    {ok, {#{stragety => rest_for_one}, [Registry, NameServer, MailboxSup]} }.