/** * MCP Refresh-Token Family Store (OAuth 2.1 single-use rotation) * * Persists one row per refresh-token family in `mcp_refresh_families`. The * opaque token handed to the client is `"."`; only the * SHA-256 hash of the whole value is stored (`current_token_hash`). On a valid * refresh the hash is overwritten (rotation); a presented token whose hash no * longer matches is a replay of a superseded token, which revokes the family. * * This keeps replay revocation O(1) with a get/put-only table abstraction: we * store family state, not individual tokens, so it stays correct even after * old tokens age out of any per-token store. Tokens are never stored in the * clear. * * Rotation is not atomic (no compare-and-set on the table, same constraint as * authCodeStore.consume): two concurrent refreshes of the same current token * both pass the hash check before either write lands, so one of the two new * tokens is orphaned (last write wins). The orphan fails safe — its next use is * a hash mismatch, which revokes the family. Benign under the real * single-client-per-refresh pattern; accepted for v1. * * Explicit field access on encode/decode (no `{ ...raw }`) — Harper * tracked-object Proxies return empty own-keys. See CLAUDE.md gotcha. */ import type { Logger, MCPRefreshFamilyRecord } from '../../types.ts'; /** * Reset the cached table reference (for testing only). * @internal */ export declare function resetMCPRefreshFamiliesTableCache(): void; /** SHA-256 of a token value, base64url-encoded. */ export declare function hashRefreshToken(token: string): string; /** Mint a fresh token for a family and return both the token and its hash. */ export declare function makeRefreshToken(familyId: string): { token: string; hash: string; }; /** * Extract the family id from a presented refresh token. Returns null when the * token is not in the expected `.` shape. */ export declare function parseRefreshToken(token: unknown): { familyId: string; } | null; /** Generate a new, unique family id. */ export declare function newFamilyId(): string; export declare class MCPRefreshFamilyStore { private logger?; constructor(logger?: Logger); set(record: MCPRefreshFamilyRecord): Promise; get(familyId: string): Promise; delete(familyId: string): Promise; }