@adonis-agora/authkit-server 0.34.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 (389) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +158 -0
  3. package/build/assets/grafana/authkit-dashboard.json +118 -0
  4. package/build/commands/clients_create.d.ts +27 -0
  5. package/build/commands/clients_create.js +121 -0
  6. package/build/commands/commands.json +292 -0
  7. package/build/commands/configure.d.ts +2 -0
  8. package/build/commands/configure.js +45 -0
  9. package/build/commands/doctor.d.ts +10 -0
  10. package/build/commands/doctor.js +113 -0
  11. package/build/commands/eject.d.ts +11 -0
  12. package/build/commands/eject.js +96 -0
  13. package/build/commands/expire_scan.d.ts +28 -0
  14. package/build/commands/expire_scan.js +92 -0
  15. package/build/commands/import_users.d.ts +17 -0
  16. package/build/commands/import_users.js +80 -0
  17. package/build/commands/keys_rotate.d.ts +21 -0
  18. package/build/commands/keys_rotate.js +126 -0
  19. package/build/commands/main.d.ts +12 -0
  20. package/build/commands/main.js +38 -0
  21. package/build/commands/settings_get.d.ts +18 -0
  22. package/build/commands/settings_get.js +43 -0
  23. package/build/commands/settings_list.d.ts +17 -0
  24. package/build/commands/settings_list.js +39 -0
  25. package/build/commands/settings_set.d.ts +20 -0
  26. package/build/commands/settings_set.js +55 -0
  27. package/build/commands/settings_unset.d.ts +18 -0
  28. package/build/commands/settings_unset.js +46 -0
  29. package/build/commands/ui_preset.d.ts +4 -0
  30. package/build/commands/ui_preset.js +32 -0
  31. package/build/database/migrations/make_authkit_oidc_table.d.ts +6 -0
  32. package/build/database/migrations/make_authkit_oidc_table.js +19 -0
  33. package/build/host/ui/admin.html +29 -0
  34. package/build/host/views/account/apps.edge +59 -0
  35. package/build/host/views/account/confirm.edge +70 -0
  36. package/build/host/views/account/email-confirmed.edge +16 -0
  37. package/build/host/views/account/login.edge +33 -0
  38. package/build/host/views/account/mfa.edge +152 -0
  39. package/build/host/views/account/orgs.edge +58 -0
  40. package/build/host/views/account/security.edge +215 -0
  41. package/build/host/views/account/tokens.edge +75 -0
  42. package/build/host/views/consent.edge +20 -0
  43. package/build/host/views/forgot.edge +43 -0
  44. package/build/host/views/login.edge +251 -0
  45. package/build/host/views/maintenance.edge +32 -0
  46. package/build/host/views/mfa-challenge.edge +107 -0
  47. package/build/host/views/otp-unlock.edge +40 -0
  48. package/build/host/views/partials/styles.edge +2 -0
  49. package/build/host/views/reset.edge +30 -0
  50. package/build/host/views/signup.edge +62 -0
  51. package/build/host/views/verify-email.edge +17 -0
  52. package/build/index.d.ts +115 -0
  53. package/build/index.js +76 -0
  54. package/build/password/common_passwords.txt +10000 -0
  55. package/build/providers/authkit_server_provider.d.ts +27 -0
  56. package/build/providers/authkit_server_provider.js +242 -0
  57. package/build/src/accounts/account_store.d.ts +578 -0
  58. package/build/src/accounts/account_store.js +60 -0
  59. package/build/src/accounts/lucid_account_store.d.ts +156 -0
  60. package/build/src/accounts/lucid_account_store.js +294 -0
  61. package/build/src/accounts/lucid_store/core.d.ts +9 -0
  62. package/build/src/accounts/lucid_store/core.js +306 -0
  63. package/build/src/accounts/lucid_store/mfa.d.ts +15 -0
  64. package/build/src/accounts/lucid_store/mfa.js +108 -0
  65. package/build/src/accounts/lucid_store/organizations.d.ts +13 -0
  66. package/build/src/accounts/lucid_store/organizations.js +294 -0
  67. package/build/src/accounts/lucid_store/password_hygiene.d.ts +20 -0
  68. package/build/src/accounts/lucid_store/password_hygiene.js +130 -0
  69. package/build/src/accounts/lucid_store/provider_identity.d.ts +8 -0
  70. package/build/src/accounts/lucid_store/provider_identity.js +59 -0
  71. package/build/src/accounts/lucid_store/shared.d.ts +113 -0
  72. package/build/src/accounts/lucid_store/shared.js +130 -0
  73. package/build/src/accounts/lucid_store/status_profile.d.ts +34 -0
  74. package/build/src/accounts/lucid_store/status_profile.js +100 -0
  75. package/build/src/accounts/lucid_store/webauthn.d.ts +8 -0
  76. package/build/src/accounts/lucid_store/webauthn.js +140 -0
  77. package/build/src/accounts/lucid_stores.d.ts +45 -0
  78. package/build/src/accounts/lucid_stores.js +30 -0
  79. package/build/src/adapters/adapter_contract.d.ts +37 -0
  80. package/build/src/adapters/adapter_contract.js +1 -0
  81. package/build/src/adapters/database_adapter.d.ts +21 -0
  82. package/build/src/adapters/database_adapter.js +79 -0
  83. package/build/src/adapters/factory.d.ts +30 -0
  84. package/build/src/adapters/factory.js +43 -0
  85. package/build/src/adapters/redis_adapter.d.ts +24 -0
  86. package/build/src/adapters/redis_adapter.js +122 -0
  87. package/build/src/audit/audit_sink.d.ts +63 -0
  88. package/build/src/audit/audit_sink.js +1 -0
  89. package/build/src/audit/lucid_audit_sink.d.ts +10 -0
  90. package/build/src/audit/lucid_audit_sink.js +99 -0
  91. package/build/src/commands/expire_scan_command.d.ts +60 -0
  92. package/build/src/commands/expire_scan_command.js +229 -0
  93. package/build/src/commands/import_clients.d.ts +40 -0
  94. package/build/src/commands/import_clients.js +79 -0
  95. package/build/src/commands/import_users.d.ts +51 -0
  96. package/build/src/commands/import_users.js +94 -0
  97. package/build/src/commands/resolve_config.d.ts +13 -0
  98. package/build/src/commands/resolve_config.js +18 -0
  99. package/build/src/commands/settings_commands.d.ts +47 -0
  100. package/build/src/commands/settings_commands.js +270 -0
  101. package/build/src/controllers/oidc_callback_controller.d.ts +22 -0
  102. package/build/src/controllers/oidc_callback_controller.js +33 -0
  103. package/build/src/define_config.d.ts +772 -0
  104. package/build/src/define_config.js +351 -0
  105. package/build/src/doctor/checks.d.ts +197 -0
  106. package/build/src/doctor/checks.js +858 -0
  107. package/build/src/events/dispatcher.d.ts +45 -0
  108. package/build/src/events/dispatcher.js +117 -0
  109. package/build/src/host/account_api/account_api_controller.d.ts +245 -0
  110. package/build/src/host/account_api/account_api_controller.js +827 -0
  111. package/build/src/host/account_deletion_ops.d.ts +80 -0
  112. package/build/src/host/account_deletion_ops.js +118 -0
  113. package/build/src/host/account_deletion_service.d.ts +63 -0
  114. package/build/src/host/account_deletion_service.js +133 -0
  115. package/build/src/host/account_export_service.d.ts +76 -0
  116. package/build/src/host/account_export_service.js +140 -0
  117. package/build/src/host/account_home.d.ts +11 -0
  118. package/build/src/host/account_home.js +11 -0
  119. package/build/src/host/account_lockout.d.ts +86 -0
  120. package/build/src/host/account_lockout.js +185 -0
  121. package/build/src/host/active_org_cookie.d.ts +28 -0
  122. package/build/src/host/active_org_cookie.js +47 -0
  123. package/build/src/host/admin_api/admin_api_guard.d.ts +16 -0
  124. package/build/src/host/admin_api/admin_api_guard.js +59 -0
  125. package/build/src/host/admin_api/admin_orgs_service.d.ts +125 -0
  126. package/build/src/host/admin_api/admin_orgs_service.js +324 -0
  127. package/build/src/host/admin_api/admin_users_service.d.ts +163 -0
  128. package/build/src/host/admin_api/admin_users_service.js +308 -0
  129. package/build/src/host/admin_api/api_clients_controller.d.ts +54 -0
  130. package/build/src/host/admin_api/api_clients_controller.js +89 -0
  131. package/build/src/host/admin_api/api_keys_controller.d.ts +19 -0
  132. package/build/src/host/admin_api/api_keys_controller.js +36 -0
  133. package/build/src/host/admin_api/api_misc_controller.d.ts +19 -0
  134. package/build/src/host/admin_api/api_misc_controller.js +44 -0
  135. package/build/src/host/admin_api/api_orgs_controller.d.ts +108 -0
  136. package/build/src/host/admin_api/api_orgs_controller.js +189 -0
  137. package/build/src/host/admin_api/api_settings_controller.d.ts +55 -0
  138. package/build/src/host/admin_api/api_settings_controller.js +134 -0
  139. package/build/src/host/admin_api/api_users_controller.d.ts +108 -0
  140. package/build/src/host/admin_api/api_users_controller.js +187 -0
  141. package/build/src/host/admin_api/dto.d.ts +131 -0
  142. package/build/src/host/admin_api/dto.js +122 -0
  143. package/build/src/host/admin_api/token_verify_service.d.ts +34 -0
  144. package/build/src/host/admin_api/token_verify_service.js +74 -0
  145. package/build/src/host/admin_clients_service.d.ts +88 -0
  146. package/build/src/host/admin_clients_service.js +181 -0
  147. package/build/src/host/admin_console/admin_shell_controller.d.ts +27 -0
  148. package/build/src/host/admin_console/admin_shell_controller.js +167 -0
  149. package/build/src/host/admin_console/console_audit_controller.d.ts +17 -0
  150. package/build/src/host/admin_console/console_audit_controller.js +25 -0
  151. package/build/src/host/admin_console/console_clients_controller.d.ts +53 -0
  152. package/build/src/host/admin_console/console_clients_controller.js +102 -0
  153. package/build/src/host/admin_console/console_impersonation_controller.d.ts +23 -0
  154. package/build/src/host/admin_console/console_impersonation_controller.js +45 -0
  155. package/build/src/host/admin_console/console_keys_controller.d.ts +24 -0
  156. package/build/src/host/admin_console/console_keys_controller.js +41 -0
  157. package/build/src/host/admin_console/console_orgs_controller.d.ts +96 -0
  158. package/build/src/host/admin_console/console_orgs_controller.js +238 -0
  159. package/build/src/host/admin_console/console_overview_controller.d.ts +27 -0
  160. package/build/src/host/admin_console/console_overview_controller.js +44 -0
  161. package/build/src/host/admin_console/console_roles_controller.d.ts +31 -0
  162. package/build/src/host/admin_console/console_roles_controller.js +108 -0
  163. package/build/src/host/admin_console/console_sessions_controller.d.ts +91 -0
  164. package/build/src/host/admin_console/console_sessions_controller.js +125 -0
  165. package/build/src/host/admin_console/console_settings_controller.d.ts +47 -0
  166. package/build/src/host/admin_console/console_settings_controller.js +115 -0
  167. package/build/src/host/admin_console/console_users_controller.d.ts +110 -0
  168. package/build/src/host/admin_console/console_users_controller.js +212 -0
  169. package/build/src/host/admin_prefix.d.ts +50 -0
  170. package/build/src/host/admin_prefix.js +77 -0
  171. package/build/src/host/admin_sessions_service.d.ts +119 -0
  172. package/build/src/host/admin_sessions_service.js +284 -0
  173. package/build/src/host/admin_stats_service.d.ts +44 -0
  174. package/build/src/host/admin_stats_service.js +130 -0
  175. package/build/src/host/admin_validators.d.ts +247 -0
  176. package/build/src/host/admin_validators.js +197 -0
  177. package/build/src/host/augmentations.d.ts +12 -0
  178. package/build/src/host/augmentations.js +1 -0
  179. package/build/src/host/auth_host_config.d.ts +22 -0
  180. package/build/src/host/auth_host_config.js +13 -0
  181. package/build/src/host/avatar_storage.d.ts +68 -0
  182. package/build/src/host/avatar_storage.js +166 -0
  183. package/build/src/host/bot_protection.d.ts +187 -0
  184. package/build/src/host/bot_protection.js +132 -0
  185. package/build/src/host/branding.d.ts +19 -0
  186. package/build/src/host/branding.js +8 -0
  187. package/build/src/host/config_locks.d.ts +38 -0
  188. package/build/src/host/config_locks.js +70 -0
  189. package/build/src/host/console_session.d.ts +27 -0
  190. package/build/src/host/console_session.js +36 -0
  191. package/build/src/host/controllers/account_apps_controller.d.ts +15 -0
  192. package/build/src/host/controllers/account_apps_controller.js +61 -0
  193. package/build/src/host/controllers/account_confirm_controller.d.ts +24 -0
  194. package/build/src/host/controllers/account_confirm_controller.js +144 -0
  195. package/build/src/host/controllers/account_mfa_controller.d.ts +28 -0
  196. package/build/src/host/controllers/account_mfa_controller.js +208 -0
  197. package/build/src/host/controllers/account_orgs_controller.d.ts +80 -0
  198. package/build/src/host/controllers/account_orgs_controller.js +401 -0
  199. package/build/src/host/controllers/account_security_controller.d.ts +43 -0
  200. package/build/src/host/controllers/account_security_controller.js +546 -0
  201. package/build/src/host/controllers/account_session_controller.d.ts +21 -0
  202. package/build/src/host/controllers/account_session_controller.js +113 -0
  203. package/build/src/host/controllers/account_tokens_controller.d.ts +7 -0
  204. package/build/src/host/controllers/account_tokens_controller.js +67 -0
  205. package/build/src/host/controllers/interaction_controller.d.ts +125 -0
  206. package/build/src/host/controllers/interaction_controller.js +981 -0
  207. package/build/src/host/controllers/pat_introspection_controller.d.ts +22 -0
  208. package/build/src/host/controllers/pat_introspection_controller.js +46 -0
  209. package/build/src/host/controllers/registration_controller.d.ts +18 -0
  210. package/build/src/host/controllers/registration_controller.js +382 -0
  211. package/build/src/host/controllers/social_controller.d.ts +8 -0
  212. package/build/src/host/controllers/social_controller.js +89 -0
  213. package/build/src/host/csrf.d.ts +29 -0
  214. package/build/src/host/csrf.js +14 -0
  215. package/build/src/host/default_mailer.d.ts +112 -0
  216. package/build/src/host/default_mailer.js +417 -0
  217. package/build/src/host/durable/account_deletion_workflow.d.ts +48 -0
  218. package/build/src/host/durable/account_deletion_workflow.js +86 -0
  219. package/build/src/host/durable/account_export_workflow.d.ts +68 -0
  220. package/build/src/host/durable/account_export_workflow.js +93 -0
  221. package/build/src/host/durable/index.d.ts +68 -0
  222. package/build/src/host/durable/index.js +77 -0
  223. package/build/src/host/email_templates.d.ts +39 -0
  224. package/build/src/host/email_templates.js +69 -0
  225. package/build/src/host/geo.d.ts +22 -0
  226. package/build/src/host/geo.js +39 -0
  227. package/build/src/host/i18n.d.ts +1416 -0
  228. package/build/src/host/i18n.js +1583 -0
  229. package/build/src/host/impersonation.d.ts +25 -0
  230. package/build/src/host/impersonation.js +31 -0
  231. package/build/src/host/key_rotation.d.ts +14 -0
  232. package/build/src/host/key_rotation.js +27 -0
  233. package/build/src/host/key_rotation_actions.d.ts +42 -0
  234. package/build/src/host/key_rotation_actions.js +27 -0
  235. package/build/src/host/login_attempt.d.ts +98 -0
  236. package/build/src/host/login_attempt.js +211 -0
  237. package/build/src/host/login_notify.d.ts +27 -0
  238. package/build/src/host/login_notify.js +142 -0
  239. package/build/src/host/middleware/account_auth.d.ts +7 -0
  240. package/build/src/host/middleware/account_auth.js +11 -0
  241. package/build/src/host/otp_lockout.d.ts +103 -0
  242. package/build/src/host/otp_lockout.js +221 -0
  243. package/build/src/host/rate_limit.d.ts +39 -0
  244. package/build/src/host/rate_limit.js +94 -0
  245. package/build/src/host/register_auth_host.d.ts +97 -0
  246. package/build/src/host/register_auth_host.js +466 -0
  247. package/build/src/host/renderers/edge_renderer.d.ts +12 -0
  248. package/build/src/host/renderers/edge_renderer.js +38 -0
  249. package/build/src/host/renderers/inertia_renderer.d.ts +70 -0
  250. package/build/src/host/renderers/inertia_renderer.js +54 -0
  251. package/build/src/host/runtime_settings.d.ts +181 -0
  252. package/build/src/host/runtime_settings.js +307 -0
  253. package/build/src/host/runtime_toggles.d.ts +807 -0
  254. package/build/src/host/runtime_toggles.js +784 -0
  255. package/build/src/host/security_notice_service.d.ts +36 -0
  256. package/build/src/host/security_notice_service.js +87 -0
  257. package/build/src/host/session_context.d.ts +23 -0
  258. package/build/src/host/session_context.js +89 -0
  259. package/build/src/host/sudo_mode.d.ts +56 -0
  260. package/build/src/host/sudo_mode.js +99 -0
  261. package/build/src/host/svg_chart.d.ts +15 -0
  262. package/build/src/host/svg_chart.js +45 -0
  263. package/build/src/host/trusted_device.d.ts +61 -0
  264. package/build/src/host/trusted_device.js +65 -0
  265. package/build/src/host/ui-dist/assets/index-CRWcmsex.js +137 -0
  266. package/build/src/host/ui-dist/assets/index-DTSmD4RU.css +1 -0
  267. package/build/src/host/ui-dist/index.html +17 -0
  268. package/build/src/host/user_agent.d.ts +18 -0
  269. package/build/src/host/user_agent.js +50 -0
  270. package/build/src/host/validators.d.ts +127 -0
  271. package/build/src/host/validators.js +53 -0
  272. package/build/src/keys/jwks_manager.d.ts +6 -0
  273. package/build/src/keys/jwks_manager.js +11 -0
  274. package/build/src/keys/keystore.d.ts +52 -0
  275. package/build/src/keys/keystore.js +68 -0
  276. package/build/src/keys/keystore_codec.d.ts +20 -0
  277. package/build/src/keys/keystore_codec.js +42 -0
  278. package/build/src/keys/keystore_crypto.d.ts +9 -0
  279. package/build/src/keys/keystore_crypto.js +27 -0
  280. package/build/src/keys/keystore_manager.d.ts +43 -0
  281. package/build/src/keys/keystore_manager.js +104 -0
  282. package/build/src/keys/keystore_vault.d.ts +113 -0
  283. package/build/src/keys/keystore_vault.js +265 -0
  284. package/build/src/mixins/json_column.d.ts +33 -0
  285. package/build/src/mixins/json_column.js +38 -0
  286. package/build/src/mixins/with_audit_log.d.ts +19 -0
  287. package/build/src/mixins/with_audit_log.js +39 -0
  288. package/build/src/mixins/with_auth_user.d.ts +24 -0
  289. package/build/src/mixins/with_auth_user.js +46 -0
  290. package/build/src/mixins/with_credentials.d.ts +20 -0
  291. package/build/src/mixins/with_credentials.js +29 -0
  292. package/build/src/mixins/with_mfa.d.ts +35 -0
  293. package/build/src/mixins/with_mfa.js +21 -0
  294. package/build/src/mixins/with_personal_access_token.d.ts +19 -0
  295. package/build/src/mixins/with_personal_access_token.js +42 -0
  296. package/build/src/mixins/with_provider_identity.d.ts +20 -0
  297. package/build/src/mixins/with_provider_identity.js +32 -0
  298. package/build/src/mixins/with_webauthn_credential.d.ts +37 -0
  299. package/build/src/mixins/with_webauthn_credential.js +46 -0
  300. package/build/src/observability/diagnostics_bridge.d.ts +6 -0
  301. package/build/src/observability/diagnostics_bridge.js +27 -0
  302. package/build/src/observability/metrics_controller.d.ts +5 -0
  303. package/build/src/observability/metrics_controller.js +24 -0
  304. package/build/src/observability/metrics_service.d.ts +2 -0
  305. package/build/src/observability/metrics_service.js +7 -0
  306. package/build/src/observability/otel_recorder.d.ts +10 -0
  307. package/build/src/observability/otel_recorder.js +59 -0
  308. package/build/src/observability/telescope/data_providers.d.ts +24 -0
  309. package/build/src/observability/telescope/data_providers.js +235 -0
  310. package/build/src/observability/telescope/extension.d.ts +29 -0
  311. package/build/src/observability/telescope/extension.js +167 -0
  312. package/build/src/observability/telescope/index.d.ts +8 -0
  313. package/build/src/observability/telescope/index.js +8 -0
  314. package/build/src/observability/wire_provider_events.d.ts +12 -0
  315. package/build/src/observability/wire_provider_events.js +30 -0
  316. package/build/src/password/common_passwords.d.ts +31 -0
  317. package/build/src/password/common_passwords.js +73 -0
  318. package/build/src/password/password_manager.d.ts +163 -0
  319. package/build/src/password/password_manager.js +191 -0
  320. package/build/src/password/policy.d.ts +71 -0
  321. package/build/src/password/policy.js +55 -0
  322. package/build/src/password/pwned.d.ts +36 -0
  323. package/build/src/password/pwned.js +52 -0
  324. package/build/src/pat/lucid_pat_store.d.ts +6 -0
  325. package/build/src/pat/lucid_pat_store.js +62 -0
  326. package/build/src/pat/pat_store.d.ts +31 -0
  327. package/build/src/pat/pat_store.js +1 -0
  328. package/build/src/pat/pat_tokens.d.ts +4 -0
  329. package/build/src/pat/pat_tokens.js +9 -0
  330. package/build/src/provider/build_provider.d.ts +45 -0
  331. package/build/src/provider/build_provider.js +219 -0
  332. package/build/src/provider/device_sources.d.ts +6 -0
  333. package/build/src/provider/device_sources.js +65 -0
  334. package/build/src/provider/interaction_actions.d.ts +36 -0
  335. package/build/src/provider/interaction_actions.js +55 -0
  336. package/build/src/provider/key_rotation_scheduler.d.ts +28 -0
  337. package/build/src/provider/key_rotation_scheduler.js +40 -0
  338. package/build/src/provider/keystore_reload.d.ts +21 -0
  339. package/build/src/provider/keystore_reload.js +39 -0
  340. package/build/src/provider/logout_sources.d.ts +13 -0
  341. package/build/src/provider/logout_sources.js +64 -0
  342. package/build/src/provider/oidc_service.d.ts +81 -0
  343. package/build/src/provider/oidc_service.js +254 -0
  344. package/build/src/provider/single_flight_lock.d.ts +18 -0
  345. package/build/src/provider/single_flight_lock.js +31 -0
  346. package/build/src/provider/token_exchange.d.ts +21 -0
  347. package/build/src/provider/token_exchange.js +124 -0
  348. package/build/src/register_routes.d.ts +16 -0
  349. package/build/src/register_routes.js +21 -0
  350. package/build/src/schema/ensure.d.ts +41 -0
  351. package/build/src/schema/ensure.js +262 -0
  352. package/build/stubs/config/authkit.stub +20 -0
  353. package/build/stubs/config/authkit_react.stub +52 -0
  354. package/build/stubs/main.d.ts +1 -0
  355. package/build/stubs/main.js +2 -0
  356. package/build/stubs/models/auth_user.stub +22 -0
  357. package/build/stubs/ui/edge/views/consent.edge +13 -0
  358. package/build/stubs/ui/edge/views/login.edge +19 -0
  359. package/build/stubs/ui/react/components/auth_shell.tsx +67 -0
  360. package/build/stubs/ui/react/pages/account/login.tsx +56 -0
  361. package/build/stubs/ui/react/pages/account/mfa.tsx +132 -0
  362. package/build/stubs/ui/react/pages/account/tokens.tsx +88 -0
  363. package/build/stubs/ui/react/pages/consent.tsx +39 -0
  364. package/build/stubs/ui/react/pages/forgot.tsx +44 -0
  365. package/build/stubs/ui/react/pages/login.tsx +171 -0
  366. package/build/stubs/ui/react/pages/mfa-challenge.tsx +72 -0
  367. package/build/stubs/ui/react/pages/reset.tsx +58 -0
  368. package/build/stubs/ui/react/pages/signup.tsx +78 -0
  369. package/build/stubs/ui/react/pages/verify-email.tsx +24 -0
  370. package/build/types.d.ts +7 -0
  371. package/build/types.js +1 -0
  372. package/package.json +147 -0
  373. package/stubs/config/authkit.stub +20 -0
  374. package/stubs/config/authkit_react.stub +52 -0
  375. package/stubs/main.ts +2 -0
  376. package/stubs/models/auth_user.stub +22 -0
  377. package/stubs/ui/edge/views/consent.edge +13 -0
  378. package/stubs/ui/edge/views/login.edge +19 -0
  379. package/stubs/ui/react/components/auth_shell.tsx +67 -0
  380. package/stubs/ui/react/pages/account/login.tsx +56 -0
  381. package/stubs/ui/react/pages/account/mfa.tsx +132 -0
  382. package/stubs/ui/react/pages/account/tokens.tsx +88 -0
  383. package/stubs/ui/react/pages/consent.tsx +39 -0
  384. package/stubs/ui/react/pages/forgot.tsx +44 -0
  385. package/stubs/ui/react/pages/login.tsx +171 -0
  386. package/stubs/ui/react/pages/mfa-challenge.tsx +72 -0
  387. package/stubs/ui/react/pages/reset.tsx +58 -0
  388. package/stubs/ui/react/pages/signup.tsx +78 -0
  389. package/stubs/ui/react/pages/verify-email.tsx +24 -0
