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


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

> Générée depuis les déclarations de types publiées de `@nodefony/framework` **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/framework`

`import { … } from "@nodefony/framework"` — 34 symboles.

### Classes (5)

#### `Controller`

```ts
class Controller extends Service implements IController
```

- `static prefix: string`
- `static scope: ControllerScope` — Portée d'instanciation de la classe — `"singleton"` par défaut, `"request"` posé par le décorateur `@Scope` (statique hérité, lu via `new.target` au constructeur et par le Resolver : 0 Reflect).
- `static assertScope(): void` — Vérifie que la portée de la classe est admise par sa lignée.
- `module?: Module`
- `template?: Eta | null`
- `get context(): ContextType` — Contexte transport courant.
- `set context(context: ContextType)` — Contexte transport courant.
- `log(pci: Pci, severity?: Severity, msgid?: Msgid, msg?: Message, moduleName?: string): import("nodefony").Pdu` — Journalise au nom du module du contrôleur, pas du noyau : `moduleName` explicite, sinon le module posé sur la requête (`context.logModule`), sinon le module propriétaire du contrôleur.
- `get route(): Route | null` — Route de l'appel en cours.
- `get request(): contextRequest`
- `set request(request: contextRequest)`
- `get response(): HttpResponse | Http2Response | WebsocketResponse | null`
- `set response(response: HttpResponse | Http2Response | WebsocketResponse | null)`
- `get user(): IRequestUser | null` — L'utilisateur CONNECTÉ, ou `null` — anonyme, ou route hors de toute zone du pare-feu.
- `get method(): HTTPMethod`
- `set method(method: HTTPMethod)`
- `get query(): Record<string, unknown>` — Paramètres d'URL de l'appel en cours — jamais le corps, qui reste dans `body`.
- `set query(value: Record<string, unknown>)` — Paramètres d'URL de l'appel en cours — jamais le corps, qui reste dans `body`.
- `get files(): readonly unknown[]` — Les fichiers reçus dans un corps multipart (`UploadedFile`) ; les champs texte du même corps sont dans `body`.
- `set files(value: readonly unknown[])` — Les fichiers reçus dans un corps multipart (`UploadedFile`) ; les champs texte du même corps sont dans `body`.
- `get body(): Record<string, unknown>` — Le CORPS de la requête, parsé — nom universel de l'écosystème (Express, Fastify, NestJS).
- `set body(value: Record<string, unknown>)` — Le CORPS de la requête, parsé — nom universel de l'écosystème (Express, Fastify, NestJS).
- `get session(): Session | null` — Session courante, ou `null`.
- `constructor(name: string, context: ContextType)`
- `setContext(context: ContextType): void` — Lie l'instance au contexte de SA requête — contrôleur par requête seulement : tout l'état de la requête (`request`, `response`, `method`, `query*`) en dérive ensuite, toujours frais.
- `setContextJson(encoding?: BufferEncoding): void`
- `setContextHtml(encoding?: BufferEncoding): void`
- `render(data: unknown, encoding?: BufferEncoding, status?: string | number, headers?: Record<string, string | number>): MaybePromise<Http2Response | HttpResponse>` — Rend une donnée sur la réponse de la requête courante (JSON, HTML ou texte selon son type).
- `renderResponse(data: unknown, encoding?: BufferEncoding, status?: string | number, headers?: OutgoingHttpHeaders): MaybePromise<Http2Response | HttpResponse | WebsocketResponse>` — Envoie une donnée déjà sérialisée sur le transport de la requête (HTTP ou WebSocket), après statut et en-têtes éventuels.
- `renderView(path: string | FileClass, param?: Record<string, unknown>, status?: string | number, headers?: Record<string, string | number>): Promise<Http2Response | HttpResponse | WebsocketResponse>`
- `renderJson(obj: unknown, status?: string | number, headers?: OutgoingHttpHeaders): MaybePromise<Http2Response | HttpResponse | WebsocketResponse>` — Sérialise en JSON puis envoie (`renderResponse`).
- `acceptsSse(): boolean` — Le client demande-t-il un flux d'événements (`Accept: text/event-stream`) ?
- `renderSse(options?: ISseStreamOptions): SseStream | Promise<SseStream>` — Répond par un flux d'événements serveur, en HTTP/1.1 comme en HTTP/2.
- `setRoute(route: Route): Route` — Pose la route de la requête courante sur l'instance (per-request).
- `setRoute(route: Route | null): Route | null` — Pose la route de la requête courante sur l'instance (per-request).
- `getSession(): Session | null`
- `redirect(url: string, status?: string | number, headers?: Record<string, string | number>): void`
- `getFlashBag(key: string): unknown`
- `setFlashBag(key: string, value: unknown): unknown`
- `addFlash(key: string, value: unknown): unknown`
- `forward(name: string, param?: unknown[]): unknown`
- `getFile(file: FileClass | string): FileClass`
- `getFileAsync(file: FileClass | string): Promise<FileClass>` — Variante **async** de `getFile()` — résout les stats via `FileClass.from` (pas de `lstatSync` bloquant).
- `renderFileDownload(file: FileClass | string, options?: ReadStreamOptions, headers?: OutgoingHttpHeaders): Promise<ReadStream>` — Sert un fichier en TÉLÉCHARGEMENT (`Content-Disposition: attachment`).
- `streamFile(file: FileClass | string, headers?: OutgoingHttpHeaders, options?: ReadStreamOptions): Promise<ReadStream>` — Envoie un fichier en FLUX, du disque vers la réponse, sans jamais le charger en mémoire.
- `renderMediaStream(file: FileClass | string, headers?: OutgoingHttpHeaders, options?: ReadStreamOptions): Promise<HttpResponse | ReadStream | WebsocketResponse>`

#### `Resolver`

```ts
class Resolver implements IResolver
```

- `injector?: Injector | null`
- `controller: ControllerConstructor | null` — Classe du controller résolu — seul son nom est lu (erreurs, journal).
- `actionName?: string` — Nom de l'action résolue.
- `action?: (...args: unknown[]) => unknown`
- `context: ContextType`
- `route: Route | null` — Route matchée, `null` tant qu'aucune ne l'est.
- `resolve: boolean` — `true` si une route a matché la requête.
- `variables: unknown[]`
- `exception?: HttpError | Error | null` — Erreur levée pendant la résolution, relue par le pipeline.
- `unrendered?: string` — Ce que l'action a rendu quand le Resolver n'a rien pu envoyer — absent sinon.
- `acceptedProtocol: string | null`
- `bypassFirewall: boolean`
- `queryOverride: Record<string, unknown> | null` — Query d'une invocation **par message** (pont WS-RPC `api.request`) — pendant de `cleanPathOverride` pour le `?…` du path invoqué.
- `methodOverride: string | null` — Méthode HTTP **logique** d'une invocation par le pont WS-RPC `api.request` quand c'est une MUTATION (POST/PUT/PATCH/DELETE).
- `messageInvocation: boolean` — Cette résolution est-elle une invocation **par message** (pont WS-RPC `api.request`) plutôt que l'établissement de la connexion ?
- `constructor(context: ContextType)`
- `match(route: Route, context: ContextType, cleanPath?: string, literal?: boolean): ((string | null)[] & Record<string, unknown>) | null` — Rejoue le match d'une route sur un contexte (WS : handshake puis frames).
- `getMatchedParams(): Record<string, unknown>` — Snapshot per-requête des variables de route matchées (`{name}` → valeur, + wildcard `*` éventuel).
- `parsePathernController(name: string): void`
- `getAction(name: string): (...args: unknown[]) => unknown | null`
- `newController(context?: ContextType): MaybePromise<Controller>` — L'instance du controller de la route, posée sur le container du contexte.
- `executeAction(data?: unknown[], reload?: boolean, metaArg?: RouteActionMeta): MaybePromise<ActionOutcome>` — Exécute l'action résolue et retourne sa **valeur brute**, SANS la rendre sur le transport (pas de `returnController`/`send`).
- `authorizeAction(): Promise<void>` — Juge les gardes de l'action résolue SANS l'exécuter — appelé par le pipeline WebSocket AVANT d'accepter le handshake (#596), pour qu'un connecté sans le rôle reçoive son 403 en statut HTTP au lieu d'u …
- `callController(data?: unknown[], reload?: boolean): MaybePromise<unknown>` — Exécute l'action PUIS rend sa valeur sur le transport.
- `executeActionGuarded(data?: unknown[], reload?: boolean): Promise<{ result: unknown; }>` — Exécute l'action AVEC la porte d'idempotence mais SANS rendu (`returnController`) — le chemin du **pont `api.request`** (WS) : la valeur nue est enveloppée `{id, result}` par le peer, jamais rendue su …
- `returnController(result: unknown): MaybePromise<unknown>` — Rend la valeur d'une action sur le transport, selon sa nature : promesse (démêlée puis re-rendue), texte, Buffer, réponse déjà construite, scalaire ou objet (auto-JSON), rien (l'action envoie elle-mêm …

#### `ResourceController`

```ts
class ResourceController<T = unknown> extends Controller
```

Controller de ressource **duplex** (V4.2 — une action, deux transports) : la logique métier est écrite UNE fois dans le service de ressource, les actions de la sous-classe ne sont que des portes (REST, WS-RPC `invoke`, GraphQL à venir) qui retournent la **valeur brute** — `returnController` l'auto-JSON en REST, le pont WS l'enveloppe (`{id,result}`), sans réécrire l'action par transport.

- `static scope: ControllerScope` — Singleton PAR DÉFAUT : la classe est conçue stateless — premier client du scope V4.3.
- `protected resource: IResourceService<T> | null` — Service de ressource — état de BOOT (posé 1× ici, jamais réassigné).
- `constructor(name: string, context: ContextType, resource?: IResourceService<T>)`
- `protected requireResource(): IResourceService<T>` — Service de ressource garanti — 500 explicite si la sous-classe ne l'a pas fourni (erreur de câblage, pas une erreur client).
- `protected listResource(criteria?: Record<string, unknown>, options?: IResourceReadOptions): Promise<T[]>` — Liste la ressource.
- `protected listPageResource(page: IResourcePageQuery): Promise<IPage<T>>` — Liste la ressource en rendant une **page** (`{ items, hasNext, total? }`) plutôt qu'un tableau nu.
- `protected getResource(id: string, options?: IResourceReadOptions): Promise<T | null>` — Lit une entité par id — `null` si absente (la porte décide du 404).
- `protected createResource(data: PartialInput<T>): Promise<T>` — Crée une entité — 501 si la ressource est read-only.
- `protected updateResource(criteria: Record<string, unknown>, data: PartialInput<T>): Promise<T | null>` — Met à jour une entité ciblée par critères — 501 si non supporté.
- `protected removeResource(criteria: Record<string, unknown>): Promise<number>` — Supprime par critères (nombre d'entités touchées) — 501 si non supporté.

#### `Route`

```ts
class Route implements IRoute
```

- `name: string` — Nom de la route (journalisation, diagnostic).
- `path?: string` — Gabarit de la route, préfixe compris (`/users/{id}`) — faible cardinalité, publié comme `routePath` sur le canal `nodefony.http.request`.
- `controller?: ControllerConstructor`
- `classMethod?: string`
- `prefix?: string`
- `method?: HTTPMethod`
- `pattern?: RegExp`
- `variables: string[]`
- `unreachableChars?: string[]` — Caractères du chemin déclaré qu'une requête ne peut PAS porter — la route est donc inatteignable.
- `defaults: Partial<Record<string, unknown>>`
- `requirements: Partial<RouteRequirements>`
- `hash?: string`
- `host?: string | string[]`
- `hostRegexp?: RegExp[]` — Patterns de domaine pré-compilés (host + `requirements.domain`), RegExp ancrées/wildcard.
- `methodsSet?: Set<string>` — P3a — requirements pré-compilés au boot (0 alloc par match) : `methodsSet` = méthodes autorisées normalisées UPPERCASE (lookup O(1)) ; `methodsAllow` = valeur du header `Allow` du 405, jointe UNE fois …
- `methodsAllow?: string`
- `varRegexp?: Record<string, RegExp>`
- `bypassFirewall: boolean`
- `areaRoleExempt: boolean` — La route décide seule de son autorisation → la zone du firewall n'applique pas son rôle par défaut.
- `fallback: boolean` — Route de repli, résolue après toutes les autres.
- `bodyStream?: boolean` — P2.9 — Cache mémoïsé : l'action attend-elle le **flux brut** du body (`@Body({ stream:true })`) ?
- `actionMeta?: RouteActionMeta` — P5 — Metadata d'action figées (`@HttpCode`/`@Header`/`@Redirect`/params/ session), memo au 1er hit comme `bodyStream` : `undefined` = pas encore résolu (via `resolveActionMeta`, 1 lecture Reflect par …
- `filePath?: string`
- `module?: { name: string; }` — Module propriétaire de la route — set par `Router.setController()` à `onBoot`, donc PAS disponible à la création de la route (via `@controller`) qui s'évalue à l'import.
- `constructor(name: string, obj?: RouteOptions)`
- `static cleanPathname(context: ContextType): string` — Normalise le pathname de la requête pour le matching : retire le(s) slash(es) final(aux) via `stripTrailingSlashes`.
- `match(context: ContextType, cleanPath?: string, methodOverride?: string, literal?: boolean): ((string | null)[] & Record<string, unknown>) | null` — Confronte la requête à cette route : chemin, hôte, puis exigences.
- `compile(): RegExp` — Compile the route into a regular expression pattern.
- `compileRequirements(): void` — Pré-compile les requirements (P3a) — méthodes normalisées en Set UPPERCASE + RegExp des requirements de variables.
- `hydrateDefaultParameters(res: RegExpMatchArray): void`
- `toString(): string` — Returns a string representation of an object.
- `toLogLine(): string` — Formatte la route en une seule ligne lisible pour le log debug — évite le JSON multi-ligne du `toString()` qui polluait ~7 lignes par route au boot.
- `toObject(): object`
- `setDefaults(arg?: Record<string, unknown>): void`
- `addDefault(key: string, value: unknown): void`
- `setPrefix(prefix?: string): void`
- `setPattern(pattern?: string): string`
- `setHostname(hostname?: string | string[]): void`
- `compileHost(): void` — Pré-compile les patterns de domaine de la route (`host` + `requirements.domain`) en `RegExp[]` ancrées, via le matcher partagé `@nodefony/http`.
- `matchHostname(context: ContextType): boolean`
- `generateId(): string` — Empreinte stable de la route — sert d'identité pour la comparer à elle-même (deux déclarations identiques donnent la même empreinte, deux chemins différents non).
- `addRequirement<K extends keyof RouteRequirements>(key: K, value: RouteRequirements[K]): RouteRequirements[K]`
- `getRequirement<K extends keyof RouteRequirements>(key: K): RouteRequirements[K]`
- `hasRequirements(): number`
- `matchRequirements(context: ContextType, methodOverride?: string): boolean`

#### `default`

```ts
class Framework extends Module<IFrameworkConfig>
```

- `constructor(kernel: Kernel)`
- `configSchema(): unknown` — JSON Schema de la config framework → data plane admin (config riche Studio).
- `onKernelRegister(): Promise<this>` — Phase `onRegister` : valide la config du module via le builder (`defineFrameworkConfig`) AVANT que les `@services` (Router, AdminBroker — qui lisent `module.options.router`/`.adminBroker`) ne soient i …
- `onKernelBoot(): Promise<this>` — Phase `onBoot` (après les `@services` à `onPreBoot` → le défaut mémoire `idempotencyStore` est déjà enregistré, ET après l'`onPreBoot` des autres modules → le service `redis` est résoluble) : si la co …
- `onKernelReady(): Promise<this>` — Phase `onReady` (après le boot de tous les modules) : enregistre le producteur admin du kernel puis monte le data plane `/nodefony/<ns>/api/*`.

### Fonctions (8)

#### `buildPlaygroundSnapshot`

```ts
function buildPlaygroundSnapshot(): { controllers: PlaygroundController[]; }
```

Construit le snapshot playground : toutes les routes à controller, groupées par classe de controller, triées (module puis nom, actions par path).

#### `createFrameworkAdminApi`

```ts
function createFrameworkAdminApi(broker?: IAdminBroker, opts?: FrameworkAdminApiOptions): IAdminApi
```

Producteur `IAdminApi` du module **framework** — exposé sous `/nodefony/framework/api/*`.

#### `createKernelAdminApi`

```ts
function createKernelAdminApi(kernel: IKernel): IAdminApi
```

#### `createSyslogAdminApi`

```ts
function createSyslogAdminApi(syslog: ISyslog, options?: SyslogAdminApiOptions): IAdminApi
```

Producteur `IAdminApi` du **syslog** (core) — exposé sous `/nodefony/syslog/api/*`. 4ᵉ et dernier producteur de P10.3.

#### `getIdempotencyStoreFactory`

```ts
function getIdempotencyStoreFactory(name: string): IdempotencyStoreFactory
```

Fabrique d'un store par nom, ou `undefined` si inconnu.

#### `listIdempotencyStores`

```ts
function listIdempotencyStores(): string[]
```

Noms de stores distribués enregistrés (résolution `auto` + validation boot). N'inclut PAS `"memory"` : dans `resolveAutoStore`, memory est le **fallback** (per-pod), jamais une préférence à sélectionner — l'y mettre fausserait le choix.

#### `registerIdempotencyStore`

```ts
function registerIdempotencyStore(name: string, factory: IdempotencyStoreFactory): void
```

Enregistre (ou remplace) la fabrique d'un store d'idempotence distribué. Appelée par l'application pour les adapters (`redis`/`drizzle`).

#### `validateRouteInput`

```ts
function validateRouteInput(schema: IRouteSchema, raw: RawRouteInput): MaybePromise<RawRouteInput>
```

Valide l'entrée d'une action contre son schéma — synchrone tant que chaque validateur l'est, asynchrone seulement si l'un d'eux rend une promesse.

### Interfaces (12)

#### `FrameworkAdminApiOptions`

```ts
interface FrameworkAdminApiOptions
```

Options de composition du producteur framework.

- `playground?: boolean` — Monte les endpoints Playground (`playground/routes`) — **dev uniquement** : la console Studio exécute des mutations depuis le navigateur.

#### `IIdempotencyStore`

```ts
interface IIdempotencyStore
```

Cache d'idempotence borné (modèle Stripe `Idempotency-Key`) — dédoublonne les **mutations** rejouées (reconnexion socket, double-clic) du data plane admin comme des controllers userland décorés `@Idempotent`.

- `begin(key: string, fingerprint: string): IdempotencyOutcome | Promise<IdempotencyOutcome>` — Réserve **atomiquement** la clé et renvoie le verdict à suivre.
- `complete(key: string, response: IdempotentResponse): void | Promise<void>` — Mémorise la réponse d'une clé *in-flight* (TTL) → rejeux futurs = `replayed`.
- `abort(key: string): void | Promise<void>` — Libère une clé *in-flight* dont l'exécution a échoué : rien n'est mémorisé (un échec doit pouvoir être réessayé).
- `gc?(now?: number): Promise<number> | number` — Purge les entrées expirées — présente UNIQUEMENT sur les impls SANS expiration native (`drizzle` → `DELETE WHERE expiresAt <= now`).
- `listPage(query: IIdempotencyListQuery): Promise<IPage<IIdempotencyKeyEntry>>` — Page de clés vivantes — introspection admin (repérer une clé figée *in-flight* qui bloque les rejeux d'un client).
- `readonly size: number` — Nombre d'entrées vivantes (observabilité / tests).

#### `IIdempotencyStoreFactoryContext`

```ts
interface IIdempotencyStoreFactoryContext
```

Contexte passé à une fabrique de store : de quoi se construire (résolutions coûteuses en lazy à l'intérieur de l'instance). Le module donne accès au container kernel (`ctx.module.kernel?.container?.get("redis")`).

- `readonly module: Module` — Module framework (porte `kernel.container` pour résoudre `redis`, etc.).
- `readonly config: IFrameworkConfig` — Config framework validée + gelée.

#### `IResourcePageQuery`

```ts
interface IResourcePageQuery extends IPageQuery
```

Requête de page telle qu'une porte la passe au service — `IPageQuery` du core, plus les critères que la sous-classe a EXPLICITEMENT décidé d'exposer.

- `criteria?: Record<string, unknown>` — Critères de filtrage — jamais dérivés de la query string automatiquement.

#### `IResourceReadOptions`

```ts
interface IResourceReadOptions
```

Options de lecture d'une liste — **pagination avant tout**.

- `limit?: number` — Nombre maximum d'enregistrements rendus.
- `offset?: number` — Enregistrements sautés (⚠️ se dégrade sur les grandes tables — curseur à venir).
- `order?: Array<[ string, "ASC" | "DESC" ]>` — Tri, sous la forme `[[champ, sens], …]` — même écriture que `IPageQuery.order` (core) et que `RepositoryReadOptions` (orm-core).
- `relations?: string[]` — Associations à charger avec l'enregistrement.

#### `IResourceService`

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

- `find(criteria?: Record<string, unknown>, options?: IResourceReadOptions): Promise<T[]> | T[]`
- `findById(id: string, options?: IResourceReadOptions): Promise<T | null> | T | null` — Lit par identifiant.
- `findPage?(page: IResourcePageQuery): Promise<IPage<T>> | IPage<T>` — Rend une PAGE plutôt qu'un tableau nu — `AbstractCrudService` l'hérite déjà (`findPage` → `paginate`).
- `create?(data: PartialInput<T>): Promise<T> | T`
- `updateOne?(criteria: Record<string, unknown>, data: PartialInput<T>): Promise<T | null> | T | null`
- `delete?(criteria: Record<string, unknown>): Promise<number> | number`

#### `IRouteSchema`

```ts
interface IRouteSchema
```

Le schéma d'une route : un Standard Schema par partie de l'entrée (Zod, Valibot, ArkType…). Chaque partie est facultative ; une partie déclarée est validée AVANT l'action, une partie omise est servie brute.

- `readonly params?: IStandardSchemaV1` — Variables de route (`/posts/{id}`).
- `readonly query?: IStandardSchemaV1` — Query (`?page=2`) — celle du chemin INVOQUÉ sur le pont WebSocket.
- `readonly body?: IStandardSchemaV1` — Corps DÉCODÉ par le transport : JSON, formulaire, ou octets (`Uint8Array` — un `Buffer` HTTP en est un).
- `readonly headers?: IStandardSchemaV1` — En-têtes (clés en minuscules) ; sur WebSocket, ceux du handshake.

#### `IdempotentResponse`

```ts
interface IdempotentResponse
```

Réponse mémorisée d'une mutation idempotente — la forme `{status, headers?, body}` produite par un endpoint (data plane admin `AdminApiController.runAdmin`, ou action userland `@Idempotent`), pour la rejouer telle quelle à un rejeu (même statut, même corps, même en-têtes).

- `status: number` — Code HTTP de la réponse mémorisée.
- `headers?: Readonly<Record<string, string>>` — En-têtes additionnels éventuels.
- `body: unknown` — Charge utile sérialisable JSON.

#### `PlaygroundAction`

```ts
interface PlaygroundAction
```

Une action invocable depuis le playground (1 route du Router).

- `route: string` — Nom de route (unique) — clé de deep-link et de rejeu.
- `path: string | null`
- `methods: string[]` — Transports déclarés (`["POST","WEBSOCKET"]`…) — majuscules.
- `duplex: boolean` — Vrai si l'action déclare AUSSI le transport WEBSOCKET (pont `api.request`).
- `action: string | null` — Nom de la méthode de classe (action).
- `variables: string[]` — Variables de path (`{id}` → `["id"]`), ordre de capture.
- `defaults: Record<string, unknown>` — Défauts de variables (hors clé interne `controller`).
- `params: PlaygroundParam[]` — Entrées de l'action.
- `schema: Partial<Record<RoutePart, Record<string, unknown> | null>> | null` — Le contrat d'une action à schéma — JSON Schema d'entrée de chaque partie déclarée (`null` quand la bibliothèque ne sait pas le décrire).
- `guards: PlaygroundGuards`

#### `PlaygroundController`

```ts
interface PlaygroundController
```

Un controller et ses actions, groupés pour la navigation Studio.

- `name: string` — Nom de classe du controller.
- `module: string | null` — Module propriétaire (`null` si non rattaché).
- `actions: PlaygroundAction[]`

#### `PlaygroundGuards`

```ts
interface PlaygroundGuards
```

Les gardes déclaratives d'une action, prêtes à afficher (badges Studio).

- `security: { clauses: { anyOf: string[]; subjectParam: string | null; }[]; } | null` — Clauses `@IsGranted`/`@RequireScope` fusionnées (AND) — `null` = non gardée.
- `scopes: string[]` — Scopes `api:action` déclarés (`@RequireScope`), dédupliqués.
- `idempotent: { required: boolean; } | null` — `@Idempotent` — `required:true` = clé obligatoire sur mutation.
- `csrfProtect: boolean`
- `csrfExempt: boolean`
- `session: unknown` — Intent `@UseSession`/`@Session` — `null` si la route n'en déclare pas.
- `bypassFirewall: boolean` — Route hors firewall (mécanisme d'auth lui-même).

#### `PlaygroundParam`

```ts
interface PlaygroundParam
```

Un paramètre décoré d'une action (`@Param`/`@Body`/`@Query`…), JSON-safe.

- `source: string` — Source d'injection (`param`, `body`, `query`, `headers`, `cookie`, `user`…).
- `key: string | null` — Clé ciblée (`@Query("q")` → `"q"`) — `null` = l'objet complet.
- `index: number` — Position dans la signature de l'action.
- `stream: boolean` — `@Body({ stream: true })` — flux brut, non rejouable par formulaire.

### Types (9)

#### `ControllerScope`

```ts
type ControllerScope = "request" | "singleton"
```

Portée d'instanciation d'un contrôleur.

#### `IdempotencyOutcome`

```ts
type IdempotencyOutcome = { state: "fresh"; } | { state: "in-flight"; } | { state: "replayed"; response: IdempotentResponse; } | { state: "mismatch"; }
```

Verdict de `IIdempotencyStore.begin` pour une clé d'idempotence donnée. Aligné sur `draft-ietf-httpapi-idempotency-key-header-06` §2.6/§2.7.

#### `IdempotencyStoreFactory`

```ts
type IdempotencyStoreFactory = (ctx: IIdempotencyStoreFactoryContext) => IIdempotencyStore
```

Fabrique d'un store d'idempotence pour un nom donné.

#### `RawRouteHeaders`

```ts
type RawRouteHeaders = Readonly<Record<string, string | string[]>>
```

En-têtes bruts, clés en minuscules.

#### `RawRouteInput`

```ts
type RawRouteInput = { params: unknown; query: unknown; body: unknown; headers: unknown; }
```

L'entrée brute d'une action, avant validation.

#### `RawRouteParams`

```ts
type RawRouteParams = Readonly<Record<string, unknown>>
```

Variables de route brutes (une valeur par défaut n'est pas forcément une chaîne).

#### `RawRouteQuery`

```ts
type RawRouteQuery = Readonly<Record<string, unknown>>
```

Query brute.

#### `RouteInput`

```ts
type RouteInput<S extends IRouteSchema = IRouteSchema, Stream extends boolean = false> = { params: RoutePartOf<S, "params", RawRouteParams>; query: RoutePartOf<S, "query", RawRouteQuery>; body: Stream extends true ? Readable : RoutePartOf<S, "body", unknown>; headers: RoutePartOf<S, "headers", RawRouteHeaders>; }
```

L'argument UNIQUE d'une action à schéma : les quatre apports de la requête, toujours présents — validés et typés par le schéma quand il les déclare, servis bruts et typés large sinon.

#### `RoutePart`

```ts
type RoutePart = keyof IRouteSchema
```

Parties de l'entrée d'une route, dans l'ordre où elles sont validées.

---

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