auth/token_lifetime.ts

API token lifetime — the temporal axis of a minted credential.

lifetime is required on account_token_create, mirroring scope: there is deliberately no default. A caller who wants a never-expiring token spells {kind: 'eternal'}, and the request records that they did — an omitted lifetime is a validation error upstream, not an eternal token. expires_at IS NULL therefore means "deliberately eternal", never "minted before the policy existed".

Lifetime is deliberately not part of the scope document — TokenScope is strict on both spines and sits on the hot resolve path. The expiry lives in the indexed api_token.expires_at column where the SQL validation gate already enforces it (expires_at IS NULL OR expires_at > NOW()).

A framework-level ceiling (max_token_ttl_days) is deferred until fuzf has an expiry story (an expiry-aware read + a 401 hint); see docs/security.md §API tokens.

view source

Declarations
#

3 declarations

token_lifetime_to_expires_at
#

auth/token_lifetime.ts view source

(lifetime: { kind: "eternal"; } | { kind: "ttl"; days: number; }, now?: Date): Date | null import {token_lifetime_to_expires_at} from '@fuzdev/fuz_app/auth/token_lifetime.js';

Resolve a lifetime input to the expires_at value the mint query stores.

lifetime

the validated lifetime input

type { kind: "eternal"; } | { kind: "ttl"; days: number; }

now

mint time (injectable for tests; defaults to the current time)

type Date
default new Date()

returns

Date | null

the expiry Date, or null for an eternal token

TOKEN_TTL_DAYS_MAX
#

auth/token_lifetime.ts view source

36500 import {TOKEN_TTL_DAYS_MAX} from '@fuzdev/fuz_app/auth/token_lifetime.js';

Upper bound on ttl.days — a sanity cap (100 years), not a policy ceiling. Shared with the Rust twin so out-of-range requests 400 identically on both spines.

TokenLifetimeInput
#

auth/token_lifetime.ts view source

ZodDiscriminatedUnion<[ZodObject<{ kind: ZodLiteral<"eternal">; }, $strict>, ZodObject<{ kind: ZodLiteral<"ttl">; days: ZodNumber; }, $strict>], "kind"> import type {TokenLifetimeInput} from '@fuzdev/fuz_app/auth/token_lifetime.js';

Caller-provided lifetime for account_token_create.

eternal mints a never-expiring token (expires_at NULL); ttl bounds it to days from mint time. eternal is deliberately the first variant so schema-driven test generators produce it by default.

Imported by
#