All files / types auth.ts

100% Statements 36/36
100% Branches 2/2
100% Functions 2/2
100% Lines 36/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 371x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 3x 3x 3x 3x 3x 3x  
/** Identity claims the UI needs, decoded from the verified Google ID token. */
export interface AuthenticatedUser {
  sub: string;
  email: string;
}
 
/**
 * Persisted session in chrome.storage.local (survives browser restarts).
 * `signedInAt` is the timestamp (ms) of the last *interactive* sign-in and
 * anchors the ~30-day session horizon (FR-014a): silent renewal refreshes
 * `idToken`/`expiresAt` but never `signedInAt`.
 */
export interface StoredAuth {
  idToken: string;
  /** Token `exp`, in epoch milliseconds. */
  expiresAt: number;
  /** Interactive sign-in time, in epoch milliseconds. */
  signedInAt: number;
  user: AuthenticatedUser;
}
 
export type AuthErrorCode =
  | "sign-in-canceled"
  | "sign-in-failed"
  | "session-expired"
  | "not-authorized";
 
export class AuthError extends Error {
  readonly code: AuthErrorCode;
 
  constructor(code: AuthErrorCode, message: string) {
    super(message);
    this.name = "AuthError";
    this.code = code;
  }
}