@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,406 @@
1
+ import { F as FortressPlugin } from '../config-B2366s_G.js';
2
+ import { F as FortressUser } from '../types-et0R8tsC.js';
3
+ import '../index-CxEkfCA0.js';
4
+ import '../jwt.js';
5
+ import '../auth-service-BkzZkWfH.js';
6
+
7
+ /**
8
+ * PKCE (Proof Key for Code Exchange) S256 implementation.
9
+ * Used by the OAuth plugin to secure authorization code flows.
10
+ */
11
+ /** Generate a cryptographically random code verifier (43-128 chars, URL-safe) */
12
+ declare function generateCodeVerifier(): string;
13
+ /** Generate S256 code challenge from a code verifier */
14
+ declare function generateCodeChallenge(verifier: string): Promise<string>;
15
+ /**
16
+ * Verify a code verifier against a stored S256 challenge.
17
+ *
18
+ * Validates the verifier against RFC 7636 §4.1 (43-128 chars, unreserved
19
+ * URL-safe character set) before computing the challenge — a verifier that
20
+ * fails this check is invalid by definition and must not unlock a code.
21
+ *
22
+ * Uses {@link timingSafeEqualHex} for the final comparison so a remote
23
+ * attacker can't differentiate "wrong verifier" from "wrong verifier with
24
+ * matching prefix" via response timing.
25
+ */
26
+ declare function verifyCodeChallenge(verifier: string, challenge: string, method: string): Promise<boolean>;
27
+
28
+ /**
29
+ * OAuth 2.0 authorization server plugin for fortress.
30
+ *
31
+ * Implements the authorization-code grant (with PKCE) and client-credentials
32
+ * grant for confidential and public clients. Persists clients, authorization
33
+ * codes, access tokens, and pending flows via the fortress database adapter,
34
+ * and exposes the standard `/authorize` and `/token` endpoints when mounted.
35
+ *
36
+ * @module
37
+ */
38
+
39
+ interface OAuthConfig {
40
+ /** Authorization code expiry in seconds (default: 600 = 10 min) */
41
+ authCodeExpirySeconds?: number;
42
+ /** Pending flow expiry in seconds (default: 600 = 10 min) */
43
+ pendingFlowExpirySeconds?: number;
44
+ /** Access token expiry in seconds (default: 3600 = 1 hour) */
45
+ accessTokenExpirySeconds?: number;
46
+ /**
47
+ * Refresh token expiry in seconds (default: 30 days). Refresh tokens are
48
+ * sliding — each rotation issues a fresh token with a new expiry. Set to
49
+ * 0 to disable refresh-token issuance entirely.
50
+ *
51
+ * @see RFC 6749 §6 · RFC 9700 §2.2.2
52
+ */
53
+ refreshTokenExpirySeconds?: number;
54
+ /**
55
+ * id_token expiry in seconds (default: 3600 = 1 hour). Only relevant
56
+ * when the request includes `scope=openid`.
57
+ *
58
+ * @see OIDC Core 1.0 §2
59
+ */
60
+ idTokenExpirySeconds?: number;
61
+ /** Seconds rotated signing keys remain published in JWKS. Default: idTokenExpirySeconds. */
62
+ signingKeyGraceSeconds?: number;
63
+ /** Map OAuth scopes to IAM permissions. Example: `{ 'read:posts': { resource: 'post', action: 'read' } }` */
64
+ scopePermissionMap?: Record<string, {
65
+ resource: string;
66
+ action: string;
67
+ }>;
68
+ /** Base URL for the OAuth server (used in OIDC discovery document) */
69
+ issuerUrl?: string;
70
+ /**
71
+ * RFC 9700 §2.1.1 escape hatch: when `true`, `/oauth/authorize` will accept
72
+ * requests without a `code_challenge` from confidential clients. Defaults
73
+ * to `false`. Strongly discouraged — PKCE is mandatory in current OAuth
74
+ * BCP. Provided only so legacy server-side RPs can be migrated
75
+ * incrementally.
76
+ */
77
+ allowNonPkceConfidentialClients?: boolean;
78
+ /**
79
+ * Static list of OIDC/OAuth scope names the AS knows about, surfaced in
80
+ * discovery's `scopes_supported`. Merged with the keys of
81
+ * {@link OAuthConfig.scopePermissionMap} and the default OIDC scopes
82
+ * (`openid`, `email`, `profile`). Optional — informational metadata only;
83
+ * does not enforce per-client allow-listing on its own.
84
+ */
85
+ scopesSupported?: string[];
86
+ /**
87
+ * Per-deployment extension hook for `/oauth/userinfo`. Receives the
88
+ * {@link FortressUser} resolved from the access token plus the token's
89
+ * scope (or `null` if no scope was issued), and returns a claims record
90
+ * that is merged into the OIDC-shaped response on top of the standard
91
+ * claims fortress emits.
92
+ *
93
+ * Use this to attach app-specific claims (tenant, roles, custom
94
+ * profile fields). Returning `{}` is the no-op; returning a key already
95
+ * emitted by fortress overwrites it (you'd typically only do that for
96
+ * `preferred_username` or `name` when the host app stores its own).
97
+ *
98
+ * @example
99
+ * ```ts
100
+ * userinfoClaims: (user, scope) => ({
101
+ * tenant_id: user.tenantId,
102
+ * ...(scope?.includes('profile') ? { picture: user.avatarUrl } : {}),
103
+ * })
104
+ * ```
105
+ */
106
+ userinfoClaims?: (user: FortressUser, scope: string | null) => Record<string, unknown> | Promise<Record<string, unknown>>;
107
+ /**
108
+ * Mount the front-door `GET /oauth/authorize` endpoint. Off by default —
109
+ * opt in once your host app has wired up `loginUrl` and `consentUrl`.
110
+ * Plugin methods (`createPendingFlow`, `handleAuthorizeRequest`) stay
111
+ * available regardless.
112
+ */
113
+ enableAuthorizeEndpoint?: boolean;
114
+ /**
115
+ * Mount the consent-API endpoints (`GET /oauth/flows/:flowId`,
116
+ * `POST /oauth/flows/:flowId/approve`, `POST /oauth/flows/:flowId/deny`).
117
+ * Off by default — opt in for the SPA-friendly consent flow (Pattern B).
118
+ * The corresponding methods stay available regardless.
119
+ */
120
+ enableConsentApi?: boolean;
121
+ /**
122
+ * Where the host app's sign-in page lives, e.g.
123
+ * `'https://app.example.com/signin'`. The authorize endpoint redirects
124
+ * unauthenticated users to `${loginUrl}?flow=<id>`.
125
+ */
126
+ loginUrl?: string;
127
+ /**
128
+ * Where the host app's consent page lives, e.g.
129
+ * `'https://app.example.com/oauth/consent'`. The authorize endpoint
130
+ * redirects authenticated users to `${consentUrl}?flow=<id>`.
131
+ */
132
+ consentUrl?: string;
133
+ }
134
+ /** RFC 6749 §2.1 / OIDC Discovery `token_endpoint_auth_methods_supported` aliases. */
135
+ type TokenEndpointAuthMethod = 'client_secret_basic' | 'client_secret_post' | 'none';
136
+ /** Persisted state for an in-flight OAuth authorization-code flow. */
137
+ interface PendingFlowRecord {
138
+ /** Internal DB primary key — never exposed to clients. */
139
+ id: string;
140
+ /** Public opaque handle used in URLs; replaces enumerable serial ids (H6). */
141
+ flowId: string;
142
+ clientId: string;
143
+ redirectUri: string;
144
+ scope: string | null;
145
+ state: string;
146
+ codeChallenge: string | null;
147
+ codeChallengeMethod: string | null;
148
+ /** OIDC Core §3.1.2.1 nonce — mirrored from the authorize query if present. */
149
+ nonce: string | null;
150
+ /**
151
+ * Subject the flow is bound to. Null until the first authenticated
152
+ * read/approve, then trust-on-first-use claims it for that user. Every
153
+ * subsequent read/approve/deny MUST match.
154
+ *
155
+ * Closes H6 (IDOR on `/oauth/flows/:flowId`): without this column, any
156
+ * authenticated user could fetch another user's RP state token or
157
+ * approve their flow.
158
+ */
159
+ userId: string | null;
160
+ /** Set during atomic approve/deny claim; prevents concurrent double-submit. */
161
+ usedAt: Date | null;
162
+ expiresAt: Date;
163
+ }
164
+ /** Client authentication extracted from HTTP request (Basic auth or body params) */
165
+ /** Resolved client credentials parsed from a token-endpoint request. */
166
+ interface ClientAuth {
167
+ clientId: string;
168
+ clientSecret: string;
169
+ }
170
+ /** Token endpoint request body (application/x-www-form-urlencoded) */
171
+ /** Body shape accepted by the OAuth `/token` endpoint. */
172
+ interface TokenRequestBody {
173
+ grant_type: string;
174
+ code?: string;
175
+ redirect_uri?: string;
176
+ client_id?: string;
177
+ client_secret?: string;
178
+ code_verifier?: string;
179
+ scope?: string;
180
+ /** RFC 6749 §6 refresh-token grant payload. */
181
+ refresh_token?: string;
182
+ }
183
+ /** Authorization endpoint query params */
184
+ /** Query parameters accepted by the OAuth `/authorize` endpoint. */
185
+ interface AuthorizeRequestParams {
186
+ client_id: string;
187
+ redirect_uri: string;
188
+ response_type: string;
189
+ scope?: string;
190
+ state?: string;
191
+ code_challenge?: string;
192
+ code_challenge_method?: string;
193
+ }
194
+ interface OAuthMethods {
195
+ createClient: (data: {
196
+ name: string;
197
+ redirectUris: string[];
198
+ grantTypes: string[];
199
+ allowedScopes?: string[];
200
+ tokenEndpointAuthMethod?: TokenEndpointAuthMethod;
201
+ }) => Promise<{
202
+ clientId: string;
203
+ clientSecret: string | null;
204
+ }>;
205
+ createAuthorizationCode: (params: {
206
+ clientId: string;
207
+ userId: string;
208
+ redirectUri: string;
209
+ scope?: string;
210
+ codeChallenge?: string;
211
+ codeChallengeMethod?: string;
212
+ nonce?: string;
213
+ authTime?: number;
214
+ }) => Promise<{
215
+ code: string;
216
+ }>;
217
+ exchangeCode: (params: {
218
+ code: string;
219
+ clientId: string;
220
+ clientSecret?: string;
221
+ redirectUri: string;
222
+ codeVerifier?: string;
223
+ }) => Promise<{
224
+ accessToken: string;
225
+ tokenType: string;
226
+ expiresIn: number;
227
+ scope?: string;
228
+ refreshToken?: string;
229
+ idToken?: string;
230
+ }>;
231
+ refreshTokenGrant: (params: {
232
+ clientId: string;
233
+ clientSecret?: string;
234
+ refreshToken: string;
235
+ scope?: string;
236
+ }) => Promise<{
237
+ accessToken: string;
238
+ tokenType: string;
239
+ expiresIn: number;
240
+ refreshToken: string;
241
+ scope?: string;
242
+ idToken?: string;
243
+ }>;
244
+ clientCredentialsGrant: (params: {
245
+ clientId: string;
246
+ clientSecret: string;
247
+ scope?: string;
248
+ }) => Promise<{
249
+ accessToken: string;
250
+ tokenType: string;
251
+ expiresIn: number;
252
+ }>;
253
+ revokeToken: (token: string) => Promise<void>;
254
+ introspectToken: (token: string) => Promise<{
255
+ active: boolean;
256
+ clientId?: string;
257
+ userId?: string;
258
+ scope?: string;
259
+ }>;
260
+ createPendingFlow: (params: {
261
+ clientId: string;
262
+ redirectUri: string;
263
+ scope?: string;
264
+ state: string;
265
+ codeChallenge?: string;
266
+ codeChallengeMethod?: string;
267
+ userId?: string;
268
+ }) => Promise<{
269
+ flowId: string;
270
+ }>;
271
+ /**
272
+ * Read a pending flow without consuming it. Throws if not found, expired,
273
+ * or (when `userId` is supplied) owned by a different user — in the
274
+ * "different user" case the error is `not_found` rather than `forbidden`
275
+ * to avoid confirming the flow's existence.
276
+ */
277
+ getPendingFlow: (flowId: string | number, context?: {
278
+ userId?: string;
279
+ }) => Promise<PendingFlowRecord>;
280
+ /** Read and delete a pending flow (single-use). Throws if not found or expired. */
281
+ resumePendingFlow: (flowId: string | number, context?: {
282
+ userId?: string;
283
+ }) => Promise<PendingFlowRecord>;
284
+ getUserInfo: (token: string) => Promise<FortressUser | null>;
285
+ /** Rotate the RS256 id-token signing key and prune expired retired keys. */
286
+ rotateSigningKey: () => Promise<{
287
+ kid: string;
288
+ }>;
289
+ handleTokenRequest: (body: TokenRequestBody, clientAuth?: ClientAuth) => Promise<Record<string, unknown>>;
290
+ handleIntrospectRequest: (body: {
291
+ token: string;
292
+ }, clientAuth: ClientAuth) => Promise<Record<string, unknown>>;
293
+ handleRevokeRequest: (body: {
294
+ token: string;
295
+ }, clientAuth: ClientAuth) => Promise<void>;
296
+ /**
297
+ * OIDC Core 1.0 §5.3 userinfo endpoint. Returns the standard claims set
298
+ * (`sub`, `email`, `email_verified`, `name`, `preferred_username`,
299
+ * `updated_at`) gated by the access token's scope (§5.4), plus anything
300
+ * the {@link OAuthConfig.userinfoClaims} hook contributes. Throws 401
301
+ * for invalid / expired tokens (RFC 6750).
302
+ */
303
+ handleUserInfoRequest: (bearerToken: string) => Promise<Record<string, unknown>>;
304
+ /**
305
+ * RFC 7517 / OIDC Discovery JWKS endpoint. Returns the AS's public
306
+ * verification keys (`{ keys: [...] }`). The first call materialises the
307
+ * active signing key if none has been generated yet; subsequent calls
308
+ * are cheap reads.
309
+ */
310
+ handleJwksRequest: () => Promise<Record<string, unknown>>;
311
+ handleDiscovery: () => Record<string, unknown>;
312
+ /**
313
+ * Handle GET /oauth/authorize. Validates the query, creates a pending
314
+ * flow, and returns the URL to redirect the browser to (login if no
315
+ * user, consent if authenticated).
316
+ */
317
+ handleAuthorizeRequest: (query: Record<string, string | undefined>, context: {
318
+ userId?: string;
319
+ }) => Promise<{
320
+ redirectUrl: string;
321
+ flowId: string;
322
+ }>;
323
+ /**
324
+ * Handle GET /oauth/flows/:flowId. Returns the consent metadata the host
325
+ * app's consent page renders. Throws if the flow is unknown or expired.
326
+ *
327
+ * Requires the request principal to own the flow — the first authenticated
328
+ * read claims the flow for `context.userId` (trust-on-first-use); every
329
+ * subsequent read MUST come from the same user or the response is 404.
330
+ */
331
+ handleGetFlow: (flowId: string | number, context: {
332
+ userId: string;
333
+ }) => Promise<{
334
+ flowId: string;
335
+ client: {
336
+ clientId: string;
337
+ name: string;
338
+ };
339
+ redirectUri: string;
340
+ scopes: string[];
341
+ state: string;
342
+ }>;
343
+ /**
344
+ * Handle POST /oauth/flows/:flowId/approve. Issues an authorization code
345
+ * for the authenticated user, deletes the pending flow, and returns the
346
+ * URL the browser should be sent back to (the OAuth client's redirect_uri
347
+ * with `?code=...&state=...`).
348
+ */
349
+ handleApproveFlow: (flowId: string | number, context: {
350
+ userId: string;
351
+ authTimeSeconds?: number;
352
+ }) => Promise<{
353
+ redirectUrl: string;
354
+ }>;
355
+ /**
356
+ * Handle POST /oauth/flows/:flowId/deny. Deletes the pending flow and
357
+ * returns the URL the browser should be sent back to (redirect_uri with
358
+ * `?error=access_denied&state=...`).
359
+ *
360
+ * Requires the request principal to own the flow.
361
+ */
362
+ handleDenyFlow: (flowId: string | number, context: {
363
+ userId: string;
364
+ }) => Promise<{
365
+ redirectUrl: string;
366
+ }>;
367
+ resolveTokenPermissions: (token: string) => Promise<{
368
+ resource: string;
369
+ action: string;
370
+ }[]>;
371
+ }
372
+ /**
373
+ * OAuth 2.0 server plugin factory. Returns a {@link FortressPlugin} that
374
+ * implements the authorization-code grant (with PKCE) and client-credentials
375
+ * grant, persists clients and tokens, and exposes `/authorize` and `/token`
376
+ * endpoints when mounted on a framework adapter.
377
+ */
378
+ declare function oauth(config?: OAuthConfig): FortressPlugin & {
379
+ readonly name: 'oauth';
380
+ };
381
+ /**
382
+ * RFC 8252 §8.4 redirect-URI matcher with the loopback exception.
383
+ *
384
+ * Confidential clients still get exact-match (the registered URI must equal
385
+ * the inbound URI byte-for-byte). Native / public clients that registered an
386
+ * `http://127.0.0.1/<path>` or `http://[::1]/<path>` redirect MUST be allowed
387
+ * to vary the port at runtime, because the loopback HTTP server picks one
388
+ * dynamically. Path, query, and fragment still have to match.
389
+ *
390
+ * This is intentionally narrow: only `127.0.0.1` and `[::1]` get the
391
+ * any-port leniency. `localhost` (DNS-resolved) is NOT widened — RFC 8252
392
+ * §8.3 actively recommends against it for security reasons (DNS rebinding).
393
+ */
394
+ declare function matchRedirectUri(registered: string, inbound: string): boolean;
395
+
396
+ /**
397
+ * Map a fortress user record to an OIDC-Core-§5.1 claims object, gated by
398
+ * the access token's scope per §5.4.
399
+ *
400
+ * Exported so host apps with a custom `handleUserInfoRequest` (e.g. one
401
+ * that adds tenant claims) can compose on top of the same baseline rather
402
+ * than re-implementing the OIDC shape from scratch.
403
+ */
404
+ declare function toOidcUserinfo(user: FortressUser, scope: string | null | undefined): Record<string, unknown>;
405
+
406
+ export { type AuthorizeRequestParams, type ClientAuth, type OAuthConfig, type OAuthMethods, type PendingFlowRecord, type TokenEndpointAuthMethod, type TokenRequestBody, generateCodeChallenge, generateCodeVerifier, matchRedirectUri, oauth, toOidcUserinfo, verifyCodeChallenge };