/** * Session policies — * * A `SessionPolicy` is a small declarative object that controls how long a * session lives and which operations require re-authentication. It is * evaluated by the `PolicyEnforcer` class, which the Noydb instance * integrates to replace the bare `sessionTimeout` timer from. * * Design decisions * ──────────────── * Policies are stateless value objects — no timers, no event listeners. * The Noydb instance is the stateful coordinator: it holds the enforcer, * calls `enforcer.touch()` on every operation, and calls * `enforcer.checkOperation()` before high-risk operations. * * This keeps the policy module easy to unit-test (no global timers to mock) * and avoids the "who owns cleanup" problem that comes with timer-based * callbacks embedded in a value object. * * `lockOnBackground` registers a `visibilitychange` listener on the document * at enforcer creation time and removes it on `destroy()`. It is a no-op in * non-browser environments (no `document`). */ import type { SessionPolicy, ReAuthOperation } from '../../kernel/types.js'; export interface PolicyEnforcerOptions { /** The policy to enforce. */ policy: SessionPolicy; /** The session ID to revoke when idle/absolute timeouts fire. */ sessionId: string; /** * Called when the policy decides the session should end (idle timeout, * absolute timeout, or lockOnBackground). Use this to trigger the * same cleanup that `Noydb.close()` would perform. */ onRevoke: (reason: 'idle' | 'absolute' | 'background') => void; } /** * Stateful enforcer for a single session policy. * * Create one per open session, call `touch()` on every operation, * call `checkOperation(op)` before export/grant/revoke/rotate/changeSecret, * and call `destroy()` when the session ends. */ export declare class PolicyEnforcer { private readonly policy; private readonly sessionId; private readonly onRevoke; private readonly createdAt; private lastActivityAt; private idleTimer; private absoluteTimer; private visibilityHandler; constructor(opts: PolicyEnforcerOptions); /** * Record an activity timestamp and reset the idle timer. * Call this at the top of every Noydb public method. */ touch(): void; /** * Check whether the given operation is allowed under the active policy. * Throws `SessionPolicyError` if the operation requires re-authentication. * Throws `SessionExpiredError` if the absolute timeout has been exceeded * (defensive check in case the timer fired before the call arrived). * * This is a synchronous check — callers don't await it. */ checkOperation(op: ReAuthOperation): void; /** * Tear down timers and background-lock listener. Call from `Noydb.close()` * and whenever the session is revoked externally. */ destroy(): void; /** How long since the last activity, in ms. */ get idleMs(): number; /** How long since session creation, in ms. */ get ageMs(): number; private scheduleIdleTimer; private scheduleAbsoluteTimer; private registerBackgroundLock; private expire; } /** * Build a `PolicyEnforcer` from a policy + session token, and return it * alongside a cleanup function. Convenience wrapper for Noydb. */ export declare function createEnforcer(opts: PolicyEnforcerOptions): PolicyEnforcer; /** * Validate that a `SessionPolicy` is well-formed. * Throws a plain `Error` (not `NoydbError`) because this is a developer * error — invalid policies passed at construction time, not at runtime. */ export declare function validateSessionPolicy(policy: SessionPolicy): void;