@bajustone/fortress 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. package/CHANGELOG.md +1011 -0
  2. package/LICENSE +21 -0
  3. package/README.md +760 -0
  4. package/SECURITY.md +197 -0
  5. package/bin/fortress.ts +667 -0
  6. package/dist/auth-service-BcyQ2PuZ.d.cts +307 -0
  7. package/dist/auth-service-BkzZkWfH.d.ts +307 -0
  8. package/dist/config-B2366s_G.d.ts +665 -0
  9. package/dist/config-GtlVt6ZD.d.cts +665 -0
  10. package/dist/convert-routes-BLCQT57f.d.ts +72 -0
  11. package/dist/convert-routes-BdMvP2_X.d.cts +72 -0
  12. package/dist/crypto.cjs +61 -0
  13. package/dist/crypto.d.cts +36 -0
  14. package/dist/crypto.d.ts +36 -0
  15. package/dist/crypto.js +35 -0
  16. package/dist/drift-BT1wtMDJ.d.cts +22 -0
  17. package/dist/drift-k9LiYpRP.d.ts +22 -0
  18. package/dist/drizzle/pg.cjs +481 -0
  19. package/dist/drizzle/pg.d.cts +15 -0
  20. package/dist/drizzle/pg.d.ts +15 -0
  21. package/dist/drizzle/pg.js +454 -0
  22. package/dist/drizzle.cjs +1442 -0
  23. package/dist/drizzle.d.cts +85 -0
  24. package/dist/drizzle.d.ts +85 -0
  25. package/dist/drizzle.js +1411 -0
  26. package/dist/express.cjs +1357 -0
  27. package/dist/express.d.cts +333 -0
  28. package/dist/express.d.ts +333 -0
  29. package/dist/express.js +1314 -0
  30. package/dist/fetcher.cjs +77 -0
  31. package/dist/fetcher.d.cts +7 -0
  32. package/dist/fetcher.d.ts +7 -0
  33. package/dist/fetcher.js +41 -0
  34. package/dist/fortress-BmSvFfqK.d.cts +1089 -0
  35. package/dist/fortress-uA-_cheR.d.ts +1089 -0
  36. package/dist/hono.cjs +1530 -0
  37. package/dist/hono.d.cts +514 -0
  38. package/dist/hono.d.ts +514 -0
  39. package/dist/hono.js +1483 -0
  40. package/dist/index-CxEkfCA0.d.cts +77 -0
  41. package/dist/index-CxEkfCA0.d.ts +77 -0
  42. package/dist/index-D054pcb-.d.cts +146 -0
  43. package/dist/index-jAMbbUAY.d.ts +146 -0
  44. package/dist/index.cjs +9046 -0
  45. package/dist/index.d.cts +717 -0
  46. package/dist/index.d.ts +717 -0
  47. package/dist/index.js +8935 -0
  48. package/dist/jwt.cjs +255 -0
  49. package/dist/jwt.d.cts +90 -0
  50. package/dist/jwt.d.ts +90 -0
  51. package/dist/jwt.js +227 -0
  52. package/dist/otel.cjs +108 -0
  53. package/dist/otel.d.cts +62 -0
  54. package/dist/otel.d.ts +62 -0
  55. package/dist/otel.js +73 -0
  56. package/dist/plugins/account-lockout.cjs +322 -0
  57. package/dist/plugins/account-lockout.d.cts +42 -0
  58. package/dist/plugins/account-lockout.d.ts +42 -0
  59. package/dist/plugins/account-lockout.js +295 -0
  60. package/dist/plugins/admin.cjs +2378 -0
  61. package/dist/plugins/admin.d.cts +72 -0
  62. package/dist/plugins/admin.d.ts +72 -0
  63. package/dist/plugins/admin.js +2351 -0
  64. package/dist/plugins/api-key.cjs +792 -0
  65. package/dist/plugins/api-key.d.cts +121 -0
  66. package/dist/plugins/api-key.d.ts +121 -0
  67. package/dist/plugins/api-key.js +765 -0
  68. package/dist/plugins/audit-log.cjs +493 -0
  69. package/dist/plugins/audit-log.d.cts +86 -0
  70. package/dist/plugins/audit-log.d.ts +86 -0
  71. package/dist/plugins/audit-log.js +468 -0
  72. package/dist/plugins/data-isolation.cjs +211 -0
  73. package/dist/plugins/data-isolation.d.cts +49 -0
  74. package/dist/plugins/data-isolation.d.ts +49 -0
  75. package/dist/plugins/data-isolation.js +186 -0
  76. package/dist/plugins/email-verification.cjs +273 -0
  77. package/dist/plugins/email-verification.d.cts +44 -0
  78. package/dist/plugins/email-verification.d.ts +44 -0
  79. package/dist/plugins/email-verification.js +246 -0
  80. package/dist/plugins/magic-link.cjs +231 -0
  81. package/dist/plugins/magic-link.d.cts +39 -0
  82. package/dist/plugins/magic-link.d.ts +39 -0
  83. package/dist/plugins/magic-link.js +204 -0
  84. package/dist/plugins/oauth.cjs +1696 -0
  85. package/dist/plugins/oauth.d.cts +406 -0
  86. package/dist/plugins/oauth.d.ts +406 -0
  87. package/dist/plugins/oauth.js +1669 -0
  88. package/dist/plugins/openapi.cjs +1185 -0
  89. package/dist/plugins/openapi.d.cts +6 -0
  90. package/dist/plugins/openapi.d.ts +6 -0
  91. package/dist/plugins/openapi.js +1158 -0
  92. package/dist/plugins/rate-limit/express.cjs +55 -0
  93. package/dist/plugins/rate-limit/express.d.cts +64 -0
  94. package/dist/plugins/rate-limit/express.d.ts +64 -0
  95. package/dist/plugins/rate-limit/express.js +30 -0
  96. package/dist/plugins/rate-limit/hono.cjs +51 -0
  97. package/dist/plugins/rate-limit/hono.d.cts +59 -0
  98. package/dist/plugins/rate-limit/hono.d.ts +59 -0
  99. package/dist/plugins/rate-limit/hono.js +26 -0
  100. package/dist/plugins/rate-limit/sveltekit.cjs +49 -0
  101. package/dist/plugins/rate-limit/sveltekit.d.cts +59 -0
  102. package/dist/plugins/rate-limit/sveltekit.d.ts +59 -0
  103. package/dist/plugins/rate-limit/sveltekit.js +24 -0
  104. package/dist/plugins/rate-limit.cjs +354 -0
  105. package/dist/plugins/rate-limit.d.cts +140 -0
  106. package/dist/plugins/rate-limit.d.ts +140 -0
  107. package/dist/plugins/rate-limit.js +325 -0
  108. package/dist/plugins/social-login.cjs +905 -0
  109. package/dist/plugins/social-login.d.cts +114 -0
  110. package/dist/plugins/social-login.d.ts +114 -0
  111. package/dist/plugins/social-login.js +880 -0
  112. package/dist/plugins/tenancy.cjs +780 -0
  113. package/dist/plugins/tenancy.d.cts +108 -0
  114. package/dist/plugins/tenancy.d.ts +108 -0
  115. package/dist/plugins/tenancy.js +753 -0
  116. package/dist/plugins/two-factor.cjs +555 -0
  117. package/dist/plugins/two-factor.d.cts +67 -0
  118. package/dist/plugins/two-factor.d.ts +67 -0
  119. package/dist/plugins/two-factor.js +526 -0
  120. package/dist/plugins/webauthn.cjs +786 -0
  121. package/dist/plugins/webauthn.d.cts +72 -0
  122. package/dist/plugins/webauthn.d.ts +72 -0
  123. package/dist/plugins/webauthn.js +766 -0
  124. package/dist/plugins/webhook.cjs +819 -0
  125. package/dist/plugins/webhook.d.cts +254 -0
  126. package/dist/plugins/webhook.d.ts +254 -0
  127. package/dist/plugins/webhook.js +789 -0
  128. package/dist/protect-D1v_0upK.d.cts +123 -0
  129. package/dist/protect-DsxV_-dJ.d.ts +123 -0
  130. package/dist/sveltekit.cjs +1258 -0
  131. package/dist/sveltekit.d.cts +420 -0
  132. package/dist/sveltekit.d.ts +420 -0
  133. package/dist/sveltekit.js +1207 -0
  134. package/dist/testing.cjs +4294 -0
  135. package/dist/testing.d.cts +197 -0
  136. package/dist/testing.d.ts +197 -0
  137. package/dist/testing.js +4264 -0
  138. package/dist/types-et0R8tsC.d.cts +217 -0
  139. package/dist/types-et0R8tsC.d.ts +217 -0
  140. package/docs/adapter-typed-helpers.md +192 -0
  141. package/docs/admin-recipes.md +227 -0
  142. package/docs/architecture.md +434 -0
  143. package/docs/ci/github-actions.yml +59 -0
  144. package/docs/ci.md +109 -0
  145. package/docs/compatibility.md +115 -0
  146. package/docs/deployment.md +305 -0
  147. package/docs/hardening.md +118 -0
  148. package/docs/host-owned-routes.md +154 -0
  149. package/docs/migrations/0001-schema-version.md +54 -0
  150. package/docs/migrations/0002-initial-schema.md +84 -0
  151. package/docs/migrations/upgrade-guide.md +160 -0
  152. package/docs/observability.md +394 -0
  153. package/docs/plugins/account-lockout.md +131 -0
  154. package/docs/plugins/admin.md +402 -0
  155. package/docs/plugins/api-key.md +327 -0
  156. package/docs/plugins/audit-log.md +261 -0
  157. package/docs/plugins/data-isolation.md +186 -0
  158. package/docs/plugins/email-verification.md +121 -0
  159. package/docs/plugins/magic-link.md +123 -0
  160. package/docs/plugins/oauth.md +544 -0
  161. package/docs/plugins/openapi.md +250 -0
  162. package/docs/plugins/rate-limit.md +223 -0
  163. package/docs/plugins/social-login.md +337 -0
  164. package/docs/plugins/tenancy.md +122 -0
  165. package/docs/plugins/two-factor.md +191 -0
  166. package/docs/plugins/webauthn.md +188 -0
  167. package/docs/plugins/webhook.md +242 -0
  168. package/docs/policy-as-code.md +156 -0
  169. package/docs/route-manifest.md +46 -0
  170. package/docs/security.md +261 -0
  171. package/docs/threat-model.md +161 -0
  172. package/examples/README.md +119 -0
  173. package/examples/express-app/index.ts +747 -0
  174. package/examples/hono-app/docker-compose.yml +14 -0
  175. package/examples/hono-app/index.ts +1009 -0
  176. package/examples/policy/fortress.policy.json +47 -0
  177. package/examples/sveltekit-app/README.md +125 -0
  178. package/examples/sveltekit-app/src/app.d.ts +16 -0
  179. package/examples/sveltekit-app/src/hooks.server.ts +23 -0
  180. package/examples/sveltekit-app/src/lib/server/fortress.ts +81 -0
  181. package/examples/sveltekit-app/src/routes/api/echo/[id]/+server.ts +32 -0
  182. package/examples/sveltekit-app/src/routes/api/fortress/[...path]/+server.ts +15 -0
  183. package/examples/sveltekit-app/src/routes/dashboard/+page.server.ts +20 -0
  184. package/examples/sveltekit-app/src/routes/login/+page.server.ts +48 -0
  185. package/examples/sveltekit-app/src/routes/oauth/consent/+page.server.ts +69 -0
  186. package/examples/sveltekit-app/src/routes/oauth/consent/+page.svelte +83 -0
  187. package/migrations/pg/0001_schema_version.down.sql +2 -0
  188. package/migrations/pg/0001_schema_version.sql +8 -0
  189. package/migrations/pg/0002_initial_schema.down.sql +36 -0
  190. package/migrations/pg/0002_initial_schema.sql +376 -0
  191. package/migrations/pg/0003_auth_continuation.down.sql +6 -0
  192. package/migrations/pg/0003_auth_continuation.sql +30 -0
  193. package/migrations/pg/0004_tenant_default_unique.down.sql +1 -0
  194. package/migrations/pg/0004_tenant_default_unique.sql +14 -0
  195. package/migrations/pg/0005_hot_indexes_timestamptz.down.sql +71 -0
  196. package/migrations/pg/0005_hot_indexes_timestamptz.sql +71 -0
  197. package/migrations/pg/0006_canonical_email.down.sql +3 -0
  198. package/migrations/pg/0006_canonical_email.sql +8 -0
  199. package/migrations/pg/0007_audit_chain_anchor.down.sql +1 -0
  200. package/migrations/pg/0007_audit_chain_anchor.sql +8 -0
  201. package/migrations/pg/0008_two_factor_hardening.down.sql +8 -0
  202. package/migrations/pg/0008_two_factor_hardening.sql +8 -0
  203. package/migrations/pg/0009_encrypt_totp_secrets.down.sql +2 -0
  204. package/migrations/pg/0009_encrypt_totp_secrets.sql +5 -0
  205. package/migrations/pg/0010_bigint_append_only_ids.down.sql +2 -0
  206. package/migrations/pg/0010_bigint_append_only_ids.sql +23 -0
  207. package/migrations/sqlite/0001_schema_version.down.sql +2 -0
  208. package/migrations/sqlite/0001_schema_version.sql +8 -0
  209. package/migrations/sqlite/0002_initial_schema.down.sql +36 -0
  210. package/migrations/sqlite/0002_initial_schema.sql +376 -0
  211. package/migrations/sqlite/0003_auth_continuation.down.sql +27 -0
  212. package/migrations/sqlite/0003_auth_continuation.sql +45 -0
  213. package/migrations/sqlite/0004_tenant_default_unique.down.sql +1 -0
  214. package/migrations/sqlite/0004_tenant_default_unique.sql +13 -0
  215. package/migrations/sqlite/0005_hot_indexes_timestamptz.down.sql +10 -0
  216. package/migrations/sqlite/0005_hot_indexes_timestamptz.sql +10 -0
  217. package/migrations/sqlite/0006_canonical_email.down.sql +3 -0
  218. package/migrations/sqlite/0006_canonical_email.sql +8 -0
  219. package/migrations/sqlite/0007_audit_chain_anchor.down.sql +1 -0
  220. package/migrations/sqlite/0007_audit_chain_anchor.sql +8 -0
  221. package/migrations/sqlite/0008_two_factor_hardening.down.sql +14 -0
  222. package/migrations/sqlite/0008_two_factor_hardening.sql +7 -0
  223. package/migrations/sqlite/0009_encrypt_totp_secrets.down.sql +2 -0
  224. package/migrations/sqlite/0009_encrypt_totp_secrets.sql +5 -0
  225. package/migrations/sqlite/0010_bigint_append_only_ids.down.sql +1 -0
  226. package/migrations/sqlite/0010_bigint_append_only_ids.sql +2 -0
  227. package/package.json +398 -0
  228. package/src/adapters/database/index.ts +63 -0
  229. package/src/adapters/database/types.ts +22 -0
  230. package/src/changelog-script.test.ts +21 -0
  231. package/src/cli.test.ts +79 -0
  232. package/src/core/auth/auth-admin.test.ts +247 -0
  233. package/src/core/auth/auth-endpoints.ts +558 -0
  234. package/src/core/auth/auth-observer.test.ts +191 -0
  235. package/src/core/auth/auth-service.ts +1464 -0
  236. package/src/core/auth/email.test.ts +17 -0
  237. package/src/core/auth/email.ts +11 -0
  238. package/src/core/auth/hooks.test.ts +251 -0
  239. package/src/core/auth/impersonation.test.ts +179 -0
  240. package/src/core/auth/jwt.test.ts +184 -0
  241. package/src/core/auth/jwt.ts +239 -0
  242. package/src/core/auth/login-timing.test.ts +77 -0
  243. package/src/core/auth/password-policy.test.ts +253 -0
  244. package/src/core/auth/password-policy.ts +220 -0
  245. package/src/core/auth/password.test.ts +42 -0
  246. package/src/core/auth/password.ts +62 -0
  247. package/src/core/auth/post-auth-gate.test.ts +258 -0
  248. package/src/core/auth/post-auth-gate.ts +228 -0
  249. package/src/core/auth/refresh-token.test.ts +86 -0
  250. package/src/core/auth/refresh-token.ts +105 -0
  251. package/src/core/auth/timing-safe.ts +23 -0
  252. package/src/core/config.ts +212 -0
  253. package/src/core/endpoint.ts +149 -0
  254. package/src/core/errors.ts +199 -0
  255. package/src/core/fetcher-interop.test.ts +106 -0
  256. package/src/core/fortress.test.ts +354 -0
  257. package/src/core/fortress.ts +550 -0
  258. package/src/core/http/call.test.ts +148 -0
  259. package/src/core/http/call.ts +149 -0
  260. package/src/core/http/cookie-serialize.test.ts +198 -0
  261. package/src/core/http/cookie-serialize.ts +107 -0
  262. package/src/core/http/csrf.test.ts +140 -0
  263. package/src/core/http/csrf.ts +173 -0
  264. package/src/core/http/dispatch.ts +652 -0
  265. package/src/core/http/error-response.test.ts +69 -0
  266. package/src/core/http/error-response.ts +93 -0
  267. package/src/core/http/fortress-rbac.test.ts +43 -0
  268. package/src/core/http/fortress-rbac.ts +127 -0
  269. package/src/core/http/handle-request.test.ts +441 -0
  270. package/src/core/http/handle-request.ts +354 -0
  271. package/src/core/http/match.test.ts +122 -0
  272. package/src/core/http/match.ts +126 -0
  273. package/src/core/http/outbound.test.ts +34 -0
  274. package/src/core/http/outbound.ts +105 -0
  275. package/src/core/http/plugin-middleware.ts +67 -0
  276. package/src/core/http/principal.test.ts +345 -0
  277. package/src/core/http/principal.ts +86 -0
  278. package/src/core/http/protect.test.ts +220 -0
  279. package/src/core/http/protect.ts +394 -0
  280. package/src/core/http/token-extraction.test.ts +59 -0
  281. package/src/core/http/token-extraction.ts +53 -0
  282. package/src/core/iam/explain.test.ts +177 -0
  283. package/src/core/iam/explain.ts +302 -0
  284. package/src/core/iam/iam-endpoints.ts +779 -0
  285. package/src/core/iam/iam-service.test.ts +829 -0
  286. package/src/core/iam/iam-service.ts +1137 -0
  287. package/src/core/iam/permission-cache.test.ts +115 -0
  288. package/src/core/iam/permission-cache.ts +71 -0
  289. package/src/core/iam/permission-check-observer.test.ts +90 -0
  290. package/src/core/iam/permission-evaluator.test.ts +291 -0
  291. package/src/core/iam/permission-evaluator.ts +198 -0
  292. package/src/core/iam/permission-sync.test.ts +166 -0
  293. package/src/core/iam/permission-sync.ts +192 -0
  294. package/src/core/iam/resource-sync.test.ts +70 -0
  295. package/src/core/iam/resource-sync.ts +182 -0
  296. package/src/core/iam/service-account-http.test.ts +529 -0
  297. package/src/core/iam/service-account.test.ts +282 -0
  298. package/src/core/internal-adapter.test.ts +389 -0
  299. package/src/core/internal-adapter.ts +435 -0
  300. package/src/core/json-schema.ts +50 -0
  301. package/src/core/manifest/__snapshots__/route-manifest.test.ts.snap +192 -0
  302. package/src/core/manifest/drift.ts +103 -0
  303. package/src/core/manifest/route-manifest.test.ts +142 -0
  304. package/src/core/manifest/route-manifest.ts +154 -0
  305. package/src/core/migrate.test.ts +72 -0
  306. package/src/core/migrations/engine.test.ts +308 -0
  307. package/src/core/migrations/engine.ts +548 -0
  308. package/src/core/migrations/migrations.ts +1771 -0
  309. package/src/core/migrations/pg-migration.integration-test.ts +353 -0
  310. package/src/core/migrations/upgrade-fixture.test.ts +378 -0
  311. package/src/core/observability/db-instrumentation.ts +205 -0
  312. package/src/core/observability/listener-list.test.ts +124 -0
  313. package/src/core/observability/listener-list.ts +73 -0
  314. package/src/core/observability/logger.test.ts +43 -0
  315. package/src/core/observability/logger.ts +49 -0
  316. package/src/core/observability/spans.test.ts +193 -0
  317. package/src/core/observability/types.ts +80 -0
  318. package/src/core/openapi-drift.test.ts +41 -0
  319. package/src/core/openapi.ts +47 -0
  320. package/src/core/plugin-methods-map.ts +75 -0
  321. package/src/core/plugin-runner.test.ts +233 -0
  322. package/src/core/plugin-runner.ts +276 -0
  323. package/src/core/plugin.ts +210 -0
  324. package/src/core/policy/apply.ts +272 -0
  325. package/src/core/policy/diff.ts +288 -0
  326. package/src/core/policy/loader.test.ts +63 -0
  327. package/src/core/policy/loader.ts +214 -0
  328. package/src/core/policy/policy.test.ts +232 -0
  329. package/src/core/policy/types.ts +105 -0
  330. package/src/core/schema-builder.test.ts +660 -0
  331. package/src/core/schema-builder.ts +881 -0
  332. package/src/core/standard-schema.ts +56 -0
  333. package/src/core/types.ts +258 -0
  334. package/src/core/validation.test.ts +195 -0
  335. package/src/core/validation.ts +192 -0
  336. package/src/drizzle/adapter.test.ts +425 -0
  337. package/src/drizzle/adapter.ts +474 -0
  338. package/src/drizzle/index.ts +31 -0
  339. package/src/drizzle/pg/adapter.integration-test.ts +456 -0
  340. package/src/drizzle/pg/index.ts +13 -0
  341. package/src/drizzle/pg/pg.integration-test.ts +1539 -0
  342. package/src/drizzle/pg/schema.ts +539 -0
  343. package/src/drizzle/pg-error-map.test.ts +218 -0
  344. package/src/drizzle/pg-error-map.ts +151 -0
  345. package/src/drizzle/schema.ts +544 -0
  346. package/src/drizzle/sqlite-serialization.test.ts +106 -0
  347. package/src/express/express-api-key-user-routes.test.ts +241 -0
  348. package/src/express/express.test.ts +442 -0
  349. package/src/express/handle.ts +191 -0
  350. package/src/express/index.ts +62 -0
  351. package/src/express/middleware.ts +551 -0
  352. package/src/express/protect.ts +154 -0
  353. package/src/express/validated.test.ts +86 -0
  354. package/src/express/validated.ts +99 -0
  355. package/src/fetcher/index.ts +81 -0
  356. package/src/hono/convert-routes.test.ts +220 -0
  357. package/src/hono/convert-routes.ts +196 -0
  358. package/src/hono/converters.test.ts +50 -0
  359. package/src/hono/converters.ts +43 -0
  360. package/src/hono/handle.ts +79 -0
  361. package/src/hono/helpers.ts +2 -0
  362. package/src/hono/hono-api-key-user-routes.test.ts +225 -0
  363. package/src/hono/hono-handlers.test.ts +861 -0
  364. package/src/hono/hono.test.ts +454 -0
  365. package/src/hono/index.ts +101 -0
  366. package/src/hono/middleware/auth.ts +236 -0
  367. package/src/hono/middleware/auth.types.test.ts +94 -0
  368. package/src/hono/middleware/csrf.test.ts +127 -0
  369. package/src/hono/middleware/csrf.ts +68 -0
  370. package/src/hono/middleware/error-handler.ts +12 -0
  371. package/src/hono/middleware/plugin-middleware.ts +35 -0
  372. package/src/hono/middleware/rbac.ts +131 -0
  373. package/src/hono/middleware/security-headers.test.ts +88 -0
  374. package/src/hono/middleware/security-headers.ts +68 -0
  375. package/src/hono/openapi.ts +237 -0
  376. package/src/hono/protect.ts +87 -0
  377. package/src/hono/validated.test.ts +123 -0
  378. package/src/hono/validated.ts +62 -0
  379. package/src/index.ts +309 -0
  380. package/src/integration.test.ts +718 -0
  381. package/src/internal/changelog.ts +56 -0
  382. package/src/otel/index.ts +158 -0
  383. package/src/otel/otel-types.test.ts +35 -0
  384. package/src/otel/otel.test.ts +235 -0
  385. package/src/plugins/account-lockout/account-lockout.test.ts +367 -0
  386. package/src/plugins/account-lockout/index.ts +267 -0
  387. package/src/plugins/admin/admin-api-key.test.ts +438 -0
  388. package/src/plugins/admin/index.ts +1612 -0
  389. package/src/plugins/api-key/api-key.test.ts +684 -0
  390. package/src/plugins/api-key/core.ts +336 -0
  391. package/src/plugins/api-key/index.ts +315 -0
  392. package/src/plugins/audit-log/audit-log.test.ts +749 -0
  393. package/src/plugins/audit-log/index.ts +680 -0
  394. package/src/plugins/data-isolation/data-isolation.test.ts +197 -0
  395. package/src/plugins/data-isolation/index.ts +157 -0
  396. package/src/plugins/email-verification/email-verification.test.ts +199 -0
  397. package/src/plugins/email-verification/index.ts +190 -0
  398. package/src/plugins/magic-link/index.ts +129 -0
  399. package/src/plugins/magic-link/magic-link.test.ts +156 -0
  400. package/src/plugins/oauth/id-token.ts +86 -0
  401. package/src/plugins/oauth/index.ts +2145 -0
  402. package/src/plugins/oauth/jwks.test.ts +32 -0
  403. package/src/plugins/oauth/jwks.ts +182 -0
  404. package/src/plugins/oauth/oauth.test.ts +2220 -0
  405. package/src/plugins/oauth/pkce.ts +58 -0
  406. package/src/plugins/openapi/index.ts +298 -0
  407. package/src/plugins/openapi/openapi.test.ts +425 -0
  408. package/src/plugins/openapi/spec-builder.ts +287 -0
  409. package/src/plugins/rate-limit/express.test.ts +89 -0
  410. package/src/plugins/rate-limit/express.ts +86 -0
  411. package/src/plugins/rate-limit/hono.test.ts +60 -0
  412. package/src/plugins/rate-limit/hono.ts +74 -0
  413. package/src/plugins/rate-limit/index.ts +383 -0
  414. package/src/plugins/rate-limit/memory-store.ts +61 -0
  415. package/src/plugins/rate-limit/rate-limit.test.ts +756 -0
  416. package/src/plugins/rate-limit/sveltekit.test.ts +58 -0
  417. package/src/plugins/rate-limit/sveltekit.ts +66 -0
  418. package/src/plugins/social-login/index.ts +715 -0
  419. package/src/plugins/social-login/providers/apple.ts +34 -0
  420. package/src/plugins/social-login/providers/discord.ts +26 -0
  421. package/src/plugins/social-login/providers/github.ts +54 -0
  422. package/src/plugins/social-login/providers/google.ts +23 -0
  423. package/src/plugins/social-login/providers/index.ts +22 -0
  424. package/src/plugins/social-login/providers/microsoft.ts +35 -0
  425. package/src/plugins/social-login/providers/oidc.ts +37 -0
  426. package/src/plugins/social-login/providers/providers.test.ts +211 -0
  427. package/src/plugins/social-login/social-login.test.ts +675 -0
  428. package/src/plugins/social-login/types.ts +80 -0
  429. package/src/plugins/tenancy/index.ts +544 -0
  430. package/src/plugins/tenancy/tenancy.test.ts +323 -0
  431. package/src/plugins/two-factor/index.ts +569 -0
  432. package/src/plugins/two-factor/two-factor.test.ts +235 -0
  433. package/src/plugins/webauthn/index.ts +554 -0
  434. package/src/plugins/webauthn/webauthn.test.ts +472 -0
  435. package/src/plugins/webhook/builtin-events.ts +29 -0
  436. package/src/plugins/webhook/delivery.test.ts +51 -0
  437. package/src/plugins/webhook/delivery.ts +154 -0
  438. package/src/plugins/webhook/hooks.ts +89 -0
  439. package/src/plugins/webhook/index.ts +445 -0
  440. package/src/plugins/webhook/queue/database.ts +67 -0
  441. package/src/plugins/webhook/queue/in-memory.test.ts +48 -0
  442. package/src/plugins/webhook/queue/in-memory.ts +71 -0
  443. package/src/plugins/webhook/queue/types.ts +51 -0
  444. package/src/plugins/webhook/registry.test.ts +48 -0
  445. package/src/plugins/webhook/registry.ts +64 -0
  446. package/src/plugins/webhook/signing.ts +45 -0
  447. package/src/plugins/webhook/ssrf.ts +198 -0
  448. package/src/plugins/webhook/types.ts +138 -0
  449. package/src/plugins/webhook/webhook.test.ts +324 -0
  450. package/src/sveltekit/actions.ts +233 -0
  451. package/src/sveltekit/catch-all.ts +43 -0
  452. package/src/sveltekit/cookies.ts +136 -0
  453. package/src/sveltekit/handle.ts +356 -0
  454. package/src/sveltekit/helpers.ts +69 -0
  455. package/src/sveltekit/index.ts +74 -0
  456. package/src/sveltekit/protect.ts +80 -0
  457. package/src/sveltekit/sveltekit-types.test.ts +31 -0
  458. package/src/sveltekit/sveltekit.test.ts +799 -0
  459. package/src/sveltekit/types.ts +134 -0
  460. package/src/sveltekit/validated.test.ts +117 -0
  461. package/src/sveltekit/validated.ts +78 -0
  462. package/src/testing/adapter-conformance.test.ts +408 -0
  463. package/src/testing/checks.test.ts +124 -0
  464. package/src/testing/checks.ts +304 -0
  465. package/src/testing/index.ts +107 -0
