@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,119 @@
1
+ import type { OidcService } from '../provider/oidc_service.js';
2
+ /** Uma sessão ativa do IdP (login do usuário no provider), apresentada ao admin. */
3
+ export interface AdminSession {
4
+ /** Id do artefato `Session` no adapter. */
5
+ id: string;
6
+ accountId: string;
7
+ /**
8
+ * Email da conta — resolvido pelo `listAllSessions()` na listagem global.
9
+ * Ausente em `listSessions(accountId)` (já é implícito pelo contexto).
10
+ */
11
+ email?: string | null;
12
+ /** Epoch (segundos) do login, quando presente no payload. */
13
+ loginTs?: number;
14
+ /** Métodos de autenticação registrados na sessão (amr), quando presentes. */
15
+ amr?: string[];
16
+ /**
17
+ * User-agent bruto do login, recuperado do audit `login.success` por join
18
+ * accountId+loginTs ({@link enrichSessionsWithContext}). Ausente quando o sink de
19
+ * auditoria não consulta ou não há evento correlacionável.
20
+ */
21
+ userAgent?: string | null;
22
+ /** Família do browser derivada do user-agent (ex.: 'Chrome'). */
23
+ browser?: string | null;
24
+ /** Sistema operacional derivado do user-agent (ex.: 'macOS'). */
25
+ os?: string | null;
26
+ /** IP do login (do mesmo audit `login.success`). */
27
+ ip?: string | null;
28
+ /** Localização legível resolvida via o hook `resolveGeo` (null sem hook/resolução). */
29
+ location?: string | null;
30
+ }
31
+ /** Um grant (autorização concedida a um client), com a contagem de tokens vivos. */
32
+ export interface AdminGrant {
33
+ /** Id do artefato `Grant` no adapter (== grantId dos tokens). */
34
+ id: string;
35
+ accountId: string;
36
+ clientId?: string;
37
+ /** Tokens de acesso vivos que referenciam este grant. */
38
+ accessTokens: number;
39
+ /** Refresh tokens vivos que referenciam este grant. */
40
+ refreshTokens: number;
41
+ }
42
+ /** Resultado de uma revogação em massa das sessões/grants de uma conta. */
43
+ export interface RevokeResult {
44
+ sessions: number;
45
+ grants: number;
46
+ accessTokens: number;
47
+ refreshTokens: number;
48
+ }
49
+ export declare class AdminSessionsService {
50
+ #private;
51
+ constructor(oidc: OidcService);
52
+ /**
53
+ * Grava uma revogação por `sub` na tabela compartilhada `auth_session_revocations`,
54
+ * para que clients COOKIE-BASED (que não têm store de sessão server-side) derrubem
55
+ * a sessão na próxima request — INSTANTÂNEO, sem esperar o refresh token falhar.
56
+ *
57
+ * Best-effort: a destruição de grants/tokens acima já é a fonte da verdade; esta
58
+ * linha só acelera o efeito nos clients. Falha (tabela ausente) é silenciosa.
59
+ *
60
+ * @param accountId Conta cujas sessões devem ser derrubadas (gravado em `sub`).
61
+ * @param revokedAt Timestamp da revogação. Default: agora. A checagem do client
62
+ * é `revoked_at >= iat(id_token)` (em segundos): uma sessão só é derrubada se
63
+ * foi estabelecida ANTES (ou no mesmo segundo) da revogação. O
64
+ * {@link revokeAllExcept} passa um `revokedAt` ANTERIOR ao `iat` da sessão
65
+ * PRESERVADA, para que esta NÃO se auto-derrube (ver lá).
66
+ */
67
+ protected recordSubRevocation(accountId: string, revokedAt?: Date): Promise<void>;
68
+ /** Indica se o adapter suporta enumeração (capacidade opcional). */
69
+ get canList(): boolean;
70
+ /**
71
+ * Conta TODAS as sessões ativas do IdP (todas as contas). 0 quando o adapter não
72
+ * enumera. Usado pelo dashboard de métricas.
73
+ */
74
+ countActiveSessions(): Promise<number>;
75
+ /** Lista as sessões ativas da conta (vazio quando o adapter não enumera). */
76
+ listSessions(accountId: string): Promise<AdminSession[]>;
77
+ /**
78
+ * Lista TODAS as sessões ativas de TODAS as contas — usada pela listagem global
79
+ * do console admin (sem `accountId`). Resolve o email de cada conta via
80
+ * `accountStore.findById` com cache por id (evita N+1). Limita a
81
+ * {@link GLOBAL_SESSION_LIMIT} entradas; quando truncado, inclui `truncated:true`
82
+ * nos metadados (accessível via `result.truncated`). Retorna vazio quando o
83
+ * adapter não enumera.
84
+ */
85
+ listAllSessions(): Promise<{
86
+ sessions: AdminSession[];
87
+ truncated: boolean;
88
+ }>;
89
+ /**
90
+ * Lista os grants da conta, com a contagem de access/refresh tokens vivos que
91
+ * referenciam cada grant (`payload.grantId`). As contagens são baratas (uma
92
+ * enumeração de cada model token), feitas só quando o adapter enumera.
93
+ */
94
+ listGrants(accountId: string): Promise<AdminGrant[]>;
95
+ /**
96
+ * Revoga todas as sessões e grants da conta EXCETO a sessão corrente (pelo id).
97
+ * Usado pela política single-session: após login, revoga todas as outras sessões
98
+ * preservando a recém-criada. Retorna as contagens do que foi removido.
99
+ *
100
+ * @param accountId Id da conta.
101
+ * @param exceptSessionId Id da sessão OIDC a preservar (a sessão corrente).
102
+ */
103
+ revokeAllExcept(accountId: string, exceptSessionId: string): Promise<RevokeResult>;
104
+ /**
105
+ * Revoga TODAS as sessões e grants da conta. Destruir os grants já invalida os
106
+ * tokens (cascata via `grant not found`); ainda assim, quando o adapter enumera,
107
+ * destruímos explicitamente as linhas de AT/RT desses grants (belt-and-braces),
108
+ * deixando o store limpo. Retorna as contagens do que foi removido.
109
+ */
110
+ revokeAll(accountId: string): Promise<RevokeResult>;
111
+ /**
112
+ * Revoga os grants de uma conta para UM client específico (+ tokens ligados),
113
+ * deixando os demais clients intactos. Reaproveita a lógica de {@link revokeAll}
114
+ * restrita ao `clientId`. Usado pelo self-service de consentimento
115
+ * (/account/apps) e por qualquer revogação granular do admin. Retorna as
116
+ * contagens do que foi removido.
117
+ */
118
+ revokeClientGrants(accountId: string, clientId: string): Promise<RevokeResult>;
119
+ }
@@ -0,0 +1,284 @@
1
+ /**
2
+ * Serviço de inspeção/revogação das SESSÕES e GRANTS ativos de uma conta,
3
+ * persistidos pelo oidc-provider via o MESMO `AdapterClass` (mesmo padrão do
4
+ * {@link AdminClientsService}). Encapsula:
5
+ * - a enumeração via a capacidade opcional `list` do adapter (degrada quando
6
+ * ausente, igual ao CRUD de clients);
7
+ * - a destruição das sessões + grants da conta. Destruir um grant CASCATEIA a
8
+ * invalidação dos tokens no oidc-provider: os consumidores de access/refresh
9
+ * token carregam `Grant.find(token.grantId)` e lançam `InvalidToken('grant not
10
+ * found')` quando o grant some (verificado em oidc-provider v9). Mesmo assim,
11
+ * por garantia (belt-and-braces), também destruímos as linhas de AT/RT que
12
+ * referenciam os grants revogados quando o adapter enumera.
13
+ */
14
+ /** Limite máximo de sessões retornadas na listagem global (proteção contra explosão de memória). */
15
+ const GLOBAL_SESSION_LIMIT = 500;
16
+ export class AdminSessionsService {
17
+ #AdapterClass;
18
+ #accountStore;
19
+ /** Conexão Lucid das tabelas authkit (schema `auth`) — onde vive auth_session_revocations. */
20
+ #schemaConnection;
21
+ constructor(oidc) {
22
+ this.#AdapterClass = oidc.config.AdapterClass;
23
+ this.#accountStore = oidc.config.accountStore;
24
+ this.#schemaConnection = oidc.config.schema?.connection;
25
+ }
26
+ #adapter(model) {
27
+ return new this.#AdapterClass(model);
28
+ }
29
+ /**
30
+ * Grava uma revogação por `sub` na tabela compartilhada `auth_session_revocations`,
31
+ * para que clients COOKIE-BASED (que não têm store de sessão server-side) derrubem
32
+ * a sessão na próxima request — INSTANTÂNEO, sem esperar o refresh token falhar.
33
+ *
34
+ * Best-effort: a destruição de grants/tokens acima já é a fonte da verdade; esta
35
+ * linha só acelera o efeito nos clients. Falha (tabela ausente) é silenciosa.
36
+ *
37
+ * @param accountId Conta cujas sessões devem ser derrubadas (gravado em `sub`).
38
+ * @param revokedAt Timestamp da revogação. Default: agora. A checagem do client
39
+ * é `revoked_at >= iat(id_token)` (em segundos): uma sessão só é derrubada se
40
+ * foi estabelecida ANTES (ou no mesmo segundo) da revogação. O
41
+ * {@link revokeAllExcept} passa um `revokedAt` ANTERIOR ao `iat` da sessão
42
+ * PRESERVADA, para que esta NÃO se auto-derrube (ver lá).
43
+ */
44
+ async recordSubRevocation(accountId, revokedAt = new Date()) {
45
+ try {
46
+ const db = (await import('@adonisjs/lucid/services/db')).default;
47
+ const conn = this.#schemaConnection
48
+ ? db.connection(this.#schemaConnection)
49
+ : db.connection();
50
+ await conn.insertQuery().table('auth_session_revocations').insert({
51
+ sid: null,
52
+ sub: accountId,
53
+ revoked_at: revokedAt,
54
+ });
55
+ }
56
+ catch {
57
+ /* tabela ausente / lucid indisponível — a invalidação server-side ainda vale */
58
+ }
59
+ }
60
+ /** Indica se o adapter suporta enumeração (capacidade opcional). */
61
+ get canList() {
62
+ return typeof this.#adapter('Session').list === 'function';
63
+ }
64
+ async #listModel(model) {
65
+ const adapter = this.#adapter(model);
66
+ if (!adapter.list)
67
+ return [];
68
+ return adapter.list();
69
+ }
70
+ /**
71
+ * Conta TODAS as sessões ativas do IdP (todas as contas). 0 quando o adapter não
72
+ * enumera. Usado pelo dashboard de métricas.
73
+ */
74
+ async countActiveSessions() {
75
+ const rows = await this.#listModel('Session');
76
+ return rows.length;
77
+ }
78
+ /** Lista as sessões ativas da conta (vazio quando o adapter não enumera). */
79
+ async listSessions(accountId) {
80
+ const rows = await this.#listModel('Session');
81
+ return rows
82
+ .filter((r) => r.payload.accountId === accountId)
83
+ .map((r) => ({
84
+ id: r.id,
85
+ accountId,
86
+ loginTs: r.payload.loginTs,
87
+ amr: r.payload.amr ?? undefined,
88
+ }));
89
+ }
90
+ /**
91
+ * Lista TODAS as sessões ativas de TODAS as contas — usada pela listagem global
92
+ * do console admin (sem `accountId`). Resolve o email de cada conta via
93
+ * `accountStore.findById` com cache por id (evita N+1). Limita a
94
+ * {@link GLOBAL_SESSION_LIMIT} entradas; quando truncado, inclui `truncated:true`
95
+ * nos metadados (accessível via `result.truncated`). Retorna vazio quando o
96
+ * adapter não enumera.
97
+ */
98
+ async listAllSessions() {
99
+ const rows = await this.#listModel('Session');
100
+ const truncated = rows.length > GLOBAL_SESSION_LIMIT;
101
+ const slice = truncated ? rows.slice(0, GLOBAL_SESSION_LIMIT) : rows;
102
+ // Cache accountId → email para evitar N+1
103
+ const emailCache = new Map();
104
+ const resolveEmail = async (accountId) => {
105
+ if (emailCache.has(accountId))
106
+ return emailCache.get(accountId);
107
+ const account = await this.#accountStore.findById(accountId);
108
+ const email = account?.email ?? null;
109
+ emailCache.set(accountId, email);
110
+ return email;
111
+ };
112
+ const sessions = await Promise.all(slice.map(async (r) => {
113
+ const accountId = r.payload.accountId ?? '';
114
+ const email = accountId ? await resolveEmail(accountId) : null;
115
+ return {
116
+ id: r.id,
117
+ accountId,
118
+ email,
119
+ loginTs: r.payload.loginTs,
120
+ amr: r.payload.amr ?? undefined,
121
+ };
122
+ }));
123
+ return { sessions, truncated };
124
+ }
125
+ /**
126
+ * Lista os grants da conta, com a contagem de access/refresh tokens vivos que
127
+ * referenciam cada grant (`payload.grantId`). As contagens são baratas (uma
128
+ * enumeração de cada model token), feitas só quando o adapter enumera.
129
+ */
130
+ async listGrants(accountId) {
131
+ const rows = await this.#listModel('Grant');
132
+ const grants = rows.filter((r) => r.payload.accountId === accountId);
133
+ if (grants.length === 0)
134
+ return [];
135
+ const atByGrant = await this.#countByGrant('AccessToken');
136
+ const rtByGrant = await this.#countByGrant('RefreshToken');
137
+ return grants.map((g) => ({
138
+ id: g.id,
139
+ accountId,
140
+ clientId: g.payload.clientId,
141
+ accessTokens: atByGrant.get(g.id) ?? 0,
142
+ refreshTokens: rtByGrant.get(g.id) ?? 0,
143
+ }));
144
+ }
145
+ /** Conta artefatos de um model token agrupados por `grantId`. */
146
+ async #countByGrant(model) {
147
+ const rows = await this.#listModel(model);
148
+ const map = new Map();
149
+ for (const r of rows) {
150
+ const gid = r.payload.grantId;
151
+ if (!gid)
152
+ continue;
153
+ map.set(gid, (map.get(gid) ?? 0) + 1);
154
+ }
155
+ return map;
156
+ }
157
+ /**
158
+ * Revoga todas as sessões e grants da conta EXCETO a sessão corrente (pelo id).
159
+ * Usado pela política single-session: após login, revoga todas as outras sessões
160
+ * preservando a recém-criada. Retorna as contagens do que foi removido.
161
+ *
162
+ * @param accountId Id da conta.
163
+ * @param exceptSessionId Id da sessão OIDC a preservar (a sessão corrente).
164
+ */
165
+ async revokeAllExcept(accountId, exceptSessionId) {
166
+ const sessionAdapter = this.#adapter('Session');
167
+ const grantAdapter = this.#adapter('Grant');
168
+ const sessions = await this.listSessions(accountId);
169
+ const preserved = sessions.find((s) => s.id === exceptSessionId);
170
+ const sessionsToRevoke = sessions.filter((s) => s.id !== exceptSessionId);
171
+ for (const s of sessionsToRevoke) {
172
+ await sessionAdapter.destroy(s.id);
173
+ }
174
+ // Revogamos todos os grants da conta (que pertencem à conta, não à sessão
175
+ // específica). A sessão corrente gerará novos grants no próximo authorize.
176
+ // Isso garante que sessões antigas não mantenham tokens vivos.
177
+ const grants = await this.listGrants(accountId);
178
+ const grantIds = new Set(grants.map((g) => g.id));
179
+ let accessTokens = 0;
180
+ let refreshTokens = 0;
181
+ accessTokens = await this.#destroyTokensOfGrants('AccessToken', grantIds);
182
+ refreshTokens = await this.#destroyTokensOfGrants('RefreshToken', grantIds);
183
+ for (const g of grants) {
184
+ await grantAdapter.revokeByGrantId(g.id);
185
+ await grantAdapter.destroy(g.id);
186
+ }
187
+ // M7: propaga a revogação por `sub` para clients COOKIE-BASED (instantâneo),
188
+ // igual ao revokeAll. Sem isto, o 1º dispositivo só cai quando o AT expira.
189
+ //
190
+ // Ordem do `iat` (CUIDADO): a sessão PRESERVADA já existe aqui (foi criada no
191
+ // completeLogin ANTES desta revogação), com `loginTs` (== iat do id_token) em
192
+ // segundos. A checagem do client é `revoked_at >= iat`. Se gravássemos
193
+ // `revoked_at = now`, como `now >= iat_preservada`, a sessão NOVA se
194
+ // auto-derrubaria. Por isso ancoramos `revoked_at` ESTRITAMENTE ANTES do
195
+ // `iat` da sessão preservada (`loginTs - 1s`): as sessões antigas (iat menor)
196
+ // continuam sendo apanhadas (`revoked_at >= iat_antiga`), enquanto a nova
197
+ // (iat = loginTs) sobrevive (`revoked_at < iat_nova`).
198
+ //
199
+ // Sem sessão preservada (exceptSessionId não encontrado / sem loginTs), caímos
200
+ // no default (`now`) — não há sessão nova a proteger nesse caminho.
201
+ const cutoff = typeof preserved?.loginTs === 'number'
202
+ ? new Date((preserved.loginTs - 1) * 1000)
203
+ : undefined;
204
+ await this.recordSubRevocation(accountId, cutoff);
205
+ return {
206
+ sessions: sessionsToRevoke.length,
207
+ grants: grants.length,
208
+ accessTokens,
209
+ refreshTokens,
210
+ };
211
+ }
212
+ /**
213
+ * Revoga TODAS as sessões e grants da conta. Destruir os grants já invalida os
214
+ * tokens (cascata via `grant not found`); ainda assim, quando o adapter enumera,
215
+ * destruímos explicitamente as linhas de AT/RT desses grants (belt-and-braces),
216
+ * deixando o store limpo. Retorna as contagens do que foi removido.
217
+ */
218
+ async revokeAll(accountId) {
219
+ const sessionAdapter = this.#adapter('Session');
220
+ const grantAdapter = this.#adapter('Grant');
221
+ const sessions = await this.listSessions(accountId);
222
+ for (const s of sessions) {
223
+ await sessionAdapter.destroy(s.id);
224
+ }
225
+ const grants = await this.listGrants(accountId);
226
+ const grantIds = new Set(grants.map((g) => g.id));
227
+ let accessTokens = 0;
228
+ let refreshTokens = 0;
229
+ // Belt-and-braces: destrói as linhas de token que referenciam os grants alvo
230
+ // ANTES de destruir os grants (quando o adapter enumera).
231
+ accessTokens = await this.#destroyTokensOfGrants('AccessToken', grantIds);
232
+ refreshTokens = await this.#destroyTokensOfGrants('RefreshToken', grantIds);
233
+ for (const g of grants) {
234
+ // `revokeByGrantId` derruba os artefatos ligados ao grant (no Redis isso
235
+ // limpa a lista do grant; no DB apaga as linhas com `grant_id`); `destroy`
236
+ // remove o próprio artefato `Grant`.
237
+ await grantAdapter.revokeByGrantId(g.id);
238
+ await grantAdapter.destroy(g.id);
239
+ }
240
+ // Revogação total → propaga p/ clients cookie-based via tabela compartilhada (instantâneo).
241
+ await this.recordSubRevocation(accountId);
242
+ return {
243
+ sessions: sessions.length,
244
+ grants: grants.length,
245
+ accessTokens,
246
+ refreshTokens,
247
+ };
248
+ }
249
+ /**
250
+ * Revoga os grants de uma conta para UM client específico (+ tokens ligados),
251
+ * deixando os demais clients intactos. Reaproveita a lógica de {@link revokeAll}
252
+ * restrita ao `clientId`. Usado pelo self-service de consentimento
253
+ * (/account/apps) e por qualquer revogação granular do admin. Retorna as
254
+ * contagens do que foi removido.
255
+ */
256
+ async revokeClientGrants(accountId, clientId) {
257
+ const grantAdapter = this.#adapter('Grant');
258
+ const grants = (await this.listGrants(accountId)).filter((g) => g.clientId === clientId);
259
+ const grantIds = new Set(grants.map((g) => g.id));
260
+ const accessTokens = await this.#destroyTokensOfGrants('AccessToken', grantIds);
261
+ const refreshTokens = await this.#destroyTokensOfGrants('RefreshToken', grantIds);
262
+ for (const g of grants) {
263
+ await grantAdapter.revokeByGrantId(g.id);
264
+ await grantAdapter.destroy(g.id);
265
+ }
266
+ return { sessions: 0, grants: grants.length, accessTokens, refreshTokens };
267
+ }
268
+ /** Destrói (quando enumerável) os artefatos de um model token cujos grantId estão em `grantIds`. */
269
+ async #destroyTokensOfGrants(model, grantIds) {
270
+ const adapter = this.#adapter(model);
271
+ if (!adapter.list)
272
+ return 0;
273
+ const rows = await adapter.list();
274
+ let count = 0;
275
+ for (const r of rows) {
276
+ const gid = r.payload.grantId;
277
+ if (gid && grantIds.has(gid)) {
278
+ await adapter.destroy(r.id);
279
+ count++;
280
+ }
281
+ }
282
+ return count;
283
+ }
284
+ }
@@ -0,0 +1,44 @@
1
+ import type { ResolvedServerConfig } from '../define_config.js';
2
+ /** Um ponto de série diária (dia ISO `YYYY-MM-DD` + contagem). */
3
+ export interface DailyPoint {
4
+ /** Data no formato `YYYY-MM-DD` (UTC). */
5
+ date: string;
6
+ count: number;
7
+ }
8
+ /** Métricas-resumo do IdP para o dashboard do console admin. */
9
+ export interface AdminStats {
10
+ /** Total de contas (do accountStore). */
11
+ totalUsers: number;
12
+ /** Sessões ativas (Session enumeradas no adapter); null quando o adapter não enumera. */
13
+ activeSessions: number | null;
14
+ /** Monthly Active Users: contas únicas com login.success nos últimos 30 dias. */
15
+ mau: number;
16
+ /** Sign-ins por dia (login.success) nos últimos 30 dias. */
17
+ signInsPerDay: DailyPoint[];
18
+ /** Sign-ups por dia (signup) nos últimos 30 dias. */
19
+ signUpsPerDay: DailyPoint[];
20
+ /** Total de sign-ins na janela de 30 dias. */
21
+ signInsTotal: number;
22
+ /** Total de sign-ups na janela de 30 dias. */
23
+ signUpsTotal: number;
24
+ /** Indica se o audit suporta consulta (`list`). Quando false, as séries vêm vazias. */
25
+ auditSupported: boolean;
26
+ /** Quantos dias a janela cobre (30). */
27
+ windowDays: number;
28
+ }
29
+ /**
30
+ * Agrega métricas do IdP para o dashboard. CAPABILITY-PROBED: a fonte das séries é
31
+ * o audit store via `list` — quando ausente, as séries/MAU degradam para vazio/0 e
32
+ * `auditSupported=false` (a UI mostra "consulta não suportada"). As sessões ativas
33
+ * vêm da enumeração do adapter OIDC (null quando o adapter não enumera).
34
+ *
35
+ * LIMITAÇÃO: a agregação é em memória sobre as {@link MAX_EVENTS} linhas mais
36
+ * recentes de cada tipo (o `AuditSink` não expõe agregação por dia/distinct). Em
37
+ * volumes muito altos a janela pode não cobrir os 30 dias inteiros; documentado e
38
+ * suficiente para um dashboard. Um sink customizado pode implementar agregação
39
+ * nativa e expor um `stats()` próprio no futuro.
40
+ */
41
+ export declare function computeAdminStats(cfg: Pick<ResolvedServerConfig, 'audit' | 'accountStore'>, sessionsService: {
42
+ canList: boolean;
43
+ countActiveSessions(): Promise<number>;
44
+ }): Promise<AdminStats>;
@@ -0,0 +1,130 @@
1
+ /** Janela de agregação (dias). */
2
+ const WINDOW_DAYS = 30;
3
+ /**
4
+ * Teto de eventos lidos do audit por tipo na agregação em memória. O sink default
5
+ * (Lucid) não tem agregação SQL exposta, então listamos as N linhas mais recentes e
6
+ * agregamos aqui. 10000 cobre ~333 logins/dia por 30 dias com folga.
7
+ */
8
+ const MAX_EVENTS = 10000;
9
+ /**
10
+ * Agrega métricas do IdP para o dashboard. CAPABILITY-PROBED: a fonte das séries é
11
+ * o audit store via `list` — quando ausente, as séries/MAU degradam para vazio/0 e
12
+ * `auditSupported=false` (a UI mostra "consulta não suportada"). As sessões ativas
13
+ * vêm da enumeração do adapter OIDC (null quando o adapter não enumera).
14
+ *
15
+ * LIMITAÇÃO: a agregação é em memória sobre as {@link MAX_EVENTS} linhas mais
16
+ * recentes de cada tipo (o `AuditSink` não expõe agregação por dia/distinct). Em
17
+ * volumes muito altos a janela pode não cobrir os 30 dias inteiros; documentado e
18
+ * suficiente para um dashboard. Um sink customizado pode implementar agregação
19
+ * nativa e expor um `stats()` próprio no futuro.
20
+ */
21
+ export async function computeAdminStats(cfg, sessionsService) {
22
+ const totalUsers = (await cfg.accountStore.listAccounts({ page: 1, limit: 1 })).total;
23
+ const activeSessions = sessionsService.canList
24
+ ? await sessionsService.countActiveSessions()
25
+ : null;
26
+ const auditSupported = typeof cfg.audit?.list === 'function';
27
+ if (!auditSupported) {
28
+ return {
29
+ totalUsers,
30
+ activeSessions,
31
+ mau: 0,
32
+ signInsPerDay: emptySeries(),
33
+ signUpsPerDay: emptySeries(),
34
+ signInsTotal: 0,
35
+ signUpsTotal: 0,
36
+ auditSupported: false,
37
+ windowDays: WINDOW_DAYS,
38
+ };
39
+ }
40
+ const windowStartMs = startOfWindowMs();
41
+ const signIns = await loadEventsInWindow(cfg.audit, 'login.success', windowStartMs);
42
+ const signUps = await loadEventsInWindow(cfg.audit, 'signup', windowStartMs);
43
+ // MAU: contas únicas com algum login.success na janela.
44
+ const mauSet = new Set();
45
+ for (const e of signIns) {
46
+ if (e.accountId)
47
+ mauSet.add(e.accountId);
48
+ }
49
+ return {
50
+ totalUsers,
51
+ activeSessions,
52
+ mau: mauSet.size,
53
+ signInsPerDay: bucketByDay(signIns),
54
+ signUpsPerDay: bucketByDay(signUps),
55
+ signInsTotal: signIns.length,
56
+ signUpsTotal: signUps.length,
57
+ auditSupported: true,
58
+ windowDays: WINDOW_DAYS,
59
+ };
60
+ }
61
+ /**
62
+ * Carrega (paginando) os eventos de um tipo dentro da janela, com teto de
63
+ * {@link MAX_EVENTS}. Para assim que a página vier mais antiga que a janela (o sink
64
+ * lista desc por createdAt) ou ao atingir o teto.
65
+ */
66
+ async function loadEventsInWindow(audit, type, windowStartMs) {
67
+ const out = [];
68
+ const limit = 200;
69
+ let page = 1;
70
+ while (out.length < MAX_EVENTS) {
71
+ const result = await audit.list({ type, page, limit });
72
+ if (result.data.length === 0)
73
+ break;
74
+ let allBelowWindow = true;
75
+ for (const e of result.data) {
76
+ const tsMs = toMs(e.createdAt);
77
+ if (tsMs === null)
78
+ continue;
79
+ if (tsMs >= windowStartMs) {
80
+ allBelowWindow = false;
81
+ out.push({ accountId: e.accountId ?? null, tsMs });
82
+ if (out.length >= MAX_EVENTS)
83
+ break;
84
+ }
85
+ }
86
+ // Página inteira anterior à janela → não há mais nada relevante (ordem desc).
87
+ if (allBelowWindow)
88
+ break;
89
+ if (result.data.length < limit)
90
+ break;
91
+ page += 1;
92
+ }
93
+ return out;
94
+ }
95
+ /** Agrupa eventos por dia (UTC `YYYY-MM-DD`), preenchendo TODOS os dias da janela com 0. */
96
+ function bucketByDay(events) {
97
+ const counts = new Map();
98
+ for (const e of events) {
99
+ const day = dayKey(e.tsMs);
100
+ counts.set(day, (counts.get(day) ?? 0) + 1);
101
+ }
102
+ return seriesDays().map((date) => ({ date, count: counts.get(date) ?? 0 }));
103
+ }
104
+ /** Série de 30 dias vazia (todos os dias com 0), p/ o degrade sem audit. */
105
+ function emptySeries() {
106
+ return seriesDays().map((date) => ({ date, count: 0 }));
107
+ }
108
+ /** Os WINDOW_DAYS dias da janela (do mais antigo ao hoje), `YYYY-MM-DD` UTC. */
109
+ function seriesDays() {
110
+ const days = [];
111
+ const todayMs = Date.now();
112
+ for (let i = WINDOW_DAYS - 1; i >= 0; i--) {
113
+ days.push(dayKey(todayMs - i * 86400000));
114
+ }
115
+ return days;
116
+ }
117
+ function startOfWindowMs() {
118
+ // Início (00:00 UTC) do primeiro dia da janela.
119
+ const firstDay = seriesDays()[0];
120
+ return Date.parse(`${firstDay}T00:00:00.000Z`);
121
+ }
122
+ function dayKey(ms) {
123
+ return new Date(ms).toISOString().slice(0, 10);
124
+ }
125
+ function toMs(createdAt) {
126
+ if (!createdAt)
127
+ return null;
128
+ const ms = createdAt instanceof Date ? createdAt.getTime() : Date.parse(createdAt);
129
+ return Number.isFinite(ms) ? ms : null;
130
+ }