import type { NodeLifeStatus } from './web-client/shared/protocol.js'; export interface PushPreferences { doneNotifications: boolean; } export interface PushSubscriptionRecord { id: string; endpoint: string; keys: { p256dh: string; auth: string; }; authScope: string; createdAt: number; lastSeenAt: number; prefs: PushPreferences; } export interface PushRegistryFile { schemaVersion: number; records: PushSubscriptionRecord[]; } export interface PushLastSeenRootState { status: NodeLifeStatus; attention_count: number; } export interface PushLastSeenAskState { present: boolean; } export interface PushLastSeenFile { schemaVersion: number; updatedAt: number; roots: Record; asks: Record; } /** A locally generated VAPID keypair, persisted so the same identity signs * every outbound push across restarts. The private key never leaves this * file/process — only `publicKey` is ever served to a client. */ export interface VapidKeypairFile { schemaVersion: number; publicKey: string; privateKey: string; subject: string; } export declare class PushRequestError extends Error { readonly statusCode: number; constructor(statusCode: number, message: string); } export declare function registryPath(): string; export declare function lastSeenPath(): string; export declare function vapidPath(): string; export declare function pushBodyMaxBytes(): number; /** Re-checkable at any later point (e.g. immediately before an outbound send, * not just at subscribe time) with no dependency on DNS resolution — the * allowlist match is a pure string check, so there is nothing to TOCTOU. */ export declare function isAllowedPushEndpoint(endpoint: string): boolean; export declare function normalizeEndpoint(endpoint: unknown): string; export declare function subscriptionIdForEndpoint(endpoint: string): string; export declare function parsePushSubscriptionBody(rawBody: string, authScope: string, now?: number): PushSubscriptionRecord; export declare function parsePushDeleteBody(rawBody: string): { endpoint: string; }; /** Load the persisted VAPID keypair, generating and persisting a fresh one on * first run. One keypair per server identity (design D8/push contract) — * every subscription is signed with the same public key for the life of this * `crtrHome()`. The private key never leaves this file/process. */ export declare function loadOrCreateVapidKeypair(path?: string, subject?: string): VapidKeypairFile; export declare class PushRegistryStore { private readonly path; private state; private readonly byId; constructor(path?: string); snapshot(): PushSubscriptionRecord[]; listByScope(authScope: string): PushSubscriptionRecord[]; upsert(record: PushSubscriptionRecord): PushSubscriptionRecord; touchById(id: string, lastSeenAt: number): PushSubscriptionRecord | null; /** Scoped delete for the HTTP DELETE verb: a caller may only remove a * subscription it owns (its authScope matches the stored record's). Pruning a * service-reported-gone endpoint is a separate, unscoped path (`deleteById`). */ deleteByEndpoint(endpoint: string, authScope: string): boolean; deleteById(id: string): boolean; private persist; } export declare class PushLastSeenStore { private readonly path; private state; constructor(path?: string); snapshot(): PushLastSeenFile; replace(next: PushLastSeenFile): void; private persist; }