---
title: "Référence d'API — nodefony/client — racine"
source: docs/api/core/client.md
url: https://nodefony.github.io/nodefony-core/docs/api/core/client/
---


[Documentation](../../../) › [Référence d'API](../../) › [`nodefony`](../) › client

> Générée depuis les déclarations de types publiées de `nodefony` **10.0.0-beta.5** : exactement ce que reçoit une application qui l'installe. Cette page n'existe dans aucun dépôt — pour la corriger, on corrige le TSDoc du code.

## `nodefony/client`

`import { … } from "nodefony/client"` — 95 symboles.

### Classes (8)

#### `AdaptiveRate`

```ts
class AdaptiveRate
```

- `constructor(options: AdaptiveRateOptions)`
- `current(): number` — Cadence courante (ms).
- `noteFrame(now: number): RateDecision | null` — À appeler à CHAQUE frame reçue.
- `checkStarvation(now: number): RateDecision | null` — Watchdog : à appeler périodiquement.

#### `BrowserWsTransport`

```ts
class BrowserWsTransport implements IRealtimeTransport
```

BrowserWsTransport — transport `IRealtimeTransport` pour le navigateur : wrap d'un `WebSocket` natif. Volontairement « bête » : il ouvre/envoie/ferme et relaie les events. L'orchestration (reconnect, backoff, heartbeat, state machine) vit AU-DESSUS dans `NodefonySocket` — qui crée un transport NEUF à chaque tentative.

- `constructor(url: string)`
- `connect(): void` — Ouvre le transport (asynchrone — l'ouverture effective est signalée par `onOpen`).
- `send(raw: RealtimeOutboundData): void` — Envoie une frame brute (texte sérialisé ou octets).
- `close(code?: number, reason?: string): void` — Ferme le transport (déclenche `onClose`).
- `get readyState(): number` — État courant (0..3, cf `TransportState`).
- `onOpen(cb: () => void): void` — Branche le handler d'ouverture (le owner relance subscribe/heartbeat).
- `onMessage(cb: (raw: RealtimeFrameData) => void): void` — Branche le pump entrant : appelé pour CHAQUE frame brute reçue, texte ou binaire — jamais filtrée ici (cf `RealtimeFrameData`).
- `onClose(cb: (code: number, reason: string) => void): void` — Branche la fermeture (le owner relance le backoff ou nettoie).
- `onError(cb: (err: unknown) => void): void` — Branche les erreurs transport (la fermeture qui suit gère le reconnect).

#### `NodefonyKernel`

```ts
class NodefonyKernel implements INodefonyKernel
```

Kernel client — se construit par `new`, comme `NodefonySocket` et `NodefonySse` : jamais un singleton de module (testabilité, HMR-safe : un module réévalué par Vite dédoublerait un singleton, gotcha vécu sur le contexte React de Studio), et plusieurs kernels coexistent en test.

- `readonly syslog: Syslog` — Journal client de série — `Pdu` isomorphes, corrélables au back.
- `constructor(options?: NodefonyKernelOptions)`
- `get<K extends keyof NodefonyKernelServices>(name: K): NodefonyKernelServices[K]` — Récupère un service composé, typé par le registre.
- `set<K extends keyof NodefonyKernelServices>(name: K, svc: NodefonyKernelServices[K]): void` — Enregistre un service sous son nom contractuel.
- `has(name: string): boolean` — Teste la présence d'un service — nom libre, y compris hors contrat.
- `get state(): NodefonyKernelState` — État courant — jamais régressif.
- `boot(): Promise<void>` — Compose et connecte les services.
- `terminate(): Promise<void>` — Flush l'observabilité et déconnecte.
- `get name(): string` — Nom du kernel — celui donné à la fabrique, `CLIENT KERNEL` par défaut.
- `get identity(): NodefonyKernelIdentity | null` — Identité runtime courante, telle que l'application l'a déclarée.
- `setIdentity(identity: NodefonyKernelIdentity | null): void` — Déclare l'identité runtime — et applique la règle de sécurité D9, née d'une fuite vécue en production.
- `on(event: NodefonyKernelEvent, handler: (...args: unknown[]) => void): this` — Abonne un handler à un événement du kernel (bus `Event` du cœur, chaînable).
- `off(event: NodefonyKernelEvent, handler: (...args: unknown[]) => void): this` — Retire un handler abonné par `on`.
- `get browserListenerCount(): number` — Nombre de listeners navigateur encore posés.

#### `NodefonyLogin`

```ts
class NodefonyLogin
```

Le **déroulé de connexion** côté navigateur : une machine à états PURE, sans DOM ni framework d'affichage, branchée sur les routes de session du framework. Le pendant de `NodefonySocket` et de `NodefonySse` pour l'authentification.

- `constructor(options?: NodefonyLoginOptions)`
- `readonly getState: () => NodefonyLoginState` — État courant — le même objet tant que rien n'a changé.
- `readonly subscribe: (listener: (state: NodefonyLoginState) => void) => () => void` — Écoute les changements d'état.
- `submitIdentifier(identifier: string): void` — Valide le compte saisi et passe à l'étape `password`.
- `submitPassword(password: string): Promise<NodefonyLoginState>` — Envoie le mot de passe du compte saisi.
- `login(identifier: string, password: string): Promise<NodefonyLoginState>` — Raccourci des formulaires d'un seul écran : compte et mot de passe d'un coup.
- `submitMfaCode(code: string): Promise<NodefonyLoginState>` — Envoie le code du second facteur (TOTP ou code de récupération).
- `loginWithPasskey(): Promise<NodefonyLoginState>` — Connexion par passkey, sans identifiant ni mot de passe.
- `loadProviders(): Promise<readonly NodefonyLoginProvider[]>` — Charge la liste des fournisseurs (une requête, rejouée seulement après échec).
- `startProvider(name: string, from?: string, back?: string): void` — Part chez un fournisseur, en navigation PLEINE PAGE — jamais par `fetch` : le navigateur doit suivre les redirections et revenir avec le cookie de session posé au retour.
- `me(): Promise<NodefonyLoginUser | null>` — Reprend une session existante ; `null` quand il n'y en a pas.
- `logout(): Promise<string | null>` — Ferme la session et revient à l'étape `identifier`.
- `back(): void` — Revient à l'étape `identifier`, en gardant le compte saisi.

#### `NodefonySocket`

```ts
class NodefonySocket<Emit extends EventsMap = DefaultEventsMap, Listen extends EventsMap = DefaultEventsMap, Actions extends ActionsMap = DefaultActionsMap> implements IRealtimeSocket<Emit, Listen>, IRealtimePeer<Emit, Actions>
```

Socket cliente de Nodefony : une connexion WebSocket JSON-RPC 2.0 vers le serveur temps réel de l'application, qui rétablit la liaison après une coupure.

- `constructor(opts?: NodefonySocketOptions, transportFactory?: RealtimeTransportFactory)`
- `static shared(opts?: NodefonySocketOptions): NodefonySocket` — Instance de connexion **partagée par URL** (résolue en absolu) sur `globalThis`.
- `get state(): RealtimeState`
- `get reconnectAttempts(): number` — Nombre de tentatives de reconnexion depuis la dernière connexion STABLE — restée ouverte au moins 5 s.
- `get nextRetryAt(): number | null` — Timestamp (ms epoch) de la prochaine tentative de reconnexion planifiée, `null` hors backoff.
- `retryNow(): void` — Force une reconnexion **immédiate** (annule le backoff en cours).
- `connect(url?: string): Promise<void>` — Ouvre la connexion WS.
- `disconnect(): void`
- `on<K extends string>(event: K, handler: K extends EventNames<Listen> ? (payload: EventPayload<Listen, K>) => void : RealtimeHandler): () => void` — Pub/sub local — handler sur un event server-pushed (notification JSON-RPC).
- `off<K extends string>(event: K, handler: K extends EventNames<Listen> ? (payload: EventPayload<Listen, K>) => void : RealtimeHandler): void` — Retire un handler d'un canal.
- `onNotice(handler: (notice: NodefonyNotice) => void): () => void` — S'abonne aux **notices normalisées** émises par le client : criticités qui cassent le temps réel (close codes RFC 6455 interprétés via `closeCodeToNotice`), erreurs serveur poussées, rétablissement de …
- `onDenied(handler: (denied: IRealtimeDenied) => void): () => void` — S'abonne aux **refus de canal** poussés par le serveur (`realtime:denied`) : un `subscribe`/push vers un canal protégé sans droit suffisant.
- `onSubscribed(handler: (ack: IRealtimeSubscribed) => void): () => void` — S'abonne aux **acquittements d'abonnement** poussés par le serveur (`realtime:subscribed`) : le canal est désormais actif sur la connexion courante.
- `whenSubscribed(channel: EventNames<Listen> | (string & {})): Promise<void>` — Attend que l'abonnement à `channel` soit EFFECTIF côté serveur — le signal qui manquait au patron « je recharge l'état, puis je suis le flux ».
- `emit<K extends string>(method: K, params?: K extends EventNames<Emit> ? EventPayload<Emit, K> : unknown): void` — Notification one-way client → server (pas de réponse attendue).
- `publish<K extends string>(channel: K, payload?: K extends EventNames<Emit> ? EventPayload<Emit, K> : unknown): void` — Émet sur un canal — verbe socket de `IRealtimeSocket.publish`.
- `subscribe(channel: EventNames<Listen> | (string & {})): void` — S'abonne à un canal pub/sub serveur (**ref-compté**).
- `unsubscribe(channel: EventNames<Listen> | (string & {})): void` — Désabonne un consommateur d'un canal (ref-compté) : émet `unsubscribe` au serveur seulement au **dernier** consommateur.
- `get subscribedChannels(): string[]` — Canaux DEMANDÉS (≥ 1 consommateur) — l'intention locale, pas un état confirmé par le serveur : l'abonnement effectif se lit sur `whenSubscribed` / `onSubscribed`.
- `get url(): string | null` — L'adresse du serveur temps réel, telle qu'elle a été donnée (ou résolue en absolu par `shared`).
- `get identity(): RealtimeIdentity | null` — Identité de la connexion, **annoncée par le serveur** au `realtime:welcome` (`RealtimeIdentity`).
- `get serverChannels(): readonly string[] | null` — Canaux pub/sub annoncés par le serveur au welcome (découverte).
- `get serverMethods(): readonly string[] | null` — Actions RPC annoncées par le serveur au welcome (découverte).
- `onIdentity(handler: (identity: RealtimeIdentity | null) => void): () => void` — S'abonne à l'identité résolue (event LOCAL `__identity__`, jamais réseau) : le handler est rappelé à chaque (re)welcome et au `disconnect()`.
- `onState(handler: (state: RealtimeState) => void): () => void` — S'abonne à l'**état de la connexion** (event LOCAL `__state__`, jamais réseau) : le handler est rappelé à chaque transition (`connecting`, `connected`, `reconnecting`, `error`, `disconnected`), jamais …
- `onStats(handler: () => void): () => void` — S'abonne au **tick d'échantillonnage des statistiques** (event LOCAL `__stats__`, jamais réseau), émis une fois par seconde après recalcul des débits par canal.
- `onBinary(handler: (data: Uint8Array<ArrayBuffer>) => void): () => void` — Lit les trames BINAIRES reçues sur la socket — le point d'extension d'un protocole binaire écrit par l'application, à côté du JSON-RPC.
- `sendBinary(data: Uint8Array<ArrayBuffer>): boolean` — Émet une trame BINAIRE, sans la sérialiser — le pendant sortant de `onBinary`.
- `onReconnect(handler: (info: RealtimeReconnectInfo) => void): () => void` — S'abonne aux **tentatives de reconnexion programmées** (event LOCAL `__reconnect__`, jamais réseau) : numéro d'essai, délai retenu par le back-off, et échéance absolue.
- `channel(name: string): IRealtimeChannel` — Handle « socket-like » d'un canal (`IRealtimeChannel`) — fine liaison sur les primitives (`subscribe`/`on`/`publish`/`unsubscribe`), forme naturelle des canaux à état (SIP, bridge) et point d'accroche …
- `adaptiveChannel(base: string, handler: RealtimeHandler, options: BindAdaptiveOptions): AdaptiveChannelBinding` — S'abonne à un canal d'ÉTAT en **cadence adaptative** (AIMD client-driven) : la lib mesure la gigue d'arrivée et ré-abonne automatiquement à une cadence plus grossière en cas de famine, plus fine quand …
- ``request<T = unknown>(path: `/${string}`, timeoutMs?: number): Promise<T>`` — Requête API par **path** — la MÊME action controller que le GET REST, via la socket (une action, N transports).
- `request<K extends string, T = unknown>(method: K, params?: ContractParams<Actions, K>, timeoutMs?: number): Promise<ContractResult<Actions, K, T>>` — Requête API par **path** — la MÊME action controller que le GET REST, via la socket (une action, N transports).
- `request<K extends ActionNames<Actions>>(method: K, params?: ActionParams<Actions, K>, timeoutMs?: number): Promise<ActionResult<Actions, K>>` — Requête API par **path** — la MÊME action controller que le GET REST, via la socket (une action, N transports).
- ``mutate<T = unknown>(path: `/${string}`, init: { method: "POST" | "PUT" | "PATCH" | "DELETE"; body?: unknown; idempotencyKey: string; timeoutMs?: number; }): Promise<T>`` — **Mutation** API par le pont `api.request` (POST/PUT/PATCH/DELETE) — pendant d'écriture de `request` (qui ne fait que des lectures GET).
- ``call<T = unknown>(path: `/${string}`, init?: { method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE"; body?: unknown; idempotencyKey?: string; timeoutMs?: number; }): Promise<IApiCallResult<T>>`` — Appel API par la socket rendant l'**enveloppe complète** — le résultat ET la méta serveur — là où `request`/`mutate` ne rendent que la valeur (forme courante, contrat « snapshot ≡ GET REST »).
- `ping(timeoutMs?: number): Promise<KernelPingResult & { rtt: number; }>` — Mesure le round-trip WS via la méthode RPC standard `nodefony:kernel:ping` — helper RÉUTILISABLE par tout consommateur (topbar Studio, debug bar, app user) : la mesure du RTT et la convention `nodefon …
- `notify<K extends EventNames<Emit>>(method: K, params?: EventPayload<Emit, K>): void` — Notification SORTANTE typée (pas de réponse).
- `register<K extends ActionNames<Actions>>(method: K, handler: TypedRpcActionHandler<Actions, K>): void` — Expose une action appelable PAR LE PAIR (requête entrante serveur→client).
- `unregister(method: ActionNames<Actions>): void` — Retire une action exposée.
- `get methods(): string[]` — Actions exposées par CE client (découverte).
- `receive(frame: unknown, size?: number): JsonRpcFrameKind` — Ingestion d'une frame ENTRANTE déjà parsée → log + classification/route par le moteur.
- `dispose(reason?: string): void` — Annule les requêtes sortantes en attente (fermeture transport / logout).
- `get framesReceived(): number` — Total de notifications reçues, tous canaux confondus (welcome inclus).
- `get framesUnsent(): number` — Total de frames qui n'ont **pas** pu partir depuis la création du client (transport fermé au moment de l'émission).
- `get binaryFramesDiscarded(): number` — Total de trames BINAIRES reçues puis écartées, faute de lecteur (`onBinary`).
- `get malformedFramesDiscarded(): number` — Total de trames TEXTE reçues puis écartées parce qu'elles ne sont pas du JSON.
- `get lastFrameAt(): number | null` — Timestamp (ms) de la dernière notification reçue.
- `get lastFrameMethod(): string | null` — `method`/canal de la dernière notification reçue.
- `getStats(): MessageStats[]` — Snapshot des stats par canal (msgCount/rate/series).
- `getChannelStats(method: string): MessageStats` — Stats d'un canal précis (== method JSON-RPC) ou `undefined`.
- `get frameLog(): readonly RealtimeFrame[]` — Log protocole : les `FRAME_LOG_MAX` dernières frames JSON-RPC (redactées), enregistrées EN CONTINU → la console « retrace l'instant » dès l'ouverture (jamais de démarrage à vide).
- `clearFrameLog(): void` — Purge le log protocole.

#### `NodefonySse`

```ts
class NodefonySse extends EventTarget
```

Client d'un flux `text/event-stream`, compatible `EventSource`, sur `fetch`.

- `static readonly CONNECTING = 0`
- `static readonly OPEN = 1`
- `static readonly CLOSED = 2`
- `readonly CONNECTING = 0`
- `readonly OPEN = 1`
- `readonly CLOSED = 2`
- `readonly url: string` — L'adresse du flux, résolue.
- `readonly withCredentials: boolean` — Les cookies partent-ils vers une autre origine ?
- `onopen: (event: Event) => void | null` — Appelé à l'ouverture de chaque connexion.
- `onmessage: (event: MessageEvent<string>) => void | null` — Appelé pour chaque événement de type `message`.
- `onerror: (event: Event) => void | null` — Appelé à chaque coupure, avant la reconnexion ou l'abandon.
- `constructor(url: string | URL, options?: NodefonySseOptions)`
- `get readyState(): number` — État de la connexion : 0 `CONNECTING`, 1 `OPEN`, 2 `CLOSED`.
- `get lastEventId(): string` — Le dernier identifiant reçu — celui que la reconnexion renverra.
- `close(): void` — Ferme la connexion et annule toute reconnexion.

#### `SseLimitError`

```ts
class SseLimitError extends RangeError
```

Un événement — ou une ligne — dépasse la taille admise.

- `constructor(limit: number)`

#### `SseParser`

```ts
class SseParser
```

Lit un flux `text/event-stream` déjà décodé en texte, morceau par morceau.

- `constructor(handlers: ISseParserHandlers, lastEventId?: string, maxEventSize?: number)`
- `get lastEventId(): string` — L'identifiant courant du flux — celui qu'une reconnexion renverra.
- `push(chunk: string): void` — Lit un morceau du flux.
- `end(): void` — Fin du flux : la ligne et le bloc inachevés sont jetés — un bloc que n'a pas clos une ligne vide n'est jamais rendu (§9.2.6).

### Fonctions (32)

#### `adaptiveRebindKey`

```ts
function adaptiveRebindKey(base: string, desiredMs: number, enabled?: boolean): string
```

Clé de **re-liaison** d'un canal en cadence adaptative.

#### `bindAdaptiveChannel`

```ts
function bindAdaptiveChannel(socket: IRealtimeSocket, base: string, handler: RealtimeHandler, options: BindAdaptiveOptions): AdaptiveChannelBinding
```

Câble un `AdaptiveRate` à une socket réelle : abonne `base` à sa cadence désirée, mesure la gigue d'arrivée, et **ré-abonne** automatiquement à une cadence plus grossière en cas de famine (MD) puis plus fine quand c'est sain (AI). Les frames continuent d'être livrées à `handler` à travers les changements de cadence.

#### `closeCodeToNotice`

```ts
function closeCodeToNotice(code: number, reason?: string): NodefonyNotice | null
```

Traduit un **code de fermeture WebSocket** (RFC 6455 §7.4) en `NodefonyNotice` — pendant CLIENT du `toWsCloseCode` serveur (`@nodefony/http`). Pur, sans état, donc trivialement testable et réutilisable.

#### `connectShared`

```ts
function connectShared(opts: ConnectSharedOptions): SharedConnection
```

Résout la socket partagée d'une adresse — ou adopte celle qu'on lui donne — et rend de quoi la démarrer sans jamais la couper.

#### `describeSocket`

```ts
function describeSocket(snapshot: SocketSnapshot): SocketDetailRow[]
```

Ce que le client sait de SA socket, mis en mots — la même description pour le tableau de la console du navigateur et pour la vignette qu'une page affiche.

#### `generateId`

```ts
function generateId(): string
```

Génère un identifiant unique (UUID v4) côté client.

#### `getCurrentRequestId`

```ts
function getCurrentRequestId(): string
```

`requestId` de la portée courante, `undefined` en dehors de `withRequestId`.

#### `getPageId`

```ts
function getPageId(): string
```

Identifiant stable de ce chargement de page (UUID v4), généré à la demande.

#### `initialSseSnapshot`

```ts
function initialSseSnapshot(url: string | URL | null): SseSnapshot
```

L'état d'un flux AVANT que `observeSse` ne l'ouvre — la valeur initiale qu'une liaison affiche au premier rendu : `CONNECTING` pour une adresse, `CLOSED` sans erreur pour `null`.

#### `installErrorCapture`

```ts
function installErrorCapture(opts: ErrorCaptureOptions): () => void
```

Installe la capture des erreurs globales du navigateur.

#### `installRequestIdProvider`

```ts
function installRequestIdProvider(): () => void
```

Branche `getCurrentRequestId` sur `Pdu.requestIdProvider`, de sorte que tout `Pdu` créé dans une portée `withRequestId` porte son `requestId` — le même champ que côté serveur, donc la même clé de recoupement, sans qu'aucun appelant ait à le répéter.

#### `installSyslogUplink`

```ts
function installSyslogUplink(opts: SyslogUplinkOptions): () => void
```

Installe la remontée des journaux du navigateur vers le pod.

#### `isLocalEvent`

```ts
function isLocalEvent(event: string): event is LocalEvent
```

Vrai si `event` est un événement local du client (jamais un canal réseau).

#### `observeAdaptiveChannel`

```ts
function observeAdaptiveChannel(client: ObservableClient, base: string, emit: Emit<unknown>, desiredMs: number, options?: AdaptiveObserveOptions): AdaptiveChannelBinding
```

Observe un canal d'ÉTAT en **cadence adaptative** (AIMD piloté par le client) : la cadence recule sous famine et remonte quand c'est sain, sans changement serveur. `emit` reçoit chaque frame à travers les changements de cadence.

#### `observeChannel`

```ts
function observeChannel(client: ObservableClient, channel: string, emit: Emit<unknown>): Dispose
```

Observe un canal pub/sub : `emit` est appelé pour chaque message reçu.

#### `observeChannelData`

```ts
function observeChannelData<T = unknown>(client: ObservableClient, channel: string, emit: Emit<T | null>, initial?: T | null): Dispose
```

Observe la **dernière valeur** reçue sur un canal — le cas le plus courant (dernière mesure d'un flux d'état). `emit` reçoit `initial` immédiatement, puis chaque nouvelle valeur : dernier arrivé gagne.

#### `observeChannelStats`

```ts
function observeChannelStats(client: ObservableClient, channel: string, emit: Emit<MessageStats | null>): Dispose
```

Observe les **statistiques** d'un canal (débit, série du VU-mètre, total), rafraîchies par l'échantillonneur du client une fois par seconde. `emit` reçoit l'instantané courant immédiatement, puis à chaque échantillon.

#### `observeIdentity`

```ts
function observeIdentity(client: ObservableClient, emit: Emit<RealtimeIdentity | null>): Dispose
```

Observe l'identité résolue par le serveur au welcome (`null` tant qu'aucun welcome n'est arrivé, et après un `disconnect()` volontaire). `emit` reçoit la valeur courante immédiatement, puis à chaque (re)welcome.

#### `observeKernelIdentity`

```ts
function observeKernelIdentity(kernel: INodefonyKernel, emit: Emit<NodefonyKernelIdentity | null>): Dispose
```

Observe l'identité DÉCLARÉE au noyau par l'application (`setIdentity`) — `null` hors session. `emit` reçoit la valeur courante immédiatement, puis à chaque changement de COMPTE.

#### `observeKernelState`

```ts
function observeKernelState(kernel: INodefonyKernel, emit: Emit<NodefonyKernelState>): Dispose
```

Observe l'état du noyau client (`created` → `booting` → `ready` → `terminated`). `emit` reçoit l'état courant **immédiatement**, puis à chaque transition.

#### `observeLogin`

```ts
function observeLogin(login: NodefonyLogin, onChange: (state: NodefonyLoginState) => void): () => void
```

Relaie l'état d'un `NodefonyLogin` vers un rappel : une fois tout de suite, puis à chaque changement. C'est le seul point d'attache des liaisons `nodefony/{react,vue,svelte,angular}` — même forme que `observeSse`.

#### `observeNoticeLog`

```ts
function observeNoticeLog(client: ObservableClient, emit: Emit<NodefonyNotice[]>, opts?: ObserveNoticeLogOptions): Dispose
```

Observe un **historique borné** des dernières notices, filtrable par source : un journal léger des incidents temps réel, distinct des notifications éphémères. `emit` reçoit le tableau complet à chaque changement.

#### `observeNotices`

```ts
function observeNotices(client: ObservableClient, emit: Emit<NodefonyNotice>): Dispose
```

Observe les **notices normalisées** du client : criticités qui cassent le temps réel (codes de fermeture RFC 6455 interprétés), erreurs poussées par le serveur, rétablissement de connexion. `emit` est appelé pour CHAQUE notice — de quoi brancher un centre de notifications.

#### `observeReconnect`

```ts
function observeReconnect(client: ObservableClient, emit: Emit<RealtimeReconnectInfo>): Dispose
```

Observe les **tentatives de reconnexion** programmées par le back-off : numéro d'essai, délai retenu, échéance absolue. De quoi rendre un compte à rebours plutôt qu'un « déconnecté » muet.

#### `observeSnapshot`

```ts
function observeSnapshot(client: ObservableClient, emit: Emit<SocketSnapshot>): Dispose
```

Observe l'instantané : `emit` reçoit la valeur courante immédiatement, puis à chaque échantillon du client (une fois par seconde), à chaque changement d'état et à chaque accueil qui change l'identité — les seuls moments où il peut avoir bougé de façon visible.

#### `observeSse`

```ts
function observeSse(url: string | URL | null, emit: Emit<SseSnapshot>, options?: ObserveSseOptions): Dispose
```

Observe un flux `text/event-stream` : l'ouvre, rend son état à `emit` à chaque transition et à chaque événement, et le ferme à la libération.

#### `observeState`

```ts
function observeState(client: ObservableClient, emit: Emit<RealtimeState>): Dispose
```

Observe l'état de la connexion. `emit` reçoit l'état courant **immédiatement**, puis à chaque transition — une liaison n'a donc rien à initialiser à part.

#### `observeSyslog`

```ts
function observeSyslog(client: ObservableClient, emit: Emit<unknown[]>, opts?: ObserveSyslogOptions): Dispose
```

Observe le **journal du serveur** : anneau borné, filtre de sévérité, et surtout le format **coalescé** du canal (`{ logs: Pdu[], dropped }`) autant que l'entrée unique. `emit` reçoit le tableau complet à chaque changement — une nouvelle référence, directement affichable.

#### `resetClientLogContext`

```ts
function resetClientLogContext(): void
```

Remet le module à son état initial — réservé aux tests, qui doivent pouvoir repartir d'une page « neuve » sans recharger un document.

#### `socketSnapshot`

```ts
function socketSnapshot(client: SnapshotSource): SocketSnapshot
```

Lit l'instantané courant. Purement local : aucune trame n'est émise, rien n'est demandé au serveur — afficher cet état ne coûte donc rien au réseau.

#### `sseRebindKey`

```ts
function sseRebindKey(url: string | URL | null, options?: ObserveSseOptions): string
```

Clé de **ré-ouverture** d'un flux : l'adresse et les types écoutés, et rien d'autre. Le rappel `onEvent` et les objets d'options changent d'identité à chaque rendu dans la plupart des frameworks ; rouvrir à chaque rendu couperait le flux en boucle. Les autres réglages (en-têtes, corps) sont lus à l'ouverture.

#### `withRequestId`

```ts
function withRequestId<T>(requestId: string, fn: () => T): T
```

Exécute `fn` en déclarant que ce qu'elle journalise appartient à la requête `requestId`.

### Constantes (5)

#### `BROWSER_ERROR_MSGID`

```ts
const BROWSER_ERROR_MSGID = "BROWSER_ERROR"
```

Catégorie par défaut d'une exception non rattrapée.

#### `BROWSER_REJECTION_MSGID`

```ts
const BROWSER_REJECTION_MSGID = "BROWSER_REJECTION"
```

Catégorie d'une promesse rejetée sans `catch`.

#### `LOCAL_EVENTS`

```ts
const LOCAL_EVENTS: { readonly state: "__state__"; readonly identity: "__identity__"; readonly stats: "__stats__"; readonly notice: "__notice__"; readonly denied: "__denied__"; readonly subscribed: "__subscribed__"; readonly reconnect: "__reconnect__"; }
```

Événements locaux du `NodefonySocket` — jamais émis ni reçus par le réseau.

#### `SSE_MAX_EVENT_SIZE`

```ts
const SSE_MAX_EVENT_SIZE: number
```

Taille maximale d'un événement par défaut, en unités UTF-16 : 4 Mi.

#### `UPLINK_MSGID`

```ts
const UPLINK_MSGID = "CLIENT_UPLINK"
```

Catégorie (`msgid`) réservée à ce que le transport dit de LUI-MÊME. Les entrées qui la portent sont **exclues** de la remontée : sans cette exclusion, un envoi qui échoue journalise son échec, ce qui produit une entrée, qui déclenche un envoi, qui échoue.

### Interfaces (37)

#### `AdaptiveChannelBinding`

```ts
interface AdaptiveChannelBinding
```

Poignée du canal adaptatif — cadence courante + coupure.

- `readonly intervalMs: number` — Cadence courante (ms).
- `readonly channel: string` — Canal effectivement abonné (`base` ou `base:<ms>`).
- `dispose(): void` — Coupe tout : watchdog + handler + `unsubscribe`.

#### `AdaptiveRateOptions`

```ts
interface AdaptiveRateOptions
```

Réglages de la cadence adaptative. Seul `intervalMs` est requis.

- `readonly intervalMs: number` — Cadence désirée la plus fine (ms) = bas de l'échelle.
- `readonly defaultMs?: number` — Cadence par défaut serveur du canal (le canal nu la vaut).
- `readonly ladder?: number[]` — Échelle de cadences (ms, croissante).
- `readonly starvationFactor?: number` — Famine : `gap observé > k × cadence courante` ⇒ décélère.
- `readonly healthyFactor?: number` — Sain : `gap ≤ k × cadence` compte comme bon échantillon.
- `readonly recoveryWindow?: number` — Nb d'échantillons sains consécutifs avant d'accélérer (AI).
- `readonly maxMs?: number` — Plafond de l'échelle dérivée (ms).

#### `AdaptiveScheduler`

```ts
interface AdaptiveScheduler
```

Planificateur du watchdog — injectable pour des tests déterministes (défaut : globals).

- `set(cb: () => void, ms: number): unknown`
- `clear(handle: unknown): void`

#### `BindAdaptiveOptions`

```ts
interface BindAdaptiveOptions extends AdaptiveRateOptions
```

Réglages du câblage adaptatif = `AdaptiveRateOptions` + crochets/injection.

- `enabled?: boolean` — Active l'AIMD.
- `onRate?: (intervalMs: number, reason: RateChangeReason) => void` — Notifié à chaque cadence effective (incl.
- `clock?: () => number` — Horloge (ms).
- `scheduler?: AdaptiveScheduler` — Planificateur du watchdog.

#### `ConnectSharedOptions`

```ts
interface ConnectSharedOptions
```

Options de `connectShared` — le noyau, la socket déjà construite, ou l'adresse.

- `kernel?: INodefonyKernel | null` — Le noyau client de l'application — la voie COMPOSÉE.
- `url?: string` — Adresse du serveur temps réel — la voie SIMPLE.
- `client?: ObservableClient` — Socket déjà construite — la voie AVANCÉE, quand l'application possède son cycle de connexion (c'est le cas de la console d'administration, qui re-négocie la socket sur changement d'identité).

#### `ErrorCaptureOptions`

```ts
interface ErrorCaptureOptions
```

- `syslog: Syslog` — Le journal client qui recevra les entrées.
- `msgid?: string` — Catégorie (`msgid`) des entrées produites.
- `dedupeMs?: number` — Fenêtre de déduplication des erreurs IDENTIQUES consécutives, en ms.

#### `IApiCallResult`

```ts
interface IApiCallResult<T = unknown>
```

Enveloppe d'un appel `NodefonySocket.call` : la valeur rendue par la route, et l'identifiant du profil serveur de cette frame (dev — `null` en production, où le serveur n'émet aucune méta).

- `result: T`
- `requestId: string | null`

#### `INodefonyKernel`

```ts
interface INodefonyKernel
```

Contrat du kernel client isomorphe (ADR-0007 D2 — surface v1, volontairement minimale : chaque méthode publiée est une promesse SemVer).

- `get<K extends keyof NodefonyKernelServices>(name: K): NodefonyKernelServices[K]` — Récupère un service enregistré (ou `undefined` s'il n'est pas composé).
- `set<K extends keyof NodefonyKernelServices>(name: K, svc: NodefonyKernelServices[K]): void` — Enregistre un service sous son nom contractuel.
- `has(name: string): boolean` — Teste la présence d'un service (nom libre, y compris hors contrat).
- `boot(): Promise<void>` — Compose et connecte les services (idempotent).
- `terminate(): Promise<void>` — Flush l'observabilité et déconnecte (best-effort sur `pagehide`).
- `readonly state: NodefonyKernelState` — État courant du kernel — jamais régressif.
- `setIdentity(identity: NodefonyKernelIdentity | null): void` — Déclare l'identité runtime courante — c'est l'application qui la connaît (login, logout, bascule de compte), le kernel qui en tire les conséquences.
- `readonly identity: NodefonyKernelIdentity | null` — Identité runtime courante, telle que l'application l'a déclarée.
- `on(event: NodefonyKernelEvent, handler: (...args: unknown[]) => void): this` — Abonne un handler à un événement du kernel (API `Event` du Core, chaînable).
- `off(event: NodefonyKernelEvent, handler: (...args: unknown[]) => void): this` — Retire un handler abonné par `on` (chaînable).
- `readonly syslog: Syslog` — Journal client de série (`Pdu` isomorphes — corrélables au back par `requestId`).

#### `ISseEvent`

```ts
interface ISseEvent
```

Un événement reçu, une fois sa ligne vide atteinte (WHATWG §9.2.6).

- `readonly type: string` — Le champ `event`, ou `"message"` quand le bloc n'en portait pas.
- `readonly data: string` — Les champs `data` du bloc, joints par un saut de ligne.
- `readonly lastEventId: string` — L'identifiant courant du flux, après ce bloc — `""` s'il n'y en a jamais eu.

#### `ISseParserHandlers`

```ts
interface ISseParserHandlers
```

Ce que l'analyseur rend à mesure qu'il lit.

- `onEvent(event: ISseEvent): void` — Un bloc complet, porteur de données.
- `onRetry?(ms: number): void` — Le serveur demande un autre délai de reconnexion (champ `retry`, en ms).

#### `KernelPingResult`

```ts
interface KernelPingResult
```

Réponse de la méthode RPC standard `nodefony:kernel:ping` — CONVENTION Nodefony : tout endpoint realtime (Studio aujourd'hui, `RealtimeService` en P13.4) y répond. Sert de liveness + base de mesure du round-trip (cf `NodefonySocket.ping`).

- `pong: true`
- `ts: number`
- `uptime: number` — uptime process serveur (s).
- `pid: number`
- `version?: string`

#### `NodefonyKernelIdentity`

```ts
interface NodefonyKernelIdentity
```

Identité runtime déclarée par l'application au kernel.

- `readonly key: string` — Clé stable du compte — l'unique critère du re-handshake (D9).
- `readonly data?: unknown` — Charge libre, opaque au kernel.

#### `NodefonyKernelOptions`

```ts
interface NodefonyKernelOptions
```

Options de `new NodefonyKernel()`.

- `name?: string` — Nom du kernel — sert de `msgid` dans les journaux client.
- `realtime?: NodefonySocket | NodefonySocketOptions | false` — La socket de l'application.
- `browserEvents?: boolean` — Ponter les événements du navigateur (`visibilitychange`, `online`/`offline`, `pagehide`) sur les événements du kernel.
- `connectOnBoot?: boolean` — Ouvrir la socket au `boot()`.
- `banner?: boolean` — Annoncer le kernel dans la console du navigateur au `boot()`.

#### `NodefonyKernelServices`

```ts
interface NodefonyKernelServices
```

Registre TYPÉ des services techniques portés par le kernel client.

- `realtime?: NodefonySocket` — La socket Nodefony de l'app (multiplexage de canaux, isomorphe).

#### `NodefonyLoginError`

```ts
interface NodefonyLoginError
```

Échec classé de la dernière action.

- `readonly kind: LoginErrorKind`
- `readonly message: string` — Message du serveur, relayé TEL QUEL — en particulier le refus uniforme d'un 401, qui ne doit jamais être reformulé : le préciser côté client dirait à un inconnu si le compte existe.
- `readonly status: number | null` — Statut HTTP, `null` quand le serveur n'a pas répondu.
- `readonly retryAt: number | null` — Fin du blocage (millisecondes depuis l'époque) — seulement pour `throttled`.

#### `NodefonyLoginOptions`

```ts
interface NodefonyLoginOptions
```

Réglages de `NodefonyLogin` — tous facultatifs.

- `readonly baseUrl?: string` — Origine du serveur ; vide = même origine que la page.
- `readonly identifier?: string` — Compte prérempli (le dernier utilisé, mémorisé par l'application).
- `readonly fetch?: typeof fetch` — `fetch` à employer ; défaut : celui du navigateur.
- `readonly navigate?: (url: string) => void` — Navigation pleine page vers un fournisseur ; défaut : `location.assign`.
- `readonly passkey?: NodefonyPasskeyAgent | null` — Signataire de passkey ; défaut : l'API WebAuthn native, si elle est complète.
- `readonly now?: () => number` — Horloge (ms) ; défaut : `Date.now`.
- `readonly defaultRetryAfterS?: number` — Attente appliquée quand un 429 ne dit pas combien de temps (secondes).

#### `NodefonyLoginProvider`

```ts
interface NodefonyLoginProvider
```

Fournisseur de connexion, tel que le SERVEUR le présente.

- `readonly name: string`
- `readonly label: string`

#### `NodefonyLoginState`

```ts
interface NodefonyLoginState
```

Photographie du déroulé — un objet NEUF à chaque changement, jamais muté.

- `readonly step: LoginStep`
- `readonly identifier: string` — Compte saisi (ou rendu par le serveur une fois connecté).
- `readonly pending: boolean` — Une requête est en vol : l'écran désactive ses boutons.
- `readonly user: NodefonyLoginUser | null` — Identité de la session, `null` tant qu'elle n'est pas ouverte.
- `readonly mfaMethods: readonly string[]` — Seconds facteurs proposés par le serveur à l'étape `mfa`, réduits à ceux que ce client sait conduire (aujourd'hui `totp`).
- `readonly error: NodefonyLoginError | null`
- `readonly providers: readonly NodefonyLoginProvider[] | null` — Fournisseurs configurés ; `null` tant que `NodefonyLogin.loadProviders` n'a pas répondu.
- `readonly passkeyAvailable: boolean` — Le navigateur sait-il signer avec une passkey ?

#### `NodefonyLoginUser`

```ts
interface NodefonyLoginUser
```

Identité rendue par le serveur une fois la session ouverte.

- `readonly id: number | string`
- `readonly identifier: string` — Identifiant de connexion (login, e-mail, sujet fédéré) — le même que `IUser.identifier`.
- `readonly email?: string`
- `readonly roles: readonly string[]`
- `readonly [field: string]: unknown`

#### `NodefonyNotice`

```ts
interface NodefonyNotice
```

Notice normalisée prête à afficher (snackbar / centre de notifications).

- `level: NoticeLevel` — Sévérité d'affichage.
- `title?: string` — Titre court (gras), optionnel.
- `message: string` — Message lisible (déjà localisé FR).
- `source: "realtime" | "api" | "server"` — Origine — `realtime` (transport WS), `api` (data plane HTTP), `server` (push).
- `code?: number` — Code corrélé : close code WS, status HTTP ou code d'erreur JSON-RPC.
- `ts: number` — Timestamp (ms epoch) de production.

#### `NodefonyPasskeyAgent`

```ts
interface NodefonyPasskeyAgent
```

Ce qui signe un défi WebAuthn. Par défaut, l'API native du navigateur ; injectable pour un test, ou pour une bibliothèque qui couvre les navigateurs anciens.

- `sign(options: unknown): Promise<unknown>` — Fait signer le défi par l'authentificateur de l'utilisateur.

#### `NodefonySocketOptions`

```ts
interface NodefonySocketOptions
```

- `url?: string`
- `token?: string | null`
- `autoReconnect?: boolean` — Reconnexion auto.
- `reconnectDelay?: number` — Délai initial entre tentatives (ms).
- `reconnectDelayMax?: number` — Délai max entre tentatives (ms).
- `connectTimeout?: number` — Délai d'ouverture (ms) : une poignée de main qui n'aboutit pas dans ce délai est abandonnée, `connect()` rejette et la reconnexion prend le relais.
- `heartbeatInterval?: number` — Heartbeat ping interval (ms).
- `probe?: RealtimeProbe | false` — Sonde d'un échec d'ouverture.
- `banner?: boolean` — Annoncer le framework dans la console du navigateur ?

#### `NodefonySseOptions`

```ts
interface NodefonySseOptions
```

Options de `NodefonySse`.

- `method?: string` — Méthode HTTP.
- `headers?: Record<string, string>` — En-têtes ajoutés à chaque connexion (un `Authorization`, par exemple).
- `body?: string` — Corps de la requête — renvoyé à chaque reconnexion.
- `withCredentials?: boolean` — Envoyer les cookies vers une autre origine (`credentials: "include"`).
- `retry?: number` — Délai de reconnexion initial (ms), jusqu'à ce que le serveur en impose un par `retry:`.
- `lastEventId?: string` — Identifiant à reprendre dès la première connexion (en-tête `Last-Event-ID`).
- `maxEventSize?: number` — Taille maximale d'un événement (unités UTF-16).
- `connectTimeout?: number` — Délai d'ouverture (ms) : une réponse qui n'arrive pas dans ce délai est abandonnée, et la reconnexion prend le relais.
- `fetch?: typeof fetch` — `fetch` à employer — injectable pour un certificat, un agent ou un test.

#### `ObserveNoticeLogOptions`

```ts
interface ObserveNoticeLogOptions
```

Options de `observeNoticeLog`.

- `max?: number` — Taille max de l'anneau (les plus anciennes notices sont évincées).
- `sources?: NodefonyNotice["source"][]` — Ne garder que ces sources (ex.

#### `ObserveSseOptions`

```ts
interface ObserveSseOptions extends NodefonySseOptions
```

Réglages de `observeSse` : ceux de `NodefonySse`, plus deux.

- `events?: readonly string[]` — Types d'événements écoutés — le champ `event:` du serveur.
- `onEvent?: (event: ISseEvent) => void` — Appelé pour CHAQUE événement reçu, avant la mise à jour de l'état.

#### `ObserveSyslogOptions`

```ts
interface ObserveSyslogOptions
```

Options de `observeSyslog`.

- `max?: number` — Taille max de l'anneau (les plus anciennes lignes sont évincées).
- `severities?: string[]` — Ne garder que ces sévérités (ex.
- `channel?: string` — Canal source.

#### `RateDecision`

```ts
interface RateDecision
```

Décision de la boucle AIMD : nouvelle cadence + pourquoi. `null` = ne rien changer.

- `readonly intervalMs: number` — Cadence cible (ms).
- `readonly reason: RateChangeReason` — Cause du changement.

#### `RealtimeFrame`

```ts
interface RealtimeFrame
```

Une frame du protocole temps réel (JSON-RPC 2.0) — pour le log/inspecteur.

- `ts: number` — Timestamp (ms epoch).
- `dir: "in" | "out"` — Sens : `out` = client→serveur, `in` = serveur→client.
- `kind: string` — Méthode (notification/requête) ou `response`/`error`/`stream`.
- `id?: number` — id JSON-RPC (requêtes/réponses), si présent.
- `channel?: string` — Canal pub/sub (`params.channel`), si présent.
- `payload: unknown` — Payload affichable — champs sensibles **redactés** (token/secret…).

#### `RealtimeReconnectInfo`

```ts
interface RealtimeReconnectInfo
```

Tentative de reconnexion programmée par le back-off — charge utile de `NodefonySocket.onReconnect`.

- `attempt: number` — Numéro de la tentative depuis la dernière connexion réussie (1 = la première).
- `delay: number` — Délai retenu avant cette tentative (ms), plafonné par `reconnectDelayMax`.
- `nextRetryAt: number` — Échéance absolue de la tentative (ms epoch) — pour un compte à rebours.

#### `SharedConnection`

```ts
interface SharedConnection
```

Résultat de `connectShared` : la socket, à qui elle appartient, et comment la démarrer.

- `socket: ObservableClient` — La socket à donner aux observateurs.
- `owned: boolean` — `true` si c'est nous qui l'avons obtenue depuis l'URL — donc à nous de la connecter.
- `start(): void` — Ouvre la connexion si elle nous appartient, sinon ne fait rien.

#### `SocketDetailRow`

```ts
interface SocketDetailRow
```

Une ligne de la description d'une socket : ce qu'on lit, et pourquoi ça compte.

- `label: string` — Libellé affiché.
- `value: string` — Valeur, déjà mise en mots pour un humain.
- `hint: string` — Une phrase qui dit ce que la valeur signifie, ou ce qu'elle garantit.

#### `SocketSnapshot`

```ts
interface SocketSnapshot
```

Ce que le client sait de sa PROPRE socket, à un instant donné.

- `url: string | null` — L'adresse du serveur temps réel — de QUELLE socket cet instantané parle.
- `state: RealtimeState` — État de la connexion.
- `channels: readonly string[]` — Canaux effectivement tenus par cette connexion.
- `frames: number` — Trames reçues depuis l'ouverture.
- `unsent: number` — Trames perdues faute de transport ouvert — un silence qui se compte.
- `lastFrame: { method: string | null; at: number | null; }` — Méthode et horodatage de la dernière trame reçue (`null` si aucune).
- `reconnectAttempts: number` — Tentatives de reconnexion depuis la dernière connexion réussie.
- `nextRetryAt: number | null` — Échéance de la prochaine tentative (ms epoch), `null` hors reconnexion.
- `identity: RealtimeIdentity | null` — Identité résolue par le serveur, `null` avant le premier welcome.
- `serverChannels: readonly string[] | null` — Canaux que le serveur annonce à l'accueil, `null` avant le premier welcome.
- `serverMethods: readonly string[] | null` — Actions que le serveur annonce à l'accueil, `null` avant le premier welcome.

#### `SseSnapshot`

```ts
interface SseSnapshot
```

L'état d'un flux observé — ce qu'une vue affiche.

- `readonly readyState: number` — 0 `CONNECTING`, 1 `OPEN`, 2 `CLOSED` — les constantes de `NodefonySse`.
- `readonly lastEvent: ISseEvent | null` — Le dernier événement reçu d'un des types écoutés, `null` tant qu'aucun.
- `readonly error: boolean` — La dernière transition était-elle une coupure ?

#### `SyslogUplinkOptions`

```ts
interface SyslogUplinkOptions
```

- `syslog: Syslog` — Le journal client à écouter.
- `publisher: UplinkPublisher` — La socket par laquelle pousser (typiquement le `NodefonySocket` partagé).
- `maxSeverity?: number` — Sévérité maximale retenue (RFC 5424 : plus le nombre est petit, plus c'est grave).
- `batchMs?: number` — Fenêtre de regroupement, en ms.
- `maxBatch?: number` — Entrées par lot au maximum ; au-delà, on envoie sans attendre.
- `maxQueue?: number` — Profondeur du tampon ; au-delà, la plus ANCIENNE est perdue.
- `maxStringLength?: number` — Longueur maximale d'une chaîne transportée (message, pile).
- `channel?: string` — Canal montant.

#### `UplinkBatch`

```ts
interface UplinkBatch
```

Enveloppe d'un lot poussé sur le canal montant.

- `pageId: string` — Identifiant de ce chargement de page — la clé de regroupement d'un onglet.
- `entries: WireLogEntry[]` — Les entrées, dans l'ordre d'émission.
- `dropped?: number` — Entrées perdues depuis le dernier lot (tampon plein).

#### `UplinkPublisher`

```ts
interface UplinkPublisher
```

Le strict nécessaire pour pousser — n'impose pas `NodefonySocket` à l'appelant.

- `publish(channel: string, payload?: unknown): void`

#### `WireLogEntry`

```ts
interface WireLogEntry
```

Une entrée de journal telle qu'elle voyage sur le fil (plate, sérialisable).

- `severity: number` — Sévérité RFC 5424 (0-7).
- `severityName: string` — Nom de la sévérité (`"ERROR"`, `"INFO"`…).
- `moduleName: string` — Module émetteur **tel que le client le prétend** — le pod ne le croit pas.
- `msgid: string`
- `msg: string`
- `timeStamp: number` — Horloge du NAVIGATEUR (ms epoch) — jamais celle du pod.
- `requestId?: string` — Requête connue au moment du journal, absente si elle ne l'était pas.
- `payload: unknown` — Charge normalisée : une `Error` devient `{name, message, stack}`.

### Types (13)

#### `AdaptiveObserveOptions`

```ts
type AdaptiveObserveOptions = Omit<BindAdaptiveOptions, "intervalMs">
```

Options de `observeAdaptiveChannel` — la cadence désirée est passée à part.

#### `Dispose`

```ts
type Dispose = () => void
```

Libération d'une souscription. Idempotente chez tous les observateurs de ce module.

#### `Emit`

```ts
type Emit<T> = (value: T) => void
```

Rappel d'une liaison de vue : reçoit la valeur courante.

#### `LocalEvent`

```ts
type LocalEvent = (typeof LOCAL_EVENTS)[keyof typeof LOCAL_EVENTS]
```

Un des noms d'événement local de la table `LOCAL_EVENTS`.

#### `LoginErrorKind`

```ts
type LoginErrorKind = "credentials" | "throttled" | "network" | "server" | "cancelled" | "unsupported"
```

Nature d'un échec, classée pour que l'écran sache QUOI dire.

#### `LoginStep`

```ts
type LoginStep = "identifier" | "password" | "mfa" | "authenticated"
```

Étape du déroulé de connexion.

#### `MessageStats`

```ts
type MessageStats = IChannelStats
```

Stats d'un canal — alias historique de `IChannelStats` (le contrat isomorphe `IRealtimeSocket`). Conservé pour les consommateurs qui importent `MessageStats`.

#### `NodefonyKernelEvent`

```ts
type NodefonyKernelEvent = "onBoot" | "onReady" | "onIdentityChange" | "onVisibility" | "onOnline" | "onTerminate"
```

Événements émis par le kernel client.

#### `NodefonyKernelState`

```ts
type NodefonyKernelState = "created" | "booting" | "ready" | "terminated"
```

États du kernel client, ordonnés et non régressifs (symétrie nominale avec les lifecycle flags du Kernel serveur — `booted`/`ready`/… — sans en singer la sémantique process).

#### `NoticeLevel`

```ts
type NoticeLevel = "success" | "info" | "warning" | "error"
```

Sévérité d'affichage — alignée sur les niveaux snackbar usuels.

#### `ObservableClient`

```ts
type ObservableClient = NodefonySocket
```

Socket sur laquelle un observateur travaille. Volontairement le client NON paramétré : une liaison de vue ne connaît pas les cartes d'événements typées de l'application.

#### `RateChangeReason`

```ts
type RateChangeReason = "init" | "decrease" | "increase"
```

Raison d'un changement de cadence (pour un badge UI).

#### `RealtimeState`

```ts
type RealtimeState = "disconnected" | "connecting" | "connected" | "reconnecting" | "error"
```

---

[← Toutes les références d'API](../../)
