theokit 0.2.4 → 0.4.0

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 (303) hide show
  1. package/dist/{actions-virtual-module-HWNTIEPI.js → actions-virtual-module-IY46EEEX.js} +2 -2
  2. package/dist/{actions-virtual-module-SEIPACG5.js → actions-virtual-module-XNHDNCZ6.js} +2 -2
  3. package/dist/add-2ZFFGGE4.js +0 -0
  4. package/dist/{app-typed-client-6GC6VWXS.js → app-typed-client-OUJO3V5J.js} +10 -5
  5. package/dist/{app-typed-client-6GC6VWXS.js.map → app-typed-client-OUJO3V5J.js.map} +1 -1
  6. package/dist/{app-typed-client-US2ZXBEC.js → app-typed-client-YOMWSA3F.js} +11 -6
  7. package/dist/{app-typed-client-US2ZXBEC.js.map → app-typed-client-YOMWSA3F.js.map} +1 -1
  8. package/dist/audit-log-BQWM5YLG.d.ts +60 -0
  9. package/dist/{aws-lambda-XYCGZH3I.js → aws-lambda-GKSTX6HD.js} +3 -3
  10. package/dist/body-parser-web-MUWBKZ3F.js +70 -0
  11. package/dist/body-parser-web-MUWBKZ3F.js.map +1 -0
  12. package/dist/broadcast-QOQGUNNK.js +0 -0
  13. package/dist/{build-MREW6MVS.js → build-D4J7XECU.js} +33 -24
  14. package/dist/build-D4J7XECU.js.map +1 -0
  15. package/dist/build-request-body-preview-II2235E6.js +0 -0
  16. package/dist/{bun-K73TQEWC.js → bun-ISHSNFIO.js} +3 -3
  17. package/dist/{check-PZR67OY5.js → check-NXYPLM6M.js} +2 -2
  18. package/dist/{chunk-WZ7CPVQB.js → chunk-27LWMYNK.js} +28 -24
  19. package/dist/chunk-27LWMYNK.js.map +1 -0
  20. package/dist/{chunk-5OKZY2VL.js → chunk-2F4FROEQ.js} +1695 -1522
  21. package/dist/chunk-2F4FROEQ.js.map +1 -0
  22. package/dist/chunk-4HBI7DHP.js +20 -0
  23. package/dist/chunk-4HBI7DHP.js.map +1 -0
  24. package/dist/{chunk-X4JAX2U3.js → chunk-4S2UCILN.js} +180 -125
  25. package/dist/chunk-4S2UCILN.js.map +1 -0
  26. package/dist/{chunk-C52GSJPF.js → chunk-4S6YHNG2.js} +11 -8
  27. package/dist/chunk-4S6YHNG2.js.map +1 -0
  28. package/dist/chunk-5ODOE6EF.js +0 -0
  29. package/dist/{chunk-KJVEJILQ.js → chunk-5PU65T5W.js} +9 -3
  30. package/dist/chunk-5PU65T5W.js.map +1 -0
  31. package/dist/chunk-5QW7IQQU.js +36 -0
  32. package/dist/chunk-5QW7IQQU.js.map +1 -0
  33. package/dist/chunk-5Z2727GV.js +1324 -0
  34. package/dist/chunk-5Z2727GV.js.map +1 -0
  35. package/dist/{chunk-YLBSSEHX.js → chunk-6NEXVBPY.js} +5 -15
  36. package/dist/chunk-6NEXVBPY.js.map +1 -0
  37. package/dist/chunk-7MQOHNHE.js +36 -0
  38. package/dist/chunk-7MQOHNHE.js.map +1 -0
  39. package/dist/{chunk-TPCT3MXV.js → chunk-ABVITXFH.js} +405 -272
  40. package/dist/chunk-ABVITXFH.js.map +1 -0
  41. package/dist/chunk-ASDXVRJD.js +185 -0
  42. package/dist/chunk-ASDXVRJD.js.map +1 -0
  43. package/dist/chunk-B3L3TJVF.js +406 -0
  44. package/dist/chunk-B3L3TJVF.js.map +1 -0
  45. package/dist/{chunk-PB4GR7EP.js → chunk-C3ZZ56YZ.js} +1 -18
  46. package/dist/chunk-C3ZZ56YZ.js.map +1 -0
  47. package/dist/{chunk-O7335ZGH.js → chunk-CG563V5M.js} +5 -3
  48. package/dist/chunk-CG563V5M.js.map +1 -0
  49. package/dist/{chunk-5OFPQK6N.js → chunk-COXLEZCN.js} +2 -1
  50. package/dist/chunk-COXLEZCN.js.map +1 -0
  51. package/dist/{chunk-O4BLVPML.js → chunk-DNMSV3R3.js} +22 -28
  52. package/dist/chunk-DNMSV3R3.js.map +1 -0
  53. package/dist/chunk-E3JH6YUM.js +1 -0
  54. package/dist/chunk-ESC54TAK.js +220 -0
  55. package/dist/chunk-ESC54TAK.js.map +1 -0
  56. package/dist/chunk-FI7MPTJW.js +77 -0
  57. package/dist/chunk-FI7MPTJW.js.map +1 -0
  58. package/dist/chunk-H4J2LECY.js +201 -0
  59. package/dist/chunk-H4J2LECY.js.map +1 -0
  60. package/dist/chunk-IAJ2JVEH.js +256 -0
  61. package/dist/chunk-IAJ2JVEH.js.map +1 -0
  62. package/dist/{chunk-F3TG5FJV.js → chunk-IEZCAT2I.js} +7 -1
  63. package/dist/{chunk-F3TG5FJV.js.map → chunk-IEZCAT2I.js.map} +1 -1
  64. package/dist/chunk-JHEAWR3L.js +1 -0
  65. package/dist/chunk-JQSKBMXP.js +17 -0
  66. package/dist/chunk-JQSKBMXP.js.map +1 -0
  67. package/dist/{chunk-4QTKSLTO.js → chunk-K4M64WD6.js} +9 -5
  68. package/dist/{chunk-4QTKSLTO.js.map → chunk-K4M64WD6.js.map} +1 -1
  69. package/dist/chunk-KI7OWQUX.js +293 -0
  70. package/dist/chunk-KI7OWQUX.js.map +1 -0
  71. package/dist/chunk-KT3MWNZG.js +0 -0
  72. package/dist/{chunk-ZJW5FFYJ.js → chunk-LC5PYNJP.js} +2 -2
  73. package/dist/{chunk-X2OLD264.js → chunk-M2EY7KDR.js} +1228 -1124
  74. package/dist/chunk-M2EY7KDR.js.map +1 -0
  75. package/dist/{chunk-YWWHK7R6.js → chunk-MR7OLIC6.js} +3 -3
  76. package/dist/chunk-NM4WF3XD.js +63 -0
  77. package/dist/chunk-NM4WF3XD.js.map +1 -0
  78. package/dist/chunk-NPMCKOX4.js +1 -0
  79. package/dist/{chunk-VRHXOKRP.js → chunk-NZXH2LQQ.js} +86 -83
  80. package/dist/chunk-NZXH2LQQ.js.map +1 -0
  81. package/dist/{chunk-2BQYEBCK.js → chunk-OLPB36O2.js} +87 -5
  82. package/dist/chunk-OLPB36O2.js.map +1 -0
  83. package/dist/chunk-PIVX3DYW.js +142 -0
  84. package/dist/chunk-PIVX3DYW.js.map +1 -0
  85. package/dist/{chunk-7TOMTMHT.js → chunk-R7OC6UDK.js} +2 -1
  86. package/dist/chunk-R7OC6UDK.js.map +1 -0
  87. package/dist/chunk-RESN62GB.js +269 -0
  88. package/dist/chunk-RESN62GB.js.map +1 -0
  89. package/dist/{chunk-64JI5LTO.js → chunk-RMU7EBRO.js} +2 -2
  90. package/dist/chunk-RMU7EBRO.js.map +1 -0
  91. package/dist/chunk-TQYSPYKU.js +131 -0
  92. package/dist/chunk-TQYSPYKU.js.map +1 -0
  93. package/dist/chunk-TSLSIRBR.js +107 -0
  94. package/dist/chunk-TSLSIRBR.js.map +1 -0
  95. package/dist/{chunk-XP7YXRHO.js → chunk-U6TPSW4L.js} +37 -5
  96. package/dist/chunk-U6TPSW4L.js.map +1 -0
  97. package/dist/chunk-UD3LFGDL.js +45 -0
  98. package/dist/chunk-UD3LFGDL.js.map +1 -0
  99. package/dist/chunk-UUFYP2UM.js +161 -0
  100. package/dist/chunk-UUFYP2UM.js.map +1 -0
  101. package/dist/{chunk-SNDZQ64K.js → chunk-VBZCVFSA.js} +85 -3
  102. package/dist/chunk-VBZCVFSA.js.map +1 -0
  103. package/dist/chunk-VMEWD57H.js +137 -0
  104. package/dist/chunk-VMEWD57H.js.map +1 -0
  105. package/dist/{chunk-BE2LKDI7.js → chunk-WEGALZEU.js} +3 -3
  106. package/dist/{chunk-ZOXNJV2O.js → chunk-WGHJD6I7.js} +35 -138
  107. package/dist/chunk-WGHJD6I7.js.map +1 -0
  108. package/dist/chunk-XMS5VRIK.js +0 -0
  109. package/dist/chunk-Y4H3JNVK.js +18 -0
  110. package/dist/chunk-Y4H3JNVK.js.map +1 -0
  111. package/dist/chunk-Z5IGLBWE.js +329 -0
  112. package/dist/chunk-Z5IGLBWE.js.map +1 -0
  113. package/dist/chunk-ZEGYW52B.js +26 -0
  114. package/dist/chunk-ZEGYW52B.js.map +1 -0
  115. package/dist/chunk-ZJQ4O76G.js +87 -0
  116. package/dist/chunk-ZJQ4O76G.js.map +1 -0
  117. package/dist/cli/index.js +44 -9
  118. package/dist/cli/index.js.map +1 -1
  119. package/dist/client/index.d.ts +107 -1
  120. package/dist/client/index.js +152 -6
  121. package/dist/client/index.js.map +1 -1
  122. package/dist/{cloudflare-LCAOTRYZ.js → cloudflare-OJGJ7R2D.js} +3 -3
  123. package/dist/configure-agent-registry-6YGTJYBC.js +0 -0
  124. package/dist/cookies-MJKMGJ7N.js +22 -0
  125. package/dist/csrf-BBrEZSBW.d.ts +107 -0
  126. package/dist/csrf-readiness-store-CjIoub3U.d.ts +43 -0
  127. package/dist/define-websocket-CdK94O-D.d.ts +64 -0
  128. package/dist/{deno-deploy-ZN4RE5HF.js → deno-deploy-BHWKFTOW.js} +3 -3
  129. package/dist/{dev-6P2DM33Q.js → dev-MJVSRZGF.js} +13 -13
  130. package/dist/{dev-emit-MLDFOLUU.js → dev-emit-5VPRCHOD.js} +39 -142
  131. package/dist/dev-emit-5VPRCHOD.js.map +1 -0
  132. package/dist/{dev-emit-PRSRPDHA.js → dev-emit-HHP2XJXE.js} +5 -5
  133. package/dist/devtools/entry.js +185 -131
  134. package/dist/devtools/entry.js.map +1 -1
  135. package/dist/{dispatcher-AQJGI3HU.js → dispatcher-63LBXYLE.js} +2 -2
  136. package/dist/{dispatcher-E6QV32BO.js → dispatcher-EJME6C6M.js} +5 -2
  137. package/dist/dispatcher-EJME6C6M.js.map +1 -0
  138. package/dist/{dist-E6BL4ZVY.js → dist-KRW6OVD4.js} +7 -7
  139. package/dist/dist-KRW6OVD4.js.map +1 -0
  140. package/dist/docker-EZDA5FT7.js +0 -0
  141. package/dist/error-envelope-BsNzzAV5.d.ts +62 -0
  142. package/dist/{generate-DT4IIAHF.js → generate-AZ2K6Z2Z.js} +75 -2
  143. package/dist/generate-AZ2K6Z2Z.js.map +1 -0
  144. package/dist/index-DWWEdFh5.d.ts +399 -0
  145. package/dist/index.d.ts +161 -1391
  146. package/dist/index.js +20 -8
  147. package/dist/index.js.map +1 -1
  148. package/dist/{info-FJ4NXKTB.js → info-47VB62MV.js} +5 -5
  149. package/dist/job-backend-CgC8Xf33.d.ts +68 -0
  150. package/dist/{lib-NL5JXGEB.js → lib-NST3PNZX.js} +31 -31
  151. package/dist/lib-NST3PNZX.js.map +1 -0
  152. package/dist/module-loader-Cfz7dgCP.d.ts +26 -0
  153. package/dist/{netlify-5VQ22Z2P.js → netlify-GSNSJGMN.js} +3 -3
  154. package/dist/{node-3APTLGWB.js → node-6I5B6RL3.js} +3 -3
  155. package/dist/node-6I5B6RL3.js.map +1 -0
  156. package/dist/{openapi-SOKZTFE3.js → openapi-NFLSNNVQ.js} +10 -10
  157. package/dist/plugin-runner-BGBkzgi0.d.ts +95 -0
  158. package/dist/plugin-types-DNJGxr4Z.d.ts +79 -0
  159. package/dist/{proper-lockfile-4Y3DP3RP.js → proper-lockfile-MVKMQGFK.js} +27 -27
  160. package/dist/proper-lockfile-MVKMQGFK.js.map +1 -0
  161. package/dist/rate-limit-BdNDZ3vt.d.ts +58 -0
  162. package/dist/registry-QHEZ3BWB.js +25 -0
  163. package/dist/router-RGZFX75G.js +274 -0
  164. package/dist/router-RGZFX75G.js.map +1 -0
  165. package/dist/{routes-XVRAUH6H.js → routes-3A4XGIEJ.js} +6 -6
  166. package/dist/{scan-C2BOKLSY.js → scan-NQFI5S7P.js} +2 -2
  167. package/dist/scan-NQFI5S7P.js.map +1 -0
  168. package/dist/schema-D3v8VB7o.d.ts +76 -0
  169. package/dist/{schema-VR6YNVLQ.js → schema-KZVOV333.js} +5 -3
  170. package/dist/schema-KZVOV333.js.map +1 -0
  171. package/dist/server/agent/index.d.ts +229 -0
  172. package/dist/server/agent/index.js +16 -0
  173. package/dist/server/agent/index.js.map +1 -0
  174. package/dist/server/auth/index.d.ts +46 -1
  175. package/dist/server/auth/index.js +10 -3
  176. package/dist/server/cost/index.d.ts +1 -3
  177. package/dist/server/cost/index.js +1 -1
  178. package/dist/server/cron/index.js +4 -2
  179. package/dist/server/define/index.d.ts +281 -0
  180. package/dist/server/define/index.js +26 -0
  181. package/dist/server/define/index.js.map +1 -0
  182. package/dist/server/http/index.d.ts +10 -0
  183. package/dist/server/http/index.js +74 -0
  184. package/dist/server/http/index.js.map +1 -0
  185. package/dist/server/index.d.ts +151 -1677
  186. package/dist/server/index.js +558 -1102
  187. package/dist/server/index.js.map +1 -1
  188. package/dist/server/jobs/index.d.ts +348 -2
  189. package/dist/server/jobs/index.js +5 -3
  190. package/dist/server/observability/index.d.ts +324 -0
  191. package/dist/server/observability/index.js +48 -0
  192. package/dist/server/observability/index.js.map +1 -0
  193. package/dist/server/plugins/index.d.ts +17 -0
  194. package/dist/server/plugins/index.js +17 -0
  195. package/dist/server/plugins/index.js.map +1 -0
  196. package/dist/server/rate-limit/index.d.ts +105 -0
  197. package/dist/server/rate-limit/index.js +25 -0
  198. package/dist/server/rate-limit/index.js.map +1 -0
  199. package/dist/server/realtime/index.d.ts +15 -0
  200. package/dist/server/realtime/index.js +8 -0
  201. package/dist/server/realtime/index.js.map +1 -0
  202. package/dist/server/scan/index.d.ts +106 -0
  203. package/dist/server/scan/index.js +43 -0
  204. package/dist/server/scan/index.js.map +1 -0
  205. package/dist/server/security/index.d.ts +193 -0
  206. package/dist/server/security/index.js +50 -0
  207. package/dist/server/security/index.js.map +1 -0
  208. package/dist/server/storage/index.d.ts +22 -0
  209. package/dist/server/storage/index.js +14 -0
  210. package/dist/server/storage/index.js.map +1 -0
  211. package/dist/server/webhook/index.d.ts +148 -0
  212. package/dist/server/webhook/index.js +19 -0
  213. package/dist/server/webhook/index.js.map +1 -0
  214. package/dist/server-error-to-envelope-NO4CCAFQ.js +8 -0
  215. package/dist/server-error-to-envelope-NO4CCAFQ.js.map +1 -0
  216. package/dist/server-error-to-envelope-UJK6OWDJ.js +134 -0
  217. package/dist/server-error-to-envelope-UJK6OWDJ.js.map +1 -0
  218. package/dist/server-routes-hmr-GZJGPWMS.js +44 -0
  219. package/dist/server-routes-hmr-GZJGPWMS.js.map +1 -0
  220. package/dist/server-routes-hmr-PBHSKCQJ.js +42 -0
  221. package/dist/server-routes-hmr-PBHSKCQJ.js.map +1 -0
  222. package/dist/services-json-Z2QNGVPW.js +142 -0
  223. package/dist/services-json-Z2QNGVPW.js.map +1 -0
  224. package/dist/{services-typed-client-XWYYBWGW.js → services-typed-client-KK6RHRDG.js} +2 -2
  225. package/dist/{services-typed-client-ZX5JUHH3.js → services-typed-client-T7M5VPBP.js} +2 -2
  226. package/dist/{sqlite-vec-ARPNUBWT.js → sqlite-vec-54KB4RD3.js} +2 -2
  227. package/dist/sqlite-vec-54KB4RD3.js.map +1 -0
  228. package/dist/{start-R7XSQL5L.js → start-CGSZPBAG.js} +23 -23
  229. package/dist/start-CGSZPBAG.js.map +1 -0
  230. package/dist/{static-TZBVBDTB.js → static-QI5NQT2X.js} +6 -6
  231. package/dist/storage-manager-C4jsO0Tp.d.ts +89 -0
  232. package/dist/storage-manager-D5KBXXKB.js +0 -0
  233. package/dist/{storage-types-DtIVejC1.d.ts → storage-types-DsDTCPbp.d.ts} +1 -1
  234. package/dist/{theo-cloud-3K4DGB3S.js → theo-cloud-RSQCBNXL.js} +4 -4
  235. package/dist/theo-cloud-RSQCBNXL.js.map +1 -0
  236. package/dist/upgrade-readiness-GUJBCJIS.js +0 -0
  237. package/dist/{vercel-MWW24ABC.js → vercel-TKPZK62A.js} +3 -3
  238. package/dist/vite-plugin/index.d.ts +3 -1
  239. package/dist/vite-plugin/index.js +20 -8
  240. package/dist/{vite-plugin-6MPHTKIW.js → vite-plugin-CR4JDFUQ.js} +9 -9
  241. package/dist/vite-plugin-CR4JDFUQ.js.map +1 -0
  242. package/package.json +59 -10
  243. package/LICENSE +0 -201
  244. package/dist/build-MREW6MVS.js.map +0 -1
  245. package/dist/chunk-2BQYEBCK.js.map +0 -1
  246. package/dist/chunk-5OFPQK6N.js.map +0 -1
  247. package/dist/chunk-5OKZY2VL.js.map +0 -1
  248. package/dist/chunk-64JI5LTO.js.map +0 -1
  249. package/dist/chunk-7TOMTMHT.js.map +0 -1
  250. package/dist/chunk-C52GSJPF.js.map +0 -1
  251. package/dist/chunk-CZM6WWWS.js +0 -2450
  252. package/dist/chunk-CZM6WWWS.js.map +0 -1
  253. package/dist/chunk-KJVEJILQ.js.map +0 -1
  254. package/dist/chunk-O4BLVPML.js.map +0 -1
  255. package/dist/chunk-O7335ZGH.js.map +0 -1
  256. package/dist/chunk-PB4GR7EP.js.map +0 -1
  257. package/dist/chunk-SNDZQ64K.js.map +0 -1
  258. package/dist/chunk-TPCT3MXV.js.map +0 -1
  259. package/dist/chunk-VRHXOKRP.js.map +0 -1
  260. package/dist/chunk-WZ7CPVQB.js.map +0 -1
  261. package/dist/chunk-X2OLD264.js.map +0 -1
  262. package/dist/chunk-X4JAX2U3.js.map +0 -1
  263. package/dist/chunk-XP7YXRHO.js.map +0 -1
  264. package/dist/chunk-YLBSSEHX.js.map +0 -1
  265. package/dist/chunk-ZOXNJV2O.js.map +0 -1
  266. package/dist/dev-emit-MLDFOLUU.js.map +0 -1
  267. package/dist/dispatcher-E6QV32BO.js.map +0 -1
  268. package/dist/dist-E6BL4ZVY.js.map +0 -1
  269. package/dist/generate-DT4IIAHF.js.map +0 -1
  270. package/dist/index-li83Swxa.d.ts +0 -506
  271. package/dist/lib-NL5JXGEB.js.map +0 -1
  272. package/dist/proper-lockfile-4Y3DP3RP.js.map +0 -1
  273. package/dist/registry-5QFTLOL2.js +0 -25
  274. package/dist/schema-CjVly9c_.d.ts +0 -274
  275. package/dist/sqlite-vec-ARPNUBWT.js.map +0 -1
  276. package/dist/start-R7XSQL5L.js.map +0 -1
  277. package/dist/theo-cloud-3K4DGB3S.js.map +0 -1
  278. /package/dist/{actions-virtual-module-HWNTIEPI.js.map → actions-virtual-module-IY46EEEX.js.map} +0 -0
  279. /package/dist/{actions-virtual-module-SEIPACG5.js.map → actions-virtual-module-XNHDNCZ6.js.map} +0 -0
  280. /package/dist/{aws-lambda-XYCGZH3I.js.map → aws-lambda-GKSTX6HD.js.map} +0 -0
  281. /package/dist/{bun-K73TQEWC.js.map → bun-ISHSNFIO.js.map} +0 -0
  282. /package/dist/{check-PZR67OY5.js.map → check-NXYPLM6M.js.map} +0 -0
  283. /package/dist/{dispatcher-AQJGI3HU.js.map → chunk-E3JH6YUM.js.map} +0 -0
  284. /package/dist/{node-3APTLGWB.js.map → chunk-JHEAWR3L.js.map} +0 -0
  285. /package/dist/{chunk-ZJW5FFYJ.js.map → chunk-LC5PYNJP.js.map} +0 -0
  286. /package/dist/{chunk-YWWHK7R6.js.map → chunk-MR7OLIC6.js.map} +0 -0
  287. /package/dist/{scan-C2BOKLSY.js.map → chunk-NPMCKOX4.js.map} +0 -0
  288. /package/dist/{chunk-BE2LKDI7.js.map → chunk-WEGALZEU.js.map} +0 -0
  289. /package/dist/{cloudflare-LCAOTRYZ.js.map → cloudflare-OJGJ7R2D.js.map} +0 -0
  290. /package/dist/{schema-VR6YNVLQ.js.map → cookies-MJKMGJ7N.js.map} +0 -0
  291. /package/dist/{deno-deploy-ZN4RE5HF.js.map → deno-deploy-BHWKFTOW.js.map} +0 -0
  292. /package/dist/{dev-6P2DM33Q.js.map → dev-MJVSRZGF.js.map} +0 -0
  293. /package/dist/{dev-emit-PRSRPDHA.js.map → dev-emit-HHP2XJXE.js.map} +0 -0
  294. /package/dist/{vite-plugin-6MPHTKIW.js.map → dispatcher-63LBXYLE.js.map} +0 -0
  295. /package/dist/{info-FJ4NXKTB.js.map → info-47VB62MV.js.map} +0 -0
  296. /package/dist/{netlify-5VQ22Z2P.js.map → netlify-GSNSJGMN.js.map} +0 -0
  297. /package/dist/{openapi-SOKZTFE3.js.map → openapi-NFLSNNVQ.js.map} +0 -0
  298. /package/dist/{registry-5QFTLOL2.js.map → registry-QHEZ3BWB.js.map} +0 -0
  299. /package/dist/{routes-XVRAUH6H.js.map → routes-3A4XGIEJ.js.map} +0 -0
  300. /package/dist/{services-typed-client-XWYYBWGW.js.map → services-typed-client-KK6RHRDG.js.map} +0 -0
  301. /package/dist/{services-typed-client-ZX5JUHH3.js.map → services-typed-client-T7M5VPBP.js.map} +0 -0
  302. /package/dist/{static-TZBVBDTB.js.map → static-QI5NQT2X.js.map} +0 -0
  303. /package/dist/{vercel-MWW24ABC.js.map → vercel-TKPZK62A.js.map} +0 -0