@@ -0,0 +1,784 @@
1
+ /**
2
+ * Runtime toggles — settings de `auth_settings` que controlam comportamento
3
+ * operacional em tempo de execução, no padrão do bot_protection resolver.
4
+ *
5
+ * Cada setting segue o contrato:
6
+ * - setting presente → manda (sobrescreve config estático)
7
+ * - setting ausente/inválido/erro DB → config estático (fail-safe total)
8
+ *
9
+ * Keys conhecidas em `auth_settings`:
10
+ * - `registration` → RegistrationSetting
11
+ * - `require_verified_email` → RequireVerifiedEmailSetting
12
+ * - `maintenance_mode` → MaintenanceModeSetting
13
+ */
14
+ // ---------------------------------------------------------------------------
15
+ // Known setting keys registry
16
+ // ---------------------------------------------------------------------------
17
+ /**
18
+ * Chaves conhecidas do catálogo de runtime settings. Centralizado aqui para
19
+ * que qualquer code-path possa importar a constante e não depender de strings.
20
+ */
21
+ export const SETTING_KEYS = {
22
+ BOT_PROTECTION: 'bot_protection',
23
+ REGISTRATION: 'registration',
24
+ REQUIRE_VERIFIED_EMAIL: 'require_verified_email',
25
+ MAINTENANCE_MODE: 'maintenance_mode',
26
+ AUTH_METHODS: 'auth_methods',
27
+ EMAIL_CHANGE: 'email_change',
28
+ SECURITY_NOTIFICATIONS: 'security_notifications',
29
+ PASSWORD_HISTORY: 'password_history',
30
+ PASSWORD_EXPIRATION: 'password_expiration',
31
+ SESSION_POLICY: 'session_policy',
32
+ LOCKOUT: 'lockout',
33
+ RATE_LIMIT: 'rate_limit',
34
+ PASSWORD_POLICY: 'password_policy',
35
+ NOTIFICATIONS: 'notifications',
36
+ TRUSTED_DEVICES: 'trusted_devices',
37
+ TOKEN_TTL: 'token_ttl',
38
+ ADMIN_IMPERSONATION: 'admin_impersonation',
39
+ ORGANIZATIONS_POLICY: 'organizations_policy',
40
+ ROLES_CATALOG: 'roles_catalog',
41
+ OTP_LOCKOUT: 'otp_lockout',
42
+ SUDO_MODE: 'sudo_mode',
43
+ ACCOUNT_EXPIRATION: 'account_expiration',
44
+ KEY_ROTATION: 'key_rotation',
45
+ };
46
+ /**
47
+ * Resolve o valor efetivo de "registration enabled" combinando a setting
48
+ * persistida em runtime com o config estático.
49
+ *
50
+ * Regras:
51
+ * - `config.registration?.enabled` pode estar em `ResolvedServerConfig`
52
+ * (quando o host o declara). Default: `true` (aberto por padrão).
53
+ * - setting presente → sobrescreve o default/config.
54
+ * - setting ausente/inválido/erro → usa configDefault.
55
+ *
56
+ * FAIL-SAFE: `getSetting` nunca lança (contrato do RuntimeSettings). Se
57
+ * retornar null, usamos configDefault.
58
+ */
59
+ export async function resolveEffectiveRegistration(configDefault = true, settings) {
60
+ const raw = await settings.getSetting(SETTING_KEYS.REGISTRATION);
61
+ if (raw === null || raw === undefined)
62
+ return configDefault;
63
+ if (typeof raw !== 'object' || typeof raw.enabled !== 'boolean') {
64
+ return configDefault; // shape inválida → fallback
65
+ }
66
+ return raw.enabled;
67
+ }
68
+ /**
69
+ * Resolve o valor efetivo de `requireVerifiedEmail` combinando a setting
70
+ * persistida em runtime com o config estático.
71
+ *
72
+ * Regras (mesmas do `resolveEffectiveRegistration`):
73
+ * - configDefault vem de `cfg.login.requireVerifiedEmail` (default false).
74
+ * - setting presente → sobrescreve.
75
+ * - setting ausente/inválido/erro → usa configDefault.
76
+ */
77
+ export async function resolveEffectiveRequireVerifiedEmail(configDefault = false, settings) {
78
+ const raw = await settings.getSetting(SETTING_KEYS.REQUIRE_VERIFIED_EMAIL);
79
+ if (raw === null || raw === undefined)
80
+ return configDefault;
81
+ if (typeof raw !== 'object' || typeof raw.enabled !== 'boolean') {
82
+ return configDefault; // shape inválida → fallback
83
+ }
84
+ return raw.enabled;
85
+ }
86
+ /**
87
+ * Resolve o valor efetivo COMPLETO de `require_verified_email` incluindo
88
+ * `graceDays`. Usado pelo gate de login para implementar a janela de graça.
89
+ *
90
+ * FAIL-SAFE: qualquer erro → `{ enabled: configDefault, graceDays: 0 }`.
91
+ */
92
+ export async function resolveEffectiveRequireVerifiedEmailFull(configDefault = false, settings) {
93
+ try {
94
+ const raw = await settings.getSetting(SETTING_KEYS.REQUIRE_VERIFIED_EMAIL);
95
+ if (raw === null || raw === undefined)
96
+ return { enabled: configDefault, graceDays: 0 };
97
+ if (typeof raw !== 'object' || typeof raw.enabled !== 'boolean') {
98
+ return { enabled: configDefault, graceDays: 0 };
99
+ }
100
+ const s = raw;
101
+ const graceDays = typeof s.graceDays === 'number' && s.graceDays >= 0 ? Math.floor(s.graceDays) : 0;
102
+ return { enabled: s.enabled, graceDays };
103
+ }
104
+ catch {
105
+ return { enabled: configDefault, graceDays: 0 };
106
+ }
107
+ }
108
+ /**
109
+ * Resolve o estado efetivo do maintenance mode a partir da setting persistida.
110
+ *
111
+ * Regras:
112
+ * - setting ausente/inválido/erro DB → `{ enabled: false }` (default: sistema UP).
113
+ * - setting presente → usa o valor da setting.
114
+ *
115
+ * FAIL-SAFE: qualquer erro → sistema considerado UP (disponibilidade > proteção).
116
+ */
117
+ export async function resolveEffectiveMaintenanceMode(settings) {
118
+ const raw = await settings.getSetting(SETTING_KEYS.MAINTENANCE_MODE);
119
+ if (raw === null || raw === undefined)
120
+ return { enabled: false };
121
+ if (typeof raw !== 'object' || typeof raw.enabled !== 'boolean') {
122
+ return { enabled: false }; // shape inválida → fail-safe
123
+ }
124
+ const setting = raw;
125
+ return {
126
+ enabled: setting.enabled,
127
+ message: typeof setting.message === 'string' ? setting.message : undefined,
128
+ };
129
+ }
130
+ /**
131
+ * Resolve os métodos de autenticação efetivos combinando config estático + setting
132
+ * persistida em runtime + capabilities.
133
+ *
134
+ * Regras:
135
+ * 1. Defaults derivados do config/capabilities.
136
+ * 2. Setting presente → sobrescreve campo a campo.
137
+ * 3. DERIVAÇÃO: `forgotPassword` efetivo = (setting.forgotPassword ?? true) && passwordEnabled.
138
+ * Sem método senha ativo, "esqueci minha senha" NUNCA aparece.
139
+ * 4. `social` efetivo = interseção do setting.social com os providers do config.
140
+ * Setting não pode LIGAR provider que o código não tem.
141
+ * 5. FAIL-SAFE all-off: se todos os métodos ficarem desligados, volta ao derivado
142
+ * do config (nunca deixar a tela sem nenhum método). Loga um aviso (console.warn).
143
+ * 6. Qualquer erro DB → defaults derivados do config (fail-safe total).
144
+ */
145
+ export async function resolveEffectiveAuthMethods(settings, capabilities = {}) {
146
+ const { configuredSocialProviders = [], magicLinkCapable = false, passkeyCapable = false, } = capabilities;
147
+ // Defaults derivados do config/capabilities.
148
+ const configDefaults = {
149
+ password: true,
150
+ magicLink: magicLinkCapable,
151
+ passkey: passkeyCapable,
152
+ social: configuredSocialProviders,
153
+ forgotPassword: true,
154
+ passkeyAutofill: passkeyCapable, // on por default quando passkey disponível
155
+ };
156
+ const raw = await settings.getSetting(SETTING_KEYS.AUTH_METHODS);
157
+ if (raw === null || raw === undefined)
158
+ return configDefaults;
159
+ if (typeof raw !== 'object' || Array.isArray(raw))
160
+ return configDefaults; // shape inválida
161
+ const s = raw;
162
+ // Aplica campo a campo, com fallback ao default quando o campo está ausente.
163
+ const passwordEnabled = typeof s.password === 'boolean' ? s.password : configDefaults.password;
164
+ const magicLinkEnabled = typeof s.magicLink === 'boolean' ? s.magicLink : configDefaults.magicLink;
165
+ const passkeyEnabled = typeof s.passkey === 'boolean' ? s.passkey : configDefaults.passkey;
166
+ // Social: interseção com os providers do config (setting não pode ligar o que não existe).
167
+ let socialEnabled;
168
+ if (Array.isArray(s.social)) {
169
+ socialEnabled = s.social.filter((p) => configuredSocialProviders.includes(p));
170
+ }
171
+ else {
172
+ socialEnabled = configDefaults.social;
173
+ }
174
+ // forgotPassword: derivado automaticamente — sem senha NUNCA existe esqueci-senha.
175
+ const forgotPasswordEnabled = passwordEnabled && (typeof s.forgotPassword === 'boolean' ? s.forgotPassword : true);
176
+ // passkeyAutofill: só faz sentido quando passkey está ligado.
177
+ const passkeyAutofillEnabled = passkeyEnabled &&
178
+ (typeof s.passkeyAutofill === 'boolean' ? s.passkeyAutofill : configDefaults.passkeyAutofill);
179
+ const resolved = {
180
+ password: passwordEnabled,
181
+ magicLink: magicLinkEnabled,
182
+ passkey: passkeyEnabled,
183
+ social: socialEnabled,
184
+ forgotPassword: forgotPasswordEnabled,
185
+ passkeyAutofill: passkeyAutofillEnabled,
186
+ };
187
+ // FAIL-SAFE all-off: se todos ficaram false/vazio, volta ao config derivado.
188
+ const allOff = !resolved.password &&
189
+ !resolved.magicLink &&
190
+ !resolved.passkey &&
191
+ resolved.social.length === 0;
192
+ if (allOff) {
193
+ // eslint-disable-next-line no-console
194
+ console.warn('[authkit] auth_methods setting deixou todos os métodos desligados — ' +
195
+ 'revertendo para os defaults do config (fail-safe). ' +
196
+ 'Verifique a setting auth_methods no console admin.');
197
+ return configDefaults;
198
+ }
199
+ return resolved;
200
+ }
201
+ /**
202
+ * Resolve as configurações efetivas de troca de e-mail, combinando a setting
203
+ * persistida em runtime com defaults.
204
+ *
205
+ * FAIL-SAFE: qualquer erro → defaults (enabled true, 24h, requirePassword true).
206
+ */
207
+ export async function resolveEffectiveEmailChange(settings) {
208
+ const defaults = { enabled: true, ttlHours: 24, requirePassword: true };
209
+ try {
210
+ const raw = await settings.getSetting(SETTING_KEYS.EMAIL_CHANGE);
211
+ if (raw === null || raw === undefined)
212
+ return defaults;
213
+ if (typeof raw !== 'object' || Array.isArray(raw))
214
+ return defaults;
215
+ const s = raw;
216
+ return {
217
+ enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
218
+ ttlHours: typeof s.ttlHours === 'number' && s.ttlHours > 0 ? s.ttlHours : defaults.ttlHours,
219
+ requirePassword: typeof s.requirePassword === 'boolean' ? s.requirePassword : defaults.requirePassword,
220
+ };
221
+ }
222
+ catch {
223
+ return defaults;
224
+ }
225
+ }
226
+ /** Todos os tipos de notificação de segurança suportados. */
227
+ export const ALL_SECURITY_NOTIFICATION_KINDS = [
228
+ 'password_changed',
229
+ 'mfa_enabled',
230
+ 'mfa_disabled',
231
+ 'passkey_added',
232
+ 'passkey_removed',
233
+ 'email_changed',
234
+ ];
235
+ /**
236
+ * Resolve as notificações de segurança efetivas, combinando a setting
237
+ * persistida em runtime com defaults.
238
+ *
239
+ * FAIL-SAFE: qualquer erro → defaults (enabled true, todos os kinds).
240
+ */
241
+ export async function resolveEffectiveSecurityNotifications(settings) {
242
+ const defaults = {
243
+ enabled: true,
244
+ kinds: [...ALL_SECURITY_NOTIFICATION_KINDS],
245
+ };
246
+ try {
247
+ const raw = await settings.getSetting(SETTING_KEYS.SECURITY_NOTIFICATIONS);
248
+ if (raw === null || raw === undefined)
249
+ return defaults;
250
+ if (typeof raw !== 'object' || Array.isArray(raw))
251
+ return defaults;
252
+ const s = raw;
253
+ const enabled = typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled;
254
+ let kinds;
255
+ if (Array.isArray(s.kinds) && s.kinds.length > 0) {
256
+ // Apenas aceita kinds válidos (interseção com os suportados).
257
+ kinds = s.kinds.filter((k) => ALL_SECURITY_NOTIFICATION_KINDS.includes(k));
258
+ if (kinds.length === 0)
259
+ kinds = [...ALL_SECURITY_NOTIFICATION_KINDS];
260
+ }
261
+ else {
262
+ kinds = [...ALL_SECURITY_NOTIFICATION_KINDS];
263
+ }
264
+ return { enabled, kinds };
265
+ }
266
+ catch {
267
+ return defaults;
268
+ }
269
+ }
270
+ /**
271
+ * Resolve as configurações efetivas de histórico de senhas.
272
+ *
273
+ * FAIL-SAFE: qualquer erro → `{ enabled: false, count: 5 }`.
274
+ */
275
+ export async function resolveEffectivePasswordHistory(settings) {
276
+ const defaults = { enabled: false, count: 5 };
277
+ try {
278
+ const raw = await settings.getSetting(SETTING_KEYS.PASSWORD_HISTORY);
279
+ if (raw === null || raw === undefined)
280
+ return defaults;
281
+ if (typeof raw !== 'object' || Array.isArray(raw))
282
+ return defaults;
283
+ const s = raw;
284
+ return {
285
+ enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
286
+ count: typeof s.count === 'number' && s.count >= 1 ? Math.floor(s.count) : defaults.count,
287
+ };
288
+ }
289
+ catch {
290
+ return defaults;
291
+ }
292
+ }
293
+ /** Defaults da session_policy quando a setting não existe. */
294
+ export const SESSION_POLICY_DEFAULTS = {
295
+ rememberEnabled: true,
296
+ rememberDays: 30,
297
+ defaultSessionHours: 168, // 7 dias em horas (= 604800 s padrão do oidc-provider)
298
+ singleSession: false,
299
+ idleTimeoutMinutes: 0,
300
+ };
301
+ /**
302
+ * Resolve as configurações efetivas de session policy.
303
+ *
304
+ * FAIL-SAFE: qualquer erro → defaults (comportamento original intacto).
305
+ *
306
+ * @param configDefaultSessionHours Horas derivadas de `config.ttl.session` (em segundos → horas).
307
+ * Quando ausente, usa 168 h (7 dias = padrão do oidc-provider).
308
+ */
309
+ export async function resolveEffectiveSessionPolicy(settings, configDefaultSessionHours) {
310
+ const defaults = {
311
+ ...SESSION_POLICY_DEFAULTS,
312
+ defaultSessionHours: configDefaultSessionHours ?? SESSION_POLICY_DEFAULTS.defaultSessionHours,
313
+ };
314
+ try {
315
+ const raw = await settings.getSetting(SETTING_KEYS.SESSION_POLICY);
316
+ if (raw === null || raw === undefined)
317
+ return defaults;
318
+ if (typeof raw !== 'object' || Array.isArray(raw))
319
+ return defaults;
320
+ const s = raw;
321
+ return {
322
+ rememberEnabled: typeof s.rememberEnabled === 'boolean' ? s.rememberEnabled : defaults.rememberEnabled,
323
+ rememberDays: typeof s.rememberDays === 'number' && s.rememberDays >= 1 ? Math.floor(s.rememberDays) : defaults.rememberDays,
324
+ defaultSessionHours: typeof s.defaultSessionHours === 'number' && s.defaultSessionHours >= 1 ? Math.floor(s.defaultSessionHours) : defaults.defaultSessionHours,
325
+ singleSession: typeof s.singleSession === 'boolean' ? s.singleSession : defaults.singleSession,
326
+ idleTimeoutMinutes: typeof s.idleTimeoutMinutes === 'number' && s.idleTimeoutMinutes >= 0 ? Math.floor(s.idleTimeoutMinutes) : defaults.idleTimeoutMinutes,
327
+ };
328
+ }
329
+ catch {
330
+ return defaults;
331
+ }
332
+ }
333
+ /**
334
+ * Resolve as configurações efetivas de expiração de senha.
335
+ *
336
+ * FAIL-SAFE: qualquer erro → `{ enabled: false, maxAgeDays: 90 }`.
337
+ */
338
+ export async function resolveEffectivePasswordExpiration(settings) {
339
+ const defaults = { enabled: false, maxAgeDays: 90 };
340
+ try {
341
+ const raw = await settings.getSetting(SETTING_KEYS.PASSWORD_EXPIRATION);
342
+ if (raw === null || raw === undefined)
343
+ return defaults;
344
+ if (typeof raw !== 'object' || Array.isArray(raw))
345
+ return defaults;
346
+ const s = raw;
347
+ return {
348
+ enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
349
+ maxAgeDays: typeof s.maxAgeDays === 'number' && s.maxAgeDays >= 1 ? Math.floor(s.maxAgeDays) : defaults.maxAgeDays,
350
+ };
351
+ }
352
+ catch {
353
+ return defaults;
354
+ }
355
+ }
356
+ const LOCKOUT_LIB_DEFAULTS = {
357
+ enabled: true,
358
+ maxAttempts: 5,
359
+ windowSec: 900,
360
+ baseLockoutSec: 60,
361
+ maxLockoutSec: 3600,
362
+ };
363
+ /**
364
+ * Resolve as configurações efetivas de lockout.
365
+ *
366
+ * Precedência: setting BD → configDefault → lib default.
367
+ * FAIL-SAFE: qualquer erro → configDefault (ou lib defaults).
368
+ */
369
+ export async function resolveEffectiveLockout(settings, configDefault = {}) {
370
+ const defaults = {
371
+ enabled: configDefault.enabled ?? LOCKOUT_LIB_DEFAULTS.enabled,
372
+ maxAttempts: configDefault.maxAttempts ?? LOCKOUT_LIB_DEFAULTS.maxAttempts,
373
+ windowSec: configDefault.windowSec ?? LOCKOUT_LIB_DEFAULTS.windowSec,
374
+ baseLockoutSec: configDefault.baseLockoutSec ?? LOCKOUT_LIB_DEFAULTS.baseLockoutSec,
375
+ maxLockoutSec: configDefault.maxLockoutSec ?? LOCKOUT_LIB_DEFAULTS.maxLockoutSec,
376
+ };
377
+ try {
378
+ const raw = await settings.getSetting(SETTING_KEYS.LOCKOUT);
379
+ if (raw === null || raw === undefined)
380
+ return defaults;
381
+ if (typeof raw !== 'object' || Array.isArray(raw))
382
+ return defaults;
383
+ const s = raw;
384
+ return {
385
+ enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
386
+ maxAttempts: typeof s.maxAttempts === 'number' && s.maxAttempts >= 1 ? Math.floor(s.maxAttempts) : defaults.maxAttempts,
387
+ windowSec: typeof s.windowSec === 'number' && s.windowSec >= 1 ? Math.floor(s.windowSec) : defaults.windowSec,
388
+ baseLockoutSec: typeof s.baseLockoutSec === 'number' && s.baseLockoutSec >= 1 ? Math.floor(s.baseLockoutSec) : defaults.baseLockoutSec,
389
+ maxLockoutSec: typeof s.maxLockoutSec === 'number' && s.maxLockoutSec >= 1 ? Math.floor(s.maxLockoutSec) : defaults.maxLockoutSec,
390
+ };
391
+ }
392
+ catch {
393
+ return defaults;
394
+ }
395
+ }
396
+ const RATE_LIMIT_LIB_DEFAULTS = {
397
+ login: { points: 10, duration: '1 min' },
398
+ introspection: { points: 60, duration: '1 min' },
399
+ };
400
+ /**
401
+ * Resolve as configurações efetivas dos buckets de rate-limit.
402
+ *
403
+ * Precedência: setting BD → configDefault → lib default.
404
+ * FAIL-SAFE: qualquer erro → configDefault.
405
+ *
406
+ * NOTA: o middleware de throttle de rota (Adonis) usa os valores do config de
407
+ * boot e NÃO é afetado por esta setting em runtime. Veja JSDoc de RateLimitSetting.
408
+ */
409
+ export async function resolveEffectiveRateLimit(settings, configDefault = {}) {
410
+ const defaults = {
411
+ login: {
412
+ points: configDefault.login?.points ?? RATE_LIMIT_LIB_DEFAULTS.login.points,
413
+ duration: configDefault.login?.duration ?? RATE_LIMIT_LIB_DEFAULTS.login.duration,
414
+ },
415
+ introspection: {
416
+ points: configDefault.introspection?.points ?? RATE_LIMIT_LIB_DEFAULTS.introspection.points,
417
+ duration: configDefault.introspection?.duration ?? RATE_LIMIT_LIB_DEFAULTS.introspection.duration,
418
+ },
419
+ };
420
+ try {
421
+ const raw = await settings.getSetting(SETTING_KEYS.RATE_LIMIT);
422
+ if (raw === null || raw === undefined)
423
+ return defaults;
424
+ if (typeof raw !== 'object' || Array.isArray(raw))
425
+ return defaults;
426
+ const s = raw;
427
+ return {
428
+ login: {
429
+ points: typeof s.login?.points === 'number' && s.login.points >= 1 ? Math.floor(s.login.points) : defaults.login.points,
430
+ duration: typeof s.login?.duration === 'string' && s.login.duration.trim() ? s.login.duration.trim() : defaults.login.duration,
431
+ },
432
+ introspection: {
433
+ points: typeof s.introspection?.points === 'number' && s.introspection.points >= 1 ? Math.floor(s.introspection.points) : defaults.introspection.points,
434
+ duration: typeof s.introspection?.duration === 'string' && s.introspection.duration.trim() ? s.introspection.duration.trim() : defaults.introspection.duration,
435
+ },
436
+ };
437
+ }
438
+ catch {
439
+ return defaults;
440
+ }
441
+ }
442
+ const PASSWORD_POLICY_LIB_DEFAULTS = {
443
+ minLength: 8,
444
+ requireUppercase: false,
445
+ requireLowercase: false,
446
+ requireNumbers: false,
447
+ requireSymbols: false,
448
+ checkPwned: false,
449
+ blockCommon: true,
450
+ };
451
+ /**
452
+ * Resolve as configurações efetivas de política de senha.
453
+ *
454
+ * Precedência: setting BD → configDefault → lib default.
455
+ * FAIL-SAFE: qualquer erro → configDefault.
456
+ */
457
+ export async function resolveEffectivePasswordPolicy(settings, configDefault = {}) {
458
+ const defaults = {
459
+ minLength: configDefault.minLength ?? PASSWORD_POLICY_LIB_DEFAULTS.minLength,
460
+ requireUppercase: configDefault.requireUppercase ?? PASSWORD_POLICY_LIB_DEFAULTS.requireUppercase,
461
+ requireLowercase: configDefault.requireLowercase ?? PASSWORD_POLICY_LIB_DEFAULTS.requireLowercase,
462
+ requireNumbers: configDefault.requireNumbers ?? PASSWORD_POLICY_LIB_DEFAULTS.requireNumbers,
463
+ requireSymbols: configDefault.requireSymbols ?? PASSWORD_POLICY_LIB_DEFAULTS.requireSymbols,
464
+ checkPwned: configDefault.checkPwned ?? PASSWORD_POLICY_LIB_DEFAULTS.checkPwned,
465
+ blockCommon: configDefault.blockCommon ?? PASSWORD_POLICY_LIB_DEFAULTS.blockCommon,
466
+ };
467
+ try {
468
+ const raw = await settings.getSetting(SETTING_KEYS.PASSWORD_POLICY);
469
+ if (raw === null || raw === undefined)
470
+ return defaults;
471
+ if (typeof raw !== 'object' || Array.isArray(raw))
472
+ return defaults;
473
+ const s = raw;
474
+ return {
475
+ minLength: typeof s.minLength === 'number' && s.minLength >= 1 ? Math.floor(s.minLength) : defaults.minLength,
476
+ requireUppercase: typeof s.requireUppercase === 'boolean' ? s.requireUppercase : defaults.requireUppercase,
477
+ requireLowercase: typeof s.requireLowercase === 'boolean' ? s.requireLowercase : defaults.requireLowercase,
478
+ requireNumbers: typeof s.requireNumbers === 'boolean' ? s.requireNumbers : defaults.requireNumbers,
479
+ requireSymbols: typeof s.requireSymbols === 'boolean' ? s.requireSymbols : defaults.requireSymbols,
480
+ checkPwned: typeof s.checkPwned === 'boolean' ? s.checkPwned : defaults.checkPwned,
481
+ blockCommon: typeof s.blockCommon === 'boolean' ? s.blockCommon : defaults.blockCommon,
482
+ };
483
+ }
484
+ catch {
485
+ return defaults;
486
+ }
487
+ }
488
+ /**
489
+ * Resolve as configurações efetivas de notificações de acesso/dispositivo.
490
+ *
491
+ * Precedência: setting BD → configDefault → lib default (true/true).
492
+ * FAIL-SAFE: qualquer erro → configDefault.
493
+ */
494
+ export async function resolveEffectiveNotifications(settings, configDefault = {}) {
495
+ const defaults = {
496
+ newLoginEmail: configDefault.newLoginEmail ?? true,
497
+ newDeviceEmail: configDefault.newDeviceEmail ?? true,
498
+ };
499
+ try {
500
+ const raw = await settings.getSetting(SETTING_KEYS.NOTIFICATIONS);
501
+ if (raw === null || raw === undefined)
502
+ return defaults;
503
+ if (typeof raw !== 'object' || Array.isArray(raw))
504
+ return defaults;
505
+ const s = raw;
506
+ return {
507
+ newLoginEmail: typeof s.newLoginEmail === 'boolean' ? s.newLoginEmail : defaults.newLoginEmail,
508
+ newDeviceEmail: typeof s.newDeviceEmail === 'boolean' ? s.newDeviceEmail : defaults.newDeviceEmail,
509
+ };
510
+ }
511
+ catch {
512
+ return defaults;
513
+ }
514
+ }
515
+ /**
516
+ * Resolve as configurações efetivas de trusted devices.
517
+ *
518
+ * Precedência: setting BD → configDefault → lib default (enabled=true, days=30).
519
+ * FAIL-SAFE: qualquer erro → configDefault.
520
+ */
521
+ export async function resolveEffectiveTrustedDevices(settings, configDefault = {}) {
522
+ const defaults = {
523
+ enabled: configDefault.enabled ?? true,
524
+ days: configDefault.days ?? 30,
525
+ };
526
+ try {
527
+ const raw = await settings.getSetting(SETTING_KEYS.TRUSTED_DEVICES);
528
+ if (raw === null || raw === undefined)
529
+ return defaults;
530
+ if (typeof raw !== 'object' || Array.isArray(raw))
531
+ return defaults;
532
+ const s = raw;
533
+ return {
534
+ enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
535
+ days: typeof s.days === 'number' && s.days >= 1 ? Math.floor(s.days) : defaults.days,
536
+ };
537
+ }
538
+ catch {
539
+ return defaults;
540
+ }
541
+ }
542
+ /**
543
+ * Resolve as configurações efetivas de TTL de tokens.
544
+ *
545
+ * Precedência: setting BD → configDefault → lib default (900s/900s/2592000s).
546
+ * FAIL-SAFE: qualquer erro → configDefault.
547
+ */
548
+ export async function resolveEffectiveTokenTtl(settings, configDefault = {}) {
549
+ const defaults = {
550
+ accessTokenSec: configDefault.accessTokenSec ?? 900,
551
+ idTokenSec: configDefault.idTokenSec ?? 900,
552
+ refreshTokenSec: configDefault.refreshTokenSec ?? 2592000,
553
+ };
554
+ try {
555
+ const raw = await settings.getSetting(SETTING_KEYS.TOKEN_TTL);
556
+ if (raw === null || raw === undefined)
557
+ return defaults;
558
+ if (typeof raw !== 'object' || Array.isArray(raw))
559
+ return defaults;
560
+ const s = raw;
561
+ return {
562
+ accessTokenSec: typeof s.accessTokenSec === 'number' && s.accessTokenSec >= 1 ? Math.floor(s.accessTokenSec) : defaults.accessTokenSec,
563
+ idTokenSec: typeof s.idTokenSec === 'number' && s.idTokenSec >= 1 ? Math.floor(s.idTokenSec) : defaults.idTokenSec,
564
+ refreshTokenSec: typeof s.refreshTokenSec === 'number' && s.refreshTokenSec >= 1 ? Math.floor(s.refreshTokenSec) : defaults.refreshTokenSec,
565
+ };
566
+ }
567
+ catch {
568
+ return defaults;
569
+ }
570
+ }
571
+ /**
572
+ * Resolve as configurações efetivas de impersonation.
573
+ *
574
+ * Precedência: setting BD → configDefault → lib default (false).
575
+ * FAIL-SAFE: qualquer erro → configDefault.
576
+ */
577
+ export async function resolveEffectiveAdminImpersonation(settings, configDefault = false) {
578
+ const defaults = { enabled: configDefault };
579
+ try {
580
+ const raw = await settings.getSetting(SETTING_KEYS.ADMIN_IMPERSONATION);
581
+ if (raw === null || raw === undefined)
582
+ return defaults;
583
+ if (typeof raw !== 'object' || Array.isArray(raw))
584
+ return defaults;
585
+ const s = raw;
586
+ return {
587
+ enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
588
+ };
589
+ }
590
+ catch {
591
+ return defaults;
592
+ }
593
+ }
594
+ const ORGS_POLICY_LIB_DEFAULTS = {
595
+ allowSelfCreate: false,
596
+ invitationTtlHours: 168,
597
+ roles: ['owner', 'admin', 'member'],
598
+ };
599
+ /** Default da lib: apenas ADMIN. */
600
+ export const ROLES_CATALOG_DEFAULT = {
601
+ roles: [{ name: 'ADMIN', description: 'Full access to the admin console' }],
602
+ };
603
+ /**
604
+ * Resolve o catálogo efetivo de roles globais a partir da setting persistida.
605
+ *
606
+ * Regras:
607
+ * - ADMIN é SEMPRE garantido no resultado (merge defensivo — é o gate do console).
608
+ * - setting ausente/inválida/erro → default (apenas ADMIN).
609
+ * - O resultado é ordenado por nome (ADMIN sempre incluído).
610
+ * - Entradas com `name` inválido (não-string ou vazio) são descartadas silenciosamente.
611
+ *
612
+ * FAIL-SAFE: qualquer erro DB → default.
613
+ */
614
+ /**
615
+ * Resolve roles catalog efetivo: org → global → default.
616
+ *
617
+ * @param settings - SettingsCapability
618
+ * @param orgId - opcional; quando fornecido, tenta settings da org antes do global
619
+ */
620
+ export async function resolveEffectiveRolesCatalog(settings, orgId) {
621
+ async function fromRaw(raw) {
622
+ if (raw === null || raw === undefined)
623
+ return null;
624
+ if (typeof raw !== 'object' || Array.isArray(raw))
625
+ return null;
626
+ const s = raw;
627
+ if (!Array.isArray(s.roles))
628
+ return null;
629
+ // Filtra entradas válidas (name deve ser string não-vazia).
630
+ const entries = s.roles
631
+ .filter((r) => typeof r === 'object' && r !== null && typeof r.name === 'string' && r.name.trim().length > 0)
632
+ .map((r) => ({
633
+ name: r.name.trim(),
634
+ ...(typeof r.description === 'string' && r.description.trim().length > 0
635
+ ? { description: r.description.trim() }
636
+ : {}),
637
+ }));
638
+ // Merge defensivo: ADMIN sempre presente.
639
+ const hasAdmin = entries.some((r) => r.name === 'ADMIN');
640
+ if (!hasAdmin) {
641
+ entries.unshift({ name: 'ADMIN', description: 'Full access to the admin console' });
642
+ }
643
+ // Ordena por nome.
644
+ entries.sort((a, b) => a.name.localeCompare(b.name));
645
+ return { roles: entries };
646
+ }
647
+ try {
648
+ // Resolução org → global → default
649
+ if (orgId) {
650
+ const orgRaw = await settings.getSetting(SETTING_KEYS.ROLES_CATALOG, orgId);
651
+ const orgResult = await fromRaw(orgRaw);
652
+ if (orgResult)
653
+ return orgResult;
654
+ }
655
+ const globalRaw = await settings.getSetting(SETTING_KEYS.ROLES_CATALOG, null);
656
+ const globalResult = await fromRaw(globalRaw);
657
+ if (globalResult)
658
+ return globalResult;
659
+ return ROLES_CATALOG_DEFAULT;
660
+ }
661
+ catch {
662
+ return ROLES_CATALOG_DEFAULT;
663
+ }
664
+ }
665
+ /**
666
+ * Resolve as configurações efetivas de política de organizações.
667
+ *
668
+ * Precedência: org-setting → global-setting → configDefault → lib default.
669
+ * FAIL-SAFE: qualquer erro → configDefault.
670
+ *
671
+ * Invariante mantida: 'owner' é sempre incluído na lista de roles (governance).
672
+ *
673
+ * @param settings - SettingsCapability
674
+ * @param configDefault - defaults estáticos do config do host
675
+ * @param orgId - opcional; quando fornecido, tenta settings da org antes do global
676
+ */
677
+ export async function resolveEffectiveOrganizationsPolicy(settings, configDefault = {}, orgId) {
678
+ const defaultRoles = configDefault.roles ?? ORGS_POLICY_LIB_DEFAULTS.roles;
679
+ const rolesWithOwner = defaultRoles.includes('owner') ? defaultRoles : ['owner', ...defaultRoles];
680
+ const defaults = {
681
+ allowSelfCreate: configDefault.allowSelfCreate ?? ORGS_POLICY_LIB_DEFAULTS.allowSelfCreate,
682
+ invitationTtlHours: configDefault.invitationTtlHours ?? ORGS_POLICY_LIB_DEFAULTS.invitationTtlHours,
683
+ roles: rolesWithOwner,
684
+ };
685
+ function applyRaw(raw) {
686
+ if (raw === null || raw === undefined)
687
+ return null;
688
+ if (typeof raw !== 'object' || Array.isArray(raw))
689
+ return null;
690
+ const s = raw;
691
+ // Roles: usa o valor da setting apenas se for um array não-vazio; sempre
692
+ // garante que 'owner' está presente (invariante de governance).
693
+ let roles = defaults.roles;
694
+ if (Array.isArray(s.roles) && s.roles.length > 0) {
695
+ roles = s.roles.includes('owner') ? s.roles : ['owner', ...s.roles];
696
+ }
697
+ return {
698
+ allowSelfCreate: typeof s.allowSelfCreate === 'boolean' ? s.allowSelfCreate : defaults.allowSelfCreate,
699
+ invitationTtlHours: typeof s.invitationTtlHours === 'number' && s.invitationTtlHours >= 1 ? Math.floor(s.invitationTtlHours) : defaults.invitationTtlHours,
700
+ roles,
701
+ };
702
+ }
703
+ try {
704
+ // Resolução org → global → defaults
705
+ if (orgId) {
706
+ const orgRaw = await settings.getSetting(SETTING_KEYS.ORGANIZATIONS_POLICY, orgId);
707
+ const orgResult = applyRaw(orgRaw);
708
+ if (orgResult)
709
+ return orgResult;
710
+ }
711
+ const globalRaw = await settings.getSetting(SETTING_KEYS.ORGANIZATIONS_POLICY, null);
712
+ const globalResult = applyRaw(globalRaw);
713
+ if (globalResult)
714
+ return globalResult;
715
+ return defaults;
716
+ }
717
+ catch {
718
+ return defaults;
719
+ }
720
+ }
721
+ /**
722
+ * Resolve o CATÁLOGO efetivo de roles de org (lista de roles permitidas),
723
+ * garantindo a invariante de governance: `owner` está sempre presente.
724
+ *
725
+ * Layer canônico de validação de role de org, compartilhado entre o caminho
726
+ * admin (`AdminOrgsService.resolveRoleCatalog`) e o member-facing
727
+ * (`account_orgs_controller`). Fail-safe: sem `settings` (null), usa o catálogo
728
+ * do config estático (mesma semântica do `resolveEffectiveOrganizationsPolicy`
729
+ * com `settings` indisponível — que cai nos `configDefault`).
730
+ *
731
+ * @param settings - SettingsCapability ou null (null → só config defaults)
732
+ * @param configDefault - defaults estáticos do config do host
733
+ * @param orgId - opcional; quando fornecido, tenta settings da org antes do global
734
+ */
735
+ export async function resolveRoleCatalogList(settings, configDefault = {}, orgId) {
736
+ if (!settings) {
737
+ const roles = configDefault.roles ?? ORGS_POLICY_LIB_DEFAULTS.roles;
738
+ return roles.includes('owner') ? roles : ['owner', ...roles];
739
+ }
740
+ const policy = await resolveEffectiveOrganizationsPolicy(settings, configDefault, orgId);
741
+ return policy.roles;
742
+ }
743
+ /**
744
+ * Função PURA: valida se um `role` faz parte do catálogo efetivo de roles de org.
745
+ *
746
+ * É o único ponto de verdade para "esta role é válida para esta org?", reusado
747
+ * tanto pelo caminho admin quanto pelo member-facing — eliminando a
748
+ * reimplementação inline `policy.roles.includes(role)` que vivia em dois layers.
749
+ * H4: bloqueia roles fora do catálogo (incluindo arbitrárias e, quando não
750
+ * catalogadas, `owner`). Fail-safe via {@link resolveRoleCatalogList}.
751
+ *
752
+ * @param role - role candidata
753
+ * @param settings - SettingsCapability ou null
754
+ * @param configDefault - defaults estáticos do config do host
755
+ * @param orgId - opcional; escopo de org para a resolução do catálogo
756
+ */
757
+ export async function isRoleInCatalog(role, settings, configDefault = {}, orgId) {
758
+ const catalog = await resolveRoleCatalogList(settings, configDefault, orgId);
759
+ return catalog.includes(role);
760
+ }
761
+ /**
762
+ * Resolve as configurações efetivas de expiração de conta.
763
+ *
764
+ * FAIL-SAFE: qualquer erro → `{ enabled: false, inactiveDays: 365, warnDays: 14 }`.
765
+ */
766
+ export async function resolveEffectiveAccountExpiration(settings) {
767
+ const defaults = { enabled: false, inactiveDays: 365, warnDays: 14 };
768
+ try {
769
+ const raw = await settings.getSetting(SETTING_KEYS.ACCOUNT_EXPIRATION);
770
+ if (raw === null || raw === undefined)
771
+ return defaults;
772
+ if (typeof raw !== 'object' || Array.isArray(raw))
773
+ return defaults;
774
+ const s = raw;
775
+ return {
776
+ enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
777
+ inactiveDays: typeof s.inactiveDays === 'number' && s.inactiveDays >= 1 ? Math.floor(s.inactiveDays) : defaults.inactiveDays,
778
+ warnDays: typeof s.warnDays === 'number' && s.warnDays >= 0 ? Math.floor(s.warnDays) : defaults.warnDays,
779
+ };
780
+ }
781
+ catch {
782
+ return defaults;
783
+ }
784
+ }