PtcRunner.Kernel.MCPOAuth.Store behaviour (PtcRunner v0.14.0)

Copy Markdown View Source

Atomic authorization-store boundary for MCP OAuth state.

Store adapters implement one closed transaction callback. The public functions below define the supported operation vocabulary; callers cannot submit arbitrary functions or inspect adapter-owned state. Every operation that reads or mutates a grant is fenced by both principal and authority epochs carried in GrantKey.

Persistent adapters must encrypt secret fields at rest, use an adapter-authoritative clock, and make each operation crash-atomic at this callback boundary. PtcRunner ships only the owner-process in-memory adapter; no durable adapter or persistence recommendation is included.

transact/3 receives the absolute deadline captured by the caller. Adapters must check it again at their serialized mutation boundary and return {:error, :timeout} without changing state when it has expired. Store wrappers must forward that exact deadline rather than replacing it with a new relative timeout.

Summary

Types

Closed transaction command issued by this module.

t()

Opaque adapter tuple.

Functions

Returns an opaque process-local identity shared by wrappers of one store.

Recovers one exact mutation only after its dispatch worker has been irreversibly fenced.

Types

operation()

@type operation() :: tuple()

Closed transaction command issued by this module.

t()

@type t() :: {module(), term()}

Opaque adapter tuple.

Callbacks

local_identity(adapter_state)

(optional)
@callback local_identity(adapter_state :: term()) :: term()

register_manager(adapter_state, pid)

(optional)
@callback register_manager(adapter_state :: term(), pid()) :: :ok | {:error, atom()}

transact(adapter_state, operation, t)

@callback transact(adapter_state :: term(), operation(), PtcRunner.Kernel.Deadline.t()) ::
  term()

Functions

acquire_mutation(store, key, mode, ttl_ms, deadline)

@spec acquire_mutation(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  :refresh | :authorization,
  pos_integer(),
  request_deadline()
) ::
  {:ok, %{fence: term(), starting_generation: non_neg_integer()}}
  | {:error, atom()}

admit_mcp(store, key, generation, ttl_ms, deadline)

@spec admit_mcp(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  non_neg_integer(),
  pos_integer(),
  request_deadline()
) :: {:ok, term()} | {:error, atom()}

admit_mcp(store, key, generation, worker_pid, ttl_ms, deadline)

@spec admit_mcp(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  non_neg_integer(),
  pid(),
  pos_integer(),
  request_deadline()
) :: {:ok, term()} | {:error, atom()}

begin_authority_retirement(store, tenant_id, installation_id, expected_fingerprint, action, idempotency_key, lease_ttl_ms, deadline)

@spec begin_authority_retirement(
  t(),
  binary(),
  binary(),
  binary(),
  {:replace, binary()} | :release,
  binary(),
  pos_integer(),
  request_deadline()
) :: {:ok, map()} | {:error, atom()}

begin_code_dispatch(store, key, flow_id, fence, binding, deadline)

@spec begin_code_dispatch(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  term(),
  term(),
  map(),
  request_deadline()
) :: :ok | {:error, atom()}

begin_flow(store, key, flow, ttl_ms, deadline)

@spec begin_flow(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  map(),
  pos_integer(),
  request_deadline()
) ::
  {:ok, map()} | {:error, atom()}

begin_mutation_dispatch(store, key, fence, binding, deadline)

@spec begin_mutation_dispatch(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  term(),
  map(),
  request_deadline()
) :: :ok | {:error, atom()}

begin_principal_retirement(store, tenant_id, principal_id, expected_epoch, idempotency_key, lease_ttl_ms, deadline)

@spec begin_principal_retirement(
  t(),
  binary(),
  binary(),
  term(),
  binary(),
  pos_integer(),
  request_deadline()
) :: {:ok, map()} | {:error, atom()}

cancel_flow(store, key, flow_id, deadline)

@spec cancel_flow(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  term(),
  request_deadline()
) ::
  :ok | {:error, atom()}

