@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,169 @@
1
+ /**
2
+ * Standard error response schemas and error code constants for fuz_app routes.
3
+ *
4
+ * Defines `ERROR_*` constants (single source of truth for machine-parseable
5
+ * error codes), Zod schemas for error response shapes, a type for error schema
6
+ * maps, and `derive_error_schemas` to auto-populate middleware-produced errors
7
+ * from a route's auth requirement and input schema.
8
+ *
9
+ * Used in `RouteSpec.errors` and `MiddlewareSpec.errors` for surface
10
+ * introspection and DEV-mode validation.
11
+ *
12
+ * @module
13
+ */
14
+ import { z } from 'zod';
15
+ import type { RouteAuth } from './route_spec.js';
16
+ /** Request body failed Zod validation. */
17
+ export declare const ERROR_INVALID_REQUEST_BODY: "invalid_request_body";
18
+ /** Request body is not valid JSON or not an object. */
19
+ export declare const ERROR_INVALID_JSON_BODY: "invalid_json_body";
20
+ /** URL path params failed Zod validation. */
21
+ export declare const ERROR_INVALID_ROUTE_PARAMS: "invalid_route_params";
22
+ /** URL query params failed Zod validation. */
23
+ export declare const ERROR_INVALID_QUERY_PARAMS: "invalid_query_params";
24
+ /** No valid session or bearer token. */
25
+ export declare const ERROR_AUTHENTICATION_REQUIRED: "authentication_required";
26
+ /** Authenticated but missing required role. */
27
+ export declare const ERROR_INSUFFICIENT_PERMISSIONS: "insufficient_permissions";
28
+ /** Rate limiter rejected the request. */
29
+ export declare const ERROR_RATE_LIMIT_EXCEEDED: "rate_limit_exceeded";
30
+ /** Username or password is wrong (intentionally vague for enumeration prevention). */
31
+ export declare const ERROR_INVALID_CREDENTIALS: "invalid_credentials";
32
+ /** Request body exceeds the maximum allowed size. */
33
+ export declare const ERROR_PAYLOAD_TOO_LARGE: "payload_too_large";
34
+ /** Request origin not in allowlist. */
35
+ export declare const ERROR_FORBIDDEN_ORIGIN: "forbidden_origin";
36
+ /** Request referer not in allowlist. */
37
+ export declare const ERROR_FORBIDDEN_REFERER: "forbidden_referer";
38
+ /** Bearer token sent with Origin/Referer header (browser context). */
39
+ export declare const ERROR_BEARER_REJECTED_BROWSER: "bearer_token_rejected_in_browser_context";
40
+ /** Bearer token failed validation (missing, malformed, or revoked). */
41
+ export declare const ERROR_INVALID_TOKEN: "invalid_token";
42
+ /** Token references a deleted account. */
43
+ export declare const ERROR_ACCOUNT_NOT_FOUND: "account_not_found";
44
+ /** Keeper routes require daemon_token credential type. */
45
+ export declare const ERROR_KEEPER_REQUIRES_DAEMON_TOKEN: "keeper_requires_daemon_token";
46
+ /** Daemon token header present but malformed or not matching current/previous token. */
47
+ export declare const ERROR_INVALID_DAEMON_TOKEN: "invalid_daemon_token";
48
+ /** Daemon token valid but keeper account not yet resolved (pre-bootstrap). */
49
+ export declare const ERROR_KEEPER_ACCOUNT_NOT_CONFIGURED: "keeper_account_not_configured";
50
+ /** Keeper account ID set but account row not found. */
51
+ export declare const ERROR_KEEPER_ACCOUNT_NOT_FOUND: "keeper_account_not_found";
52
+ /** Bootstrap lock already acquired — system already bootstrapped. */
53
+ export declare const ERROR_ALREADY_BOOTSTRAPPED: "already_bootstrapped";
54
+ /** Bootstrap token file not found on disk. */
55
+ export declare const ERROR_TOKEN_FILE_MISSING: "token_file_missing";
56
+ /** Bootstrap endpoint called but no token path configured. */
57
+ export declare const ERROR_BOOTSTRAP_NOT_CONFIGURED: "bootstrap_not_configured";
58
+ /** No unclaimed invite matches the signup credentials. */
59
+ export declare const ERROR_NO_MATCHING_INVITE: "no_matching_invite";
60
+ /** Signup conflict — username or email already taken (intentionally vague for enumeration prevention). */
61
+ export declare const ERROR_SIGNUP_CONFLICT: "signup_conflict";
62
+ /** Invite not found (for delete operations). */
63
+ export declare const ERROR_INVITE_NOT_FOUND: "invite_not_found";
64
+ /** Invite must have at least an email or username. */
65
+ export declare const ERROR_INVITE_MISSING_IDENTIFIER: "invite_missing_identifier";
66
+ /** An unclaimed invite already exists for this email or username. */
67
+ export declare const ERROR_INVITE_DUPLICATE: "invite_duplicate";
68
+ /** An account already exists with this invite's username. */
69
+ export declare const ERROR_INVITE_ACCOUNT_EXISTS_USERNAME: "invite_account_exists_username";
70
+ /** An account already exists with this invite's email. */
71
+ export declare const ERROR_INVITE_ACCOUNT_EXISTS_EMAIL: "invite_account_exists_email";
72
+ /** Admin tried to grant a role that is not web-grantable. */
73
+ export declare const ERROR_ROLE_NOT_WEB_GRANTABLE: "role_not_web_grantable";
74
+ /** Permit ID not found or not owned by the target actor. */
75
+ export declare const ERROR_PERMIT_NOT_FOUND: "permit_not_found";
76
+ /** Query parameter `event_type` is not a valid audit event type. */
77
+ export declare const ERROR_INVALID_EVENT_TYPE: "invalid_event_type";
78
+ /** DELETE blocked by a foreign key constraint. */
79
+ export declare const ERROR_FOREIGN_KEY_VIOLATION: "foreign_key_violation";
80
+ /** Table name not found in `information_schema`. */
81
+ export declare const ERROR_TABLE_NOT_FOUND: "table_not_found";
82
+ /** Table has no primary key constraint (cannot delete by PK). */
83
+ export declare const ERROR_TABLE_NO_PRIMARY_KEY: "table_no_primary_key";
84
+ /** Row with the given PK value not found. */
85
+ export declare const ERROR_ROW_NOT_FOUND: "row_not_found";
86
+ /** Base API error — all JSON error responses have at least `{error: string}`. */
87
+ export declare const ApiError: z.ZodObject<{
88
+ error: z.ZodString;
89
+ }, z.core.$loose>;
90
+ export type ApiError = z.infer<typeof ApiError>;
91
+ /**
92
+ * Input validation error — returned when the request body fails Zod parsing.
93
+ *
94
+ * `issues` contains the Zod validation issues for diagnostic display.
95
+ */
96
+ export declare const ValidationError: z.ZodObject<{
97
+ error: z.ZodString;
98
+ issues: z.ZodArray<z.ZodObject<{
99
+ code: z.ZodString;
100
+ message: z.ZodString;
101
+ path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
102
+ }, z.core.$loose>>;
103
+ }, z.core.$loose>;
104
+ export type ValidationError = z.infer<typeof ValidationError>;
105
+ /** Permission error — returned by `require_role()` when the required role is missing. */
106
+ export declare const PermissionError: z.ZodObject<{
107
+ error: z.ZodLiteral<"insufficient_permissions">;
108
+ required_role: z.ZodString;
109
+ }, z.core.$loose>;
110
+ export type PermissionError = z.infer<typeof PermissionError>;
111
+ /** Keeper credential error — returned by `require_keeper` when credential type is wrong. */
112
+ export declare const KeeperError: z.ZodObject<{
113
+ error: z.ZodLiteral<"keeper_requires_daemon_token">;
114
+ credential_type: z.ZodString;
115
+ }, z.core.$loose>;
116
+ export type KeeperError = z.infer<typeof KeeperError>;
117
+ /** Rate limit error — returned when a rate limiter rejects the request. */
118
+ export declare const RateLimitError: z.ZodObject<{
119
+ error: z.ZodLiteral<"rate_limit_exceeded">;
120
+ retry_after: z.ZodNumber;
121
+ }, z.core.$loose>;
122
+ export type RateLimitError = z.infer<typeof RateLimitError>;
123
+ /** Payload too large error — returned when the request body exceeds the size limit. */
124
+ export declare const PayloadTooLargeError: z.ZodObject<{
125
+ error: z.ZodLiteral<"payload_too_large">;
126
+ }, z.core.$loose>;
127
+ export type PayloadTooLargeError = z.infer<typeof PayloadTooLargeError>;
128
+ /** Foreign key violation error — returned when a delete is blocked by references. */
129
+ export declare const ForeignKeyError: z.ZodObject<{
130
+ error: z.ZodLiteral<"foreign_key_violation">;
131
+ }, z.core.$loose>;
132
+ export type ForeignKeyError = z.infer<typeof ForeignKeyError>;
133
+ /**
134
+ * Error schema map — maps HTTP status codes to Zod schemas.
135
+ *
136
+ * Used on `RouteSpec.errors` and internally by `derive_error_schemas`.
137
+ */
138
+ export type RouteErrorSchemas = Partial<Record<number, z.ZodType>>;
139
+ /**
140
+ * Rate limit key type — declares what a route's rate limiter is keyed on.
141
+ *
142
+ * - `'ip'` — per-IP rate limiting (bootstrap, password change, bearer auth)
143
+ * - `'account'` — per-account rate limiting (keyed on submitted identifier)
144
+ * - `'both'` — both per-IP and per-account (login)
145
+ */
146
+ export type RateLimitKey = 'ip' | 'account' | 'both';
147
+ /**
148
+ * Derive error schemas from a route's auth requirement, input schema, and rate limit config.
149
+ *
150
+ * Returns the error schemas that middleware will auto-produce for this route.
151
+ * Route handlers can declare additional error schemas via `RouteSpec.errors`;
152
+ * explicit entries override auto-derived ones for the same status code.
153
+ *
154
+ * Derivation rules:
155
+ * - **Has input schema** (non-null) or **has params schema** or **has query schema**: 400 (validation error with issues)
156
+ * - **auth: authenticated**: 401
157
+ * - **auth: role**: 401 + 403 (with `required_role`)
158
+ * - **auth: keeper**: 401 + 403 (keeper-specific)
159
+ * - **rate_limit**: 429 (rate limit exceeded with `retry_after`)
160
+ *
161
+ * @param auth - the route's auth requirement
162
+ * @param has_input - whether the route has a non-null input schema
163
+ * @param has_params - whether the route has a params schema
164
+ * @param has_query - whether the route has a query schema
165
+ * @param rate_limit - the rate limit key type, if any
166
+ * @returns error schemas keyed by HTTP status code
167
+ */
168
+ export declare const derive_error_schemas: (auth: RouteAuth, has_input: boolean, has_params?: boolean, has_query?: boolean, rate_limit?: RateLimitKey) => RouteErrorSchemas;
169
+ //# sourceMappingURL=error_schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error_schemas.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/error_schemas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Standard error response schemas and error code constants for fuz_app routes.
3
+ *
4
+ * Defines `ERROR_*` constants (single source of truth for machine-parseable
5
+ * error codes), Zod schemas for error response shapes, a type for error schema
6
+ * maps, and `derive_error_schemas` to auto-populate middleware-produced errors
7
+ * from a route's auth requirement and input schema.
8
+ *
9
+ * Used in `RouteSpec.errors` and `MiddlewareSpec.errors` for surface
10
+ * introspection and DEV-mode validation.
11
+ *
12
+ * @module
13
+ */
14
+ import { z } from 'zod';
15
+ // --- Core: Validation (auto-derived by route spec middleware) ---
16
+ /** Request body failed Zod validation. */
17
+ export const ERROR_INVALID_REQUEST_BODY = 'invalid_request_body';
18
+ /** Request body is not valid JSON or not an object. */
19
+ export const ERROR_INVALID_JSON_BODY = 'invalid_json_body';
20
+ /** URL path params failed Zod validation. */
21
+ export const ERROR_INVALID_ROUTE_PARAMS = 'invalid_route_params';
22
+ /** URL query params failed Zod validation. */
23
+ export const ERROR_INVALID_QUERY_PARAMS = 'invalid_query_params';
24
+ // --- Core: Authentication & authorization (auto-derived by auth middleware) ---
25
+ /** No valid session or bearer token. */
26
+ export const ERROR_AUTHENTICATION_REQUIRED = 'authentication_required';
27
+ /** Authenticated but missing required role. */
28
+ export const ERROR_INSUFFICIENT_PERMISSIONS = 'insufficient_permissions';
29
+ /** Rate limiter rejected the request. */
30
+ export const ERROR_RATE_LIMIT_EXCEEDED = 'rate_limit_exceeded';
31
+ /** Username or password is wrong (intentionally vague for enumeration prevention). */
32
+ export const ERROR_INVALID_CREDENTIALS = 'invalid_credentials';
33
+ /** Request body exceeds the maximum allowed size. */
34
+ export const ERROR_PAYLOAD_TOO_LARGE = 'payload_too_large';
35
+ // --- Origin & bearer token verification ---
36
+ /** Request origin not in allowlist. */
37
+ export const ERROR_FORBIDDEN_ORIGIN = 'forbidden_origin';
38
+ /** Request referer not in allowlist. */
39
+ export const ERROR_FORBIDDEN_REFERER = 'forbidden_referer';
40
+ /** Bearer token sent with Origin/Referer header (browser context). */
41
+ export const ERROR_BEARER_REJECTED_BROWSER = 'bearer_token_rejected_in_browser_context';
42
+ /** Bearer token failed validation (missing, malformed, or revoked). */
43
+ export const ERROR_INVALID_TOKEN = 'invalid_token';
44
+ /** Token references a deleted account. */
45
+ export const ERROR_ACCOUNT_NOT_FOUND = 'account_not_found';
46
+ // --- Keeper / daemon token ---
47
+ /** Keeper routes require daemon_token credential type. */
48
+ export const ERROR_KEEPER_REQUIRES_DAEMON_TOKEN = 'keeper_requires_daemon_token';
49
+ /** Daemon token header present but malformed or not matching current/previous token. */
50
+ export const ERROR_INVALID_DAEMON_TOKEN = 'invalid_daemon_token';
51
+ /** Daemon token valid but keeper account not yet resolved (pre-bootstrap). */
52
+ export const ERROR_KEEPER_ACCOUNT_NOT_CONFIGURED = 'keeper_account_not_configured';
53
+ /** Keeper account ID set but account row not found. */
54
+ export const ERROR_KEEPER_ACCOUNT_NOT_FOUND = 'keeper_account_not_found';
55
+ // --- Bootstrap ---
56
+ /** Bootstrap lock already acquired — system already bootstrapped. */
57
+ export const ERROR_ALREADY_BOOTSTRAPPED = 'already_bootstrapped';
58
+ /** Bootstrap token file not found on disk. */
59
+ export const ERROR_TOKEN_FILE_MISSING = 'token_file_missing';
60
+ /** Bootstrap endpoint called but no token path configured. */
61
+ export const ERROR_BOOTSTRAP_NOT_CONFIGURED = 'bootstrap_not_configured';
62
+ // --- Signup / Invites ---
63
+ /** No unclaimed invite matches the signup credentials. */
64
+ export const ERROR_NO_MATCHING_INVITE = 'no_matching_invite';
65
+ /** Signup conflict — username or email already taken (intentionally vague for enumeration prevention). */
66
+ export const ERROR_SIGNUP_CONFLICT = 'signup_conflict';
67
+ /** Invite not found (for delete operations). */
68
+ export const ERROR_INVITE_NOT_FOUND = 'invite_not_found';
69
+ /** Invite must have at least an email or username. */
70
+ export const ERROR_INVITE_MISSING_IDENTIFIER = 'invite_missing_identifier';
71
+ /** An unclaimed invite already exists for this email or username. */
72
+ export const ERROR_INVITE_DUPLICATE = 'invite_duplicate';
73
+ /** An account already exists with this invite's username. */
74
+ export const ERROR_INVITE_ACCOUNT_EXISTS_USERNAME = 'invite_account_exists_username';
75
+ /** An account already exists with this invite's email. */
76
+ export const ERROR_INVITE_ACCOUNT_EXISTS_EMAIL = 'invite_account_exists_email';
77
+ // --- Admin routes ---
78
+ /** Admin tried to grant a role that is not web-grantable. */
79
+ export const ERROR_ROLE_NOT_WEB_GRANTABLE = 'role_not_web_grantable';
80
+ /** Permit ID not found or not owned by the target actor. */
81
+ export const ERROR_PERMIT_NOT_FOUND = 'permit_not_found';
82
+ /** Query parameter `event_type` is not a valid audit event type. */
83
+ export const ERROR_INVALID_EVENT_TYPE = 'invalid_event_type';
84
+ // --- DB table browser ---
85
+ /** DELETE blocked by a foreign key constraint. */
86
+ export const ERROR_FOREIGN_KEY_VIOLATION = 'foreign_key_violation';
87
+ /** Table name not found in `information_schema`. */
88
+ export const ERROR_TABLE_NOT_FOUND = 'table_not_found';
89
+ /** Table has no primary key constraint (cannot delete by PK). */
90
+ export const ERROR_TABLE_NO_PRIMARY_KEY = 'table_no_primary_key';
91
+ /** Row with the given PK value not found. */
92
+ export const ERROR_ROW_NOT_FOUND = 'row_not_found';
93
+ // --- Standard error shapes ---
94
+ // Using z.looseObject — error responses may carry extra context fields.
95
+ /** Base API error — all JSON error responses have at least `{error: string}`. */
96
+ export const ApiError = z.looseObject({ error: z.string() });
97
+ /**
98
+ * Input validation error — returned when the request body fails Zod parsing.
99
+ *
100
+ * `issues` contains the Zod validation issues for diagnostic display.
101
+ */
102
+ export const ValidationError = z.looseObject({
103
+ error: z.string(),
104
+ issues: z.array(z.looseObject({
105
+ code: z.string(),
106
+ message: z.string(),
107
+ path: z.array(z.union([z.string(), z.number()])),
108
+ })),
109
+ });
110
+ /** Permission error — returned by `require_role()` when the required role is missing. */
111
+ export const PermissionError = z.looseObject({
112
+ error: z.literal(ERROR_INSUFFICIENT_PERMISSIONS),
113
+ required_role: z.string(),
114
+ });
115
+ /** Keeper credential error — returned by `require_keeper` when credential type is wrong. */
116
+ export const KeeperError = z.looseObject({
117
+ error: z.literal(ERROR_KEEPER_REQUIRES_DAEMON_TOKEN),
118
+ credential_type: z.string(),
119
+ });
120
+ /** Rate limit error — returned when a rate limiter rejects the request. */
121
+ export const RateLimitError = z.looseObject({
122
+ error: z.literal(ERROR_RATE_LIMIT_EXCEEDED),
123
+ retry_after: z.number(),
124
+ });
125
+ /** Payload too large error — returned when the request body exceeds the size limit. */
126
+ export const PayloadTooLargeError = z.looseObject({
127
+ error: z.literal(ERROR_PAYLOAD_TOO_LARGE),
128
+ });
129
+ /** Foreign key violation error — returned when a delete is blocked by references. */
130
+ export const ForeignKeyError = z.looseObject({
131
+ error: z.literal(ERROR_FOREIGN_KEY_VIOLATION),
132
+ });
133
+ /**
134
+ * Derive error schemas from a route's auth requirement, input schema, and rate limit config.
135
+ *
136
+ * Returns the error schemas that middleware will auto-produce for this route.
137
+ * Route handlers can declare additional error schemas via `RouteSpec.errors`;
138
+ * explicit entries override auto-derived ones for the same status code.
139
+ *
140
+ * Derivation rules:
141
+ * - **Has input schema** (non-null) or **has params schema** or **has query schema**: 400 (validation error with issues)
142
+ * - **auth: authenticated**: 401
143
+ * - **auth: role**: 401 + 403 (with `required_role`)
144
+ * - **auth: keeper**: 401 + 403 (keeper-specific)
145
+ * - **rate_limit**: 429 (rate limit exceeded with `retry_after`)
146
+ *
147
+ * @param auth - the route's auth requirement
148
+ * @param has_input - whether the route has a non-null input schema
149
+ * @param has_params - whether the route has a params schema
150
+ * @param has_query - whether the route has a query schema
151
+ * @param rate_limit - the rate limit key type, if any
152
+ * @returns error schemas keyed by HTTP status code
153
+ */
154
+ export const derive_error_schemas = (auth, has_input, has_params = false, has_query = false, rate_limit) => {
155
+ const errors = {};
156
+ if (has_input || has_params || has_query) {
157
+ errors[400] = ValidationError;
158
+ }
159
+ switch (auth.type) {
160
+ case 'none':
161
+ break;
162
+ case 'authenticated':
163
+ errors[401] = ApiError;
164
+ break;
165
+ case 'role':
166
+ errors[401] = ApiError;
167
+ errors[403] = PermissionError;
168
+ break;
169
+ case 'keeper':
170
+ errors[401] = ApiError;
171
+ errors[403] = KeeperError;
172
+ break;
173
+ }
174
+ if (rate_limit) {
175
+ errors[429] = RateLimitError;
176
+ }
177
+ return errors;
178
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Middleware spec type — named middleware layer definition.
3
+ *
4
+ * Separated from `route_spec.ts` so middleware modules can import this
5
+ * type without creating an upward dependency on routes.
6
+ *
7
+ * @module
8
+ */
9
+ import type { MiddlewareHandler } from 'hono';
10
+ import type { RouteErrorSchemas } from './error_schemas.js';
11
+ /** A named middleware layer. */
12
+ export interface MiddlewareSpec {
13
+ name: string;
14
+ path: string;
15
+ handler: MiddlewareHandler;
16
+ /** Error response schemas this middleware can produce, keyed by HTTP status code. */
17
+ errors?: RouteErrorSchemas;
18
+ }
19
+ //# sourceMappingURL=middleware_spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware_spec.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/middleware_spec.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,MAAM,CAAC;AAE5C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AAE1D,gCAAgC;AAChC,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,iBAAiB,CAAC;IAC3B,qFAAqF;IACrF,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC3B"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Middleware spec type — named middleware layer definition.
3
+ *
4
+ * Separated from `route_spec.ts` so middleware modules can import this
5
+ * type without creating an upward dependency on routes.
6
+ *
7
+ * @module
8
+ */
9
+ export {};
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Request source verification middleware for API protection.
3
+ *
4
+ * Verifies requests are coming from expected origins/referers.
5
+ * CSRF protection is provided by `SameSite: strict` on session cookies
6
+ * (see `session_middleware.ts`). This module provides origin allowlisting
7
+ * for locally-running services — preventing untrusted websites from
8
+ * making requests as the user browses the web.
9
+ *
10
+ * @module
11
+ */
12
+ import type { Handler } from 'hono';
13
+ /**
14
+ * Parses ALLOWED_ORIGINS env var into regex matchers for request source verification.
15
+ * Origin allowlisting for locally-running services — not the CSRF layer
16
+ * (that's `SameSite: strict` on session cookies).
17
+ *
18
+ * Accepts comma-separated patterns with limited wildcards:
19
+ * - Exact origins: `https://api.fuz.dev`
20
+ * - Wildcard subdomains: `https://*.fuz.dev` (matches exactly one subdomain level)
21
+ * - Multiple wildcards: `https://*.staging.*.fuz.dev` (for deep subdomains)
22
+ * - Wildcard ports: `http://localhost:*` (matches any port or no port)
23
+ * - IPv6 addresses: `http://[::1]:3000`, `https://[2001:db8::1]`
24
+ * - Combined: `https://*.fuz.dev:*`
25
+ *
26
+ * Examples:
27
+ * - `http://localhost:3000,https://prod.fuz.dev`
28
+ * - `https://*.api.fuz.dev,http://127.0.0.1:*`
29
+ * - `http://[::1]:*,https://*.*.corp.fuz.dev:*`
30
+ *
31
+ * @throws if any individual pattern is invalid (missing protocol, partial wildcards, etc.)
32
+ */
33
+ export declare const parse_allowed_origins: (env_value: string | undefined) => Array<RegExp>;
34
+ /**
35
+ * Tests if a request source (origin or referer) matches any of the allowed patterns.
36
+ * Pattern matching is case-insensitive for domains (as per web standards).
37
+ */
38
+ export declare const should_allow_origin: (origin: string, allowed_patterns: Array<RegExp>) => boolean;
39
+ /**
40
+ * Middleware that verifies the request source against an allowlist.
41
+ *
42
+ * Origin allowlisting (not the CSRF layer — that's `SameSite: strict` cookies) that:
43
+ * - Checks the Origin header first (if present)
44
+ * - Falls back to Referer header (if no Origin)
45
+ * - Allows requests without Origin/Referer headers (direct access, curl, etc.)
46
+ *
47
+ * This is useful for:
48
+ * - Protecting locally-running services from being called by
49
+ * untrusted websites as the user browses the web
50
+ * - Restricting which domains can make requests to your API
51
+ * - Preventing embedding of your service in unexpected sites
52
+ * - Basic source verification for locally-running services
53
+ *
54
+ * @param allowed_patterns - array of compiled regex patterns from parse_allowed_origins
55
+ */
56
+ export declare const verify_request_source: (allowed_patterns: Array<RegExp>) => Handler;
57
+ //# sourceMappingURL=origin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"origin.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/origin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;AAIlC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,qBAAqB,GAAI,WAAW,MAAM,GAAG,SAAS,KAAG,KAAK,CAAC,MAAM,CAO5E,CAAC;AAEP;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,QAAQ,MAAM,EAAE,kBAAkB,KAAK,CAAC,MAAM,CAAC,KAAG,OACzC,CAAC;AAE9C;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,qBAAqB,GAChC,kBAAkB,KAAK,CAAC,MAAM,CAAC,KAAG,OA2BlC,CAAC"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Request source verification middleware for API protection.
3
+ *
4
+ * Verifies requests are coming from expected origins/referers.
5
+ * CSRF protection is provided by `SameSite: strict` on session cookies
6
+ * (see `session_middleware.ts`). This module provides origin allowlisting
7
+ * for locally-running services — preventing untrusted websites from
8
+ * making requests as the user browses the web.
9
+ *
10
+ * @module
11
+ */
12
+ import { escape_regexp } from '@fuzdev/fuz_util/regexp.js';
13
+ import { ERROR_FORBIDDEN_ORIGIN, ERROR_FORBIDDEN_REFERER } from './error_schemas.js';
14
+ /**
15
+ * Parses ALLOWED_ORIGINS env var into regex matchers for request source verification.
16
+ * Origin allowlisting for locally-running services — not the CSRF layer
17
+ * (that's `SameSite: strict` on session cookies).
18
+ *
19
+ * Accepts comma-separated patterns with limited wildcards:
20
+ * - Exact origins: `https://api.fuz.dev`
21
+ * - Wildcard subdomains: `https://*.fuz.dev` (matches exactly one subdomain level)
22
+ * - Multiple wildcards: `https://*.staging.*.fuz.dev` (for deep subdomains)
23
+ * - Wildcard ports: `http://localhost:*` (matches any port or no port)
24
+ * - IPv6 addresses: `http://[::1]:3000`, `https://[2001:db8::1]`
25
+ * - Combined: `https://*.fuz.dev:*`
26
+ *
27
+ * Examples:
28
+ * - `http://localhost:3000,https://prod.fuz.dev`
29
+ * - `https://*.api.fuz.dev,http://127.0.0.1:*`
30
+ * - `http://[::1]:*,https://*.*.corp.fuz.dev:*`
31
+ *
32
+ * @throws if any individual pattern is invalid (missing protocol, partial wildcards, etc.)
33
+ */
34
+ export const parse_allowed_origins = (env_value) => env_value
35
+ ? env_value
36
+ .split(',')
37
+ .map((s) => s.trim())
38
+ .filter(Boolean)
39
+ .map(origin_pattern_to_regexp)
40
+ : [];
41
+ /**
42
+ * Tests if a request source (origin or referer) matches any of the allowed patterns.
43
+ * Pattern matching is case-insensitive for domains (as per web standards).
44
+ */
45
+ export const should_allow_origin = (origin, allowed_patterns) => allowed_patterns.some((p) => p.test(origin));
46
+ /**
47
+ * Middleware that verifies the request source against an allowlist.
48
+ *
49
+ * Origin allowlisting (not the CSRF layer — that's `SameSite: strict` cookies) that:
50
+ * - Checks the Origin header first (if present)
51
+ * - Falls back to Referer header (if no Origin)
52
+ * - Allows requests without Origin/Referer headers (direct access, curl, etc.)
53
+ *
54
+ * This is useful for:
55
+ * - Protecting locally-running services from being called by
56
+ * untrusted websites as the user browses the web
57
+ * - Restricting which domains can make requests to your API
58
+ * - Preventing embedding of your service in unexpected sites
59
+ * - Basic source verification for locally-running services
60
+ *
61
+ * @param allowed_patterns - array of compiled regex patterns from parse_allowed_origins
62
+ */
63
+ export const verify_request_source = (allowed_patterns) => (c, next) => {
64
+ // Check origin header (preferred, sent by browsers for CORS requests).
65
+ // Uses !== undefined so empty-string Origin headers are treated as
66
+ // present (abnormal, checked against allowlist — empty string never matches).
67
+ const origin = c.req.header('origin');
68
+ if (origin !== undefined) {
69
+ if (!should_allow_origin(origin, allowed_patterns)) {
70
+ return c.json({ error: ERROR_FORBIDDEN_ORIGIN }, 403);
71
+ }
72
+ return next();
73
+ }
74
+ // Check referer header (fallback for some requests like gets and navigation).
75
+ // Same !== undefined check as origin.
76
+ const referer = c.req.header('referer');
77
+ if (referer !== undefined) {
78
+ const referer_origin = extract_origin_from_referer(referer);
79
+ if (!should_allow_origin(referer_origin, allowed_patterns)) {
80
+ return c.json({ error: ERROR_FORBIDDEN_REFERER }, 403);
81
+ }
82
+ return next();
83
+ }
84
+ // No origin or referer - direct access (curl, CLI, etc.)
85
+ // Allow through since token auth is the primary security control.
86
+ return next();
87
+ };
88
+ /**
89
+ * Converts origin patterns with wildcards to regex patterns.
90
+ *
91
+ * Pattern format: protocol://hostname[:port]
92
+ *
93
+ * Wildcard support:
94
+ * - Subdomain wildcards: `*.fuz.dev` matches `sub.fuz.dev` (NOT `fuz.dev`)
95
+ * - Multiple wildcards: `*.*.fuz.dev` matches `api.staging.fuz.dev`
96
+ * - Port wildcards: `fuz.dev:*` matches any port or no port
97
+ * - IPv6 support: `[::1]`, `[2001:db8::1]` (no wildcards in IPv6)
98
+ *
99
+ * Restrictions:
100
+ * - No paths allowed (origins don't include paths)
101
+ * - Wildcards must be complete labels (`*.fuz.dev`, not `*fuz.dev`)
102
+ * - No wildcards in IPv6 addresses
103
+ * - Port wildcards must be `:*` exactly
104
+ *
105
+ * Note: Patterns are normalized via URL constructor. IPv4-mapped IPv6 addresses
106
+ * like `[::ffff:127.0.0.1]` will be normalized to `[::ffff:7f00:1]`. IPv6 zone
107
+ * identifiers (e.g., `%eth0`) are not supported.
108
+ *
109
+ * @throws if pattern format is invalid
110
+ */
111
+ const origin_pattern_to_regexp = (pattern) => {
112
+ // Quick validation: no paths, query strings, or fragments allowed
113
+ const protocol_idx = pattern.indexOf('://');
114
+ if (protocol_idx === -1) {
115
+ throw new Error(`Invalid origin pattern: ${pattern}`);
116
+ }
117
+ const after_protocol = pattern.slice(protocol_idx + 3);
118
+ if (/[/?#]/.test(after_protocol)) {
119
+ throw new Error(`Paths not allowed in origin patterns: ${pattern}`);
120
+ }
121
+ // Check for wildcards in IPv6 before URL parsing (URL rejects these with unhelpful error)
122
+ const ipv6_match = /^\[([^\]]+)\]/.exec(after_protocol);
123
+ if (ipv6_match?.[1]?.includes('*')) {
124
+ throw new Error(`Wildcards not allowed in IPv6 addresses: ${pattern}`);
125
+ }
126
+ // Handle port wildcard - must be at the end
127
+ let port_wildcard = false;
128
+ let parse_pattern = pattern;
129
+ if (pattern.endsWith(':*')) {
130
+ port_wildcard = true;
131
+ parse_pattern = pattern.slice(0, -2);
132
+ }
133
+ // Parse with URL constructor for robust handling of protocol, hostname, port, IPv6
134
+ let url;
135
+ try {
136
+ url = new URL(parse_pattern);
137
+ }
138
+ catch {
139
+ throw new Error(`Invalid origin pattern: ${pattern}`);
140
+ }
141
+ // Validate protocol is http or https
142
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') {
143
+ throw new Error(`Invalid origin pattern: ${pattern}`);
144
+ }
145
+ const hostname = url.hostname;
146
+ const is_ipv6 = hostname.startsWith('[');
147
+ // For regular hostnames, wildcards must be complete labels
148
+ if (!is_ipv6) {
149
+ for (const label of hostname.split('.')) {
150
+ if (label.includes('*') && label !== '*') {
151
+ throw new Error(`Wildcards must be complete labels (e.g., *.fuz.dev, not *fuz.dev): ${pattern}`);
152
+ }
153
+ }
154
+ }
155
+ // Build regex pattern
156
+ let regex_pattern = '^' + escape_regexp(url.protocol) + '//';
157
+ // Handle hostname
158
+ if (is_ipv6) {
159
+ // IPv6 address - URL.hostname includes brackets
160
+ regex_pattern += escape_regexp(hostname);
161
+ }
162
+ else {
163
+ // Regular hostname - process wildcards
164
+ const labels = hostname.split('.');
165
+ regex_pattern += labels
166
+ .map((label) => (label === '*' ? '[^./:]+' : escape_regexp(label)))
167
+ .join('\\.');
168
+ }
169
+ // Handle port
170
+ if (port_wildcard) {
171
+ // Optional port (matches both with and without port)
172
+ regex_pattern += '(:\\d+)?';
173
+ }
174
+ else {
175
+ // URL normalizes default ports (80 for HTTP, 443 for HTTPS) away,
176
+ // so check original pattern for explicit port when url.port is empty
177
+ let port = url.port;
178
+ if (!port) {
179
+ const port_match = /:(\d+)$/.exec(parse_pattern);
180
+ if (port_match?.[1]) {
181
+ port = port_match[1];
182
+ }
183
+ }
184
+ if (port) {
185
+ regex_pattern += ':' + escape_regexp(port);
186
+ }
187
+ }
188
+ regex_pattern += '$';
189
+ // Case-insensitive matching (web standards specify domains are case-insensitive)
190
+ return new RegExp(regex_pattern, 'i');
191
+ };
192
+ /**
193
+ * Extracts the origin from a referer URL, removing the path, query string, and fragment.
194
+ *
195
+ * @param referer - the referer URL (e.g., `https://fuz.dev/path?query#hash`)
196
+ * @returns the origin part (e.g., `https://fuz.dev`)
197
+ */
198
+ const extract_origin_from_referer = (referer) => {
199
+ try {
200
+ return new URL(referer).origin;
201
+ }
202
+ catch {
203
+ // If URL parsing fails, return the original string
204
+ // (it will likely fail pattern matching anyway)
205
+ return referer;
206
+ }
207
+ };