@@ -0,0 +1,134 @@
1
+ /**
2
+ * SvelteKit adapter types. Public handle/action signatures are anchored to
3
+ * the real optional `@sveltejs/kit` peer so strict-mode consumers can assign
4
+ * them without casts. Small request/cookie subsets remain for framework-free
5
+ * helpers and tests; every real RequestEvent structurally satisfies them.
6
+ */
7
+
8
+ import type { Handle, RequestEvent } from '@sveltejs/kit';
9
+ import type { DatabaseAdapter } from '../adapters/database';
10
+ import type { Subject, TokenClaims } from '../core/types';
11
+
12
+ // ── Minimal SvelteKit type subset ───────────────────────────────────
13
+
14
+ /** Cookie options accepted by SvelteKit's `event.cookies.set` / `delete`. */
15
+ export interface SvelteKitCookieOptions {
16
+ path?: string;
17
+ domain?: string;
18
+ httpOnly?: boolean;
19
+ secure?: boolean;
20
+ sameSite?: 'lax' | 'strict' | 'none' | boolean;
21
+ maxAge?: number;
22
+ expires?: Date;
23
+ }
24
+
25
+ /** SvelteKit `Cookies` API surface used by the fortress adapter. */
26
+ export interface SvelteKitCookies {
27
+ get: (name: string) => string | undefined;
28
+ set: (name: string, value: string, opts: SvelteKitCookieOptions & { path: string }) => void;
29
+ delete: (name: string, opts: SvelteKitCookieOptions & { path: string }) => void;
30
+ getAll?: () => { name: string; value: string }[];
31
+ }
32
+
33
+ /**
34
+ * Minimal `RequestEvent` shape consumed by the adapter. Compatible by
35
+ * structural typing with `@sveltejs/kit`'s real `RequestEvent`. The
36
+ * `locals.fortress` field comes from the consumer augmenting `App.Locals`
37
+ * with {@link FortressLocals}.
38
+ *
39
+ * `TLocals` is constrained to `object` (not `Record<string, unknown>`) so
40
+ * the {@link FortressLocals} interface — which only declares the
41
+ * `fortress` key without an index signature — satisfies it.
42
+ */
43
+ export interface SvelteKitRequestEvent<TLocals extends object = object> {
44
+ request: Request;
45
+ url: URL;
46
+ cookies: SvelteKitCookies;
47
+ locals: TLocals;
48
+ params: Record<string, string>;
49
+ setHeaders?: (headers: Record<string, string>) => void;
50
+ }
51
+
52
+ /** Exact SvelteKit `Handle` hook signature, including the resolve options overload. */
53
+ export type SvelteKitHandle = Handle;
54
+
55
+ /** SvelteKit-compatible form action signature with a narrowed result type. */
56
+ export type SvelteKitAction<TResult = unknown> = (
57
+ event: RequestEvent,
58
+ ) => Promise<TResult> | TResult;
59
+
60
+ // ── Fortress-specific types ─────────────────────────────────────────
61
+
62
+ /**
63
+ * Shape of `event.locals.fortress` after the fortress handle hook runs.
64
+ *
65
+ * Consumers augment SvelteKit's `App.Locals` with this interface so server
66
+ * load functions and `+server.ts` handlers can read the auth context with
67
+ * full type safety.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * // src/app.d.ts
72
+ * import type { FortressLocals } from '@bajustone/fortress/sveltekit';
73
+ *
74
+ * declare global {
75
+ * namespace App {
76
+ * interface Locals extends FortressLocals {}
77
+ * }
78
+ * }
79
+ * ```
80
+ */
81
+ export interface FortressLocals {
82
+ fortress: {
83
+ /**
84
+ * Resolved principal for the current request. Set for every
85
+ * authenticated request regardless of credential type (JWT, api-key,
86
+ * future OAuth client_credentials, mTLS). Check `subject.type` to
87
+ * distinguish `USER` / `SERVICE_ACCOUNT` / `GROUP`.
88
+ */
89
+ subject?: Subject;
90
+ /**
91
+ * Convenience alias for `subject.id` — set **only** when
92
+ * `subject.type === 'USER'`. Non-USER principals (e.g. a service
93
+ * account via api-key) leave this undefined; fall back to `subject`.
94
+ */
95
+ userId?: string;
96
+ /**
97
+ * Verified JWT claims, if the request was authenticated via a JWT.
98
+ * Plugin-resolved principals (api-key, etc.) do not populate this.
99
+ */
100
+ claims?: TokenClaims;
101
+ /** Credential-level narrowing scopes (for example API-key scopes). */
102
+ scopes?: string[] | null;
103
+ /** Per-request DB adapter with plugin `wrapAdapter` chain applied. */
104
+ db?: DatabaseAdapter;
105
+ /** Lazily compute a model-scoped DB adapter (data-isolation aware). */
106
+ getScopedDb?: (model: string) => Promise<DatabaseAdapter>;
107
+ };
108
+ }
109
+
110
+ /** Options accepted by {@link createSvelteKitHandle}. */
111
+ export interface SvelteKitAdapterOptions {
112
+ /**
113
+ * Path prefix the fortress routes live under (defaults to `/api`).
114
+ *
115
+ * Example: with `basePath: '/api'`, the request `/api/auth/login` is
116
+ * internally rewritten to `/auth/login` before being passed to
117
+ * `fortress.handleRequest`. Plugin and IAM routes follow the same prefix.
118
+ */
119
+ basePath?: string;
120
+ /**
121
+ * Optional declarative route → `(resource, action)` map for user-owned
122
+ * routes. Used by the user-route RBAC pass to call
123
+ * `fortress.iam.checkPermission` for non-fortress paths. Format:
124
+ * `'GET /api/users': { resource: 'user', action: 'list' }`.
125
+ */
126
+ routeMap?: Record<string, { resource: string; action: string }>;
127
+ /** Behavior for user-owned routes absent from routeMap (default: allow). */
128
+ unmappedRoutes?: 'allow' | 'deny';
129
+ /**
130
+ * Paths the user-route RBAC pass should skip entirely (supports `*`).
131
+ * Example: `['/api/health', '/api/public/*']`.
132
+ */
133
+ skipPaths?: string[];
134
+ }
@@ -0,0 +1,117 @@
1
+ import type { SvelteKitRequestEvent } from './types';
2
+ import type { InferOutput } from './validated';
3
+ import { describe, expect, expectTypeOf, it } from 'vitest';
4
+ import { FortressError } from '../core/errors';
5
+ import { obj, str } from '../core/schema-builder';
6
+ import { vBody, vParam, vQuery } from './validated';
7
+
8
+ const CreateUserBody = obj({ name: str(), email: str() }, 'name', 'email');
9
+ const IdParam = obj({ id: str('User ID') }, 'id');
10
+ const SearchQuery = obj({ q: str('Search query'), page: str() }, 'q');
11
+
12
+ function fakeEvent(opts: {
13
+ body?: unknown;
14
+ params?: Record<string, string>;
15
+ url?: string;
16
+ }): SvelteKitRequestEvent {
17
+ const url = new URL(opts.url ?? 'http://localhost/');
18
+ const request = new Request(url, {
19
+ method: opts.body !== undefined ? 'POST' : 'GET',
20
+ headers: opts.body !== undefined ? { 'Content-Type': 'application/json' } : {},
21
+ body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,
22
+ });
23
+ return {
24
+ request,
25
+ url,
26
+ cookies: { get: () => undefined, set: () => {}, delete: () => {} },
27
+ locals: {} as any,
28
+ params: opts.params ?? {},
29
+ };
30
+ }
31
+
32
+ describe('vBody', () => {
33
+ it('returns parsed JSON body when valid', async () => {
34
+ const event = fakeEvent({ body: { name: 'Alice', email: 'alice@test.com' } });
35
+ const data = await vBody(event, CreateUserBody);
36
+ expect(data).toEqual({ name: 'Alice', email: 'alice@test.com' });
37
+ });
38
+
39
+ it('throws VALIDATION_ERROR when body is missing required fields', async () => {
40
+ const event = fakeEvent({ body: { name: 'Alice' } });
41
+ await expect(vBody(event, CreateUserBody)).rejects.toMatchObject({
42
+ code: 'VALIDATION_ERROR',
43
+ statusCode: 422,
44
+ });
45
+ });
46
+
47
+ it('throws VALIDATION_ERROR when body is unparseable', async () => {
48
+ const url = new URL('http://localhost/');
49
+ const request = new Request(url, {
50
+ method: 'POST',
51
+ headers: { 'Content-Type': 'application/json' },
52
+ body: 'not json',
53
+ });
54
+ const event: SvelteKitRequestEvent = {
55
+ request,
56
+ url,
57
+ cookies: { get: () => undefined, set: () => {}, delete: () => {} },
58
+ locals: {} as any,
59
+ params: {},
60
+ };
61
+ await expect(vBody(event, CreateUserBody)).rejects.toBeInstanceOf(FortressError);
62
+ });
63
+ });
64
+
65
+ describe('vParam', () => {
66
+ it('returns route params when valid', async () => {
67
+ const event = fakeEvent({ params: { id: '42' } });
68
+ const data = await vParam(event, IdParam);
69
+ expect(data.id).toBe('42');
70
+ });
71
+
72
+ it('throws VALIDATION_ERROR when required param missing', async () => {
73
+ const event = fakeEvent({ params: {} });
74
+ await expect(vParam(event, IdParam)).rejects.toMatchObject({
75
+ code: 'VALIDATION_ERROR',
76
+ statusCode: 422,
77
+ });
78
+ });
79
+ });
80
+
81
+ describe('vQuery', () => {
82
+ it('returns query parameters when valid', async () => {
83
+ const event = fakeEvent({ url: 'http://localhost/?q=hello' });
84
+ const data = await vQuery(event, SearchQuery);
85
+ expect(data.q).toBe('hello');
86
+ });
87
+
88
+ it('throws VALIDATION_ERROR when required query field missing', async () => {
89
+ const event = fakeEvent({ url: 'http://localhost/' });
90
+ await expect(vQuery(event, SearchQuery)).rejects.toMatchObject({
91
+ code: 'VALIDATION_ERROR',
92
+ statusCode: 422,
93
+ });
94
+ });
95
+ });
96
+
97
+ describe('type inference', () => {
98
+ it('infers vBody return type from schema', () => {
99
+ const fn = (e: SvelteKitRequestEvent) => vBody(e, CreateUserBody);
100
+ expectTypeOf(fn).returns.resolves.toEqualTypeOf<{ name: string; email: string }>();
101
+ });
102
+
103
+ it('infers vParam return type from schema', () => {
104
+ const fn = (e: SvelteKitRequestEvent) => vParam(e, IdParam);
105
+ expectTypeOf(fn).returns.resolves.toEqualTypeOf<{ id: string }>();
106
+ });
107
+
108
+ it('infers vQuery return type from schema', () => {
109
+ const fn = (e: SvelteKitRequestEvent) => vQuery(e, SearchQuery);
110
+ expectTypeOf(fn).returns.resolves.toEqualTypeOf<{ q: string; page?: string }>();
111
+ });
112
+
113
+ it('exports InferOutput utility type', () => {
114
+ type Expected = InferOutput<typeof CreateUserBody>;
115
+ expectTypeOf<Expected>().toEqualTypeOf<{ name: string; email: string }>();
116
+ });
117
+ });
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Typed extraction-and-validation helpers for SvelteKit `+server.ts` handlers
3
+ * and form actions.
4
+ *
5
+ * These helpers extract request data (body, params, query) **and validate
6
+ * it at runtime** against the supplied Standard Schema. On success they
7
+ * return the parsed value with full TypeScript inference; on failure they
8
+ * throw `FortressError('VALIDATION_ERROR', 422)` — the same shape every
9
+ * fortress-managed endpoint produces — so the existing SvelteKit error
10
+ * mapping (via `errorToResponse`) formats it identically.
11
+ *
12
+ * Works with any Standard Schema V1 library: Zod, Valibot, ArkType, or
13
+ * fortress's built-in schema builders.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * // src/routes/api/users/[id]/+server.ts
18
+ * import { vBody, vParam } from '@bajustone/fortress/sveltekit';
19
+ * import { obj, str } from '@bajustone/fortress';
20
+ *
21
+ * const UpdateBody = obj({ name: str() }, 'name');
22
+ * const Params = obj({ id: str() }, 'id');
23
+ *
24
+ * export async function PATCH(event) {
25
+ * const { id } = await vParam(event, Params);
26
+ * const { name } = await vBody(event, UpdateBody);
27
+ * // ...
28
+ * }
29
+ * ```
30
+ *
31
+ * Validation runs per call, so the first failing helper throws and any
32
+ * downstream helpers in the same handler do not run. If you need to
33
+ * aggregate body+query+params issues into a single response, use the
34
+ * framework-agnostic `validateRequest` from `@bajustone/fortress` instead.
35
+ */
36
+
37
+ import type { StandardSchemaV1 } from '../core/standard-schema';
38
+ import type { SvelteKitRequestEvent } from './types';
39
+ import { validateValue } from '../core/validation';
40
+
41
+ /** Infer the output type of a Standard Schema V1 schema. */
42
+ export type InferOutput<T extends StandardSchemaV1> = StandardSchemaV1.InferOutput<T>;
43
+
44
+ /**
45
+ * Extract and validate the JSON request body. Returns the parsed value typed
46
+ * as `InferOutput<T>`, or throws `FortressError('VALIDATION_ERROR', 422)`.
47
+ */
48
+ export async function vBody<T extends StandardSchemaV1>(
49
+ event: SvelteKitRequestEvent,
50
+ schema: T,
51
+ ): Promise<InferOutput<T>> {
52
+ const body = await event.request.json().catch(() => undefined);
53
+ return validateValue(schema, body, 'body');
54
+ }
55
+
56
+ /**
57
+ * Extract and validate route parameters from a `[param]`-style file. Returns
58
+ * the parsed value typed as `InferOutput<T>`, or throws
59
+ * `FortressError('VALIDATION_ERROR', 422)`.
60
+ */
61
+ export async function vParam<T extends StandardSchemaV1>(
62
+ event: SvelteKitRequestEvent,
63
+ schema: T,
64
+ ): Promise<InferOutput<T>> {
65
+ return validateValue(schema, event.params, 'params');
66
+ }
67
+
68
+ /**
69
+ * Extract and validate query parameters from `event.url.searchParams`.
70
+ * Returns the parsed value typed as `InferOutput<T>`, or throws
71
+ * `FortressError('VALIDATION_ERROR', 422)`.
72
+ */
73
+ export async function vQuery<T extends StandardSchemaV1>(
74
+ event: SvelteKitRequestEvent,
75
+ schema: T,
76
+ ): Promise<InferOutput<T>> {
77
+ return validateValue(schema, Object.fromEntries(event.url.searchParams), 'query');
78
+ }