@fuzdev/fuz_app 0.1.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 (457) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +49 -0
  3. package/dist/actions/action_bridge.d.ts +65 -0
  4. package/dist/actions/action_bridge.d.ts.map +1 -0
  5. package/dist/actions/action_bridge.js +76 -0
  6. package/dist/actions/action_codegen.d.ts +97 -0
  7. package/dist/actions/action_codegen.d.ts.map +1 -0
  8. package/dist/actions/action_codegen.js +280 -0
  9. package/dist/actions/action_registry.d.ts +35 -0
  10. package/dist/actions/action_registry.d.ts.map +1 -0
  11. package/dist/actions/action_registry.js +83 -0
  12. package/dist/actions/action_spec.d.ts +169 -0
  13. package/dist/actions/action_spec.d.ts.map +1 -0
  14. package/dist/actions/action_spec.js +76 -0
  15. package/dist/auth/account_queries.d.ts +96 -0
  16. package/dist/auth/account_queries.d.ts.map +1 -0
  17. package/dist/auth/account_queries.js +172 -0
  18. package/dist/auth/account_routes.d.ts +86 -0
  19. package/dist/auth/account_routes.d.ts.map +1 -0
  20. package/dist/auth/account_routes.js +406 -0
  21. package/dist/auth/account_schema.d.ts +192 -0
  22. package/dist/auth/account_schema.d.ts.map +1 -0
  23. package/dist/auth/account_schema.js +105 -0
  24. package/dist/auth/admin_routes.d.ts +29 -0
  25. package/dist/auth/admin_routes.d.ts.map +1 -0
  26. package/dist/auth/admin_routes.js +193 -0
  27. package/dist/auth/api_token.d.ts +33 -0
  28. package/dist/auth/api_token.d.ts.map +1 -0
  29. package/dist/auth/api_token.js +36 -0
  30. package/dist/auth/api_token_queries.d.ts +80 -0
  31. package/dist/auth/api_token_queries.d.ts.map +1 -0
  32. package/dist/auth/api_token_queries.js +116 -0
  33. package/dist/auth/app_settings_queries.d.ts +33 -0
  34. package/dist/auth/app_settings_queries.d.ts.map +1 -0
  35. package/dist/auth/app_settings_queries.js +51 -0
  36. package/dist/auth/app_settings_routes.d.ts +27 -0
  37. package/dist/auth/app_settings_routes.d.ts.map +1 -0
  38. package/dist/auth/app_settings_routes.js +66 -0
  39. package/dist/auth/app_settings_schema.d.ts +35 -0
  40. package/dist/auth/app_settings_schema.d.ts.map +1 -0
  41. package/dist/auth/app_settings_schema.js +22 -0
  42. package/dist/auth/audit_log_queries.d.ts +90 -0
  43. package/dist/auth/audit_log_queries.d.ts.map +1 -0
  44. package/dist/auth/audit_log_queries.js +205 -0
  45. package/dist/auth/audit_log_routes.d.ts +33 -0
  46. package/dist/auth/audit_log_routes.d.ts.map +1 -0
  47. package/dist/auth/audit_log_routes.js +106 -0
  48. package/dist/auth/audit_log_schema.d.ts +259 -0
  49. package/dist/auth/audit_log_schema.d.ts.map +1 -0
  50. package/dist/auth/audit_log_schema.js +123 -0
  51. package/dist/auth/bearer_auth.d.ts +32 -0
  52. package/dist/auth/bearer_auth.d.ts.map +1 -0
  53. package/dist/auth/bearer_auth.js +90 -0
  54. package/dist/auth/bootstrap_account.d.ts +82 -0
  55. package/dist/auth/bootstrap_account.d.ts.map +1 -0
  56. package/dist/auth/bootstrap_account.js +97 -0
  57. package/dist/auth/bootstrap_routes.d.ts +74 -0
  58. package/dist/auth/bootstrap_routes.d.ts.map +1 -0
  59. package/dist/auth/bootstrap_routes.js +154 -0
  60. package/dist/auth/daemon_token.d.ts +49 -0
  61. package/dist/auth/daemon_token.d.ts.map +1 -0
  62. package/dist/auth/daemon_token.js +49 -0
  63. package/dist/auth/daemon_token_middleware.d.ts +93 -0
  64. package/dist/auth/daemon_token_middleware.d.ts.map +1 -0
  65. package/dist/auth/daemon_token_middleware.js +167 -0
  66. package/dist/auth/ddl.d.ts +27 -0
  67. package/dist/auth/ddl.d.ts.map +1 -0
  68. package/dist/auth/ddl.js +111 -0
  69. package/dist/auth/deps.d.ts +52 -0
  70. package/dist/auth/deps.d.ts.map +1 -0
  71. package/dist/auth/deps.js +10 -0
  72. package/dist/auth/invite_queries.d.ts +68 -0
  73. package/dist/auth/invite_queries.d.ts.map +1 -0
  74. package/dist/auth/invite_queries.js +105 -0
  75. package/dist/auth/invite_routes.d.ts +18 -0
  76. package/dist/auth/invite_routes.d.ts.map +1 -0
  77. package/dist/auth/invite_routes.js +129 -0
  78. package/dist/auth/invite_schema.d.ts +51 -0
  79. package/dist/auth/invite_schema.d.ts.map +1 -0
  80. package/dist/auth/invite_schema.js +25 -0
  81. package/dist/auth/keyring.d.ts +87 -0
  82. package/dist/auth/keyring.d.ts.map +1 -0
  83. package/dist/auth/keyring.js +142 -0
  84. package/dist/auth/middleware.d.ts +40 -0
  85. package/dist/auth/middleware.d.ts.map +1 -0
  86. package/dist/auth/middleware.js +64 -0
  87. package/dist/auth/migrations.d.ts +42 -0
  88. package/dist/auth/migrations.d.ts.map +1 -0
  89. package/dist/auth/migrations.js +79 -0
  90. package/dist/auth/password.d.ts +39 -0
  91. package/dist/auth/password.d.ts.map +1 -0
  92. package/dist/auth/password.js +25 -0
  93. package/dist/auth/password_argon2.d.ts +43 -0
  94. package/dist/auth/password_argon2.d.ts.map +1 -0
  95. package/dist/auth/password_argon2.js +76 -0
  96. package/dist/auth/permit_queries.d.ts +72 -0
  97. package/dist/auth/permit_queries.d.ts.map +1 -0
  98. package/dist/auth/permit_queries.js +116 -0
  99. package/dist/auth/request_context.d.ts +114 -0
  100. package/dist/auth/request_context.d.ts.map +1 -0
  101. package/dist/auth/request_context.js +176 -0
  102. package/dist/auth/require_keeper.d.ts +20 -0
  103. package/dist/auth/require_keeper.d.ts.map +1 -0
  104. package/dist/auth/require_keeper.js +35 -0
  105. package/dist/auth/role_schema.d.ts +69 -0
  106. package/dist/auth/role_schema.d.ts.map +1 -0
  107. package/dist/auth/role_schema.js +70 -0
  108. package/dist/auth/route_guards.d.ts +21 -0
  109. package/dist/auth/route_guards.d.ts.map +1 -0
  110. package/dist/auth/route_guards.js +32 -0
  111. package/dist/auth/session_cookie.d.ts +158 -0
  112. package/dist/auth/session_cookie.d.ts.map +1 -0
  113. package/dist/auth/session_cookie.js +135 -0
  114. package/dist/auth/session_lifecycle.d.ts +35 -0
  115. package/dist/auth/session_lifecycle.d.ts.map +1 -0
  116. package/dist/auth/session_lifecycle.js +27 -0
  117. package/dist/auth/session_middleware.d.ts +33 -0
  118. package/dist/auth/session_middleware.d.ts.map +1 -0
  119. package/dist/auth/session_middleware.js +62 -0
  120. package/dist/auth/session_queries.d.ts +135 -0
  121. package/dist/auth/session_queries.d.ts.map +1 -0
  122. package/dist/auth/session_queries.js +186 -0
  123. package/dist/auth/signup_routes.d.ts +32 -0
  124. package/dist/auth/signup_routes.d.ts.map +1 -0
  125. package/dist/auth/signup_routes.js +150 -0
  126. package/dist/cli/args.d.ts +48 -0
  127. package/dist/cli/args.d.ts.map +1 -0
  128. package/dist/cli/args.js +76 -0
  129. package/dist/cli/config.d.ts +48 -0
  130. package/dist/cli/config.d.ts.map +1 -0
  131. package/dist/cli/config.js +77 -0
  132. package/dist/cli/daemon.d.ts +82 -0
  133. package/dist/cli/daemon.d.ts.map +1 -0
  134. package/dist/cli/daemon.js +149 -0
  135. package/dist/cli/help.d.ts +85 -0
  136. package/dist/cli/help.d.ts.map +1 -0
  137. package/dist/cli/help.js +138 -0
  138. package/dist/cli/logger.d.ts +46 -0
  139. package/dist/cli/logger.d.ts.map +1 -0
  140. package/dist/cli/logger.js +48 -0
  141. package/dist/cli/util.d.ts +36 -0
  142. package/dist/cli/util.d.ts.map +1 -0
  143. package/dist/cli/util.js +50 -0
  144. package/dist/crypto.d.ts +13 -0
  145. package/dist/crypto.d.ts.map +1 -0
  146. package/dist/crypto.js +19 -0
  147. package/dist/db/assert_row.d.ts +18 -0
  148. package/dist/db/assert_row.d.ts.map +1 -0
  149. package/dist/db/assert_row.js +24 -0
  150. package/dist/db/create_db.d.ts +38 -0
  151. package/dist/db/create_db.d.ts.map +1 -0
  152. package/dist/db/create_db.js +57 -0
  153. package/dist/db/db.d.ts +97 -0
  154. package/dist/db/db.d.ts.map +1 -0
  155. package/dist/db/db.js +76 -0
  156. package/dist/db/db_pg.d.ts +21 -0
  157. package/dist/db/db_pg.d.ts.map +1 -0
  158. package/dist/db/db_pg.js +45 -0
  159. package/dist/db/db_pglite.d.ts +21 -0
  160. package/dist/db/db_pglite.d.ts.map +1 -0
  161. package/dist/db/db_pglite.js +28 -0
  162. package/dist/db/migrate.d.ts +67 -0
  163. package/dist/db/migrate.d.ts.map +1 -0
  164. package/dist/db/migrate.js +118 -0
  165. package/dist/db/pg_error.d.ts +16 -0
  166. package/dist/db/pg_error.d.ts.map +1 -0
  167. package/dist/db/pg_error.js +15 -0
  168. package/dist/db/query_deps.d.ts +14 -0
  169. package/dist/db/query_deps.d.ts.map +1 -0
  170. package/dist/db/query_deps.js +9 -0
  171. package/dist/db/sql_identifier.d.ts +27 -0
  172. package/dist/db/sql_identifier.d.ts.map +1 -0
  173. package/dist/db/sql_identifier.js +31 -0
  174. package/dist/db/status.d.ts +62 -0
  175. package/dist/db/status.d.ts.map +1 -0
  176. package/dist/db/status.js +116 -0
  177. package/dist/dev/setup.d.ts +159 -0
  178. package/dist/dev/setup.d.ts.map +1 -0
  179. package/dist/dev/setup.js +265 -0
  180. package/dist/env/dotenv.d.ts +25 -0
  181. package/dist/env/dotenv.d.ts.map +1 -0
  182. package/dist/env/dotenv.js +52 -0
  183. package/dist/env/load.d.ts +52 -0
  184. package/dist/env/load.d.ts.map +1 -0
  185. package/dist/env/load.js +79 -0
  186. package/dist/env/mask.d.ts +19 -0
  187. package/dist/env/mask.d.ts.map +1 -0
  188. package/dist/env/mask.js +26 -0
  189. package/dist/env/resolve.d.ts +126 -0
  190. package/dist/env/resolve.d.ts.map +1 -0
  191. package/dist/env/resolve.js +200 -0
  192. package/dist/hono_context.d.ts +48 -0
  193. package/dist/hono_context.d.ts.map +1 -0
  194. package/dist/hono_context.js +22 -0
  195. package/dist/http/common_routes.d.ts +52 -0
  196. package/dist/http/common_routes.d.ts.map +1 -0
  197. package/dist/http/common_routes.js +65 -0
  198. package/dist/http/db_routes.d.ts +57 -0
  199. package/dist/http/db_routes.d.ts.map +1 -0
  200. package/dist/http/db_routes.js +176 -0
  201. package/dist/http/error_schemas.d.ts +169 -0
  202. package/dist/http/error_schemas.d.ts.map +1 -0
  203. package/dist/http/error_schemas.js +178 -0
  204. package/dist/http/middleware_spec.d.ts +19 -0
  205. package/dist/http/middleware_spec.d.ts.map +1 -0
  206. package/dist/http/middleware_spec.js +9 -0
  207. package/dist/http/origin.d.ts +57 -0
  208. package/dist/http/origin.d.ts.map +1 -0
  209. package/dist/http/origin.js +207 -0
  210. package/dist/http/proxy.d.ts +112 -0
  211. package/dist/http/proxy.d.ts.map +1 -0
  212. package/dist/http/proxy.js +240 -0
  213. package/dist/http/route_spec.d.ts +197 -0
  214. package/dist/http/route_spec.d.ts.map +1 -0
  215. package/dist/http/route_spec.js +243 -0
  216. package/dist/http/schema_helpers.d.ts +64 -0
  217. package/dist/http/schema_helpers.d.ts.map +1 -0
  218. package/dist/http/schema_helpers.js +90 -0
  219. package/dist/http/surface.d.ts +132 -0
  220. package/dist/http/surface.d.ts.map +1 -0
  221. package/dist/http/surface.js +156 -0
  222. package/dist/http/surface_query.d.ts +77 -0
  223. package/dist/http/surface_query.d.ts.map +1 -0
  224. package/dist/http/surface_query.js +86 -0
  225. package/dist/rate_limiter.d.ts +94 -0
  226. package/dist/rate_limiter.d.ts.map +1 -0
  227. package/dist/rate_limiter.js +156 -0
  228. package/dist/realtime/sse.d.ts +80 -0
  229. package/dist/realtime/sse.d.ts.map +1 -0
  230. package/dist/realtime/sse.js +109 -0
  231. package/dist/realtime/sse_auth_guard.d.ts +93 -0
  232. package/dist/realtime/sse_auth_guard.d.ts.map +1 -0
  233. package/dist/realtime/sse_auth_guard.js +111 -0
  234. package/dist/realtime/subscriber_registry.d.ts +85 -0
  235. package/dist/realtime/subscriber_registry.d.ts.map +1 -0
  236. package/dist/realtime/subscriber_registry.js +108 -0
  237. package/dist/runtime/deno.d.ts +21 -0
  238. package/dist/runtime/deno.d.ts.map +1 -0
  239. package/dist/runtime/deno.js +83 -0
  240. package/dist/runtime/deps.d.ts +113 -0
  241. package/dist/runtime/deps.d.ts.map +1 -0
  242. package/dist/runtime/deps.js +10 -0
  243. package/dist/runtime/fs.d.ts +15 -0
  244. package/dist/runtime/fs.d.ts.map +1 -0
  245. package/dist/runtime/fs.js +17 -0
  246. package/dist/runtime/mock.d.ts +81 -0
  247. package/dist/runtime/mock.d.ts.map +1 -0
  248. package/dist/runtime/mock.js +195 -0
  249. package/dist/runtime/node.d.ts +17 -0
  250. package/dist/runtime/node.d.ts.map +1 -0
  251. package/dist/runtime/node.js +117 -0
  252. package/dist/schema_meta.d.ts +16 -0
  253. package/dist/schema_meta.d.ts.map +1 -0
  254. package/dist/schema_meta.js +9 -0
  255. package/dist/sensitivity.d.ts +15 -0
  256. package/dist/sensitivity.d.ts.map +1 -0
  257. package/dist/sensitivity.js +9 -0
  258. package/dist/server/app_backend.d.ts +74 -0
  259. package/dist/server/app_backend.d.ts.map +1 -0
  260. package/dist/server/app_backend.js +39 -0
  261. package/dist/server/app_server.d.ts +201 -0
  262. package/dist/server/app_server.d.ts.map +1 -0
  263. package/dist/server/app_server.js +266 -0
  264. package/dist/server/env.d.ts +68 -0
  265. package/dist/server/env.d.ts.map +1 -0
  266. package/dist/server/env.js +95 -0
  267. package/dist/server/startup.d.ts +22 -0
  268. package/dist/server/startup.d.ts.map +1 -0
  269. package/dist/server/startup.js +48 -0
  270. package/dist/server/static.d.ts +39 -0
  271. package/dist/server/static.d.ts.map +1 -0
  272. package/dist/server/static.js +38 -0
  273. package/dist/server/validate_nginx.d.ts +34 -0
  274. package/dist/server/validate_nginx.d.ts.map +1 -0
  275. package/dist/server/validate_nginx.js +118 -0
  276. package/dist/testing/CLAUDE.md +3 -0
  277. package/dist/testing/admin_integration.d.ts +45 -0
  278. package/dist/testing/admin_integration.d.ts.map +1 -0
  279. package/dist/testing/admin_integration.js +840 -0
  280. package/dist/testing/adversarial_404.d.ts +15 -0
  281. package/dist/testing/adversarial_404.d.ts.map +1 -0
  282. package/dist/testing/adversarial_404.js +118 -0
  283. package/dist/testing/adversarial_headers.d.ts +36 -0
  284. package/dist/testing/adversarial_headers.d.ts.map +1 -0
  285. package/dist/testing/adversarial_headers.js +128 -0
  286. package/dist/testing/adversarial_input.d.ts +56 -0
  287. package/dist/testing/adversarial_input.d.ts.map +1 -0
  288. package/dist/testing/adversarial_input.js +494 -0
  289. package/dist/testing/app_server.d.ts +169 -0
  290. package/dist/testing/app_server.d.ts.map +1 -0
  291. package/dist/testing/app_server.js +240 -0
  292. package/dist/testing/assert_dev_env.d.ts +10 -0
  293. package/dist/testing/assert_dev_env.d.ts.map +1 -0
  294. package/dist/testing/assert_dev_env.js +13 -0
  295. package/dist/testing/assertions.d.ts +61 -0
  296. package/dist/testing/assertions.d.ts.map +1 -0
  297. package/dist/testing/assertions.js +96 -0
  298. package/dist/testing/attack_surface.d.ts +63 -0
  299. package/dist/testing/attack_surface.d.ts.map +1 -0
  300. package/dist/testing/attack_surface.js +224 -0
  301. package/dist/testing/audit_completeness.d.ts +29 -0
  302. package/dist/testing/audit_completeness.d.ts.map +1 -0
  303. package/dist/testing/audit_completeness.js +410 -0
  304. package/dist/testing/auth_apps.d.ts +55 -0
  305. package/dist/testing/auth_apps.d.ts.map +1 -0
  306. package/dist/testing/auth_apps.js +122 -0
  307. package/dist/testing/data_exposure.d.ts +62 -0
  308. package/dist/testing/data_exposure.d.ts.map +1 -0
  309. package/dist/testing/data_exposure.js +297 -0
  310. package/dist/testing/db.d.ts +111 -0
  311. package/dist/testing/db.d.ts.map +1 -0
  312. package/dist/testing/db.js +258 -0
  313. package/dist/testing/entities.d.ts +21 -0
  314. package/dist/testing/entities.d.ts.map +1 -0
  315. package/dist/testing/entities.js +42 -0
  316. package/dist/testing/error_coverage.d.ts +78 -0
  317. package/dist/testing/error_coverage.d.ts.map +1 -0
  318. package/dist/testing/error_coverage.js +135 -0
  319. package/dist/testing/integration.d.ts +37 -0
  320. package/dist/testing/integration.d.ts.map +1 -0
  321. package/dist/testing/integration.js +1139 -0
  322. package/dist/testing/integration_helpers.d.ts +107 -0
  323. package/dist/testing/integration_helpers.d.ts.map +1 -0
  324. package/dist/testing/integration_helpers.js +246 -0
  325. package/dist/testing/middleware.d.ts +125 -0
  326. package/dist/testing/middleware.d.ts.map +1 -0
  327. package/dist/testing/middleware.js +210 -0
  328. package/dist/testing/rate_limiting.d.ts +43 -0
  329. package/dist/testing/rate_limiting.d.ts.map +1 -0
  330. package/dist/testing/rate_limiting.js +216 -0
  331. package/dist/testing/round_trip.d.ts +37 -0
  332. package/dist/testing/round_trip.d.ts.map +1 -0
  333. package/dist/testing/round_trip.js +128 -0
  334. package/dist/testing/schema_generators.d.ts +33 -0
  335. package/dist/testing/schema_generators.d.ts.map +1 -0
  336. package/dist/testing/schema_generators.js +137 -0
  337. package/dist/testing/standard.d.ts +49 -0
  338. package/dist/testing/standard.d.ts.map +1 -0
  339. package/dist/testing/standard.js +16 -0
  340. package/dist/testing/stubs.d.ts +96 -0
  341. package/dist/testing/stubs.d.ts.map +1 -0
  342. package/dist/testing/stubs.js +192 -0
  343. package/dist/testing/surface_invariants.d.ts +189 -0
  344. package/dist/testing/surface_invariants.d.ts.map +1 -0
  345. package/dist/testing/surface_invariants.js +450 -0
  346. package/dist/ui/AccountSessions.svelte +75 -0
  347. package/dist/ui/AccountSessions.svelte.d.ts +19 -0
  348. package/dist/ui/AccountSessions.svelte.d.ts.map +1 -0
  349. package/dist/ui/AdminAccounts.svelte +107 -0
  350. package/dist/ui/AdminAccounts.svelte.d.ts +19 -0
  351. package/dist/ui/AdminAccounts.svelte.d.ts.map +1 -0
  352. package/dist/ui/AdminAuditLog.svelte +144 -0
  353. package/dist/ui/AdminAuditLog.svelte.d.ts +4 -0
  354. package/dist/ui/AdminAuditLog.svelte.d.ts.map +1 -0
  355. package/dist/ui/AdminInvites.svelte +142 -0
  356. package/dist/ui/AdminInvites.svelte.d.ts +4 -0
  357. package/dist/ui/AdminInvites.svelte.d.ts.map +1 -0
  358. package/dist/ui/AdminOverview.svelte +337 -0
  359. package/dist/ui/AdminOverview.svelte.d.ts +4 -0
  360. package/dist/ui/AdminOverview.svelte.d.ts.map +1 -0
  361. package/dist/ui/AdminPermitHistory.svelte +61 -0
  362. package/dist/ui/AdminPermitHistory.svelte.d.ts +19 -0
  363. package/dist/ui/AdminPermitHistory.svelte.d.ts.map +1 -0
  364. package/dist/ui/AdminSessions.svelte +85 -0
  365. package/dist/ui/AdminSessions.svelte.d.ts +19 -0
  366. package/dist/ui/AdminSessions.svelte.d.ts.map +1 -0
  367. package/dist/ui/AdminSettings.svelte +32 -0
  368. package/dist/ui/AdminSettings.svelte.d.ts +19 -0
  369. package/dist/ui/AdminSettings.svelte.d.ts.map +1 -0
  370. package/dist/ui/AdminSurface.svelte +42 -0
  371. package/dist/ui/AdminSurface.svelte.d.ts +4 -0
  372. package/dist/ui/AdminSurface.svelte.d.ts.map +1 -0
  373. package/dist/ui/AppShell.svelte +93 -0
  374. package/dist/ui/AppShell.svelte.d.ts +20 -0
  375. package/dist/ui/AppShell.svelte.d.ts.map +1 -0
  376. package/dist/ui/BootstrapForm.svelte +105 -0
  377. package/dist/ui/BootstrapForm.svelte.d.ts +4 -0
  378. package/dist/ui/BootstrapForm.svelte.d.ts.map +1 -0
  379. package/dist/ui/ColumnLayout.svelte +46 -0
  380. package/dist/ui/ColumnLayout.svelte.d.ts +11 -0
  381. package/dist/ui/ColumnLayout.svelte.d.ts.map +1 -0
  382. package/dist/ui/ConfirmButton.svelte +125 -0
  383. package/dist/ui/ConfirmButton.svelte.d.ts +54 -0
  384. package/dist/ui/ConfirmButton.svelte.d.ts.map +1 -0
  385. package/dist/ui/Datatable.svelte +185 -0
  386. package/dist/ui/Datatable.svelte.d.ts +35 -0
  387. package/dist/ui/Datatable.svelte.d.ts.map +1 -0
  388. package/dist/ui/LoginForm.svelte +82 -0
  389. package/dist/ui/LoginForm.svelte.d.ts +8 -0
  390. package/dist/ui/LoginForm.svelte.d.ts.map +1 -0
  391. package/dist/ui/LogoutButton.svelte +36 -0
  392. package/dist/ui/LogoutButton.svelte.d.ts +10 -0
  393. package/dist/ui/LogoutButton.svelte.d.ts.map +1 -0
  394. package/dist/ui/MenuLink.svelte +35 -0
  395. package/dist/ui/MenuLink.svelte.d.ts +12 -0
  396. package/dist/ui/MenuLink.svelte.d.ts.map +1 -0
  397. package/dist/ui/OpenSignupToggle.svelte +36 -0
  398. package/dist/ui/OpenSignupToggle.svelte.d.ts +19 -0
  399. package/dist/ui/OpenSignupToggle.svelte.d.ts.map +1 -0
  400. package/dist/ui/PopoverButton.svelte +136 -0
  401. package/dist/ui/PopoverButton.svelte.d.ts +63 -0
  402. package/dist/ui/PopoverButton.svelte.d.ts.map +1 -0
  403. package/dist/ui/SignupForm.svelte +117 -0
  404. package/dist/ui/SignupForm.svelte.d.ts +7 -0
  405. package/dist/ui/SignupForm.svelte.d.ts.map +1 -0
  406. package/dist/ui/SurfaceExplorer.svelte +287 -0
  407. package/dist/ui/SurfaceExplorer.svelte.d.ts +8 -0
  408. package/dist/ui/SurfaceExplorer.svelte.d.ts.map +1 -0
  409. package/dist/ui/account_sessions_state.svelte.d.ts +15 -0
  410. package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -0
  411. package/dist/ui/account_sessions_state.svelte.js +45 -0
  412. package/dist/ui/admin_accounts_state.svelte.d.ts +19 -0
  413. package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -0
  414. package/dist/ui/admin_accounts_state.svelte.js +65 -0
  415. package/dist/ui/admin_invites_state.svelte.d.ts +19 -0
  416. package/dist/ui/admin_invites_state.svelte.d.ts.map +1 -0
  417. package/dist/ui/admin_invites_state.svelte.js +71 -0
  418. package/dist/ui/admin_sessions_state.svelte.d.ts +18 -0
  419. package/dist/ui/admin_sessions_state.svelte.d.ts.map +1 -0
  420. package/dist/ui/admin_sessions_state.svelte.js +62 -0
  421. package/dist/ui/app_settings_state.svelte.d.ts +14 -0
  422. package/dist/ui/app_settings_state.svelte.d.ts.map +1 -0
  423. package/dist/ui/app_settings_state.svelte.js +44 -0
  424. package/dist/ui/audit_log_state.svelte.d.ts +40 -0
  425. package/dist/ui/audit_log_state.svelte.d.ts.map +1 -0
  426. package/dist/ui/audit_log_state.svelte.js +153 -0
  427. package/dist/ui/auth_state.svelte.d.ts +85 -0
  428. package/dist/ui/auth_state.svelte.d.ts.map +1 -0
  429. package/dist/ui/auth_state.svelte.js +238 -0
  430. package/dist/ui/datatable.d.ts +25 -0
  431. package/dist/ui/datatable.d.ts.map +1 -0
  432. package/dist/ui/datatable.js +9 -0
  433. package/dist/ui/enter_advance.d.ts +13 -0
  434. package/dist/ui/enter_advance.d.ts.map +1 -0
  435. package/dist/ui/enter_advance.js +30 -0
  436. package/dist/ui/loadable.svelte.d.ts +55 -0
  437. package/dist/ui/loadable.svelte.d.ts.map +1 -0
  438. package/dist/ui/loadable.svelte.js +75 -0
  439. package/dist/ui/popover.svelte.d.ts +137 -0
  440. package/dist/ui/popover.svelte.d.ts.map +1 -0
  441. package/dist/ui/popover.svelte.js +288 -0
  442. package/dist/ui/position_helpers.d.ts +27 -0
  443. package/dist/ui/position_helpers.d.ts.map +1 -0
  444. package/dist/ui/position_helpers.js +81 -0
  445. package/dist/ui/sidebar_state.svelte.d.ts +30 -0
  446. package/dist/ui/sidebar_state.svelte.d.ts.map +1 -0
  447. package/dist/ui/sidebar_state.svelte.js +39 -0
  448. package/dist/ui/table_state.svelte.d.ts +63 -0
  449. package/dist/ui/table_state.svelte.d.ts.map +1 -0
  450. package/dist/ui/table_state.svelte.js +117 -0
  451. package/dist/ui/ui_fetch.d.ts +29 -0
  452. package/dist/ui/ui_fetch.d.ts.map +1 -0
  453. package/dist/ui/ui_fetch.js +37 -0
  454. package/dist/ui/ui_format.d.ts +63 -0
  455. package/dist/ui/ui_format.d.ts.map +1 -0
  456. package/dist/ui/ui_format.js +196 -0
  457. package/package.json +121 -0