@@ -0,0 +1,185 @@
1
+ import {
2
+ InMemoryStore
3
+ } from "./chunk-VMEWD57H.js";
4
+ import {
5
+ parseCookieHeader
6
+ } from "./chunk-ZJQ4O76G.js";
7
+
8
+ // src/server/rate-limit/rate-limit-per-route.ts
9
+ function normalizePath(input) {
10
+ const noQuery = input.split("?")[0];
11
+ if (noQuery.length > 1 && noQuery.endsWith("/")) return noQuery.slice(0, -1);
12
+ return noQuery;
13
+ }
14
+ function matchRoutePattern(path, pattern) {
15
+ const canonical = normalizePath(path);
16
+ if (typeof pattern === "string") {
17
+ return canonical === normalizePath(pattern);
18
+ }
19
+ pattern.lastIndex = 0;
20
+ return pattern.test(canonical);
21
+ }
22
+ async function hashFragment(input) {
23
+ const buf = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(input));
24
+ const bytes = new Uint8Array(buf);
25
+ let bin = "";
26
+ for (const b of bytes) bin += String.fromCharCode(b);
27
+ const b64url = btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
28
+ return b64url.slice(0, 16);
29
+ }
30
+ function readCookie(req, name) {
31
+ return parseCookieHeader(req.headers.cookie ?? void 0).get(name);
32
+ }
33
+ async function deriveKey(req, keyBy, cookieName) {
34
+ if (typeof keyBy === "function") return keyBy(req);
35
+ const ip = req.socket?.remoteAddress ?? "unknown";
36
+ switch (keyBy) {
37
+ case "session": {
38
+ const cookie = readCookie(req, cookieName);
39
+ return cookie ? `session:${await hashFragment(cookie)}` : `ip:${ip}`;
40
+ }
41
+ case "user": {
42
+ const userId = req.user?.id;
43
+ return userId ? `user:${userId}` : `ip:${ip}`;
44
+ }
45
+ case "ip":
46
+ default:
47
+ return `ip:${ip}`;
48
+ }
49
+ }
50
+ function createRouteRateLimiter(config) {
51
+ const isFlat = "windowMs" in config && "max" in config && !("default" in config) && !("routes" in config);
52
+ const cfg = isFlat ? { default: config } : config;
53
+ const store = cfg.store ?? new InMemoryStore();
54
+ if (!(store instanceof InMemoryStore)) {
55
+ throw new Error(
56
+ "createRouteRateLimiter: async RateLimitStore implementations require a dedicated async middleware path. Use the InMemoryStore default for the sync fa\xE7ade."
57
+ );
58
+ }
59
+ const inMemoryStore = store;
60
+ const keyBy = cfg.keyBy ?? "ip";
61
+ const cookieName = cfg.cookieName ?? "theo_session";
62
+ const patternList = [];
63
+ if (cfg.routes) {
64
+ for (const [pattern, c] of Object.entries(cfg.routes)) patternList.push([pattern, c]);
65
+ }
66
+ if (cfg.routePatterns) {
67
+ for (const tuple of cfg.routePatterns) patternList.push(tuple);
68
+ }
69
+ return async function checkRouteRateLimit(req) {
70
+ const url = req.url ?? "";
71
+ let matched;
72
+ for (const [pattern, c] of patternList) {
73
+ if (matchRoutePattern(url, pattern)) {
74
+ matched = c;
75
+ break;
76
+ }
77
+ }
78
+ const effective = matched ?? cfg.default;
79
+ if (!effective) {
80
+ return { limited: false, headers: {} };
81
+ }
82
+ const bucketSuffix = typeof matched === "undefined" ? "*default*" : normalizePath(url);
83
+ const key = `${await deriveKey(req, keyBy, cookieName)}|${bucketSuffix}`;
84
+ const state = inMemoryStore.incrSync(key, effective.windowMs);
85
+ if (state.count > effective.max) {
86
+ const retryAfter = Math.ceil((state.resetAt - Date.now()) / 1e3);
87
+ return {
88
+ limited: true,
89
+ headers: {
90
+ "X-RateLimit-Limit": String(effective.max),
91
+ "X-RateLimit-Remaining": "0",
92
+ "Retry-After": String(retryAfter)
93
+ }
94
+ };
95
+ }
96
+ return {
97
+ limited: false,
98
+ headers: {
99
+ "X-RateLimit-Limit": String(effective.max),
100
+ "X-RateLimit-Remaining": String(Math.max(0, effective.max - state.count))
101
+ }
102
+ };
103
+ };
104
+ }
105
+ async function deriveKeyFromRequest(request, keyBy, cookieName, ctx = {}) {
106
+ const ip = ctx.clientIp ?? "unknown";
107
+ switch (keyBy) {
108
+ case "session": {
109
+ const { getCookieFromRequest } = await import("./cookies-MJKMGJ7N.js");
110
+ const cookie = getCookieFromRequest(request, cookieName);
111
+ return cookie ? `session:${await hashFragment(cookie)}` : `ip:${ip}`;
112
+ }
113
+ case "user": {
114
+ return ctx.userId ? `user:${ctx.userId}` : `ip:${ip}`;
115
+ }
116
+ case "ip":
117
+ default:
118
+ return `ip:${ip}`;
119
+ }
120
+ }
121
+ function createRouteRateLimiterWeb(config) {
122
+ const isFlat = "windowMs" in config && "max" in config && !("default" in config) && !("routes" in config);
123
+ const cfg = isFlat ? { default: config } : config;
124
+ const store = cfg.store ?? new InMemoryStore();
125
+ if (!(store instanceof InMemoryStore)) {
126
+ throw new Error(
127
+ "createRouteRateLimiterWeb: async RateLimitStore implementations require a dedicated async middleware path. Use the InMemoryStore default for the Web fa\xE7ade."
128
+ );
129
+ }
130
+ const inMemoryStore = store;
131
+ const keyBy = cfg.keyBy ?? "ip";
132
+ const cookieName = cfg.cookieName ?? "theo_session";
133
+ const patternList = [];
134
+ if (cfg.routes) {
135
+ for (const [pattern, c] of Object.entries(cfg.routes)) patternList.push([pattern, c]);
136
+ }
137
+ if (cfg.routePatterns) {
138
+ for (const tuple of cfg.routePatterns) patternList.push(tuple);
139
+ }
140
+ return async function checkRouteRateLimitWeb(request, ctx = {}) {
141
+ const parsed = new URL(request.url);
142
+ const url = `${parsed.pathname}${parsed.search}`;
143
+ let matched;
144
+ for (const [pattern, c] of patternList) {
145
+ if (matchRoutePattern(url, pattern)) {
146
+ matched = c;
147
+ break;
148
+ }
149
+ }
150
+ const effective = matched ?? cfg.default;
151
+ if (!effective) {
152
+ return { limited: false, headers: {} };
153
+ }
154
+ const bucketSuffix = typeof matched === "undefined" ? "*default*" : normalizePath(url);
155
+ const key = `${await deriveKeyFromRequest(request, keyBy, cookieName, ctx)}|${bucketSuffix}`;
156
+ const state = inMemoryStore.incrSync(key, effective.windowMs);
157
+ if (state.count > effective.max) {
158
+ const retryAfter = Math.ceil((state.resetAt - Date.now()) / 1e3);
159
+ return {
160
+ limited: true,
161
+ headers: {
162
+ "X-RateLimit-Limit": String(effective.max),
163
+ "X-RateLimit-Remaining": "0",
164
+ "Retry-After": String(retryAfter)
165
+ }
166
+ };
167
+ }
168
+ return {
169
+ limited: false,
170
+ headers: {
171
+ "X-RateLimit-Limit": String(effective.max),
172
+ "X-RateLimit-Remaining": String(Math.max(0, effective.max - state.count))
173
+ }
174
+ };
175
+ };
176
+ }
177
+
178
+ export {
179
+ matchRoutePattern,
180
+ deriveKey,
181
+ createRouteRateLimiter,
182
+ deriveKeyFromRequest,
183
+ createRouteRateLimiterWeb
184
+ };
185
+ //# sourceMappingURL=chunk-ASDXVRJD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server/rate-limit/rate-limit-per-route.ts"],"sourcesContent":["// T5a.1d — Web Crypto migration. The last node:crypto consumer in server/.\n// `createHash('sha256')` is sync but Web Crypto's `subtle.digest('SHA-256', ...)`\n// is async. This propagates through hashFragment → deriveKey → the factory's\n// returned checker. createRouteRateLimiter has NO production consumers\n// (verified via grep; api-middleware uses the sibling createRateLimiter from\n// rate-limit.ts), so the cascade only affects test sites. IncomingMessage stays\n// as a type-only import (TS-erased; runtime-clean).\nimport type { IncomingMessage } from 'node:http'\n\nimport { parseCookieHeader } from '../http/cookies.js'\n\nimport { InMemoryStore, type RateLimitStore } from './rate-limit-store.js'\nimport type { RateLimitConfig, RateLimitResult } from './rate-limit.js'\n\n/**\n * T2.2 — Per-route + per-user rate limiting.\n *\n * Layered on top of `rate-limit-store.ts`. The route map allows\n * declarative policies (\"strict /api/login, loose everything else\")\n * driven by config, not handler-decorated. `keyBy` selects what\n * identifier the limiter buckets on.\n *\n * ADR D2: per-route via path matching, NOT per-handler decorator.\n * Operators can tune policies without touching route definitions.\n */\n\nexport type KeyByMode = 'ip' | 'session' | 'user' | ((req: IncomingMessage) => string)\n\nexport interface RouteRateLimitConfig {\n /** Fallback config used when no per-route entry matches. */\n default?: RateLimitConfig\n /** Map of path pattern → config. Exact-string keys (RegExp via API). */\n routes?: Record<string, RateLimitConfig>\n /** Same as `routes` but each entry is a [pattern, config] tuple, RegExp allowed. */\n routePatterns?: readonly [string | RegExp, RateLimitConfig][]\n /** Bucket identifier strategy. Default 'ip'. */\n keyBy?: KeyByMode\n /** Cookie name used by keyBy='session'. Defaults to 'theo_session'. */\n cookieName?: string\n /** Optional shared store (for multi-route correlation). Default per-limiter InMemoryStore. */\n store?: RateLimitStore\n}\n\n/**\n * Normalize a path for matching: strip query string, drop trailing slash\n * unless root. EC-5: `/api/login` and `/api/login/` collapse to the same\n * canonical form so attackers can't bypass strict limits.\n */\nfunction normalizePath(input: string): string {\n const noQuery = input.split('?')[0]\n if (noQuery.length > 1 && noQuery.endsWith('/')) return noQuery.slice(0, -1)\n return noQuery\n}\n\n/**\n * Test whether `path` matches `pattern`. String patterns are compared\n * after trailing-slash normalization (EC-5). RegExp uses `.test` after\n * resetting `lastIndex` (defensive against `/g` flag).\n */\nexport function matchRoutePattern(path: string, pattern: string | RegExp): boolean {\n const canonical = normalizePath(path)\n if (typeof pattern === 'string') {\n return canonical === normalizePath(pattern)\n }\n pattern.lastIndex = 0\n return pattern.test(canonical)\n}\n\n/**\n * Hash a string with SHA-256 and return the first 16 base64url chars.\n * Used by `keyBy='session'` so the raw cookie value never lands in a\n * rate-limit key (which may flow into audit logs).\n *\n * T5a.1d — async via Web Crypto subtle.digest (no node:crypto). The\n * base64url encoding is done manually because btoa+url-safe transform is\n * available everywhere but `digest('base64url')` is Node-only.\n */\nasync function hashFragment(input: string): Promise<string> {\n const buf = await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(input))\n const bytes = new Uint8Array(buf)\n let bin = ''\n for (const b of bytes) bin += String.fromCharCode(b)\n // eslint-disable-next-line sonarjs/slow-regex -- input is fixed-length 44 chars (SHA-256 base64), trailing '=' padding ≤ 2 chars, no ReDoS surface\n const b64url = btoa(bin).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n return b64url.slice(0, 16)\n}\n\n// T3.2 DRY consolidation: cookie parsing moved to ../http/cookies.ts.\n// The canonical `parseCookieHeader` returns a Map for O(1) lookup; this\n// wrapper preserves the original `readCookie(req, name)` signature so the\n// rest of the file stays untouched.\nfunction readCookie(req: IncomingMessage, name: string): string | undefined {\n return parseCookieHeader(req.headers.cookie ?? undefined).get(name)\n}\n\n/**\n * Build the rate-limit bucket key for the request based on `keyBy`.\n *\n * EC-6: session mode reads the configured `cookieName`. With the wrong\n * cookie name (e.g., default 'theo_session' but app uses 'app_session'),\n * we fall back to IP so anonymous users still get rate-limited rather\n * than sharing an empty bucket.\n */\nexport async function deriveKey(\n req: IncomingMessage,\n keyBy: KeyByMode,\n cookieName: string,\n): Promise<string> {\n if (typeof keyBy === 'function') return keyBy(req)\n // `req.socket` is typed as always-present in Node typings, but in test\n // doubles (object literals without `socket`) it can be missing — the\n // optional chain keeps the fallback path reachable.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- defensive for test doubles\n const ip = req.socket?.remoteAddress ?? 'unknown'\n switch (keyBy) {\n case 'session': {\n const cookie = readCookie(req, cookieName)\n return cookie ? `session:${await hashFragment(cookie)}` : `ip:${ip}`\n }\n case 'user': {\n const userId = (req as unknown as { user?: { id?: string } }).user?.id\n return userId ? `user:${userId}` : `ip:${ip}`\n }\n case 'ip':\n default:\n return `ip:${ip}`\n }\n}\n\n/**\n * Per-route rate limiter factory. Returns a sync checker compatible with\n * the existing api-middleware shape.\n *\n * Backwards-compatibility (ADR D2): a flat `{ windowMs, max }` config is\n * accepted and treated as `default` (no per-route variants).\n */\nexport function createRouteRateLimiter(config: RouteRateLimitConfig | RateLimitConfig) {\n // Detect legacy flat shape\n const isFlat =\n 'windowMs' in config && 'max' in config && !('default' in config) && !('routes' in config)\n const cfg: RouteRateLimitConfig = isFlat ? { default: config } : config\n\n const store = cfg.store ?? new InMemoryStore()\n // CR-005: validate store shape ONCE at construction. The previous\n // implementation ran `instanceof InMemoryStore` on every request and\n // threw at request-time if a non-InMemoryStore was passed — which\n // turned a clear config error into a runtime 500 on the first request.\n if (!(store instanceof InMemoryStore)) {\n throw new Error(\n 'createRouteRateLimiter: async RateLimitStore implementations require a dedicated async middleware path. ' +\n 'Use the InMemoryStore default for the sync façade.',\n )\n }\n const inMemoryStore = store\n const keyBy = cfg.keyBy ?? 'ip'\n const cookieName = cfg.cookieName ?? 'theo_session'\n\n // Build a pre-compiled list of (pattern, config) tuples for matching.\n const patternList: [string | RegExp, RateLimitConfig][] = []\n if (cfg.routes) {\n for (const [pattern, c] of Object.entries(cfg.routes)) patternList.push([pattern, c])\n }\n if (cfg.routePatterns) {\n for (const tuple of cfg.routePatterns) patternList.push(tuple)\n }\n\n return async function checkRouteRateLimit(req: IncomingMessage): Promise<RateLimitResult> {\n const url = req.url ?? ''\n let matched: RateLimitConfig | undefined\n for (const [pattern, c] of patternList) {\n if (matchRoutePattern(url, pattern)) {\n matched = c\n break\n }\n }\n const effective = matched ?? cfg.default\n if (!effective) {\n // No route match + no default → not limited.\n return { limited: false, headers: {} }\n }\n\n // Bucket key includes normalized path so /api/login and /api/login/\n // collapse to the same bucket (EC-5).\n const bucketSuffix = typeof matched === 'undefined' ? '*default*' : normalizePath(url)\n const key = `${await deriveKey(req, keyBy, cookieName)}|${bucketSuffix}`\n const state = inMemoryStore.incrSync(key, effective.windowMs)\n\n if (state.count > effective.max) {\n const retryAfter = Math.ceil((state.resetAt - Date.now()) / 1000)\n return {\n limited: true,\n headers: {\n 'X-RateLimit-Limit': String(effective.max),\n 'X-RateLimit-Remaining': '0',\n 'Retry-After': String(retryAfter),\n },\n }\n }\n return {\n limited: false,\n headers: {\n 'X-RateLimit-Limit': String(effective.max),\n 'X-RateLimit-Remaining': String(Math.max(0, effective.max - state.count)),\n },\n }\n }\n}\n\n/**\n * T5a.2 Phase D slice 1/3 — Web-Standards rate-limiter inputs context.\n *\n * Web `Request` has no equivalent of `req.socket.remoteAddress` (Node\n * runtime concept) or `req.user` (set by upstream middleware). The\n * Web-shaped rate-limiter requires the caller to pass these explicitly:\n *\n * - `clientIp` — resolved per-runtime (Node: `socket.remoteAddress`;\n * CF Workers: `request.headers.get('cf-connecting-ip')`; Vercel:\n * `x-forwarded-for` first hop; Bun/Deno: adapter-specific).\n * - `userId` — resolved by auth middleware (Phase D slice 3/3 ships\n * the Web-shaped session helper).\n *\n * Defaults: `clientIp = 'unknown'`, `userId = undefined` (matches the\n * IncomingMessage path's fallback semantics).\n */\nexport interface DeriveKeyRequestContext {\n clientIp?: string\n userId?: string\n}\n\n/**\n * T5a.2 Phase D slice 1/3 — Web-Standards-shaped key derivation.\n *\n * Mirror of `deriveKey(req: IncomingMessage, keyBy, cookieName)` for the\n * Web `Request` shape. Same `'ip' | 'session' | 'user'` enum cases (the\n * `function` callback case is IncomingMessage-only because the existing\n * `KeyByMode` callback type is Node-shaped; Web callers use the enum\n * cases or call a future `KeyByModeWeb` shape — out of T5a.2 Phase D scope).\n *\n * Uses `getCookieFromRequest` (Phase B slice 6/6) for session-mode cookie\n * lookup. Cookie parsing has the same CR-009 percent-encoding safety.\n */\nexport async function deriveKeyFromRequest(\n request: Request,\n keyBy: Exclude<KeyByMode, (req: IncomingMessage) => string>,\n cookieName: string,\n ctx: DeriveKeyRequestContext = {},\n): Promise<string> {\n const ip = ctx.clientIp ?? 'unknown'\n switch (keyBy) {\n case 'session': {\n // Reuse the Web cookie helper extracted in Phase B slice 6/6 so\n // CR-009 percent-encoding sanity stays consistent across paths.\n const { getCookieFromRequest } = await import('../http/cookies.js')\n const cookie = getCookieFromRequest(request, cookieName)\n return cookie ? `session:${await hashFragment(cookie)}` : `ip:${ip}`\n }\n case 'user': {\n return ctx.userId ? `user:${ctx.userId}` : `ip:${ip}`\n }\n case 'ip':\n default:\n return `ip:${ip}`\n }\n}\n\n/**\n * T5a.2 Phase D slice 1/3 — Web-Standards rate-limiter factory.\n *\n * Mirror of `createRouteRateLimiter(config)` returning a checker that\n * accepts `(request: Request, ctx?: DeriveKeyRequestContext)` instead of\n * `(req: IncomingMessage)`. Same `RouteRateLimitConfig` accepted; same\n * `keyBy` enum cases; same `InMemoryStore` constraint (CR-005 guard).\n *\n * Same returned `RateLimitResult` shape (headers + limited boolean).\n *\n * Web `Request` has no `req.url` path-only property — uses\n * `new URL(request.url).pathname + search` to derive the URL the way the\n * IncomingMessage path's `req.url ?? ''` would.\n */\nexport function createRouteRateLimiterWeb(config: RouteRateLimitConfig | RateLimitConfig) {\n const isFlat =\n 'windowMs' in config && 'max' in config && !('default' in config) && !('routes' in config)\n const cfg: RouteRateLimitConfig = isFlat ? { default: config } : config\n\n const store = cfg.store ?? new InMemoryStore()\n if (!(store instanceof InMemoryStore)) {\n throw new Error(\n 'createRouteRateLimiterWeb: async RateLimitStore implementations require a dedicated async middleware path. ' +\n 'Use the InMemoryStore default for the Web façade.',\n )\n }\n const inMemoryStore = store\n const keyBy = (cfg.keyBy ?? 'ip') as Exclude<KeyByMode, (req: IncomingMessage) => string>\n const cookieName = cfg.cookieName ?? 'theo_session'\n\n const patternList: [string | RegExp, RateLimitConfig][] = []\n if (cfg.routes) {\n for (const [pattern, c] of Object.entries(cfg.routes)) patternList.push([pattern, c])\n }\n if (cfg.routePatterns) {\n for (const tuple of cfg.routePatterns) patternList.push(tuple)\n }\n\n return async function checkRouteRateLimitWeb(\n request: Request,\n ctx: DeriveKeyRequestContext = {},\n ): Promise<RateLimitResult> {\n // Web Request guarantees absolute URL — extract path+query for pattern\n // matching (mirror of IncomingMessage's `req.url ?? ''`).\n const parsed = new URL(request.url)\n const url = `${parsed.pathname}${parsed.search}`\n let matched: RateLimitConfig | undefined\n for (const [pattern, c] of patternList) {\n if (matchRoutePattern(url, pattern)) {\n matched = c\n break\n }\n }\n const effective = matched ?? cfg.default\n if (!effective) {\n return { limited: false, headers: {} }\n }\n\n const bucketSuffix = typeof matched === 'undefined' ? '*default*' : normalizePath(url)\n const key = `${await deriveKeyFromRequest(request, keyBy, cookieName, ctx)}|${bucketSuffix}`\n const state = inMemoryStore.incrSync(key, effective.windowMs)\n\n if (state.count > effective.max) {\n const retryAfter = Math.ceil((state.resetAt - Date.now()) / 1000)\n return {\n limited: true,\n headers: {\n 'X-RateLimit-Limit': String(effective.max),\n 'X-RateLimit-Remaining': '0',\n 'Retry-After': String(retryAfter),\n },\n }\n }\n return {\n limited: false,\n headers: {\n 'X-RateLimit-Limit': String(effective.max),\n 'X-RateLimit-Remaining': String(Math.max(0, effective.max - state.count)),\n },\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,406 @@
1
+ import {
2
+ safeAudit
3
+ } from "./chunk-UD3LFGDL.js";
4
+
5
+ // src/server/security/csrf-readiness-store.ts
6
+ var CsrfReadinessStore = class _CsrfReadinessStore {
7
+ static MAX_ENTRIES = 1e3;
8
+ entries = /* @__PURE__ */ new Map();
9
+ keyFor(event) {
10
+ return `${event.method}\0${event.path}\0${event.reason}`;
11
+ }
12
+ record(event) {
13
+ const key = this.keyFor(event);
14
+ const now = (/* @__PURE__ */ new Date()).toISOString();
15
+ const existing = this.entries.get(key);
16
+ if (existing) {
17
+ existing.count++;
18
+ existing.lastSeen = now;
19
+ return;
20
+ }
21
+ if (this.entries.size >= _CsrfReadinessStore.MAX_ENTRIES) {
22
+ const firstKey = this.entries.keys().next().value;
23
+ if (firstKey !== void 0) this.entries.delete(firstKey);
24
+ }
25
+ this.entries.set(key, { count: 1, firstSeen: now, lastSeen: now });
26
+ }
27
+ summary() {
28
+ let total = 0;
29
+ const routes = [];
30
+ for (const [key, entry] of this.entries) {
31
+ const [method, path, reason] = key.split("\0");
32
+ routes.push({
33
+ method,
34
+ path,
35
+ reason,
36
+ count: entry.count,
37
+ firstSeen: entry.firstSeen,
38
+ lastSeen: entry.lastSeen
39
+ });
40
+ total += entry.count;
41
+ }
42
+ return {
43
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
44
+ totalEvents: total,
45
+ routes
46
+ };
47
+ }
48
+ reset() {
49
+ this.entries.clear();
50
+ }
51
+ };
52
+
53
+ // src/server/security/csp-report.ts
54
+ var CSP_REPORT_PATH = "/__theo/csp-report";
55
+ var MAX_BODY = 16 * 1024;
56
+ function pickHeader(value) {
57
+ if (typeof value === "string") return value;
58
+ if (Array.isArray(value) && value.length > 0) return value[0];
59
+ return "";
60
+ }
61
+ function toStringSafe(value, fallback = "(missing)") {
62
+ if (typeof value === "string") return value;
63
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
64
+ return fallback;
65
+ }
66
+ function normalizeLegacy(raw) {
67
+ return {
68
+ blockedUrl: toStringSafe(raw["blocked-uri"]),
69
+ documentUrl: toStringSafe(raw["document-uri"]),
70
+ violatedDirective: toStringSafe(raw["violated-directive"]),
71
+ effectiveDirective: typeof raw["effective-directive"] === "string" ? raw["effective-directive"] : void 0,
72
+ originalPolicy: typeof raw["original-policy"] === "string" ? raw["original-policy"] : void 0,
73
+ disposition: raw.disposition === "enforce" || raw.disposition === "report" ? raw.disposition : void 0,
74
+ statusCode: typeof raw["status-code"] === "number" ? raw["status-code"] : void 0,
75
+ sourceFile: typeof raw["source-file"] === "string" ? raw["source-file"] : void 0,
76
+ lineNumber: typeof raw["line-number"] === "number" ? raw["line-number"] : void 0,
77
+ columnNumber: typeof raw["column-number"] === "number" ? raw["column-number"] : void 0
78
+ };
79
+ }
80
+ function normalizeNew(entry) {
81
+ if (!entry || typeof entry !== "object") return null;
82
+ const body = entry.body;
83
+ if (!body || typeof body !== "object") return null;
84
+ const b = body;
85
+ return {
86
+ blockedUrl: toStringSafe(b.blockedURL),
87
+ documentUrl: toStringSafe(b.documentURL),
88
+ violatedDirective: toStringSafe(b.violatedDirective),
89
+ effectiveDirective: typeof b.effectiveDirective === "string" ? b.effectiveDirective : void 0,
90
+ originalPolicy: typeof b.originalPolicy === "string" ? b.originalPolicy : void 0,
91
+ disposition: b.disposition === "enforce" || b.disposition === "report" ? b.disposition : void 0,
92
+ statusCode: typeof b.statusCode === "number" ? b.statusCode : void 0,
93
+ sourceFile: typeof b.sourceFile === "string" ? b.sourceFile : void 0,
94
+ lineNumber: typeof b.lineNumber === "number" ? b.lineNumber : void 0,
95
+ columnNumber: typeof b.columnNumber === "number" ? b.columnNumber : void 0
96
+ };
97
+ }
98
+ async function readBody(req, maxBytes) {
99
+ return await new Promise((resolve, reject) => {
100
+ const chunks = [];
101
+ let total = 0;
102
+ req.on("data", (chunk) => {
103
+ total += chunk.length;
104
+ if (total > maxBytes) {
105
+ reject(new Error("body too large"));
106
+ req.destroy();
107
+ return;
108
+ }
109
+ chunks.push(chunk);
110
+ });
111
+ req.on("end", () => {
112
+ resolve(Buffer.concat(chunks).toString("utf8"));
113
+ });
114
+ req.on("error", reject);
115
+ });
116
+ }
117
+ async function handleCspReport(req, res, opts) {
118
+ const ctHeader = req.headers["content-type"];
119
+ const ct = pickHeader(ctHeader);
120
+ let raw;
121
+ try {
122
+ raw = await readBody(req, MAX_BODY);
123
+ } catch {
124
+ res.statusCode = 413;
125
+ res.end();
126
+ return;
127
+ }
128
+ let violations;
129
+ try {
130
+ if (ct.startsWith("application/csp-report")) {
131
+ const parsed = JSON.parse(raw);
132
+ const inner = parsed["csp-report"];
133
+ if (!inner || typeof inner !== "object") {
134
+ res.statusCode = 204;
135
+ res.end();
136
+ return;
137
+ }
138
+ violations = [normalizeLegacy(inner)];
139
+ } else if (ct.startsWith("application/reports+json")) {
140
+ const parsed = JSON.parse(raw);
141
+ const entries = Array.isArray(parsed) ? parsed : [];
142
+ violations = entries.map((e) => normalizeNew(e)).filter((v) => v !== null);
143
+ } else {
144
+ res.statusCode = 415;
145
+ res.end();
146
+ return;
147
+ }
148
+ } catch {
149
+ res.statusCode = 400;
150
+ res.end();
151
+ return;
152
+ }
153
+ for (const v of violations) {
154
+ safeAudit(opts.auditLogger, {
155
+ action: "csp.violation",
156
+ metadata: v
157
+ });
158
+ try {
159
+ opts.devtoolsDispatcher?.onCspViolation?.(v);
160
+ } catch {
161
+ }
162
+ try {
163
+ opts.onViolation?.(v);
164
+ } catch {
165
+ }
166
+ }
167
+ res.statusCode = 204;
168
+ res.end();
169
+ }
170
+ async function readBodyFromRequest(request, maxBytes) {
171
+ const contentLengthHeader = request.headers.get("content-length");
172
+ if (contentLengthHeader !== null) {
173
+ const declared = Number.parseInt(contentLengthHeader, 10);
174
+ if (Number.isFinite(declared) && declared > maxBytes) return null;
175
+ }
176
+ const text = await request.text();
177
+ if (text.length > maxBytes) return null;
178
+ return text;
179
+ }
180
+ function dispatchViolations(violations, opts) {
181
+ for (const v of violations) {
182
+ safeAudit(opts.auditLogger, {
183
+ action: "csp.violation",
184
+ metadata: v
185
+ });
186
+ try {
187
+ opts.devtoolsDispatcher?.onCspViolation?.(v);
188
+ } catch {
189
+ }
190
+ try {
191
+ opts.onViolation?.(v);
192
+ } catch {
193
+ }
194
+ }
195
+ }
196
+ async function handleCspReportRequest(request, opts) {
197
+ const ct = request.headers.get("content-type") ?? "";
198
+ const raw = await readBodyFromRequest(request, MAX_BODY);
199
+ if (raw === null) {
200
+ return new Response(null, { status: 413 });
201
+ }
202
+ let violations;
203
+ try {
204
+ if (ct.startsWith("application/csp-report")) {
205
+ const parsed = JSON.parse(raw);
206
+ const inner = parsed["csp-report"];
207
+ if (!inner || typeof inner !== "object") {
208
+ return new Response(null, { status: 204 });
209
+ }
210
+ violations = [normalizeLegacy(inner)];
211
+ } else if (ct.startsWith("application/reports+json")) {
212
+ const parsed = JSON.parse(raw);
213
+ const entries = Array.isArray(parsed) ? parsed : [];
214
+ violations = entries.map((e) => normalizeNew(e)).filter((v) => v !== null);
215
+ } else {
216
+ return new Response(null, { status: 415 });
217
+ }
218
+ } catch {
219
+ return new Response(null, { status: 400 });
220
+ }
221
+ dispatchViolations(violations, opts);
222
+ return new Response(null, { status: 204 });
223
+ }
224
+
225
+ // src/server/security/csrf-readiness-endpoint.ts
226
+ var CSRF_READINESS_PATH = "/__theo/csrf-readiness";
227
+ var CSRF_READINESS_RESET_PATH = "/__theo/csrf-readiness/reset";
228
+ function originMatchesHost(req) {
229
+ const origin = req.headers.origin;
230
+ if (typeof origin !== "string") return false;
231
+ const host = req.headers.host;
232
+ if (typeof host !== "string") return false;
233
+ try {
234
+ const parsed = new URL(origin);
235
+ return parsed.host === host;
236
+ } catch {
237
+ return false;
238
+ }
239
+ }
240
+ function sendJson(res, status, body) {
241
+ res.writeHead(status, { "content-type": "application/json" });
242
+ res.end(JSON.stringify(body));
243
+ }
244
+ function sendNoContent(res) {
245
+ res.writeHead(204);
246
+ res.end();
247
+ }
248
+ function sendError(res, status, code, message) {
249
+ res.writeHead(status, { "content-type": "application/json" });
250
+ res.end(JSON.stringify({ error: { code, message } }));
251
+ }
252
+ async function handleCsrfReadiness(req, res, store) {
253
+ const url = (req.url ?? "").split("?")[0];
254
+ const method = req.method ?? "GET";
255
+ if (url === CSRF_READINESS_PATH) {
256
+ if (method === "GET") {
257
+ sendJson(res, 200, store.summary());
258
+ return true;
259
+ }
260
+ sendError(res, 405, "METHOD_NOT_ALLOWED", `Use GET on ${CSRF_READINESS_PATH}`);
261
+ return true;
262
+ }
263
+ if (url === CSRF_READINESS_RESET_PATH) {
264
+ if (method !== "POST") {
265
+ sendError(res, 405, "METHOD_NOT_ALLOWED", `Use POST on ${CSRF_READINESS_RESET_PATH}`);
266
+ return true;
267
+ }
268
+ const hasHeader = req.headers["x-theo-action"] === "1";
269
+ if (!hasHeader || !originMatchesHost(req)) {
270
+ sendError(res, 403, "CSRF_INVALID", "Reset requires X-Theo-Action: 1 + same-origin");
271
+ return true;
272
+ }
273
+ store.reset();
274
+ sendNoContent(res);
275
+ return true;
276
+ }
277
+ return false;
278
+ }
279
+ function buildJsonResponse(status, body) {
280
+ return new Response(JSON.stringify(body), {
281
+ status,
282
+ headers: { "content-type": "application/json" }
283
+ });
284
+ }
285
+ function buildErrorResponse(status, code, message) {
286
+ return buildJsonResponse(status, { error: { code, message } });
287
+ }
288
+ function originMatchesHostFromRequest(request) {
289
+ const origin = request.headers.get("origin");
290
+ if (origin === null || origin.length === 0) return false;
291
+ const host = request.headers.get("host");
292
+ if (host === null || host.length === 0) {
293
+ try {
294
+ const reqHost = new URL(request.url).host;
295
+ const originHost = new URL(origin).host;
296
+ return originHost === reqHost;
297
+ } catch {
298
+ return false;
299
+ }
300
+ }
301
+ try {
302
+ return new URL(origin).host === host;
303
+ } catch {
304
+ return false;
305
+ }
306
+ }
307
+ async function handleCsrfReadinessRequest(request, store) {
308
+ const url = new URL(request.url).pathname;
309
+ const method = request.method.toUpperCase();
310
+ if (url === CSRF_READINESS_PATH) {
311
+ if (method === "GET") {
312
+ return buildJsonResponse(200, store.summary());
313
+ }
314
+ return buildErrorResponse(405, "METHOD_NOT_ALLOWED", `Use GET on ${CSRF_READINESS_PATH}`);
315
+ }
316
+ if (url === CSRF_READINESS_RESET_PATH) {
317
+ if (method !== "POST") {
318
+ return buildErrorResponse(
319
+ 405,
320
+ "METHOD_NOT_ALLOWED",
321
+ `Use POST on ${CSRF_READINESS_RESET_PATH}`
322
+ );
323
+ }
324
+ const hasHeader = request.headers.get("x-theo-action") === "1";
325
+ if (!hasHeader || !originMatchesHostFromRequest(request)) {
326
+ return buildErrorResponse(
327
+ 403,
328
+ "CSRF_INVALID",
329
+ "Reset requires X-Theo-Action: 1 + same-origin"
330
+ );
331
+ }
332
+ store.reset();
333
+ return new Response(null, { status: 204 });
334
+ }
335
+ return null;
336
+ }
337
+
338
+ // src/server/security/security-headers.ts
339
+ var DEFAULT_CSP = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self' ws: wss:; frame-ancestors 'none'; report-uri /__theo/csp-report";
340
+ var DEFAULT_PERMISSIONS_POLICY = "geolocation=(), camera=(), microphone=(), payment=(), usb=(), accelerometer=(), gyroscope=()";
341
+ var DEFAULT_HSTS = "max-age=31536000; includeSubDomains";
342
+ function applyNonceToCsp(policy, nonce) {
343
+ return policy.split(";").map((directive) => {
344
+ const trimmed = directive.trim();
345
+ if (!trimmed.startsWith("script-src")) return directive;
346
+ if (trimmed.includes("'unsafe-inline'")) {
347
+ return directive.replace("'unsafe-inline'", `'nonce-${nonce}'`);
348
+ }
349
+ return `${directive} 'nonce-${nonce}'`;
350
+ }).join(";");
351
+ }
352
+ function applyCsp(out, config, effectiveNonce) {
353
+ if (config.csp === false || config.cspMode === "off") return;
354
+ let policy = typeof config.csp === "string" ? config.csp : DEFAULT_CSP;
355
+ if (effectiveNonce) {
356
+ policy = applyNonceToCsp(policy, effectiveNonce);
357
+ }
358
+ const mode = config.cspMode ?? "enforce";
359
+ if (mode === "enforce") {
360
+ out["Content-Security-Policy"] = policy;
361
+ } else {
362
+ out["Content-Security-Policy-Report-Only"] = policy;
363
+ }
364
+ }
365
+ function buildSecurityHeaders(config, env, options = {}) {
366
+ const out = {};
367
+ const effectiveNonce = options.prerender ? void 0 : options.nonce;
368
+ applyCsp(out, config, effectiveNonce);
369
+ out["X-Frame-Options"] = config.frameOptions ?? "DENY";
370
+ out["X-Content-Type-Options"] = config.contentTypeOptions ?? "nosniff";
371
+ out["Referrer-Policy"] = config.referrerPolicy ?? "strict-origin-when-cross-origin";
372
+ if (config.permissionsPolicy !== false) {
373
+ out["Permissions-Policy"] = typeof config.permissionsPolicy === "string" ? config.permissionsPolicy : DEFAULT_PERMISSIONS_POLICY;
374
+ }
375
+ if (env.production && config.hsts !== false) {
376
+ out["Strict-Transport-Security"] = typeof config.hsts === "string" ? config.hsts : DEFAULT_HSTS;
377
+ }
378
+ if (effectiveNonce) {
379
+ out["Cache-Control"] = "private, no-store";
380
+ }
381
+ return out;
382
+ }
383
+ function applySecurityHeaders(res, config, env, options = {}) {
384
+ const headers = buildSecurityHeaders(config, env, options);
385
+ for (const [key, value] of Object.entries(headers)) {
386
+ res.setHeader(key, value);
387
+ }
388
+ }
389
+
390
+ export {
391
+ CsrfReadinessStore,
392
+ CSP_REPORT_PATH,
393
+ normalizeLegacy,
394
+ normalizeNew,
395
+ handleCspReport,
396
+ handleCspReportRequest,
397
+ CSRF_READINESS_PATH,
398
+ CSRF_READINESS_RESET_PATH,
399
+ handleCsrfReadiness,
400
+ handleCsrfReadinessRequest,
401
+ DEFAULT_CSP,
402
+ DEFAULT_PERMISSIONS_POLICY,
403
+ buildSecurityHeaders,
404
+ applySecurityHeaders
405
+ };
406
+ //# sourceMappingURL=chunk-B3L3TJVF.js.map