PtcRunner.Kernel.MCPOAuth.TokenManager (PtcRunner v0.14.0)

Copy Markdown View Source

Principal-scoped bearer-token owner for one installed MCP authority.

The owner serializes only refresh leadership and lifecycle transitions. Store, discovery, credential-resolution, and network work runs outside the owner. Before returning a header, the admitted caller reloads the current store generation and takes a dispatch admission for that exact generation. Callers must release the returned admission after the HTTP attempt.

A 401 marks only the generation actually sent. A 403 requirement is persisted only after the caller supplies one strictly parsed Bearer challenge. The manager atomically installs the corresponding runtime-shared local fence and starts a bounded non-owner persistence worker before replying, so caller death, manager replacement, or a failed durable transition cannot reissue the rejected authority. A strictly newer sufficient grant clears that fallback fence. Shutdown drains these bounded persistence workers before discarding local state. A failed persistence is retained and retried on close; close fails without stopping the manager if that retry also fails. Neither response is replayed automatically. Session-owner death adopts unsettled persistence through the bounded cleanup owner before the registrar's cooperative shutdown window ends.

Summary

Types

issued()

@type issued() :: %{
  header: {binary(), binary()},
  generation: non_neg_integer(),
  admission: term(),
  egress: map(),
  release: (integer() -> :ok | {:error, atom()})
}

t()

@type t() :: %PtcRunner.Kernel.MCPOAuth.TokenManager{pid: pid(), resource: binary()}

Functions

authorization_header(manager, deadline_ms, admission_owner \\ self())

@spec authorization_header(t(), integer(), pid()) ::
  {:ok, issued()} | {:error, atom()}

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

close(manager)

@spec close(t()) :: :ok | {:error, :persistence_failed | :timeout}

reject(token_manager, generation, request_deadline_ms)

@spec reject(t(), non_neg_integer(), integer()) :: :ok | {:error, atom()}

release(token_manager, admission, deadline_ms)

@spec release(t(), term(), integer()) :: :ok | {:error, atom()}

require_scopes(arg1, generation, authenticate_headers, arg4)

@spec require_scopes(t(), non_neg_integer(), [binary()], integer()) ::
  :ok | {:error, atom()}

start(opts)

@spec start(keyword()) :: {:ok, t()} | {:error, atom()}