import { PushTokenEventDetail } from './types'; /** * Dispatched by `shell-native/push.ts` on OS registration. Re-declared here * rather than imported: `shared/*` must not depend on `shell-native/*`. */ export declare const PUSH_TOKEN_EVENT = "burdenoff:pushToken"; /** * Stable per-install device id, independent of the OS token (which rotates). * The backend retires the previous row for the same `deviceId` when a rotated * token arrives, so this key is what stops a registry filling with dead tokens. */ export declare const PUSH_DEVICE_ID_STORAGE_KEY = "burdenoff:deviceId"; export type PushDevicePlatform = PushTokenEventDetail['platform']; /** * `global-auth-svc` `registerDeviceToken`. `productSlug` is a top-level * argument because `global-channel-svc` resolves the Firebase project (the * fleet is split across five of them) from the DEVICE row — a device minted by * one app install belongs to exactly one project. It is mirrored into * `metadata` so a consumer reading the free-form blob sees the same value. * * NOTE the shape of the arguments: no `userId`, no `actorId`, no `id`. The * mutation is `@rbac(scopeType: "self")`, which is an AUTHENTICATION gate only; * an identity-shaped argument on a self-scoped field would let any * authenticated caller register a device for anybody. */ export declare const REGISTER_DEVICE_TOKEN_MUTATION = "\n mutation RegisterDeviceToken(\n $deviceId: String!\n $token: String!\n $platform: String!\n $productSlug: String!\n $metadata: JSONObject\n ) {\n registerDeviceToken(\n deviceId: $deviceId\n token: $token\n platform: $platform\n productSlug: $productSlug\n metadata: $metadata\n ) {\n id\n deviceId\n platform\n lastUsedAt\n }\n }\n"; /** * Pre-`productSlug` spelling of the same mutation, used only as a fallback (see * `isUnknownProductSlugArgumentError`). The product slug still travels in * `metadata`, so a device registered through this path is recoverable. */ export declare const REGISTER_DEVICE_TOKEN_MUTATION_LEGACY = "\n mutation RegisterDeviceToken(\n $deviceId: String!\n $token: String!\n $platform: String!\n $metadata: JSONObject\n ) {\n registerDeviceToken(\n deviceId: $deviceId\n token: $token\n platform: $platform\n metadata: $metadata\n ) {\n id\n deviceId\n platform\n lastUsedAt\n }\n }\n"; export declare const UNREGISTER_DEVICE_TOKEN_MUTATION = "\n mutation UnregisterDeviceToken($deviceId: String!) {\n unregisterDeviceToken(deviceId: $deviceId)\n }\n"; /** The exact `graphqlFetch` options this module sends. */ export interface PushRegistrationRequest { gateway: 'global'; query: string; operationName: string; variables: Record; authToken?: string; /** * Always true: registration is fire-and-forget background sync. A failure * (offline, cold subgraph, a token attached a beat after login) must never * raise the global "[Burdenoff backend error]" toast. */ suppressGlobalErrorEvent: true; } export interface PushRegistrationResponse { data?: unknown; errors?: Array<{ message: string; extensions?: Record; }>; } export type PushRegistrationTransport = (request: PushRegistrationRequest) => Promise; /** * Stable per-install id, persisted in `localStorage`. When storage is * unavailable (private mode, storage disabled) the id is still stable for the * lifetime of the page — a fresh id per call would create one registry row per * launch. */ export declare function getOrCreatePushDeviceId(): string; export interface RegisterPushDeviceOptions { /** The OS push token (APNs/FCM) or, on web, the serialised subscription. */ token: string; platform: PushDevicePlatform; /** Product slug, e.g. `vibecontrols` — resolves the Firebase project. */ productSlug: string; /** * Access token, passed explicitly. Profile storage may not be flushed yet * immediately after login, so relying on `graphqlFetch`'s storage fallback * would race the very call we care about. */ authToken?: string; appVersion?: string; locale?: string; /** Only used to scope the "already sent this" cache — never sent. */ userId?: string; deviceId?: string; transport?: PushRegistrationTransport; } /** * Register (or refresh) this device. Idempotent on the backend, and additionally * de-duplicated here so a remount storm cannot hammer the mutation. * * Resolves `true` only when the device is registered AND routable — i.e. the * backend stamped a Firebase project on it. It resolves `false` both when the * mutation failed and when the row had to be written through the legacy, * project-less shape during a gateway schema-skew window: that row exists but * nothing can be delivered to it, and reporting it as success is what turns a * deliberate server-side rejection into a device that silently never receives. */ export declare function registerPushDevice(options: RegisterPushDeviceOptions): Promise; export interface UnregisterPushDeviceOptions { authToken?: string; deviceId?: string; transport?: PushRegistrationTransport; } /** * Revoke this device's registration — call on explicit logout / push opt-out. * Clears the de-duplication cache so a subsequent login re-registers. */ export declare function unregisterPushDevice(options?: UnregisterPushDeviceOptions): Promise; export interface PushDeviceRegistrationOptions { productSlug: string; /** Read lazily so a token arriving mid-session picks up the current token. */ getAuthToken?: () => string | null | undefined; getUserId?: () => string | null | undefined; appVersion?: string; locale?: string; transport?: PushRegistrationTransport; /** Called with the outcome of every attempt (logging hook for the shell). */ onResult?: (registered: boolean) => void; onError?: (error: Error) => void; } /** * Listen for `burdenoff:pushToken` AND replay the token boot already captured. * * The replay is not optional: the OS `registration` callback fires during * `bootNativeShell()`, before React mounts, so a listener-only implementation * misses the token on every cold start. * * Returns a disposer. Safe to call again after login — the de-duplication cache * means an unchanged (user, device, product, token) tuple is not re-sent. */ export declare function installPushDeviceRegistration(options: PushDeviceRegistrationOptions): () => void; /** Test seam — clears the module-level device id and de-duplication caches. */ export declare function resetPushDeviceRegistrationForTests(): void; //# sourceMappingURL=push-registration.d.ts.map