/** * Default email-verification lifetime — 24 hours. * * Longer than the other two on purpose, and the asymmetry is the point. A * magic link and a reset link are CREDENTIALS: whoever holds one signs in, so * a short fuse is worth the friction of asking for another. A verification * link grants nothing — redeeming it only asserts that the address reaches its * owner — so the cost of a short lifetime is all friction and no security, paid * by exactly the users who check mail once a day. */ export declare const EMAIL_VERIFY_TTL_S: number; /** Hash a plaintext token for storage / lookup. SHA-256 is sufficient — * the token is high-entropy (32 random bytes), so there's no * brute-force surface that would need a slow KDF. */ export declare const hashToken: (plaintext: string) => string; /** Default magic-link lifetime — short, since it's an inbox round-trip. */ export declare const MAGIC_LINK_TTL_S: number; /** Lifetime of the short-lived MFA pending token (the second-factor * challenge). Long enough for the user to fetch a TOTP code, short enough * that a leaked challenge is near-useless. * * Lives HERE rather than beside the MFA handler that mints it, because the * default-TTL table below has to be exhaustive over `TokenPurpose` and a * constant imported from `handlers.ts` would be a cycle. `handlers.ts` * re-exports it, so the public spelling is unchanged. */ export declare const MFA_PENDING_TTL_S: number; export declare interface MintedToken { /** The plaintext — put this in the emailed link. Never stored. */ readonly token: string; /** SHA-256 of the plaintext — store this. */ readonly tokenHash: string; /** Unix-ms expiry. */ readonly expiresAt: Date; readonly purpose: TokenPurpose; } /** * Mint a fresh single-use secret with NO purpose attached — 32 CSPRNG bytes, * its SHA-256, and an expiry. * * Exists for the credentials that are single-use, hashed and expiring but do * NOT live in `authTokens`: a tenant invitation carries its own row (with an * address, a tenant and a role), so it has no `TokenPurpose` to name. Reaching * for `mintToken('magic-link', …)` just to obtain the bytes would file an * invitation under a purpose it does not have, in a type everything else reads * as authoritative. */ export declare const mintSecret: (ttlSeconds: number) => Omit; /** * Mint a fresh single-use token. The caller persists `{ tokenHash, * userId, purpose, expiresAt }` via `UserStore.insertToken` and emails * the plaintext `token` in a link. */ export declare const mintToken: (purpose: TokenPurpose, ttlSeconds?: number) => MintedToken; /** Default password-reset lifetime — a bit longer. */ export declare const PASSWORD_RESET_TTL_S: number; declare type TokenPurpose = 'magic-link' | 'password-reset' | 'mfa-pending' | 'email-verify'; export { }