@@ -0,0 +1,156 @@
1
+ /**
2
+ * App surface generation — JSON-serializable attack surface from route and middleware specs.
3
+ *
4
+ * Pure schema helpers (`is_null_schema`, `schema_to_surface`, `middleware_applies`,
5
+ * `merge_error_schemas`) live in `schema_helpers.ts`.
6
+ *
7
+ * @module
8
+ */
9
+ import { z } from 'zod';
10
+ import { schema_to_surface, middleware_applies, merge_error_schemas, is_null_schema, is_strict_object_schema, } from './schema_helpers.js';
11
+ // --- Surface generation ---
12
+ /**
13
+ * Collect error schemas from all middleware that applies to a route path.
14
+ *
15
+ * @param middleware - the middleware specs
16
+ * @param route_path - the route path to match against
17
+ * @returns merged middleware error schemas, or `null` if none
18
+ */
19
+ export const collect_middleware_errors = (middleware, route_path) => {
20
+ const errors = {};
21
+ for (const mw of middleware) {
22
+ if (mw.errors && middleware_applies(mw.path, route_path)) {
23
+ Object.assign(errors, mw.errors);
24
+ }
25
+ }
26
+ return Object.keys(errors).length > 0 ? errors : null;
27
+ };
28
+ /**
29
+ * Convert env schema to surface entries using `.meta()` metadata.
30
+ *
31
+ * @param schema - Zod object schema with `.meta()` on fields
32
+ * @returns array of env surface entries
33
+ */
34
+ export const env_schema_to_surface = (schema) => {
35
+ const entries = [];
36
+ for (const [name, field_schema] of Object.entries(schema.shape)) {
37
+ const field = field_schema;
38
+ const meta = field.meta();
39
+ const undef_result = field.safeParse(undefined);
40
+ entries.push({
41
+ name,
42
+ description: meta?.description ?? '',
43
+ sensitivity: meta?.sensitivity ?? null,
44
+ has_default: undef_result.success && undef_result.data !== undefined,
45
+ optional: undef_result.success,
46
+ });
47
+ }
48
+ return entries;
49
+ };
50
+ /**
51
+ * Convert SSE event specs to surface entries.
52
+ *
53
+ * @param event_specs - event specs to convert
54
+ * @returns array of event surface entries
55
+ */
56
+ export const events_to_surface = (event_specs) => {
57
+ return event_specs.map((spec) => ({
58
+ method: spec.method,
59
+ description: spec.description,
60
+ channel: spec.channel ?? null,
61
+ params_schema: schema_to_surface(spec.params),
62
+ }));
63
+ };
64
+ /**
65
+ * Generate a JSON-serializable attack surface from middleware, route specs,
66
+ * and optional env/event metadata.
67
+ *
68
+ * @param options - the surface generation options
69
+ * @returns the attack surface
70
+ */
71
+ export const generate_app_surface = (options) => {
72
+ const { route_specs, middleware_specs, env_schema, event_specs } = options;
73
+ const diagnostics = [];
74
+ // Spec-level diagnostics: check for non-strict input schemas
75
+ for (const r of route_specs) {
76
+ if (!is_null_schema(r.input) && !is_strict_object_schema(r.input)) {
77
+ diagnostics.push({
78
+ level: 'warning',
79
+ category: 'schema',
80
+ message: 'Input schema is not z.strictObject() — unknown keys will be silently stripped',
81
+ source: `${r.method} ${r.path} input`,
82
+ });
83
+ }
84
+ }
85
+ return {
86
+ diagnostics,
87
+ middleware: middleware_specs.map((m) => {
88
+ let mw_error_schemas = null;
89
+ if (m.errors) {
90
+ const schemas = {};
91
+ for (const [status, schema] of Object.entries(m.errors)) {
92
+ const json_schema = schema_to_surface(schema);
93
+ if (json_schema !== null) {
94
+ schemas[status] = json_schema;
95
+ }
96
+ }
97
+ if (Object.keys(schemas).length > 0) {
98
+ mw_error_schemas = schemas;
99
+ }
100
+ }
101
+ return { name: m.name, path: m.path, error_schemas: mw_error_schemas };
102
+ }),
103
+ routes: route_specs.map((r) => {
104
+ const applicable_middleware = middleware_specs
105
+ .filter((m) => middleware_applies(m.path, r.path))
106
+ .map((m) => m.name);
107
+ // Merge auto-derived + middleware + explicit error schemas
108
+ const mw_errors = collect_middleware_errors(middleware_specs, r.path);
109
+ const merged_errors = merge_error_schemas(r, mw_errors);
110
+ let error_schemas = null;
111
+ if (merged_errors) {
112
+ const schemas = {};
113
+ for (const [status, schema] of Object.entries(merged_errors)) {
114
+ const json_schema = schema_to_surface(schema);
115
+ if (json_schema !== null) {
116
+ schemas[status] = json_schema;
117
+ }
118
+ }
119
+ if (Object.keys(schemas).length > 0) {
120
+ error_schemas = schemas;
121
+ }
122
+ }
123
+ return {
124
+ method: r.method,
125
+ path: r.path,
126
+ auth: r.auth,
127
+ applicable_middleware,
128
+ description: r.description,
129
+ is_mutation: r.method !== 'GET',
130
+ transaction: r.transaction ?? r.method !== 'GET',
131
+ rate_limit_key: r.rate_limit ?? null,
132
+ params_schema: r.params ? schema_to_surface(r.params) : null,
133
+ query_schema: r.query ? schema_to_surface(r.query) : null,
134
+ input_schema: schema_to_surface(r.input),
135
+ output_schema: schema_to_surface(r.output),
136
+ error_schemas,
137
+ };
138
+ }),
139
+ env: env_schema ? env_schema_to_surface(env_schema) : [],
140
+ events: event_specs?.length ? events_to_surface(event_specs) : [],
141
+ };
142
+ };
143
+ /**
144
+ * Create an `AppSurfaceSpec` — the surface bundled with its source specs.
145
+ *
146
+ * @param options - the surface generation options
147
+ * @returns the surface spec with surface and raw specs
148
+ */
149
+ export const create_app_surface_spec = (options) => {
150
+ const surface = generate_app_surface(options);
151
+ return {
152
+ surface,
153
+ route_specs: options.route_specs,
154
+ middleware_specs: options.middleware_specs,
155
+ };
156
+ };
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Pure query functions over `AppSurface` data.
3
+ *
4
+ * Usable in tests, the adversarial auth runner, and future surface explorer UI.
5
+ * Replaces duplicated inline `.filter()` patterns.
6
+ *
7
+ * TODO @surface-explorer Used by test utilities (test_auth_surface, adversarial_input,
8
+ * surface_invariants) and SurfaceExplorer.svelte (surface_auth_summary, format_route_key).
9
+ * Several query functions (filter_authenticated_routes, filter_keeper_routes,
10
+ * routes_by_auth_type, filter_routes_by_prefix) are pre-built for richer surface
11
+ * explorer features and consumer test suites — leverage more as the surface UI matures.
12
+ *
13
+ * @module
14
+ */
15
+ import type { AppSurface, AppSurfaceRoute } from './surface.js';
16
+ /** Filter routes that require any form of authentication. */
17
+ export declare const filter_protected_routes: (surface: AppSurface) => Array<AppSurfaceRoute>;
18
+ /** Filter routes that are publicly accessible (no auth). */
19
+ export declare const filter_public_routes: (surface: AppSurface) => Array<AppSurfaceRoute>;
20
+ /** Filter all role-guarded routes (any role). */
21
+ export declare const filter_role_routes: (surface: AppSurface) => Array<AppSurfaceRoute & {
22
+ auth: {
23
+ type: "role";
24
+ role: string;
25
+ };
26
+ }>;
27
+ /** Filter routes that require basic authentication (no specific role). */
28
+ export declare const filter_authenticated_routes: (surface: AppSurface) => Array<AppSurfaceRoute & {
29
+ auth: {
30
+ type: "authenticated";
31
+ };
32
+ }>;
33
+ /** Filter routes that require keeper credentials. */
34
+ export declare const filter_keeper_routes: (surface: AppSurface) => Array<AppSurfaceRoute & {
35
+ auth: {
36
+ type: "keeper";
37
+ };
38
+ }>;
39
+ /** Filter routes that require a specific named role. */
40
+ export declare const filter_routes_for_role: (surface: AppSurface, role: string) => Array<AppSurfaceRoute & {
41
+ auth: {
42
+ type: "role";
43
+ role: string;
44
+ };
45
+ }>;
46
+ /**
47
+ * Group routes by auth type.
48
+ *
49
+ * @returns a map from auth type string to route arrays, with role routes keyed as `'role:name'`
50
+ */
51
+ export declare const routes_by_auth_type: (surface: AppSurface) => Map<string, Array<AppSurfaceRoute>>;
52
+ /** Filter routes whose path starts with `prefix`. */
53
+ export declare const filter_routes_by_prefix: (surface: AppSurface, prefix: string) => Array<AppSurfaceRoute>;
54
+ /** Filter routes that have a non-null input schema. */
55
+ export declare const filter_routes_with_input: (surface: AppSurface) => Array<AppSurfaceRoute>;
56
+ /** Filter routes that have a non-null params schema. */
57
+ export declare const filter_routes_with_params: (surface: AppSurface) => Array<AppSurfaceRoute>;
58
+ /** Filter routes that have a non-null query schema. */
59
+ export declare const filter_routes_with_query: (surface: AppSurface) => Array<AppSurfaceRoute>;
60
+ /** Filter routes that are mutations (POST, PUT, DELETE, PATCH). */
61
+ export declare const filter_mutation_routes: (surface: AppSurface) => Array<AppSurfaceRoute>;
62
+ /** Filter routes that declare rate limiting. */
63
+ export declare const filter_rate_limited_routes: (surface: AppSurface) => Array<AppSurfaceRoute>;
64
+ /** Format a route as `'METHOD /path'` (e.g. `'GET /health'`). */
65
+ export declare const format_route_key: (route: AppSurfaceRoute) => string;
66
+ /**
67
+ * Summarize route auth distribution across the surface.
68
+ *
69
+ * @returns counts by auth type, with role counts broken out by role name
70
+ */
71
+ export declare const surface_auth_summary: (surface: AppSurface) => {
72
+ none: number;
73
+ authenticated: number;
74
+ role: Map<string, number>;
75
+ keeper: number;
76
+ };
77
+ //# sourceMappingURL=surface_query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface_query.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/surface_query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAE,eAAe,EAAC,MAAM,cAAc,CAAC;AAE9D,6DAA6D;AAC7D,eAAO,MAAM,uBAAuB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEtD,4DAA4D;AAC5D,eAAO,MAAM,oBAAoB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC3B,CAAC;AAEtD,iDAAiD;AACjD,eAAO,MAAM,kBAAkB,GAC9B,SAAS,UAAU,KACjB,KAAK,CAAC,eAAe,GAAG;IAAC,IAAI,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC,CAG7D,CAAC;AAEH,0EAA0E;AAC1E,eAAO,MAAM,2BAA2B,GACvC,SAAS,UAAU,KACjB,KAAK,CAAC,eAAe,GAAG;IAAC,IAAI,EAAE;QAAC,IAAI,EAAE,eAAe,CAAA;KAAC,CAAA;CAAC,CAGxD,CAAC;AAEH,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,GAChC,SAAS,UAAU,KACjB,KAAK,CAAC,eAAe,GAAG;IAAC,IAAI,EAAE;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAC,CAAA;CAAC,CAGjD,CAAC;AAEH,wDAAwD;AACxD,eAAO,MAAM,sBAAsB,GAClC,SAAS,UAAU,EACnB,MAAM,MAAM,KACV,KAAK,CAAC,eAAe,GAAG;IAAC,IAAI,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC,CAI7D,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAS,UAAU,KAAG,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,eAAe,CAAC,CAY3F,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,uBAAuB,GACnC,SAAS,UAAU,EACnB,QAAQ,MAAM,KACZ,KAAK,CAAC,eAAe,CAA4D,CAAC;AAErF,uDAAuD;AACvD,eAAO,MAAM,wBAAwB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEvD,wDAAwD;AACxD,eAAO,MAAM,yBAAyB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAExD,uDAAuD;AACvD,eAAO,MAAM,wBAAwB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEvD,mEAAmE;AACnE,eAAO,MAAM,sBAAsB,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CACtC,CAAC;AAE7C,gDAAgD;AAChD,eAAO,MAAM,0BAA0B,GAAI,SAAS,UAAU,KAAG,KAAK,CAAC,eAAe,CAC9B,CAAC;AAEzD,iEAAiE;AACjE,eAAO,MAAM,gBAAgB,GAAI,OAAO,eAAe,KAAG,MAAyC,CAAC;AAEpG;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAChC,SAAS,UAAU,KACjB;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAwBjF,CAAC"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Pure query functions over `AppSurface` data.
3
+ *
4
+ * Usable in tests, the adversarial auth runner, and future surface explorer UI.
5
+ * Replaces duplicated inline `.filter()` patterns.
6
+ *
7
+ * TODO @surface-explorer Used by test utilities (test_auth_surface, adversarial_input,
8
+ * surface_invariants) and SurfaceExplorer.svelte (surface_auth_summary, format_route_key).
9
+ * Several query functions (filter_authenticated_routes, filter_keeper_routes,
10
+ * routes_by_auth_type, filter_routes_by_prefix) are pre-built for richer surface
11
+ * explorer features and consumer test suites — leverage more as the surface UI matures.
12
+ *
13
+ * @module
14
+ */
15
+ /** Filter routes that require any form of authentication. */
16
+ export const filter_protected_routes = (surface) => surface.routes.filter((r) => r.auth.type !== 'none');
17
+ /** Filter routes that are publicly accessible (no auth). */
18
+ export const filter_public_routes = (surface) => surface.routes.filter((r) => r.auth.type === 'none');
19
+ /** Filter all role-guarded routes (any role). */
20
+ export const filter_role_routes = (surface) => surface.routes.filter((r) => r.auth.type === 'role');
21
+ /** Filter routes that require basic authentication (no specific role). */
22
+ export const filter_authenticated_routes = (surface) => surface.routes.filter((r) => r.auth.type === 'authenticated');
23
+ /** Filter routes that require keeper credentials. */
24
+ export const filter_keeper_routes = (surface) => surface.routes.filter((r) => r.auth.type === 'keeper');
25
+ /** Filter routes that require a specific named role. */
26
+ export const filter_routes_for_role = (surface, role) => surface.routes.filter((r) => r.auth.type === 'role' && r.auth.role === role);
27
+ /**
28
+ * Group routes by auth type.
29
+ *
30
+ * @returns a map from auth type string to route arrays, with role routes keyed as `'role:name'`
31
+ */
32
+ export const routes_by_auth_type = (surface) => {
33
+ const groups = new Map();
34
+ for (const r of surface.routes) {
35
+ const key = r.auth.type === 'role' ? `role:${r.auth.role}` : r.auth.type;
36
+ let group = groups.get(key);
37
+ if (!group) {
38
+ group = [];
39
+ groups.set(key, group);
40
+ }
41
+ group.push(r);
42
+ }
43
+ return groups;
44
+ };
45
+ /** Filter routes whose path starts with `prefix`. */
46
+ export const filter_routes_by_prefix = (surface, prefix) => surface.routes.filter((r) => r.path.startsWith(prefix));
47
+ /** Filter routes that have a non-null input schema. */
48
+ export const filter_routes_with_input = (surface) => surface.routes.filter((r) => r.input_schema !== null);
49
+ /** Filter routes that have a non-null params schema. */
50
+ export const filter_routes_with_params = (surface) => surface.routes.filter((r) => r.params_schema !== null);
51
+ /** Filter routes that have a non-null query schema. */
52
+ export const filter_routes_with_query = (surface) => surface.routes.filter((r) => r.query_schema !== null);
53
+ /** Filter routes that are mutations (POST, PUT, DELETE, PATCH). */
54
+ export const filter_mutation_routes = (surface) => surface.routes.filter((r) => r.is_mutation);
55
+ /** Filter routes that declare rate limiting. */
56
+ export const filter_rate_limited_routes = (surface) => surface.routes.filter((r) => r.rate_limit_key !== null);
57
+ /** Format a route as `'METHOD /path'` (e.g. `'GET /health'`). */
58
+ export const format_route_key = (route) => `${route.method} ${route.path}`;
59
+ /**
60
+ * Summarize route auth distribution across the surface.
61
+ *
62
+ * @returns counts by auth type, with role counts broken out by role name
63
+ */
64
+ export const surface_auth_summary = (surface) => {
65
+ let none = 0;
66
+ let authenticated = 0;
67
+ const role = new Map();
68
+ let keeper = 0;
69
+ for (const r of surface.routes) {
70
+ switch (r.auth.type) {
71
+ case 'none':
72
+ none++;
73
+ break;
74
+ case 'authenticated':
75
+ authenticated++;
76
+ break;
77
+ case 'role':
78
+ role.set(r.auth.role, (role.get(r.auth.role) ?? 0) + 1);
79
+ break;
80
+ case 'keeper':
81
+ keeper++;
82
+ break;
83
+ }
84
+ }
85
+ return { none, authenticated, role, keeper };
86
+ };
@@ -0,0 +1,94 @@
1
+ /**
2
+ * In-memory sliding window rate limiter.
3
+ *
4
+ * Tracks failed attempts per key (typically IP address) using a sliding
5
+ * time window. No external dependencies — state resets on server restart.
6
+ *
7
+ * @module
8
+ */
9
+ import type { Context } from 'hono';
10
+ /**
11
+ * Configuration for a rate limiter instance.
12
+ */
13
+ export interface RateLimiterOptions {
14
+ /** Maximum allowed attempts within the window. */
15
+ max_attempts: number;
16
+ /** Sliding window duration in milliseconds. */
17
+ window_ms: number;
18
+ /** Interval for pruning stale entries (0 disables the timer). */
19
+ cleanup_interval_ms: number;
20
+ }
21
+ /** Default options for per-IP login rate limiting: 5 attempts per 15 minutes. */
22
+ export declare const DEFAULT_LOGIN_IP_RATE_LIMIT: RateLimiterOptions;
23
+ /** Default options for per-account login rate limiting: 10 attempts per 30 minutes. */
24
+ export declare const DEFAULT_LOGIN_ACCOUNT_RATE_LIMIT: RateLimiterOptions;
25
+ /**
26
+ * Result of a rate limit check or record operation.
27
+ */
28
+ export interface RateLimitResult {
29
+ /** Whether the request is allowed. */
30
+ allowed: boolean;
31
+ /** Remaining attempts before blocking. */
32
+ remaining: number;
33
+ /** Seconds until the oldest active attempt expires (0 if allowed). */
34
+ retry_after: number;
35
+ }
36
+ /**
37
+ * In-memory sliding window rate limiter.
38
+ *
39
+ * Stores an array of timestamps per key. On `check`/`record`, timestamps
40
+ * outside the window are pruned. `retry_after` reports seconds until the
41
+ * oldest active timestamp expires.
42
+ *
43
+ * Parameters that accept `RateLimiter | null` (e.g. `ip_rate_limiter`,
44
+ * `login_account_rate_limiter`) silently disable rate limiting when `null`
45
+ * is passed — no checks are performed and all requests are allowed through.
46
+ */
47
+ export declare class RateLimiter {
48
+ #private;
49
+ readonly options: RateLimiterOptions;
50
+ constructor(options: RateLimiterOptions);
51
+ /** Number of tracked keys. */
52
+ get size(): number;
53
+ /**
54
+ * Check whether `key` is allowed without recording an attempt.
55
+ *
56
+ * @param key - rate limit key (e.g. IP address)
57
+ * @param now - current timestamp in ms (defaults to `Date.now()`)
58
+ */
59
+ check(key: string, now?: number): RateLimitResult;
60
+ /**
61
+ * Record a failed attempt for `key` and return the updated result.
62
+ *
63
+ * @param key - rate limit key (e.g. IP address)
64
+ * @param now - current timestamp in ms (defaults to `Date.now()`)
65
+ */
66
+ record(key: string, now?: number): RateLimitResult;
67
+ /**
68
+ * Clear all attempts for `key` (e.g. after successful login).
69
+ */
70
+ reset(key: string): void;
71
+ /**
72
+ * Remove entries whose timestamps are all outside the window.
73
+ *
74
+ * @param now - current timestamp in ms (defaults to `Date.now()`)
75
+ */
76
+ cleanup(now?: number): void;
77
+ /** Stop the cleanup timer. Safe to call multiple times. */
78
+ dispose(): void;
79
+ }
80
+ /**
81
+ * Create a `RateLimiter` with sensible defaults for per-IP login protection.
82
+ *
83
+ * @param options - override individual options; unset fields use `DEFAULT_LOGIN_IP_RATE_LIMIT`
84
+ */
85
+ export declare const create_rate_limiter: (options?: Partial<RateLimiterOptions>) => RateLimiter;
86
+ /**
87
+ * Build a 429 rate-limit-exceeded JSON response with `Retry-After` header.
88
+ *
89
+ * @param c - Hono context
90
+ * @param retry_after - seconds until the client should retry
91
+ * @returns a 429 Response
92
+ */
93
+ export declare const rate_limit_exceeded_response: (c: Context, retry_after: number) => Response;
94
+ //# sourceMappingURL=rate_limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate_limiter.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/rate_limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;AAIlC;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,mBAAmB,EAAE,MAAM,CAAC;CAC5B;AAED,iFAAiF;AACjF,eAAO,MAAM,2BAA2B,EAAE,kBAIzC,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,gCAAgC,EAAE,kBAI9C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,WAAW;;IACvB,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;gBAOzB,OAAO,EAAE,kBAAkB;IAWvC,8BAA8B;IAC9B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;OAKG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,eAAe;IA2B7D;;;;;OAKG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,eAAe;IA0B9D;;OAEG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIxB;;;;OAIG;IACH,OAAO,CAAC,GAAG,GAAE,MAAmB,GAAG,IAAI;IAYvC,2DAA2D;IAC3D,OAAO,IAAI,IAAI;CAMf;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,UAAU,OAAO,CAAC,kBAAkB,CAAC,KAAG,WAE3E,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,GAAI,GAAG,OAAO,EAAE,aAAa,MAAM,KAAG,QAI7E,CAAC"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * In-memory sliding window rate limiter.
3
+ *
4
+ * Tracks failed attempts per key (typically IP address) using a sliding
5
+ * time window. No external dependencies — state resets on server restart.
6
+ *
7
+ * @module
8
+ */
9
+ import { ERROR_RATE_LIMIT_EXCEEDED } from './http/error_schemas.js';
10
+ /** Default options for per-IP login rate limiting: 5 attempts per 15 minutes. */
11
+ export const DEFAULT_LOGIN_IP_RATE_LIMIT = {
12
+ max_attempts: 5,
13
+ window_ms: 15 * 60_000,
14
+ cleanup_interval_ms: 5 * 60_000,
15
+ };
16
+ /** Default options for per-account login rate limiting: 10 attempts per 30 minutes. */
17
+ export const DEFAULT_LOGIN_ACCOUNT_RATE_LIMIT = {
18
+ max_attempts: 10,
19
+ window_ms: 30 * 60_000,
20
+ cleanup_interval_ms: 5 * 60_000,
21
+ };
22
+ /**
23
+ * In-memory sliding window rate limiter.
24
+ *
25
+ * Stores an array of timestamps per key. On `check`/`record`, timestamps
26
+ * outside the window are pruned. `retry_after` reports seconds until the
27
+ * oldest active timestamp expires.
28
+ *
29
+ * Parameters that accept `RateLimiter | null` (e.g. `ip_rate_limiter`,
30
+ * `login_account_rate_limiter`) silently disable rate limiting when `null`
31
+ * is passed — no checks are performed and all requests are allowed through.
32
+ */
33
+ export class RateLimiter {
34
+ options;
35
+ /** Key → array of attempt timestamps. */
36
+ #attempts = new Map();
37
+ #cleanup_timer = null;
38
+ constructor(options) {
39
+ this.options = options;
40
+ if (options.cleanup_interval_ms > 0) {
41
+ this.#cleanup_timer = setInterval(() => this.cleanup(), options.cleanup_interval_ms);
42
+ // Allow the process to exit even if the timer is still active.
43
+ if (typeof this.#cleanup_timer === 'object' && 'unref' in this.#cleanup_timer) {
44
+ this.#cleanup_timer.unref();
45
+ }
46
+ }
47
+ }
48
+ /** Number of tracked keys. */
49
+ get size() {
50
+ return this.#attempts.size;
51
+ }
52
+ /**
53
+ * Check whether `key` is allowed without recording an attempt.
54
+ *
55
+ * @param key - rate limit key (e.g. IP address)
56
+ * @param now - current timestamp in ms (defaults to `Date.now()`)
57
+ */
58
+ check(key, now = Date.now()) {
59
+ const { max_attempts, window_ms } = this.options;
60
+ const cutoff = now - window_ms;
61
+ const timestamps = this.#attempts.get(key);
62
+ if (!timestamps) {
63
+ return { allowed: true, remaining: max_attempts, retry_after: 0 };
64
+ }
65
+ const active = timestamps.filter((t) => t > cutoff);
66
+ if (active.length !== timestamps.length) {
67
+ if (active.length === 0) {
68
+ this.#attempts.delete(key);
69
+ }
70
+ else {
71
+ this.#attempts.set(key, active);
72
+ }
73
+ }
74
+ if (active.length < max_attempts) {
75
+ return { allowed: true, remaining: max_attempts - active.length, retry_after: 0 };
76
+ }
77
+ const oldest = active[0];
78
+ const retry_after = Math.ceil((oldest + window_ms - now) / 1000);
79
+ return { allowed: false, remaining: 0, retry_after };
80
+ }
81
+ /**
82
+ * Record a failed attempt for `key` and return the updated result.
83
+ *
84
+ * @param key - rate limit key (e.g. IP address)
85
+ * @param now - current timestamp in ms (defaults to `Date.now()`)
86
+ */
87
+ record(key, now = Date.now()) {
88
+ const { max_attempts, window_ms } = this.options;
89
+ const cutoff = now - window_ms;
90
+ let timestamps = this.#attempts.get(key);
91
+ if (timestamps) {
92
+ // Prune expired entries in place.
93
+ const active = timestamps.filter((t) => t > cutoff);
94
+ active.push(now);
95
+ this.#attempts.set(key, active);
96
+ timestamps = active;
97
+ }
98
+ else {
99
+ timestamps = [now];
100
+ this.#attempts.set(key, timestamps);
101
+ }
102
+ const count = timestamps.length;
103
+ if (count <= max_attempts) {
104
+ return { allowed: true, remaining: max_attempts - count, retry_after: 0 };
105
+ }
106
+ const oldest = timestamps[0];
107
+ const retry_after = Math.ceil((oldest + window_ms - now) / 1000);
108
+ return { allowed: false, remaining: 0, retry_after };
109
+ }
110
+ /**
111
+ * Clear all attempts for `key` (e.g. after successful login).
112
+ */
113
+ reset(key) {
114
+ this.#attempts.delete(key);
115
+ }
116
+ /**
117
+ * Remove entries whose timestamps are all outside the window.
118
+ *
119
+ * @param now - current timestamp in ms (defaults to `Date.now()`)
120
+ */
121
+ cleanup(now = Date.now()) {
122
+ const cutoff = now - this.options.window_ms;
123
+ for (const [key, timestamps] of this.#attempts) {
124
+ const active = timestamps.filter((t) => t > cutoff);
125
+ if (active.length === 0) {
126
+ this.#attempts.delete(key);
127
+ }
128
+ else {
129
+ this.#attempts.set(key, active);
130
+ }
131
+ }
132
+ }
133
+ /** Stop the cleanup timer. Safe to call multiple times. */
134
+ dispose() {
135
+ if (this.#cleanup_timer !== null) {
136
+ clearInterval(this.#cleanup_timer);
137
+ this.#cleanup_timer = null;
138
+ }
139
+ }
140
+ }
141
+ /**
142
+ * Create a `RateLimiter` with sensible defaults for per-IP login protection.
143
+ *
144
+ * @param options - override individual options; unset fields use `DEFAULT_LOGIN_IP_RATE_LIMIT`
145
+ */
146
+ export const create_rate_limiter = (options) => {
147
+ return new RateLimiter({ ...DEFAULT_LOGIN_IP_RATE_LIMIT, ...options });
148
+ };
149
+ /**
150
+ * Build a 429 rate-limit-exceeded JSON response with `Retry-After` header.
151
+ *
152
+ * @param c - Hono context
153
+ * @param retry_after - seconds until the client should retry
154
+ * @returns a 429 Response
155
+ */
156
+ export const rate_limit_exceeded_response = (c, retry_after) => c.json({ error: ERROR_RATE_LIMIT_EXCEEDED, retry_after }, { status: 429, headers: { 'Retry-After': String(Math.ceil(retry_after)) } });
@@ -0,0 +1,80 @@
1
+ /**
2
+ * SSE (Server-Sent Events) streaming utilities for Hono.
3
+ *
4
+ * Provides generic helpers for creating SSE response streams
5
+ * and a notification type aligned with JSON-RPC 2.0.
6
+ *
7
+ * @module
8
+ */
9
+ import type { Context } from 'hono';
10
+ import { z } from 'zod';
11
+ import type { Logger } from '@fuzdev/fuz_util/log.js';
12
+ /**
13
+ * Generic SSE stream controller interface.
14
+ *
15
+ * Transport-agnostic — works with any serializable type.
16
+ */
17
+ export interface SseStream<T = unknown> {
18
+ /** Send data to the client as a JSON SSE event. */
19
+ send: (data: T) => void;
20
+ /** Send a comment (for keep-alive pings). */
21
+ comment: (text: string) => void;
22
+ /** Close the stream. */
23
+ close: () => void;
24
+ /** Register a listener called when the stream closes (client disconnect or explicit close). */
25
+ on_close: (fn: () => void) => void;
26
+ }
27
+ /**
28
+ * Notification shape aligned with JSON-RPC 2.0.
29
+ *
30
+ * Uses `{method, params}` to match the JSON-RPC notification format.
31
+ */
32
+ export interface SseNotification {
33
+ /** Notification method name (e.g. 'run_created', 'host_updated'). */
34
+ method: string;
35
+ /** Method-specific payload. */
36
+ params: unknown;
37
+ }
38
+ /**
39
+ * Create an SSE response for a Hono context.
40
+ *
41
+ * Wraps Hono's `streamSSE` to provide a `{response, stream}` API
42
+ * compatible with `SubscriberRegistry` push-based broadcasting.
43
+ * The callback suspends via a promise that resolves on client disconnect
44
+ * or explicit `close()`, keeping the stream alive for external sends.
45
+ *
46
+ * Uses `hono_stream.write()` directly (not `writeSSE`) to avoid
47
+ * Hono's HTML callback resolution — keeps the same `data: JSON\n\n` format.
48
+ *
49
+ * @param c - Hono context
50
+ * @returns object with response and stream controller
51
+ */
52
+ export declare const create_sse_response: <T = unknown>(c: Context, log: Logger) => {
53
+ response: Response;
54
+ stream: SseStream<T>;
55
+ };
56
+ /** SSE comment sent on connect to flush headers through proxies. Exported for test assertions. */
57
+ export declare const SSE_CONNECTED_COMMENT = ": connected\n\n";
58
+ /** Spec for an SSE event — declares params schema, description, and channel. */
59
+ export interface SseEventSpec {
60
+ method: string;
61
+ params: z.ZodType;
62
+ description: string;
63
+ channel?: string;
64
+ }
65
+ /**
66
+ * Create a broadcaster that validates events in DEV mode.
67
+ *
68
+ * In DEV: warns on unknown methods and invalid params.
69
+ * In production: passes through with zero overhead.
70
+ *
71
+ * @param broadcaster - duck-typed broadcaster (e.g. `SubscriberRegistry`)
72
+ * @param event_specs - event specs to validate against
73
+ * @returns validated broadcaster wrapper (passthrough in production)
74
+ */
75
+ export declare const create_validated_broadcaster: <T extends SseNotification>(broadcaster: {
76
+ broadcast: (channel: string, data: T) => void;
77
+ }, event_specs: Array<SseEventSpec>, log: Logger) => {
78
+ broadcast: (channel: string, data: T) => void;
79
+ };
80
+ //# sourceMappingURL=sse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/realtime/sse.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;AAElC,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD;;;;GAIG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG,OAAO;IACrC,mDAAmD;IACnD,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IACxB,6CAA6C;IAC7C,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,wBAAwB;IACxB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,+FAA+F;IAC/F,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,MAAM,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,GAAI,CAAC,GAAG,OAAO,EAC9C,GAAG,OAAO,EACV,KAAK,MAAM,KACT;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;CAiD3C,CAAC;AAEF,kGAAkG;AAClG,eAAO,MAAM,qBAAqB,oBAAoB,CAAC;AAEvD,gFAAgF;AAChF,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,GAAI,CAAC,SAAS,eAAe,EACrE,aAAa;IAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,KAAK,IAAI,CAAA;CAAC,EAC5D,aAAa,KAAK,CAAC,YAAY,CAAC,EAChC,KAAK,MAAM,KACT;IAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,KAAK,IAAI,CAAA;CAmBhD,CAAC"}