@nodefony/http 10.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/LICENSE +544 -0
  2. package/README.md +77 -0
  3. package/dist/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js +9 -0
  4. package/dist/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js +6 -0
  5. package/dist/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateParam.js +8 -0
  6. package/dist/index.js +108 -0
  7. package/dist/nodefony/command/assetsPublishCommand.js +102 -0
  8. package/dist/nodefony/command/certificatesCommand.js +47 -0
  9. package/dist/nodefony/command/networkCommand.js +27 -0
  10. package/dist/nodefony/command/proxyGenerateCommand.js +66 -0
  11. package/dist/nodefony/config/config.js +335 -0
  12. package/dist/nodefony/config/defineModuleConfig.js +93 -0
  13. package/dist/nodefony/interfaces/IContext.js +1 -0
  14. package/dist/nodefony/interfaces/ICookie.js +1 -0
  15. package/dist/nodefony/interfaces/IErrorRenderer.js +1 -0
  16. package/dist/nodefony/interfaces/IHttpConfig.js +1 -0
  17. package/dist/nodefony/interfaces/IHttpKernel.js +1 -0
  18. package/dist/nodefony/interfaces/IRequest.js +1 -0
  19. package/dist/nodefony/interfaces/IRequestLogger.js +1 -0
  20. package/dist/nodefony/interfaces/IResponse.js +1 -0
  21. package/dist/nodefony/interfaces/ISession.js +1 -0
  22. package/dist/nodefony/interfaces/IUpload.js +1 -0
  23. package/dist/nodefony/interfaces/index.js +1 -0
  24. package/dist/nodefony/service/HttpAdminApi.js +376 -0
  25. package/dist/nodefony/service/ProfilerAdminApi.js +73 -0
  26. package/dist/nodefony/service/audit-logger.js +159 -0
  27. package/dist/nodefony/service/certificates.js +545 -0
  28. package/dist/nodefony/service/error-renderer.js +320 -0
  29. package/dist/nodefony/service/http-kernel.js +948 -0
  30. package/dist/nodefony/service/pretty-request-logger.js +72 -0
  31. package/dist/nodefony/service/request-logger.js +54 -0
  32. package/dist/nodefony/service/servers/clientError.js +20 -0
  33. package/dist/nodefony/service/servers/server-http.js +135 -0
  34. package/dist/nodefony/service/servers/server-https.js +204 -0
  35. package/dist/nodefony/service/servers/server-static.js +192 -0
  36. package/dist/nodefony/service/servers/server-websocket-secure.js +104 -0
  37. package/dist/nodefony/service/servers/server-websocket.js +104 -0
  38. package/dist/nodefony/service/servers/serverShutdown.js +31 -0
  39. package/dist/nodefony/service/servers/wsHeartbeat.js +64 -0
  40. package/dist/nodefony/service/sessions/sessions-service.js +580 -0
  41. package/dist/nodefony/service/trace.js +72 -0
  42. package/dist/nodefony/service/upload/upload-service.js +171 -0
  43. package/dist/nodefony/src/assets/collectAssets.js +34 -0
  44. package/dist/nodefony/src/assets/prebuiltUi.js +125 -0
  45. package/dist/nodefony/src/context/Context.js +415 -0
  46. package/dist/nodefony/src/context/domainMatcher.js +88 -0
  47. package/dist/nodefony/src/context/forwarded.js +185 -0
  48. package/dist/nodefony/src/context/http/HttpContext.js +309 -0
  49. package/dist/nodefony/src/context/http/Request.js +543 -0
  50. package/dist/nodefony/src/context/http/Response.js +368 -0
  51. package/dist/nodefony/src/context/http/parser.js +188 -0
  52. package/dist/nodefony/src/context/http/urlFastPath.js +103 -0
  53. package/dist/nodefony/src/context/http2/Request.js +29 -0
  54. package/dist/nodefony/src/context/http2/Response.js +97 -0
  55. package/dist/nodefony/src/context/metaData.js +47 -0
  56. package/dist/nodefony/src/context/requestId.js +41 -0
  57. package/dist/nodefony/src/context/trustProxy.js +167 -0
  58. package/dist/nodefony/src/context/websocket/Response.js +181 -0
  59. package/dist/nodefony/src/context/websocket/WebsocketContext.js +389 -0
  60. package/dist/nodefony/src/context/websocket/wsBackpressure.js +56 -0
  61. package/dist/nodefony/src/context/websocket/wsLogContent.js +68 -0
  62. package/dist/nodefony/src/cookies/cookie.js +258 -0
  63. package/dist/nodefony/src/errors/httpError.js +69 -0
  64. package/dist/nodefony/src/profiler/FrameProfile.js +95 -0
  65. package/dist/nodefony/src/profiler/Profiler.js +139 -0
  66. package/dist/nodefony/src/proxy/generateProxyConfig.js +157 -0
  67. package/dist/nodefony/src/rateLimit/IRateLimitStore.js +1 -0
  68. package/dist/nodefony/src/rateLimit/MemoryRateLimitStore.js +146 -0
  69. package/dist/nodefony/src/rateLimit/WsConnectionCounter.js +64 -0
  70. package/dist/nodefony/src/rateLimit/rateLimitFilters.js +20 -0
  71. package/dist/nodefony/src/servers/portBinder.js +114 -0
  72. package/dist/nodefony/src/session/session.js +390 -0
  73. package/dist/nodefony/src/session/storage/MemorySessionStorage.js +185 -0
  74. package/dist/nodefony/src/session/storage/RevocationGuardStorage.js +137 -0
  75. package/dist/nodefony/src/session/storage/sessionFilters.js +83 -0
  76. package/dist/nodefony/src/session/storage/sessionSort.js +53 -0
  77. package/dist/types/index.d.ts +83 -0
  78. package/dist/types/nodefony/command/assetsPublishCommand.d.ts +23 -0
  79. package/dist/types/nodefony/command/certificatesCommand.d.ts +17 -0
  80. package/dist/types/nodefony/command/networkCommand.d.ts +8 -0
  81. package/dist/types/nodefony/command/proxyGenerateCommand.d.ts +19 -0
  82. package/dist/types/nodefony/config/config.d.ts +197 -0
  83. package/dist/types/nodefony/config/defineModuleConfig.d.ts +39 -0
  84. package/dist/types/nodefony/interfaces/IContext.d.ts +138 -0
  85. package/dist/types/nodefony/interfaces/ICookie.d.ts +47 -0
  86. package/dist/types/nodefony/interfaces/IErrorRenderer.d.ts +55 -0
  87. package/dist/types/nodefony/interfaces/IHttpConfig.d.ts +12 -0
  88. package/dist/types/nodefony/interfaces/IHttpKernel.d.ts +10 -0
  89. package/dist/types/nodefony/interfaces/IRequest.d.ts +35 -0
  90. package/dist/types/nodefony/interfaces/IRequestLogger.d.ts +31 -0
  91. package/dist/types/nodefony/interfaces/IResponse.d.ts +39 -0
  92. package/dist/types/nodefony/interfaces/ISession.d.ts +283 -0
  93. package/dist/types/nodefony/interfaces/IUpload.d.ts +66 -0
  94. package/dist/types/nodefony/interfaces/index.d.ts +7 -0
  95. package/dist/types/nodefony/service/HttpAdminApi.d.ts +18 -0
  96. package/dist/types/nodefony/service/ProfilerAdminApi.d.ts +23 -0
  97. package/dist/types/nodefony/service/audit-logger.d.ts +143 -0
  98. package/dist/types/nodefony/service/certificates.d.ts +246 -0
  99. package/dist/types/nodefony/service/error-renderer.d.ts +74 -0
  100. package/dist/types/nodefony/service/http-kernel.d.ts +377 -0
  101. package/dist/types/nodefony/service/pretty-request-logger.d.ts +25 -0
  102. package/dist/types/nodefony/service/request-logger.d.ts +18 -0
  103. package/dist/types/nodefony/service/servers/clientError.d.ts +14 -0
  104. package/dist/types/nodefony/service/servers/server-http.d.ts +42 -0
  105. package/dist/types/nodefony/service/servers/server-https.d.ts +41 -0
  106. package/dist/types/nodefony/service/servers/server-static.d.ts +62 -0
  107. package/dist/types/nodefony/service/servers/server-websocket-secure.d.ts +29 -0
  108. package/dist/types/nodefony/service/servers/server-websocket.d.ts +29 -0
  109. package/dist/types/nodefony/service/servers/serverShutdown.d.ts +27 -0
  110. package/dist/types/nodefony/service/servers/wsHeartbeat.d.ts +46 -0
  111. package/dist/types/nodefony/service/sessions/sessions-service.d.ts +218 -0
  112. package/dist/types/nodefony/service/trace.d.ts +39 -0
  113. package/dist/types/nodefony/service/upload/upload-service.d.ts +61 -0
  114. package/dist/types/nodefony/src/assets/collectAssets.d.ts +35 -0
  115. package/dist/types/nodefony/src/assets/prebuiltUi.d.ts +99 -0
  116. package/dist/types/nodefony/src/context/Context.d.ts +195 -0
  117. package/dist/types/nodefony/src/context/domainMatcher.d.ts +67 -0
  118. package/dist/types/nodefony/src/context/forwarded.d.ts +95 -0
  119. package/dist/types/nodefony/src/context/http/HttpContext.d.ts +85 -0
  120. package/dist/types/nodefony/src/context/http/Request.d.ts +203 -0
  121. package/dist/types/nodefony/src/context/http/Response.d.ts +68 -0
  122. package/dist/types/nodefony/src/context/http/parser.d.ts +65 -0
  123. package/dist/types/nodefony/src/context/http/urlFastPath.d.ts +52 -0
  124. package/dist/types/nodefony/src/context/http2/Request.d.ts +14 -0
  125. package/dist/types/nodefony/src/context/http2/Response.d.ts +20 -0
  126. package/dist/types/nodefony/src/context/metaData.d.ts +58 -0
  127. package/dist/types/nodefony/src/context/requestId.d.ts +28 -0
  128. package/dist/types/nodefony/src/context/trustProxy.d.ts +77 -0
  129. package/dist/types/nodefony/src/context/websocket/Response.d.ts +53 -0
  130. package/dist/types/nodefony/src/context/websocket/WebsocketContext.d.ts +125 -0
  131. package/dist/types/nodefony/src/context/websocket/wsBackpressure.d.ts +73 -0
  132. package/dist/types/nodefony/src/context/websocket/wsLogContent.d.ts +37 -0
  133. package/dist/types/nodefony/src/cookies/cookie.d.ts +88 -0
  134. package/dist/types/nodefony/src/errors/httpError.d.ts +15 -0
  135. package/dist/types/nodefony/src/profiler/FrameProfile.d.ts +110 -0
  136. package/dist/types/nodefony/src/profiler/Profiler.d.ts +192 -0
  137. package/dist/types/nodefony/src/proxy/generateProxyConfig.d.ts +76 -0
  138. package/dist/types/nodefony/src/rateLimit/IRateLimitStore.d.ts +98 -0
  139. package/dist/types/nodefony/src/rateLimit/MemoryRateLimitStore.d.ts +40 -0
  140. package/dist/types/nodefony/src/rateLimit/WsConnectionCounter.d.ts +37 -0
  141. package/dist/types/nodefony/src/rateLimit/rateLimitFilters.d.ts +18 -0
  142. package/dist/types/nodefony/src/servers/portBinder.d.ts +102 -0
  143. package/dist/types/nodefony/src/session/session.d.ts +171 -0
  144. package/dist/types/nodefony/src/session/storage/MemorySessionStorage.d.ts +77 -0
  145. package/dist/types/nodefony/src/session/storage/RevocationGuardStorage.d.ts +81 -0
  146. package/dist/types/nodefony/src/session/storage/sessionFilters.d.ts +102 -0
  147. package/dist/types/nodefony/src/session/storage/sessionSort.d.ts +45 -0
  148. package/docs/cookies.md +365 -0
  149. package/docs/index.md +163 -0
  150. package/docs/observabilite.md +460 -0
  151. package/docs/rate-limit.md +372 -0
  152. package/docs/servers.md +935 -0
  153. package/docs/session.md +768 -0
  154. package/docs/upload.md +460 -0
  155. package/package.json +101 -0
