anchor.diff:                               invalid_lease |
                                invalid_key |
                                invalid_macaroon |
  +                             worker_died |
                                worker_timeout |
                                path_violation |
                                other_error}.
  
positive.code: %%% Internal functions
  %%%===================================================================
  
  -spec p_generate_token(KeyId, Path, MaxLeaseTime, WorkerPort, Timeout)
                        -> {Token, Public, Secret}
                               when KeyId :: binary(),
                                    Path :: binary(),
                                    MaxLeaseTime :: integer(),
                                    WorkerPort :: port(),
                                    Timeout :: integer(),
                                    Token :: binary(),
                                    Public :: binary(),
                                    Secret :: binary().
  p_generate_token(KeyId, Path, MaxLeaseTime, WorkerPort, Timeout) ->
      ReqBody = jsx:encode(#{<<"key_id">> => KeyId, <<"path">> => Path,
                            <<"max_lease_time">> => MaxLeaseTime}),
      p_write_request(WorkerPort, ?kGenerateToken, ReqBody),
      {ok, {_Size, ReplyBody}} = p_read_reply(WorkerPort, Timeout),
      #{<<"token">> := Token, <<"id">> := Public, <<"secret">> := Secret}
          = jsx:decode(ReplyBody, [return_maps]),
      {Public, Secret, Token}.
  
  
  -spec p_get_token_id(Token, WorkerPort, Timeout)
                      -> {ok, PublicId} | {error, invalid_macaroon}
                             when Token :: binary(),
                                  WorkerPort :: port(),
                                  Timeout :: integer(),
                                  PublicId :: binary().
  p_get_token_id(Token, WorkerPort, Timeout) ->
      p_write_request(WorkerPort, ?kGetTokenId, Token),
      case p_read_reply(WorkerPort, Timeout) of
          {ok, {_, Reply}} ->
  
negative.code:                 #{<<"status">> := <<"error">>, <<"reason">> := <<"io_error">>} ->
                      {error, io_error}
              end;
          {error, worker_died} ->
              gen_server:reply(From, {error, worker_died}),
              exit(self(), kill);
          {error, worker_timeout} ->
              {error, worker_timeout}
      end.
  