claim_authorities(store, tenant_id, authorities, deadline)

@spec claim_authorities(t(), binary(), [{binary(), binary()}], request_deadline()) ::
  {:ok, %{required(binary()) => term()}} | {:error, atom()}

claim_principal(store, tenant_id, principal_id, deadline)

@spec claim_principal(t(), binary(), binary(), request_deadline()) ::
  {:ok, term()} | {:error, atom()}

commit_grant(store, key, fence, grant, ttl_ms, anchor, deadline)

@spec commit_grant(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  term(),
  map(),
  pos_integer(),
  term(),
  request_deadline()
) :: {:ok, map()} | {:error, atom()}

complete_authority_retirement(store, intent_id, coordinator, deadline)

@spec complete_authority_retirement(t(), term(), term(), request_deadline()) ::
  {:ok, term()} | {:error, atom()}

complete_principal_retirement(store, intent_id, coordinator, deadline)

@spec complete_principal_retirement(t(), term(), term(), request_deadline()) ::
  {:ok, term()} | {:error, atom()}

consume_callback(store, key, flow_id, state, issuer, deadline)

@spec consume_callback(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  term(),
  binary(),
  binary() | nil,
  request_deadline()
) :: {:ok, map()} | {:error, atom()}

deny_flow(store, key, flow_id, state, issuer, deadline)

@spec deny_flow(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  term(),
  binary(),
  binary() | nil,
  request_deadline()
) :: :ok | {:error, atom()}

fail_mutation(store, key, fence, outcome, deadline)

@spec fail_mutation(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  term(),
  :not_dispatched | :possibly_dispatched | :invalid_grant,
  request_deadline()
) :: :ok | {:error, atom()}

inspect_retirements(store, tenant_id, deadline)

@spec inspect_retirements(t(), binary(), request_deadline()) ::
  {:ok, [map()]} | {:error, atom()}

load_grant(store, key, deadline)

@spec load_grant(t(), PtcRunner.Kernel.MCPOAuth.GrantKey.t(), request_deadline()) ::
  {:ok, map() | nil} | {:error, atom()}

load_requirement(store, key, deadline)

@spec load_requirement(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  request_deadline()
) ::
  {:ok, map() | nil} | {:error, atom()}

local_identity(store)

@spec local_identity(t()) :: term()

Returns an opaque process-local identity shared by wrappers of one store.

Adapters that can be wrapped should implement local_identity/1 and return the same non-secret identity for every handle to the same backing store.

mark_access_rejected(store, key, generation, deadline)

@spec mark_access_rejected(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  non_neg_integer(),
  request_deadline()
) :: :ok | {:error, atom()}

new(module, adapter_state)

@spec new(module(), term()) :: {:ok, t()} | {:error, :invalid_store}

recover_mutation(store, key, fence, atom, deadline)

@spec recover_mutation(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  term(),
  :worker_fenced,
  request_deadline()
) :: :ok | {:error, atom()}

Recovers one exact mutation only after its dispatch worker has been irreversibly fenced.

A refresh is poisoned and an authorization-code flow is terminalized. Lease expiry alone is not proof of fencing and is insufficient for this operation.

release_mcp(store, admission, deadline)

@spec release_mcp(t(), term(), request_deadline()) :: :ok | {:error, atom()}

terminalize_flow(store, key, flow_id, deadline)

@spec terminalize_flow(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  term(),
  request_deadline()
) ::
  :ok | {:error, atom()}

time_anchor(store, deadline)

@spec time_anchor(t(), request_deadline()) :: {:ok, term()} | {:error, atom()}

upsert_requirement(store, key, generation, scopes, ttl_ms, deadline)

@spec upsert_requirement(
  t(),
  PtcRunner.Kernel.MCPOAuth.GrantKey.t(),
  non_neg_integer(),
  MapSet.t(binary()),
  pos_integer(),
  request_deadline()
) :: {:ok, non_neg_integer()} | {:error, atom()}