@@ -0,0 +1,137 @@
1
+ //#region nodefony/src/session/storage/RevocationGuardStorage.ts
2
+ /**
3
+ * Durée de vie (ms) d'une pierre tombale de révocation. Couvre la fenêtre
4
+ * pendant laquelle une requête « en vol » — qui avait chargé la session AVANT
5
+ * sa révocation — pourrait tenter un `write` tardif (autosave de fin de requête)
6
+ * et la ressusciter. Une requête HTTP dure des secondes ; on prend large (5 min)
7
+ * pour couvrir les requêtes longues (upload/SSE) sans risque : un id révoqué
8
+ * n'est JAMAIS réémis (ids opaques CSPRNG), tombstoner ne bloque aucune session
9
+ * légitime.
10
+ */
11
+ const TOMBSTONE_TTL_MS = 3e5;
12
+ /**
13
+ * Garde-fou de révocation **décoré au-dessus** de n'importe quel
14
+ * {@link ISessionStorage} (file, drizzle, redis, mongo…). Pose une « pierre
15
+ * tombale » sur tout id détruit et REFUSE un `write` ultérieur de ce même id
16
+ * pendant {@link TOMBSTONE_TTL_MS}.
17
+ *
18
+ * **Pourquoi ici, pas dans chaque store** : la résurrection est une propriété du
19
+ * CYCLE DE VIE de session — révoquer une session puis l'autosave de fin de
20
+ * requête (la requête la portait encore en mémoire, `dirty`) la ré-écrit — et
21
+ * NON d'un backend particulier. Un seul garde-fou décoré sur le storage actif
22
+ * couvre donc TOUS les backends, présents et futurs, **sans en modifier aucun**.
23
+ *
24
+ * Découvert en live le 2026-06-21 (« révoquer une session ne déconnecte pas ») ;
25
+ * le store réel était `drizzle`, pas `files` — d'où la décoration générique.
26
+ *
27
+ * Couvre deux scénarios :
28
+ * - **self** : l'admin révoque SA PROPRE session ; l'autosave de la requête de
29
+ * révocation tente de la réécrire → refusé.
30
+ * - **race** : un autre client du user révoqué a une requête en vol dont
31
+ * l'autosave arrive après la révocation → refusé.
32
+ *
33
+ * **Perf** : décorateur **singleton** (1 par service). Délégation directe sur le
34
+ * hot-path lecture (`read`/`start`/`listAll`) ; `write` ne paie qu'un test
35
+ * `=== null` tant qu'aucune session n'a été révoquée (Map **lazy**, jamais de
36
+ * `Date.now()` dans ce cas).
37
+ */
38
+ var RevocationGuardStorage = class {
39
+ /** Storage réel décoré — exposé pour l'introspection admin (nom du driver). */
40
+ inner;
41
+ /** `id → epoch ms d'expiration`. **Lazy** : `null` tant qu'aucune révocation. */
42
+ #tombstones = null;
43
+ /**
44
+ * Énumération admin — (ré)assignée dans le constructeur **uniquement** si le
45
+ * backend décoré la supporte, pour que `SessionsService.supportsEnumeration`
46
+ * (`typeof storage.listAll === "function"`) reflète la vraie capacité du store.
47
+ */
48
+ listAll;
49
+ /**
50
+ * Touch (prolongation d'idle) — (ré)assignée seulement si le backend décoré la
51
+ * supporte, pour que `Session.touchIfNeeded` (`typeof storage.touch`) reflète la
52
+ * vraie capacité. **Respecte la pierre tombale** : ne prolonge JAMAIS une session
53
+ * révoquée (cohérent avec `write` — une révocation ne doit pas être contournée
54
+ * par un touch tardif d'une requête en vol).
55
+ */
56
+ touch;
57
+ /**
58
+ * Énumération admin **paginée** — (ré)assignée seulement si le backend décoré
59
+ * la supporte, même raison que {@link listAll} : `supportsEnumeration` teste la
60
+ * présence de la méthode, elle doit donc refléter la vraie capacité du store
61
+ * décoré et non celle du décorateur.
62
+ */
63
+ listPage;
64
+ /** `COUNT` filtré — (ré)assigné seulement si le backend décoré le supporte. */
65
+ countSessions;
66
+ /**
67
+ * `COUNT(DISTINCT user)` — (ré)assigné seulement si le backend décoré le
68
+ * supporte, même raison que {@link countSessions} : une capacité perdue dans
69
+ * le décorateur ferait afficher « inconnu » là où la base sait répondre.
70
+ */
71
+ countDistinctUsers;
72
+ /**
73
+ * Capacité de tri du backend décoré, relayée telle quelle.
74
+ *
75
+ * Une capacité qui se PERD dans un décorateur est pire qu'une capacité
76
+ * absente : elle est déclarée par le store réel, invisible au-dessus, et le
77
+ * data plane refuse alors (400) un tri que la base sait parfaitement faire.
78
+ * Comme ce décorateur est posé en production dès qu'une révocation est
79
+ * possible, l'oubli aurait désactivé le tri **partout**.
80
+ */
81
+ sortableFields;
82
+ constructor(inner) {
83
+ this.inner = inner;
84
+ this.sortableFields = inner.sortableFields;
85
+ if (typeof inner.listAll === "function") this.listAll = (filter) => inner.listAll(filter);
86
+ if (typeof inner.listPage === "function") this.listPage = (query) => inner.listPage(query);
87
+ if (typeof inner.countSessions === "function") this.countSessions = (query) => inner.countSessions(query);
88
+ if (typeof inner.countDistinctUsers === "function") this.countDistinctUsers = (query) => inner.countDistinctUsers(query);
89
+ if (typeof inner.touch === "function") this.touch = (id, idleSeconds) => {
90
+ if (this.#isRevoked(id)) return Promise.resolve();
91
+ return inner.touch(id, idleSeconds);
92
+ };
93
+ }
94
+ read(id) {
95
+ return this.inner.read(id);
96
+ }
97
+ start(id) {
98
+ return this.inner.start(id);
99
+ }
100
+ open() {
101
+ return this.inner.open();
102
+ }
103
+ close() {
104
+ return this.inner.close();
105
+ }
106
+ gc(idleSeconds, absoluteSeconds) {
107
+ return this.inner.gc(idleSeconds, absoluteSeconds);
108
+ }
109
+ async destroy(id) {
110
+ this.#revoke(id);
111
+ return this.inner.destroy(id);
112
+ }
113
+ write(id, data) {
114
+ if (this.#isRevoked(id)) return Promise.resolve(data);
115
+ return this.inner.write(id, data);
116
+ }
117
+ #revoke(id) {
118
+ const now = Date.now();
119
+ this.#purgeExpired(now);
120
+ if (this.#tombstones === null) this.#tombstones = /* @__PURE__ */ new Map();
121
+ this.#tombstones.set(id, now + TOMBSTONE_TTL_MS);
122
+ }
123
+ #isRevoked(id) {
124
+ const t = this.#tombstones;
125
+ if (t === null) return false;
126
+ const expiry = t.get(id);
127
+ return expiry !== void 0 && expiry > Date.now();
128
+ }
129
+ #purgeExpired(now) {
130
+ const t = this.#tombstones;
131
+ if (t === null) return;
132
+ for (const [id, expiry] of t) if (expiry <= now) t.delete(id);
133
+ if (t.size === 0) this.#tombstones = null;
134
+ }
135
+ };
136
+ //#endregion
137
+ export { RevocationGuardStorage as default };
@@ -0,0 +1,83 @@
1
+ //#region nodefony/src/session/storage/sessionFilters.ts
2
+ /**
3
+ * **Le vocabulaire de filtre des sessions**, en noms PUBLICS — celui que la
4
+ * console d'administration écrit dans l'URL (`?user=alice`).
5
+ *
6
+ * Frère de `SESSION_SORTABLE_FIELDS` (`sessionSort.ts`), posé au même endroit
7
+ * pour la même raison : le vocabulaire appartient au module propriétaire du
8
+ * contrat, la mécanique de lecture au cœur (`parseFilters`).
9
+ *
10
+ * `user` est un filtre **portable par construction** (égalité stricte) : il
11
+ * s'exprime dans tous les backends — `WHERE` indexé en SQL et Mongo, prédicat en
12
+ * mémoire, filtre de batch en Redis — donc aucun store n'a besoin de matérialiser
13
+ * la collection pour l'honorer. C'est la propriété qui justifie qu'il soit au
14
+ * contrat plutôt que dans une couche de filtrage applicative.
15
+ *
16
+ * `tenantId` n'y figure pas parce qu'il appartient au **contrat de page**
17
+ * (`PAGE_QUERY_KEYS`, réserve multi-tenant) : le déclarer ici en ferait un
18
+ * second lecteur du même paramètre.
19
+ */
20
+ const SESSION_FILTERS = {
21
+ /** Sessions d'un utilisateur donné (égalité stricte sur l'identifiant). */
22
+ user: "string",
23
+ /**
24
+ * `true` = sessions rattachées à un utilisateur, `false` = anonymes, absent =
25
+ * les deux. Le contrat le définit comme « `user` non vide » — tous les stores
26
+ * l'honorent déjà (c'est ainsi que `sessions/stats` compte ses facettes).
27
+ *
28
+ * Il n'était pas exposé à l'URL, et la console ne pouvait donc pas MONTRER la
29
+ * population qu'elle affichait en carte : cliquer « Anonymes » demandait un
30
+ * paramètre que la liste refusait. Une facette n'existe que si le contrat de
31
+ * liste sait la filtrer — celle-ci le savait partout sauf sur le fil.
32
+ *
33
+ * ⚠️ Redondant avec `user` **par construction** (même donnée). Les combiner
34
+ * de façon contradictoire (`?user=alice&authenticated=false`) rend l'ENSEMBLE
35
+ * VIDE, jamais la page de l'un des deux — garde posée dans le banc de contrat
36
+ * partagé, donc rejouée sur les six backends.
37
+ */
38
+ authenticated: "boolean"
39
+ };
40
+ /**
41
+ * **Les facettes des sessions** — les questions fermées que la console pose à la
42
+ * collection ENTIÈRE, pour ses cartes de tête.
43
+ *
44
+ * Distinct de `SESSION_FILTERS`, qui dit ce qu'un client a le droit d'écrire
45
+ * dans l'URL : une facette n'est pas saisie, elle est posée par le serveur. Les
46
+ * deux se recoupent par construction — une facette n'existe que si le contrat de
47
+ * liste sait déjà la filtrer, sinon elle serait un compteur approximatif de plus.
48
+ *
49
+ * `authenticated` suffit à couvrir les deux populations : le contrat le définit
50
+ * comme « `user` non vide », donc `false` rend exactement les sessions anonymes.
51
+ * Aucune facette n'est déduite d'une soustraction (cf `countFacets`).
52
+ *
53
+ * Le décompte d'utilisateurs **distincts** n'est PAS ici : ce n'est pas un
54
+ * `COUNT` filtré mais une agrégation, qu'un store en curseur ne peut pas rendre.
55
+ * Il vit en capacité déclarée du backend (`ISessionStorage.countDistinctUsers`).
56
+ */
57
+ const SESSION_FACETS = {
58
+ /** Toutes les sessions persistées, sans filtre. */
59
+ total: {},
60
+ /** Sessions rattachées à un utilisateur authentifié. */
61
+ authenticated: { authenticated: true },
62
+ /** Sessions anonymes (aucun utilisateur rattaché). */
63
+ anonymous: { authenticated: false }
64
+ };
65
+ /**
66
+ * Ce que l'endpoint de COMPTEURS accepte de filtrer — {@link SESSION_FILTERS}
67
+ * **moins** le champ que ses facettes décomposent (`authenticated`).
68
+ *
69
+ * Le demander ici rendrait une réponse qui se contredit : le total suivrait le
70
+ * filtre pendant que chaque facette l'écraserait par le sien (« 5 sessions au
71
+ * total, dont 40 anonymes »). `user` reste : il découpe une AUTRE dimension, et
72
+ * « combien de sessions pour alice, dont combien d'anonymes ? » est une question
73
+ * cohérente — qui rend d'ailleurs l'ensemble vide, la réponse honnête.
74
+ *
75
+ * Frère de `USER_STATS_FILTERS` / `TOKEN_STATS_FILTERS` / `WEBHOOK_STATS_FILTERS`.
76
+ * Les sessions n'en avaient pas : `authenticated` n'était exposé nulle part, si
77
+ * bien que le trou était fermé par accident plutôt que par décision. Ouvrir le
78
+ * filtre sur la liste — pour que les cartes deviennent cliquables — l'aurait
79
+ * rouvert du même geste.
80
+ */
81
+ const SESSION_STATS_FILTERS = { user: "string" };
82
+ //#endregion
83
+ export { SESSION_FACETS, SESSION_FILTERS, SESSION_STATS_FILTERS };
@@ -0,0 +1,53 @@
1
+ import { renameOrderFields } from "nodefony";
2
+ //#region nodefony/src/session/storage/sessionSort.ts
3
+ /**
4
+ * **Le vocabulaire de tri des sessions**, en noms PUBLICS — ceux qu'un client
5
+ * écrit dans l'URL (`?order=updatedAt:DESC`), jamais des noms de colonne.
6
+ *
7
+ * Il vit ici, chez le propriétaire du contrat (`@nodefony/http`), et non dans
8
+ * chaque backend : c'est ce qui garantit qu'une console offre le même tri que
9
+ * l'application tourne sur mémoire, SQLite, PostgreSQL ou Mongo. Un store qui
10
+ * nomme ses colonnes autrement (SQL stocke l'identifiant en `session_id`)
11
+ * **traduit chez lui** — cf {@link SESSION_COLUMN_ALIASES}.
12
+ *
13
+ * - `updatedAt` — dernière activité (l'axe naturel d'une console de sessions).
14
+ * - `createdAt` — ouverture de la session (« qui s'est connecté en premier »).
15
+ * - `user` — porteur, pour regrouper les sessions d'un même compte à l'œil.
16
+ * - `id` — identifiant de session, utile surtout en départage.
17
+ *
18
+ * Ce que la liste n'inclut PAS, et pourquoi : `ip` et `ua` ne sont **pas des
19
+ * champs** mais des entrées du sac de métadonnées (`metaBag`, sérialisé en
20
+ * JSON). Aucun backend ne peut les ordonner sans matérialiser la collection —
21
+ * la console les affiche donc en colonnes non triables, au lieu d'offrir un
22
+ * tri qui serait refusé (SQL) ou coûteux (mémoire).
23
+ */
24
+ const SESSION_SORTABLE_FIELDS = [
25
+ "updatedAt",
26
+ "createdAt",
27
+ "user",
28
+ "id"
29
+ ];
30
+ /**
31
+ * Ordre contractuel appliqué quand le client n'en demande aucun : activité la
32
+ * plus récente d'abord, départagée par identifiant pour rester **déterministe**
33
+ * à horodatage égal (sans quoi une pagination peut sauter ou répéter une ligne
34
+ * entre deux pages).
35
+ */
36
+ const SESSION_DEFAULT_ORDER = [["updatedAt", "DESC"], ["id", "ASC"]];
37
+ /**
38
+ * Table d'alias des backends dont le schéma nomme l'identifiant de session
39
+ * `session_id` (SQL comme Mongo) — à passer à `renameOrderFields` (core).
40
+ *
41
+ * C'est une **donnée** du schéma, pas du code : la règle « réécrire les noms »
42
+ * vit au core en un exemplaire, et chaque backend n'apporte que sa table. Sans
43
+ * cette traduction, `?order=id:ASC` partirait vers une colonne `id` inexistante
44
+ * — l'erreur ne se verrait qu'à l'exécution, sur le backend concerné seulement.
45
+ */
46
+ const SESSION_COLUMN_ALIASES = { id: "session_id" };
47
+ /**
48
+ * Ordre par défaut des backends dont le schéma nomme l'identifiant
49
+ * `session_id` — {@link SESSION_DEFAULT_ORDER} déjà traduit.
50
+ */
51
+ const SESSION_DEFAULT_ORDER_SQL = renameOrderFields(SESSION_DEFAULT_ORDER, SESSION_COLUMN_ALIASES);
52
+ //#endregion
53
+ export { SESSION_COLUMN_ALIASES, SESSION_DEFAULT_ORDER, SESSION_DEFAULT_ORDER_SQL, SESSION_SORTABLE_FIELDS };
@@ -0,0 +1,83 @@
1
+ import { Kernel, Module } from "nodefony";
2
+ import type { IHttpConfig, IHttpConfigInput } from "./nodefony/interfaces/IHttpConfig.js";
3
+ import { Profiler } from "./nodefony/src/profiler/Profiler.js";
4
+ import HttpKernel from "./nodefony/service/http-kernel.js";
5
+ import SessionsService from "./nodefony/service/sessions/sessions-service.js";
6
+ import Context from "./nodefony/src/context/Context.js";
7
+ import Session from "./nodefony/src/session/session.js";
8
+ import HttpError from "./nodefony/src/errors/httpError.js";
9
+ import Response from "./nodefony/src/context/http/Response.js";
10
+ import Http2Response from "./nodefony/src/context/http2/Response.js";
11
+ import wsResponse from "./nodefony/src/context/websocket/Response.js";
12
+ import Cookie from "./nodefony/src/cookies/cookie.js";
13
+ import DefaultErrorRenderer from "./nodefony/service/error-renderer.js";
14
+ import DefaultRequestLogger from "./nodefony/service/request-logger.js";
15
+ import JsonAuditLogger from "./nodefony/service/audit-logger.js";
16
+ import PrettyRequestLogger from "./nodefony/service/pretty-request-logger.js";
17
+ import HttpContext from "./nodefony/src/context/http/HttpContext.js";
18
+ import WebsocketContext from "./nodefony/src/context/websocket/WebsocketContext.js";
19
+ import HttpRequest from "./nodefony/src/context/http/Request.js";
20
+ import Http2Request from "./nodefony/src/context/http2/Request.js";
21
+ declare module "nodefony" {
22
+ interface NodefonyModuleConfig {
23
+ "@nodefony/http": IHttpConfigInput;
24
+ }
25
+ }
26
+ declare class Http extends Module<IHttpConfig> {
27
+ constructor(kernel: Kernel);
28
+ /**
29
+ * Expose le JSON Schema de la config http (dérivé du schéma Zod, flags `meta()`
30
+ * inclus) au data plane admin → Studio rend la config en réglages documentés
31
+ * (type, défaut, état, valeur effective) au lieu d'un dump brut. Override du
32
+ * seam {@link Module.configSchema}.
33
+ */
34
+ configSchema(): unknown;
35
+ /**
36
+ * Phase `onRegister` : valide la config (défauts + override `module-http` +
37
+ * défauts kernel) via `defineHttpConfig`, puis la ré-assigne à `this.options`
38
+ * AVANT l'instanciation des `@services` (phase `onBoot`). Plante propre avec
39
+ * messages clairs si la config est invalide (convention Zod figée 2026-05-28).
40
+ *
41
+ * Config NON gelée : les services mutent `module.options` (upload `uploadDir`,
42
+ * certificats `serialNumber`) — cf `defineHttpConfig`.
43
+ */
44
+ onKernelRegister(): Promise<this>;
45
+ /**
46
+ * Phase `onBoot` : s'enregistre comme producteur admin (`/nodefony/http/api/*`)
47
+ * auprès du broker, AVANT que framework ne monte le data plane à `onReady`.
48
+ *
49
+ * Importe seulement `IAdminRegistry` (core) — jamais `@nodefony/framework`
50
+ * (dépendance circulaire). Le broker est résolu du container partagé.
51
+ */
52
+ onKernelBoot(): Promise<this>;
53
+ onKernelReady(): Promise<this>;
54
+ }
55
+ export default Http;
56
+ export { defineHttpConfig, httpConfigJsonSchema, } from "./nodefony/config/defineModuleConfig.js";
57
+ export { httpConfigSchema, type HttpConfig, type HttpConfigInput, } from "./nodefony/config/config.js";
58
+ export type { IHttpConfig, IHttpConfigInput, } from "./nodefony/interfaces/IHttpConfig.js";
59
+ export { decideSend, readBackpressureOptions, type WsBackpressurePolicy, type WsSendDecision, type IWsBackpressureOptions, type IBackpressureSocket, type IBackpressureTarget, } from "./nodefony/src/context/websocket/wsBackpressure.js";
60
+ export { compileDomainPattern, compileDomainPatterns, compileTrustedHosts, isDomainAllowed, } from "./nodefony/src/context/domainMatcher.js";
61
+ export type { DomainPattern, TrustedHostsConfig, } from "./nodefony/src/context/domainMatcher.js";
62
+ export { MemoryRateLimitStore } from "./nodefony/src/rateLimit/MemoryRateLimitStore.js";
63
+ export type { IRateLimitStore, IRateLimitOptions, RateLimitVerdict, } from "./nodefony/src/rateLimit/IRateLimitStore.js";
64
+ export { Context, Session, SessionsService, HttpError, HttpKernel, Response, Http2Response, Response as HttpResponse, wsResponse, wsResponse as WebsocketResponse, Cookie, HttpContext, WebsocketContext, HttpRequest, Http2Request, DefaultErrorRenderer, DefaultRequestLogger, JsonAuditLogger, PrettyRequestLogger, Profiler, };
65
+ export { schemaMismatchOf, type SchemaMismatchConfidence, } from "./nodefony/service/error-renderer.js";
66
+ export type { ProfileEntry, ProfileSummary, ProfilePhase, ProfileQuery, ProfileSecurity, } from "./nodefony/src/profiler/Profiler.js";
67
+ export { FrameProfile } from "./nodefony/src/profiler/FrameProfile.js";
68
+ export type { FrameProfileInit, ProfiledArea, ProfiledResolver, } from "./nodefony/src/profiler/FrameProfile.js";
69
+ export { resolveUiDelivery, PrebuiltUi, } from "./nodefony/src/assets/prebuiltUi.js";
70
+ export type { UiDeliveryMode, UiDeliveryResolved, IUiDeliveryResolution, IUiDeliveryOptions, IPrebuiltUiOptions, } from "./nodefony/src/assets/prebuiltUi.js";
71
+ export type { IContext, IHttpContext, IWebsocketContext, ServerType, SchemeType, WebSocketStateType, CookiesMap, ISecurityTrace, SecurityOutcome, } from "./nodefony/interfaces/IContext.js";
72
+ export type { ICookie, ICookieOptions, IWsCookie, SameSiteType, PriorityType, } from "./nodefony/interfaces/ICookie.js";
73
+ export type { ISession, ISessionStorage, ISerializedSession, ISessionSummary, ISessionRecord, ISessionListFilter, ISessionListQuery, SessionIntent, SessionStatusType, SessionStrategyType, FlashBagType, MetaBagType, } from "./nodefony/interfaces/ISession.js";
74
+ export { SESSION_SORTABLE_FIELDS, SESSION_DEFAULT_ORDER, SESSION_DEFAULT_ORDER_SQL, SESSION_COLUMN_ALIASES, } from "./nodefony/src/session/storage/sessionSort.js";
75
+ export type { IHttpRequest, IHttp2Request, IWsRequest, HTTPMethodType, } from "./nodefony/interfaces/IRequest.js";
76
+ export type { IHttpResponse, IWebsocketResponse, } from "./nodefony/interfaces/IResponse.js";
77
+ export type { IHttpKernel } from "./nodefony/interfaces/IHttpKernel.js";
78
+ export type { IUploadedFile, IUploadService, IParsedUploadFile, IUploadOptions, } from "./nodefony/interfaces/IUpload.js";
79
+ export type { IErrorRenderer, IErrorHttpResult, IErrorWebsocketResult, } from "./nodefony/interfaces/IErrorRenderer.js";
80
+ export type { IRequestLogger, IRequestLogEntry, } from "./nodefony/interfaces/IRequestLogger.js";
81
+ export type { AuditLogEntry, AuditErrorEntry, JsonAuditLoggerOptions, } from "./nodefony/service/audit-logger.js";
82
+ export type { ContextType, httpRequest, httpResponse, ProtocolType, } from "./nodefony/service/http-kernel.js";
83
+ export type { contextRequest, contextResponse, HTTPMethod, WebSocketState, Cookies, } from "./nodefony/src/context/Context.js";
@@ -0,0 +1,23 @@
1
+ import { CliKernel, Command } from "nodefony";
2
+ /**
3
+ * Commande CLI `assets:publish` — assemble TOUS les assets statiques servables
4
+ * (publics de module montés sous `/<module>/` + bundles `@nodefony/frontend`
5
+ * sous `/_assets/<name>/`) dans UN arbre `dist-assets/` miroir des préfixes
6
+ * d'URL, plus un `manifest.json`.
7
+ *
8
+ * Provider-agnostic — Nodefony ASSEMBLE, l'orchestrateur PUBLIE (cloud-native) :
9
+ * `aws s3 sync dist-assets s3://bucket`, `rsync`, upload CI… Pas de dépendance
10
+ * cloud embarquée dans le framework. Combine avec `frontend.assetBaseUrl` pour
11
+ * que les URLs émises pointent le CDN qui sert cet arbre.
12
+ */
13
+ declare class AssetsPublish extends Command {
14
+ constructor(cli: CliKernel);
15
+ generate(opts: {
16
+ out?: string;
17
+ clean?: boolean;
18
+ json?: boolean;
19
+ }): Promise<this>;
20
+ /** Sources = mounts natifs (`server-static`) + bundles `@nodefony/frontend`. */
21
+ private collectSources;
22
+ }
23
+ export default AssetsPublish;
@@ -0,0 +1,17 @@
1
+ import { CliKernel, Command } from "nodefony";
2
+ /**
3
+ * Commande CLI `certificates` — (re)génère et inspecte le certificat TLS de
4
+ * DÉVELOPPEMENT. La génération reste un confort de dev : en production, fournir
5
+ * un vrai certificat (`certificates.strategy: "explicit"`).
6
+ *
7
+ * Réutilise le service `certificates` du module `@nodefony/http` (source unique)
8
+ * → la commande, le boot auto et un futur endpoint Studio appellent le même code.
9
+ */
10
+ declare class Certificates extends Command {
11
+ constructor(cli: CliKernel);
12
+ generate(opts: {
13
+ force?: boolean;
14
+ json?: boolean;
15
+ }): Promise<this>;
16
+ }
17
+ export default Certificates;
@@ -0,0 +1,8 @@
1
+ import { CliKernel, Command } from "nodefony";
2
+ declare class Network extends Command {
3
+ constructor(cli: CliKernel);
4
+ generate(arg: string, opts: {
5
+ json: boolean;
6
+ }): Promise<this>;
7
+ }
8
+ export default Network;
@@ -0,0 +1,19 @@
1
+ import { CliKernel, Command } from "nodefony";
2
+ /**
3
+ * Commande CLI `proxy:generate <nginx|haproxy>` — génère une configuration
4
+ * reverse-proxy DÉRIVÉE de l'introspection Nodefony (domaines de confiance,
5
+ * dossiers statiques servis, ports). Évite d'écrire la conf à la main et de la
6
+ * laisser diverger ; résout le « trou statiques multi-modules » côté nginx.
7
+ */
8
+ declare class ProxyGenerate extends Command {
9
+ constructor(cli: CliKernel);
10
+ generate(target: string, opts: {
11
+ out?: string;
12
+ backend?: string;
13
+ listen?: string;
14
+ reencrypt?: boolean;
15
+ }): Promise<this>;
16
+ /** Construit le modèle d'introspection depuis le kernel + le service statique. */
17
+ private buildIntrospection;
18
+ }
19
+ export default ProxyGenerate;
@@ -0,0 +1,197 @@
1
+ import { z } from "zod";
2
+ export declare const httpConfigSchema: z.ZodObject<{
3
+ headerServer: z.ZodDefault<z.ZodNullable<z.ZodString>>;
4
+ trustProxy: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString, z.ZodArray<z.ZodString>]>>;
5
+ trustedHosts: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString, z.ZodArray<z.ZodString>]>>;
6
+ securityHeaders: z.ZodDefault<z.ZodObject<{
7
+ contentTypeOptions: z.ZodDefault<z.ZodNullable<z.ZodString>>;
8
+ frameOptions: z.ZodDefault<z.ZodNullable<z.ZodString>>;
9
+ strictTransportSecurity: z.ZodDefault<z.ZodNullable<z.ZodObject<{
10
+ maxAge: z.ZodDefault<z.ZodNumber>;
11
+ includeSubDomains: z.ZodDefault<z.ZodBoolean>;
12
+ preload: z.ZodDefault<z.ZodBoolean>;
13
+ }, z.core.$strict>>>;
14
+ }, z.core.$strict>>;
15
+ maxBodySize: z.ZodDefault<z.ZodNumber>;
16
+ upload: z.ZodDefault<z.ZodObject<{
17
+ uploadDir: z.ZodDefault<z.ZodString>;
18
+ maxFileSize: z.ZodDefault<z.ZodNumber>;
19
+ maxTotalFileSize: z.ZodDefault<z.ZodNumber>;
20
+ maxFiles: z.ZodDefault<z.ZodNumber>;
21
+ maxFields: z.ZodDefault<z.ZodNumber>;
22
+ maxFieldsSize: z.ZodDefault<z.ZodNumber>;
23
+ hashAlgorithm: z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodEnum<{
24
+ md5: "md5";
25
+ sha1: "sha1";
26
+ sha256: "sha256";
27
+ }>]>>;
28
+ encoding: z.ZodDefault<z.ZodString>;
29
+ }, z.core.$strict>>;
30
+ queryString: z.ZodDefault<z.ZodObject<{
31
+ parameterLimit: z.ZodDefault<z.ZodNumber>;
32
+ delimiter: z.ZodDefault<z.ZodString>;
33
+ ignoreQueryPrefix: z.ZodDefault<z.ZodBoolean>;
34
+ }, z.core.$loose>>;
35
+ http: z.ZodDefault<z.ZodObject<{
36
+ maxHeadersCount: z.ZodDefault<z.ZodNumber>;
37
+ keepAliveTimeout: z.ZodDefault<z.ZodNumber>;
38
+ timeout: z.ZodDefault<z.ZodNumber>;
39
+ requestTimeout: z.ZodDefault<z.ZodNumber>;
40
+ responseTimeout: z.ZodDefault<z.ZodNumber>;
41
+ shutdownTimeout: z.ZodDefault<z.ZodNumber>;
42
+ headers: z.ZodDefault<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodString>>>;
43
+ }, z.core.$loose>>;
44
+ https: z.ZodDefault<z.ZodObject<{
45
+ maxHeadersCount: z.ZodDefault<z.ZodNumber>;
46
+ keepAliveTimeout: z.ZodDefault<z.ZodNumber>;
47
+ timeout: z.ZodDefault<z.ZodNumber>;
48
+ requestTimeout: z.ZodDefault<z.ZodNumber>;
49
+ responseTimeout: z.ZodDefault<z.ZodNumber>;
50
+ shutdownTimeout: z.ZodDefault<z.ZodNumber>;
51
+ headers: z.ZodDefault<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodString>>>;
52
+ rejectUnauthorized: z.ZodDefault<z.ZodBoolean>;
53
+ }, z.core.$loose>>;
54
+ http2: z.ZodDefault<z.ZodObject<{
55
+ maxConcurrentStreams: z.ZodDefault<z.ZodNumber>;
56
+ maxSessionMemory: z.ZodDefault<z.ZodNumber>;
57
+ }, z.core.$loose>>;
58
+ http3: z.ZodDefault<z.ZodObject<{}, z.core.$loose>>;
59
+ certificates: z.ZodDefault<z.ZodObject<{
60
+ strategy: z.ZodDefault<z.ZodEnum<{
61
+ auto: "auto";
62
+ explicit: "explicit";
63
+ mkcert: "mkcert";
64
+ selfsigned: "selfsigned";
65
+ }>>;
66
+ ca: z.ZodDefault<z.ZodString>;
67
+ key: z.ZodDefault<z.ZodString>;
68
+ cert: z.ZodDefault<z.ZodString>;
69
+ privateKeyMode: z.ZodDefault<z.ZodNumber>;
70
+ san: z.ZodDefault<z.ZodObject<{
71
+ dns: z.ZodDefault<z.ZodArray<z.ZodString>>;
72
+ ip: z.ZodDefault<z.ZodArray<z.ZodString>>;
73
+ }, z.core.$strict>>;
74
+ dev: z.ZodDefault<z.ZodObject<{
75
+ useMkcert: z.ZodDefault<z.ZodBoolean>;
76
+ }, z.core.$strict>>;
77
+ openssl: z.ZodDefault<z.ZodObject<{
78
+ size: z.ZodDefault<z.ZodNumber>;
79
+ hash: z.ZodDefault<z.ZodEnum<{
80
+ sha256: "sha256";
81
+ sha384: "sha384";
82
+ sha512: "sha512";
83
+ }>>;
84
+ validityDays: z.ZodDefault<z.ZodNumber>;
85
+ backdateMinutes: z.ZodDefault<z.ZodNumber>;
86
+ attrs: z.ZodDefault<z.ZodArray<z.ZodObject<{
87
+ name: z.ZodOptional<z.ZodString>;
88
+ value: z.ZodOptional<z.ZodString>;
89
+ shortName: z.ZodOptional<z.ZodString>;
90
+ }, z.core.$loose>>>;
91
+ }, z.core.$strict>>;
92
+ }, z.core.$strict>>;
93
+ websocket: z.ZodDefault<z.ZodObject<{
94
+ keepaliveInterval: z.ZodDefault<z.ZodNumber>;
95
+ keepaliveGracePeriod: z.ZodDefault<z.ZodNumber>;
96
+ closeTimeout: z.ZodDefault<z.ZodNumber>;
97
+ maxPayload: z.ZodDefault<z.ZodNumber>;
98
+ allowedOrigins: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString, z.ZodArray<z.ZodString>]>>;
99
+ perMessageDeflate: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
100
+ serverNoContextTakeover: z.ZodOptional<z.ZodBoolean>;
101
+ clientNoContextTakeover: z.ZodOptional<z.ZodBoolean>;
102
+ serverMaxWindowBits: z.ZodOptional<z.ZodNumber>;
103
+ clientMaxWindowBits: z.ZodOptional<z.ZodNumber>;
104
+ threshold: z.ZodOptional<z.ZodNumber>;
105
+ concurrencyLimit: z.ZodOptional<z.ZodNumber>;
106
+ }, z.core.$loose>]>>;
107
+ skipUTF8Validation: z.ZodDefault<z.ZodBoolean>;
108
+ autoPong: z.ZodDefault<z.ZodBoolean>;
109
+ allowSynchronousEvents: z.ZodDefault<z.ZodBoolean>;
110
+ maxBackpressure: z.ZodDefault<z.ZodNumber>;
111
+ backpressureCloseAfterDrops: z.ZodDefault<z.ZodNumber>;
112
+ backpressurePolicy: z.ZodDefault<z.ZodEnum<{
113
+ close: "close";
114
+ drop: "drop";
115
+ }>>;
116
+ }, z.core.$loose>>;
117
+ websocketSecure: z.ZodDefault<z.ZodObject<{
118
+ keepaliveInterval: z.ZodDefault<z.ZodNumber>;
119
+ keepaliveGracePeriod: z.ZodDefault<z.ZodNumber>;
120
+ closeTimeout: z.ZodDefault<z.ZodNumber>;
121
+ maxPayload: z.ZodDefault<z.ZodNumber>;
122
+ allowedOrigins: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString, z.ZodArray<z.ZodString>]>>;
123
+ perMessageDeflate: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
124
+ serverNoContextTakeover: z.ZodOptional<z.ZodBoolean>;
125
+ clientNoContextTakeover: z.ZodOptional<z.ZodBoolean>;
126
+ serverMaxWindowBits: z.ZodOptional<z.ZodNumber>;
127
+ clientMaxWindowBits: z.ZodOptional<z.ZodNumber>;
128
+ threshold: z.ZodOptional<z.ZodNumber>;
129
+ concurrencyLimit: z.ZodOptional<z.ZodNumber>;
130
+ }, z.core.$loose>]>>;
131
+ skipUTF8Validation: z.ZodDefault<z.ZodBoolean>;
132
+ autoPong: z.ZodDefault<z.ZodBoolean>;
133
+ allowSynchronousEvents: z.ZodDefault<z.ZodBoolean>;
134
+ maxBackpressure: z.ZodDefault<z.ZodNumber>;
135
+ backpressureCloseAfterDrops: z.ZodDefault<z.ZodNumber>;
136
+ backpressurePolicy: z.ZodDefault<z.ZodEnum<{
137
+ close: "close";
138
+ drop: "drop";
139
+ }>>;
140
+ }, z.core.$loose>>;
141
+ statics: z.ZodDefault<z.ZodObject<{
142
+ enabled: z.ZodDefault<z.ZodBoolean>;
143
+ defaultOptions: z.ZodDefault<z.ZodObject<{
144
+ cacheControl: z.ZodOptional<z.ZodBoolean>;
145
+ maxAge: z.ZodOptional<z.ZodNumber>;
146
+ }, z.core.$loose>>;
147
+ web: z.ZodDefault<z.ZodObject<{
148
+ path: z.ZodString;
149
+ options: z.ZodOptional<z.ZodObject<{
150
+ cacheControl: z.ZodOptional<z.ZodBoolean>;
151
+ maxAge: z.ZodOptional<z.ZodNumber>;
152
+ }, z.core.$loose>>;
153
+ }, z.core.$loose>>;
154
+ }, z.core.$loose>>;
155
+ session: z.ZodDefault<z.ZodObject<{
156
+ strictMode: z.ZodDefault<z.ZodBoolean>;
157
+ name: z.ZodDefault<z.ZodString>;
158
+ store: z.ZodDefault<z.ZodString>;
159
+ gcIntervalS: z.ZodDefault<z.ZodNumber>;
160
+ gcJitter: z.ZodDefault<z.ZodBoolean>;
161
+ idleTimeoutS: z.ZodDefault<z.ZodNumber>;
162
+ absoluteTimeoutS: z.ZodDefault<z.ZodNumber>;
163
+ refererCheck: z.ZodDefault<z.ZodBoolean>;
164
+ cookie: z.ZodDefault<z.ZodObject<{
165
+ maxAge: z.ZodDefault<z.ZodNumber>;
166
+ httpOnly: z.ZodDefault<z.ZodBoolean>;
167
+ secure: z.ZodDefault<z.ZodBoolean>;
168
+ signed: z.ZodDefault<z.ZodBoolean>;
169
+ hostPrefix: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
170
+ }, z.core.$strict>>;
171
+ }, z.core.$strict>>;
172
+ rateLimit: z.ZodDefault<z.ZodObject<{
173
+ enabled: z.ZodDefault<z.ZodBoolean>;
174
+ windowS: z.ZodDefault<z.ZodNumber>;
175
+ max: z.ZodDefault<z.ZodNumber>;
176
+ maxTracked: z.ZodDefault<z.ZodNumber>;
177
+ gcIntervalS: z.ZodDefault<z.ZodNumber>;
178
+ gcJitter: z.ZodDefault<z.ZodBoolean>;
179
+ }, z.core.$strict>>;
180
+ health: z.ZodDefault<z.ZodObject<{
181
+ enabled: z.ZodDefault<z.ZodBoolean>;
182
+ livenessPath: z.ZodDefault<z.ZodString>;
183
+ readinessPath: z.ZodDefault<z.ZodString>;
184
+ shutdownDelay: z.ZodDefault<z.ZodNumber>;
185
+ }, z.core.$loose>>;
186
+ wsMaxConnectionsPerIp: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
187
+ }, z.core.$strict>;
188
+ /** Type de sortie (config normalisée + défauts appliqués). */
189
+ export type HttpConfig = z.infer<typeof httpConfigSchema>;
190
+ /** Type d'entrée (toutes sections omissibles — défauts du schéma). */
191
+ export type HttpConfigInput = z.input<typeof httpConfigSchema>;
192
+ /**
193
+ * Défauts du module, matérialisés depuis le schéma (source unique). Toujours
194
+ * valides par construction ; passés au `super(..., config)` du Module class.
195
+ */
196
+ declare const config: HttpConfig;
197
+ export default config;