/** * This Source Code is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright (c) Infonomic Company Limited */ /** * `RefreshTokensRepository` — the persistence contract for the * `byline_admin_refresh_tokens` table. * * Lives under `modules/auth` rather than at the package root because this * table exists to serve the built-in JWT session provider — a third-party * session provider (Lucia, WorkOS, Clerk) would not use it. `token_hash` * stores the SHA-256 of the plaintext refresh token; the plaintext leaves * the server exactly once, when it is issued to the caller. */ export interface RefreshTokenRow { id: string admin_user_id: string token_hash: string /** Null only for legacy rows, which cannot authorize native sessions. */ sid: string | null session_version: number issued_at: Date expires_at: Date revoked_at: Date | null rotated_to_id: string | null last_used_at: Date | null user_agent: string | null ip: string | null } export interface IssueRefreshTokenInput { /** Omitted only by legacy fixtures/imports; never accepted for native renewal. */ sid?: string | null id: string admin_user_id: string token_hash: string /** Account generation observed under the native issuance lock. */ session_version: number expires_at: Date user_agent?: string | null ip?: string | null } export interface RefreshTokensRepository { /** Insert a new refresh-token row. `id` is supplied by the caller (UUIDv7). */ issue(input: IssueRefreshTokenInput): Promise findByHash(tokenHash: string): Promise findById(id: string): Promise /** Stamp `last_used_at` for observability. */ touch(id: string, at?: Date): Promise /** * Revoke `oldId` and set its `rotated_to_id` to `newId`. This is not * independently a compare-and-swap. Native callers must hold the account * lock, reread the predecessor, and insert the successor before this write, * all through the same `withSessionLock` transaction. */ markRotated(oldId: string, newId: string, at?: Date): Promise /** Revoke a single token. Idempotent. */ revoke(id: string, at?: Date): Promise /** Revoke all refresh rows sharing the start member's sid, without traversal. */ revokeChain(startId: string, at?: Date): Promise /** Revoke every non-revoked token for a user. Used on password change / sign-out everywhere. */ revokeAllForUser(adminUserId: string, at?: Date): Promise /** Remove rows whose `expires_at` is in the past. Housekeeping. */ purgeExpired(now?: Date): Promise /** All non-revoked tokens for a user. Primarily for tests. */ listActiveForUser(adminUserId: string): Promise /** All tokens (including revoked) for a user. Primarily for tests and debugging. */ listAllForUser(adminUserId: string): Promise /** All tokens descended from `startId` via the rotation chain. Utility for tests. */ listRotationChain(startId: string): Promise }