Internal Resolve Token

Internal-only PAT resolution for the keyless MCP server. That container talks to Postgres as the least-privilege mcp_role (migration 0040), which is deliberately denied ALL access to personal_access_tokens -- the auth table -- so it cannot resolve its own bearer tokens. It POSTs the token here instead; this process (as relay, the legitimate owner of the token table) runs the exact same tokens.resolve_token used everywhere else and returns ONLY the owning user_id.

Minimal surface by design: the token arrives in the request BODY (never a query string / URL, so it can't land in an access log), and the response is just {"user_id": <uuid str> | null} -- no token_hash, name, prefix, or any other column of the row. Locked behind the internal-read secret (require_internal_secret, distinct from the relay hook secret) and the same Caddy @internal_only matcher, so it is never reachable from the public internet.

The best-effort last_used_at bump inside resolve_token runs here now, as relay, so token telemetry is preserved despite mcp_role's lack of UPDATE.

Build 1.5 (MCP OAuth): the response carries kind/scope/aud alongside user_id so the resource server can enforce audience binding and tool scope. Additive - an older mcp-server reads user_id and ignores the rest, which is what makes the mcp-server-first deploy order safe.

post/internal/resolve-token

Request

  • Base URL: https://sleipnir.tv (the document declares no server; this is the origin it was published from)
  • URL: https://sleipnir.tv/internal/resolve-token
  • Auth: none declared

Headers

X-Sleipnir-Hook-Authstring nullable

Request body

tokenstring nullable

Response

Successful Response

unknown required

Changes

No recorded changes to this operation across all 1 revision of this API.