@adonis-agora/authkit-server 0.47.0 → 0.48.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 (188) hide show
  1. package/build/commands/clients_create.js +4 -4
  2. package/build/commands/configure.js +3 -2
  3. package/build/commands/doctor.js +8 -5
  4. package/build/commands/eject.js +1 -1
  5. package/build/commands/expire_scan.js +7 -5
  6. package/build/commands/import_users.js +1 -1
  7. package/build/commands/keys_rotate.js +7 -4
  8. package/build/host/views/account/apps.edge +5 -5
  9. package/build/host/views/account/login.edge +1 -1
  10. package/build/host/views/account/mfa.edge +7 -7
  11. package/build/host/views/account/orgs.edge +5 -5
  12. package/build/host/views/account/security.edge +10 -10
  13. package/build/host/views/account/tokens.edge +5 -5
  14. package/build/index.d.ts +7 -7
  15. package/build/index.js +5 -5
  16. package/build/providers/authkit_server_provider.d.ts +2 -2
  17. package/build/providers/authkit_server_provider.js +20 -11
  18. package/build/services/main.d.ts +1 -1
  19. package/build/services/main.js +2 -2
  20. package/build/src/accounts/lucid_account_store.d.ts +3 -3
  21. package/build/src/accounts/lucid_account_store.js +6 -8
  22. package/build/src/accounts/lucid_store/core.js +1 -1
  23. package/build/src/accounts/lucid_store/mfa.js +1 -1
  24. package/build/src/accounts/lucid_store/organizations.js +2 -4
  25. package/build/src/accounts/lucid_store/password_hygiene.js +1 -4
  26. package/build/src/accounts/lucid_store/shared.d.ts +1 -1
  27. package/build/src/accounts/lucid_stores.d.ts +3 -3
  28. package/build/src/accounts/lucid_stores.js +2 -2
  29. package/build/src/adapters/database_adapter.js +3 -1
  30. package/build/src/adapters/factory.js +1 -1
  31. package/build/src/adapters/redis_adapter.js +2 -1
  32. package/build/src/commands/expire_scan_command.js +19 -5
  33. package/build/src/commands/settings_commands.js +22 -5
  34. package/build/src/define_config.d.ts +20 -20
  35. package/build/src/define_config.js +62 -67
  36. package/build/src/doctor/checks.js +45 -20
  37. package/build/src/events/dispatcher.d.ts +1 -1
  38. package/build/src/events/dispatcher.js +10 -10
  39. package/build/src/host/account_api/account_api_controller.js +95 -39
  40. package/build/src/host/account_deletion_ops.d.ts +4 -4
  41. package/build/src/host/account_deletion_ops.js +5 -5
  42. package/build/src/host/account_deletion_service.d.ts +2 -2
  43. package/build/src/host/account_deletion_service.js +2 -2
  44. package/build/src/host/account_export_service.d.ts +1 -1
  45. package/build/src/host/account_export_service.js +4 -6
  46. package/build/src/host/account_home.d.ts +0 -8
  47. package/build/src/host/account_home.js +6 -4
  48. package/build/src/host/account_login_url.d.ts +6 -3
  49. package/build/src/host/account_login_url.js +16 -8
  50. package/build/src/host/account_paths.d.ts +120 -0
  51. package/build/src/host/account_paths.js +161 -0
  52. package/build/src/host/admin_api/admin_orgs_service.d.ts +2 -2
  53. package/build/src/host/admin_api/admin_orgs_service.js +3 -2
  54. package/build/src/host/admin_api/admin_users_service.d.ts +12 -12
  55. package/build/src/host/admin_api/admin_users_service.js +20 -20
  56. package/build/src/host/admin_api/api_clients_controller.js +2 -2
  57. package/build/src/host/admin_api/api_misc_controller.js +2 -2
  58. package/build/src/host/admin_api/api_orgs_controller.js +3 -3
  59. package/build/src/host/admin_api/api_settings_controller.js +11 -5
  60. package/build/src/host/admin_api/api_users_controller.d.ts +2 -2
  61. package/build/src/host/admin_api/api_users_controller.js +37 -38
  62. package/build/src/host/admin_api/dto.d.ts +4 -4
  63. package/build/src/host/admin_clients_service.js +5 -4
  64. package/build/src/host/admin_console/admin_shell_controller.js +4 -2
  65. package/build/src/host/admin_console/console_audit_controller.js +1 -1
  66. package/build/src/host/admin_console/console_clients_controller.js +5 -3
  67. package/build/src/host/admin_console/console_impersonation_controller.js +1 -1
  68. package/build/src/host/admin_console/console_keys_controller.js +2 -4
  69. package/build/src/host/admin_console/console_orgs_controller.js +3 -3
  70. package/build/src/host/admin_console/console_roles_controller.js +30 -12
  71. package/build/src/host/admin_console/console_sessions_controller.js +3 -3
  72. package/build/src/host/admin_console/console_settings_controller.js +11 -5
  73. package/build/src/host/admin_console/console_users_controller.d.ts +2 -2
  74. package/build/src/host/admin_console/console_users_controller.js +46 -47
  75. package/build/src/host/admin_prefix.js +2 -2
  76. package/build/src/host/admin_sessions_service.js +1 -3
  77. package/build/src/host/adonis_auth_sync.d.ts +1 -1
  78. package/build/src/host/adonis_auth_user_provider.d.ts +1 -1
  79. package/build/src/host/app_key.js +1 -1
  80. package/build/src/host/avatar_storage.js +1 -3
  81. package/build/src/host/config_locks.js +1 -3
  82. package/build/src/host/console_session.js +1 -1
  83. package/build/src/host/controllers/account_apps_controller.js +3 -2
  84. package/build/src/host/controllers/account_confirm_controller.js +2 -6
  85. package/build/src/host/controllers/account_mfa_controller.js +63 -12
  86. package/build/src/host/controllers/account_orgs_controller.js +47 -27
  87. package/build/src/host/controllers/account_security_controller.d.ts +2 -2
  88. package/build/src/host/controllers/account_security_controller.js +114 -115
  89. package/build/src/host/controllers/account_session_controller.js +5 -5
  90. package/build/src/host/controllers/account_tokens_controller.js +3 -2
  91. package/build/src/host/controllers/interaction_controller.js +59 -22
  92. package/build/src/host/controllers/registration_controller.js +28 -13
  93. package/build/src/host/default_mailer.js +11 -7
  94. package/build/src/host/durable/account_deletion_workflow.d.ts +2 -2
  95. package/build/src/host/durable/account_deletion_workflow.js +14 -14
  96. package/build/src/host/durable/account_export_workflow.d.ts +2 -2
  97. package/build/src/host/durable/account_export_workflow.js +12 -12
  98. package/build/src/host/durable/index.d.ts +5 -5
  99. package/build/src/host/durable/index.js +6 -6
  100. package/build/src/host/i18n.d.ts +1376 -1376
  101. package/build/src/host/i18n.js +1380 -1380
  102. package/build/src/host/impersonation.js +1 -7
  103. package/build/src/host/key_rotation_actions.d.ts +1 -1
  104. package/build/src/host/login_attempt.js +35 -6
  105. package/build/src/host/login_notify.js +1 -1
  106. package/build/src/host/otp_lockout.js +1 -3
  107. package/build/src/host/rate_limit.js +1 -1
  108. package/build/src/host/register_auth_host.d.ts +30 -0
  109. package/build/src/host/register_auth_host.js +120 -74
  110. package/build/src/host/renderers/edge_renderer.js +15 -2
  111. package/build/src/host/renderers/inertia_renderer.d.ts +9 -1
  112. package/build/src/host/renderers/inertia_renderer.js +9 -1
  113. package/build/src/host/runtime_settings.js +1 -1
  114. package/build/src/host/runtime_toggles.d.ts +3 -3
  115. package/build/src/host/runtime_toggles.js +69 -24
  116. package/build/src/host/security_notice_service.d.ts +1 -1
  117. package/build/src/host/security_notice_service.js +1 -1
  118. package/build/src/host/session_context.js +1 -1
  119. package/build/src/host/sudo/index.d.ts +3 -3
  120. package/build/src/host/sudo/index.js +3 -3
  121. package/build/src/host/sudo/methods/magic_link.js +6 -5
  122. package/build/src/host/sudo/methods/passkey.js +7 -4
  123. package/build/src/host/sudo/methods/password.js +8 -3
  124. package/build/src/host/sudo/runtime.js +6 -13
  125. package/build/src/host/sudo_mode.js +3 -2
  126. package/build/src/host/ui-dist/assets/index-BQoTDiLV.js +137 -0
  127. package/build/src/host/ui-dist/index.html +1 -1
  128. package/build/src/keys/jwks_manager.js +1 -1
  129. package/build/src/keys/keystore.js +1 -1
  130. package/build/src/keys/keystore_manager.d.ts +2 -2
  131. package/build/src/keys/keystore_manager.js +2 -2
  132. package/build/src/keys/keystore_vault.js +8 -4
  133. package/build/src/mixins/with_audit_log.d.ts +1 -1
  134. package/build/src/mixins/with_auth_user.d.ts +1 -1
  135. package/build/src/mixins/with_auth_user.js +1 -1
  136. package/build/src/mixins/with_credentials.d.ts +1 -1
  137. package/build/src/mixins/with_mfa.d.ts +1 -1
  138. package/build/src/mixins/with_personal_access_token.d.ts +1 -1
  139. package/build/src/mixins/with_provider_identity.d.ts +1 -1
  140. package/build/src/mixins/with_webauthn_credential.d.ts +1 -1
  141. package/build/src/observability/diagnostics_bridge.js +2 -2
  142. package/build/src/observability/metrics_service.js +1 -1
  143. package/build/src/observability/telescope/data_providers.d.ts +1 -1
  144. package/build/src/observability/telescope/data_providers.js +29 -43
  145. package/build/src/observability/telescope/extension.d.ts +1 -1
  146. package/build/src/observability/telescope/extension.js +58 -58
  147. package/build/src/observability/telescope/index.d.ts +2 -2
  148. package/build/src/observability/telescope/index.js +2 -2
  149. package/build/src/observability/wire_provider_events.d.ts +1 -1
  150. package/build/src/observability/wire_provider_events.js +11 -11
  151. package/build/src/password/common_passwords.js +1 -1
  152. package/build/src/password/password_manager.d.ts +1 -1
  153. package/build/src/password/password_manager.js +4 -4
  154. package/build/src/pat/lucid_pat_store.js +2 -6
  155. package/build/src/pat/pat_tokens.js +1 -1
  156. package/build/src/provider/interaction_actions.js +1 -1
  157. package/build/src/provider/key_rotation_scheduler.js +3 -1
  158. package/build/src/provider/logout_sources.js +2 -8
  159. package/build/src/provider/oidc_service.d.ts +2 -2
  160. package/build/src/provider/oidc_service.js +22 -14
  161. package/build/src/provider/single_flight_lock.js +1 -3
  162. package/build/src/provider/token_exchange.d.ts +1 -1
  163. package/build/src/schema/ensure.js +3 -1
  164. package/build/stubs/ui/react/components/auth_shell.tsx +19 -19
  165. package/build/stubs/ui/react/pages/account/login.tsx +6 -7
  166. package/build/stubs/ui/react/pages/account/mfa.tsx +16 -15
  167. package/build/stubs/ui/react/pages/account/tokens.tsx +27 -17
  168. package/build/stubs/ui/react/pages/consent.tsx +12 -12
  169. package/build/stubs/ui/react/pages/forgot.tsx +7 -7
  170. package/build/stubs/ui/react/pages/login.tsx +22 -24
  171. package/build/stubs/ui/react/pages/mfa-challenge.tsx +9 -10
  172. package/build/stubs/ui/react/pages/reset.tsx +10 -10
  173. package/build/stubs/ui/react/pages/signup.tsx +30 -16
  174. package/build/stubs/ui/react/pages/verify-email.tsx +6 -6
  175. package/package.json +1 -1
  176. package/stubs/main.ts +2 -2
  177. package/stubs/ui/react/components/auth_shell.tsx +19 -19
  178. package/stubs/ui/react/pages/account/login.tsx +6 -7
  179. package/stubs/ui/react/pages/account/mfa.tsx +16 -15
  180. package/stubs/ui/react/pages/account/tokens.tsx +27 -17
  181. package/stubs/ui/react/pages/consent.tsx +12 -12
  182. package/stubs/ui/react/pages/forgot.tsx +7 -7
  183. package/stubs/ui/react/pages/login.tsx +22 -24
  184. package/stubs/ui/react/pages/mfa-challenge.tsx +9 -10
  185. package/stubs/ui/react/pages/reset.tsx +10 -10
  186. package/stubs/ui/react/pages/signup.tsx +30 -16
  187. package/stubs/ui/react/pages/verify-email.tsx +6 -6
  188. package/build/src/host/ui-dist/assets/index-BmI_J87g.js +0 -137
@@ -89,11 +89,12 @@ export class AdminClientsService {
89
89
  // grantTypes derrubava token-exchange).
90
90
  const merged = {
91
91
  clientId,
92
- redirectUris: input.redirectUris ?? (existing.redirect_uris ?? []),
93
- postLogoutRedirectUris: input.postLogoutRedirectUris ?? (existing.post_logout_redirect_uris ?? []),
94
- grantTypes: input.grantTypes ?? (existing.grant_types ?? []),
92
+ redirectUris: input.redirectUris ?? existing.redirect_uris ?? [],
93
+ postLogoutRedirectUris: input.postLogoutRedirectUris ?? existing.post_logout_redirect_uris ?? [],
94
+ grantTypes: input.grantTypes ?? existing.grant_types ?? [],
95
95
  tokenEndpointAuthMethod: input.tokenEndpointAuthMethod ??
96
- (existing.token_endpoint_auth_method ?? 'client_secret_basic'),
96
+ existing.token_endpoint_auth_method ??
97
+ 'client_secret_basic',
97
98
  backchannelLogoutUri: input.backchannelLogoutUri ?? existing.backchannel_logout_uri,
98
99
  backchannelLogoutSessionRequired: input.backchannelLogoutSessionRequired ??
99
100
  existing.backchannel_logout_session_required,
@@ -1,7 +1,7 @@
1
1
  import { readFile } from 'node:fs/promises';
2
2
  import { extname } from 'node:path';
3
- import { getAdminPrefix } from '../admin_prefix.js';
4
3
  import { resolveAccountRoles } from '../account_roles.js';
4
+ import { getAdminPrefix } from '../admin_prefix.js';
5
5
  // ─── Shell HTML cache ─────────────────────────────────────────────────────────
6
6
  /**
7
7
  * Points to the Vite-built index.html inside build/host/ui-dist/.
@@ -147,7 +147,9 @@ export default class AdminShellController {
147
147
  async serveAsset(ctx) {
148
148
  // AdonisJS wildcard route `*` → params['*'] is an array of path segments.
149
149
  const wildcardParams = ctx.request.params()['*'];
150
- const file = Array.isArray(wildcardParams) ? wildcardParams.join('/') : String(wildcardParams ?? '');
150
+ const file = Array.isArray(wildcardParams)
151
+ ? wildcardParams.join('/')
152
+ : String(wildcardParams ?? '');
151
153
  if (!file || file.includes('..') || file.includes('\0')) {
152
154
  return ctx.response.notFound();
153
155
  }
@@ -1,5 +1,5 @@
1
1
  import '../augmentations.js';
2
- import { auditDto, apiError } from '../admin_api/dto.js';
2
+ import { apiError, auditDto } from '../admin_api/dto.js';
3
3
  /**
4
4
  * Endpoints JSON do log de auditoria do console admin React.
5
5
  *
@@ -1,7 +1,7 @@
1
1
  import '../augmentations.js';
2
+ import { apiError, clientDto, createdClientDto } from '../admin_api/dto.js';
2
3
  import { AdminClientsService } from '../admin_clients_service.js';
3
- import { clientDto, createdClientDto, apiError } from '../admin_api/dto.js';
4
- import { clientInputValidator, clientCreateInput, clientPartialInput } from '../admin_validators.js';
4
+ import { clientCreateInput, clientInputValidator, clientPartialInput, } from '../admin_validators.js';
5
5
  /**
6
6
  * Endpoints JSON de clients OIDC do console admin React.
7
7
  *
@@ -89,7 +89,9 @@ export default class ConsoleClientsController {
89
89
  newSecret = await svc.regenerateSecret(id);
90
90
  }
91
91
  catch (err) {
92
- return ctx.response.status(409).send(apiError('not_applicable', err.message ?? 'Cannot regenerate secret for a public client.'));
92
+ return ctx.response
93
+ .status(409)
94
+ .send(apiError('not_applicable', err.message ?? 'Cannot regenerate secret for a public client.'));
93
95
  }
94
96
  await cfg.audit?.record({
95
97
  type: 'client.secret_regenerated',
@@ -1,6 +1,6 @@
1
1
  import '../augmentations.js';
2
- import { buildImpersonationPanel } from '../impersonation.js';
3
2
  import { apiError } from '../admin_api/dto.js';
3
+ import { buildImpersonationPanel } from '../impersonation.js';
4
4
  import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
5
5
  /**
6
6
  * Endpoint JSON do painel de impersonation do console admin React.
@@ -1,11 +1,9 @@
1
1
  import '../augmentations.js';
2
- import { resolveRuntimeSettings } from '../runtime_settings.js';
3
2
  import { apiError } from '../admin_api/dto.js';
4
3
  import { buildKeysStatus, rotateNow } from '../key_rotation_actions.js';
4
+ import { resolveRuntimeSettings } from '../runtime_settings.js';
5
5
  function notSupported(ctx) {
6
- return ctx.response
7
- .status(501)
8
- .send(apiError('not_implemented', 'jwks não é managed+store.'));
6
+ return ctx.response.status(501).send(apiError('not_implemented', 'jwks não é managed+store.'));
9
7
  }
10
8
  /**
11
9
  * Endpoints JSON de gestão da chave de assinatura managed para o console admin React.
@@ -1,9 +1,9 @@
1
1
  import '../augmentations.js';
2
- import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
3
2
  import { AdminOrgsService } from '../admin_api/admin_orgs_service.js';
3
+ import { apiError, orgDetailDto, orgDto } from '../admin_api/dto.js';
4
+ import { orgAddMemberValidator, orgCreateValidator, orgInvitationValidator, orgMemberRoleValidator, orgUpdateValidator, } from '../admin_validators.js';
5
+ import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
4
6
  import { resolveRuntimeSettings } from '../runtime_settings.js';
5
- import { orgDto, orgDetailDto, apiError } from '../admin_api/dto.js';
6
- import { orgCreateValidator, orgUpdateValidator, orgAddMemberValidator, orgMemberRoleValidator, orgInvitationValidator, } from '../admin_validators.js';
7
7
  /**
8
8
  * Endpoints JSON de organizações do console admin React.
9
9
  * 404 honesto quando o store não suporta organizações (`capability_unsupported`).
@@ -1,9 +1,9 @@
1
1
  import '../augmentations.js';
2
- import { resolveRuntimeSettings } from '../runtime_settings.js';
3
- import { resolveEffectiveRolesCatalog, SETTING_KEYS, } from '../runtime_toggles.js';
4
- import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
5
2
  import { apiError } from '../admin_api/dto.js';
6
3
  import { roleCreateValidator, roleUpdateValidator } from '../admin_validators.js';
4
+ import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
5
+ import { resolveRuntimeSettings } from '../runtime_settings.js';
6
+ import { SETTING_KEYS, resolveEffectiveRolesCatalog, } from '../runtime_toggles.js';
7
7
  /** Regex de validação: nome de role — letras maiúsculas, dígitos e underscore. */
8
8
  const ROLE_NAME_RE = /^[A-Z][A-Z0-9_]*$/;
9
9
  /** ADMIN é protegido: não pode ser removido. */
@@ -53,7 +53,12 @@ export default class ConsoleRolesController {
53
53
  newEntry.description = description;
54
54
  const updated = [...current.roles, newEntry].sort((a, b) => a.name.localeCompare(b.name));
55
55
  await rs.setSetting(SETTING_KEYS.ROLES_CATALOG, { roles: updated }, actorId);
56
- await cfg.audit?.record({ type: 'roles_catalog.updated', actorId, ip, metadata: { action: 'create', role: name } });
56
+ await cfg.audit?.record({
57
+ type: 'roles_catalog.updated',
58
+ actorId,
59
+ ip,
60
+ metadata: { action: 'create', role: name },
61
+ });
57
62
  return { name, description: description || undefined };
58
63
  }
59
64
  /** PATCH {prefix}/api/roles/:name — { description? } */
@@ -72,11 +77,14 @@ export default class ConsoleRolesController {
72
77
  if (!current.roles.some((r) => r.name === roleName)) {
73
78
  return ctx.response.notFound(apiError('not_found', 'Role não encontrada.'));
74
79
  }
75
- const updatedRoles = current.roles.map((r) => r.name === roleName
76
- ? { name: r.name, ...(description ? { description } : {}) }
77
- : r);
80
+ const updatedRoles = current.roles.map((r) => r.name === roleName ? { name: r.name, ...(description ? { description } : {}) } : r);
78
81
  await rs.setSetting(SETTING_KEYS.ROLES_CATALOG, { roles: updatedRoles }, actorId);
79
- await cfg.audit?.record({ type: 'roles_catalog.updated', actorId, ip, metadata: { action: 'edit', role: roleName } });
82
+ await cfg.audit?.record({
83
+ type: 'roles_catalog.updated',
84
+ actorId,
85
+ ip,
86
+ metadata: { action: 'edit', role: roleName },
87
+ });
80
88
  const found = updatedRoles.find((r) => r.name === roleName);
81
89
  return found;
82
90
  }
@@ -88,7 +96,9 @@ export default class ConsoleRolesController {
88
96
  const ip = ctx.request.ip?.() ?? null;
89
97
  const roleName = decodeURIComponent(ctx.request.param('name'));
90
98
  if (roleName === PROTECTED_ROLE) {
91
- return ctx.response.status(409).send(apiError('protected', cfg.messages['admin.roles.admin_protected'] ?? 'A role ADMIN é protegida.'));
99
+ return ctx.response
100
+ .status(409)
101
+ .send(apiError('protected', cfg.messages['admin.roles.admin_protected'] ?? 'A role ADMIN é protegida.'));
92
102
  }
93
103
  const rs = await resolveRuntimeSettings(ctx);
94
104
  if (!rs)
@@ -97,12 +107,20 @@ export default class ConsoleRolesController {
97
107
  if (!current.roles.some((r) => r.name === roleName)) {
98
108
  return ctx.response.notFound(apiError('not_found', 'Role não encontrada.'));
99
109
  }
100
- let updatedRoles = current.roles.filter((r) => r.name !== roleName);
110
+ const updatedRoles = current.roles.filter((r) => r.name !== roleName);
101
111
  if (!updatedRoles.some((r) => r.name === PROTECTED_ROLE)) {
102
- updatedRoles.unshift({ name: PROTECTED_ROLE, description: 'Full access to the admin console' });
112
+ updatedRoles.unshift({
113
+ name: PROTECTED_ROLE,
114
+ description: 'Full access to the admin console',
115
+ });
103
116
  }
104
117
  await rs.setSetting(SETTING_KEYS.ROLES_CATALOG, { roles: updatedRoles }, actorId);
105
- await cfg.audit?.record({ type: 'roles_catalog.updated', actorId, ip, metadata: { action: 'delete', role: roleName } });
118
+ await cfg.audit?.record({
119
+ type: 'roles_catalog.updated',
120
+ actorId,
121
+ ip,
122
+ metadata: { action: 'delete', role: roleName },
123
+ });
106
124
  return { ok: true, deleted: roleName };
107
125
  }
108
126
  }
@@ -1,9 +1,9 @@
1
1
  import '../augmentations.js';
2
+ import { apiError, grantDto, sessionDto } from '../admin_api/dto.js';
2
3
  import { AdminSessionsService } from '../admin_sessions_service.js';
3
- import { enrichSessionsWithContext } from '../session_context.js';
4
- import { sessionDto, grantDto, apiError } from '../admin_api/dto.js';
5
- import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
6
4
  import { sessionAccountValidator } from '../admin_validators.js';
5
+ import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
6
+ import { enrichSessionsWithContext } from '../session_context.js';
7
7
  /**
8
8
  * Endpoints JSON de sessões/grants do console admin React.
9
9
  *
@@ -1,7 +1,7 @@
1
1
  import '../augmentations.js';
2
+ import { apiError, settingDto } from '../admin_api/dto.js';
3
+ import { SettingLockedError, isSettingLocked, lockedSettingKeys } from '../config_locks.js';
2
4
  import { resolveRuntimeSettings } from '../runtime_settings.js';
3
- import { settingDto, apiError } from '../admin_api/dto.js';
4
- import { isSettingLocked, lockedSettingKeys, SettingLockedError } from '../config_locks.js';
5
5
  /** 423 Locked: setting travada via defineConfig. */
6
6
  function lockedResponse(ctx, err) {
7
7
  return ctx.response
@@ -15,8 +15,8 @@ function notSupported(ctx) {
15
15
  function resolveOrgId(ctx) {
16
16
  const qs = ctx.request.qs();
17
17
  if ('organizationId' in qs) {
18
- const v = qs['organizationId'];
19
- return v && v.trim() ? v.trim() : null;
18
+ const v = qs.organizationId;
19
+ return v?.trim() ? v.trim() : null;
20
20
  }
21
21
  return null;
22
22
  }
@@ -80,7 +80,13 @@ export default class ConsoleSettingsController {
80
80
  metadata: { key, value: body.value, source: 'admin-console', organizationId: orgId },
81
81
  });
82
82
  const saved = await svc.getSetting(key, orgId);
83
- return settingDto({ key, organizationId: orgId, value: saved, updatedAt: new Date(), updatedBy: null });
83
+ return settingDto({
84
+ key,
85
+ organizationId: orgId,
86
+ value: saved,
87
+ updatedAt: new Date(),
88
+ updatedBy: null,
89
+ });
84
90
  }
85
91
  /** DELETE {prefix}/api/settings/:key */
86
92
  async destroy(ctx) {
@@ -1,5 +1,5 @@
1
- import "../augmentations.js";
2
- import type { HttpContext } from "@adonisjs/core/http";
1
+ import '../augmentations.js';
2
+ import type { HttpContext } from '@adonisjs/core/http';
3
3
  /**
4
4
  * Endpoints JSON de usuários do console admin React.
5
5
  *
@@ -1,13 +1,13 @@
1
- import "../augmentations.js";
2
- import { AdminUsersService } from "../admin_api/admin_users_service.js";
3
- import { AdminSessionsService } from "../admin_sessions_service.js";
4
- import { enrichSessionsWithContext } from "../session_context.js";
5
- import { resolveRuntimeSettings } from "../runtime_settings.js";
6
- import { resolveEffectiveRolesCatalog } from "../runtime_toggles.js";
7
- import { userDto, sessionDto, grantDto, apiError } from "../admin_api/dto.js";
8
- import { ACCOUNT_SESSION_KEY } from "../middleware/account_auth.js";
9
- import { supportsAccountDeletion, supportsAccountStatus, } from "../../accounts/account_store.js";
10
- import { adminUserCreateValidator, adminUserRolesValidator, } from "../admin_validators.js";
1
+ import '../augmentations.js';
2
+ import { supportsAccountDeletion, supportsAccountStatus } from '../../accounts/account_store.js';
3
+ import { AdminUsersService } from '../admin_api/admin_users_service.js';
4
+ import { apiError, grantDto, sessionDto, userDto } from '../admin_api/dto.js';
5
+ import { AdminSessionsService } from '../admin_sessions_service.js';
6
+ import { adminUserCreateValidator, adminUserRolesValidator } from '../admin_validators.js';
7
+ import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
8
+ import { resolveRuntimeSettings } from '../runtime_settings.js';
9
+ import { resolveEffectiveRolesCatalog } from '../runtime_toggles.js';
10
+ import { enrichSessionsWithContext } from '../session_context.js';
11
11
  const PAGE_SIZE = 20;
12
12
  /**
13
13
  * Endpoints JSON de usuários do console admin React.
@@ -28,12 +28,11 @@ const PAGE_SIZE = 20;
28
28
  export default class ConsoleUsersController {
29
29
  /** GET {prefix}/api/users */
30
30
  async index(ctx) {
31
- const service = await ctx.containerResolver.make("authkit.server");
31
+ const service = await ctx.containerResolver.make('authkit.server');
32
32
  const cfg = service.config;
33
- const search = ctx.request.input("search", "").trim();
34
- const page = Math.max(1, Number.parseInt(ctx.request.input("page", "1"), 10) || 1);
35
- const perPage = Math.max(1, Math.min(100, Number.parseInt(ctx.request.input("perPage", String(PAGE_SIZE)), 10) ||
36
- PAGE_SIZE));
33
+ const search = ctx.request.input('search', '').trim();
34
+ const page = Math.max(1, Number.parseInt(ctx.request.input('page', '1'), 10) || 1);
35
+ const perPage = Math.max(1, Math.min(100, Number.parseInt(ctx.request.input('perPage', String(PAGE_SIZE)), 10) || PAGE_SIZE));
37
36
  const result = await cfg.accountStore.listAccounts({
38
37
  search,
39
38
  page,
@@ -45,12 +44,12 @@ export default class ConsoleUsersController {
45
44
  }
46
45
  /** GET {prefix}/api/users/:id */
47
46
  async show(ctx) {
48
- const service = await ctx.containerResolver.make("authkit.server");
47
+ const service = await ctx.containerResolver.make('authkit.server');
49
48
  const cfg = service.config;
50
- const id = ctx.request.param("id");
49
+ const id = ctx.request.param('id');
51
50
  const account = await cfg.accountStore.findById(id);
52
51
  if (!account)
53
- return ctx.response.notFound(apiError("not_found", "Usuário não encontrado."));
52
+ return ctx.response.notFound(apiError('not_found', 'Usuário não encontrado.'));
54
53
  const users = new AdminUsersService(cfg);
55
54
  const disabled = await users.isDisabled(id);
56
55
  // Sessões ativas (degradam quando adapter não enumera).
@@ -82,7 +81,7 @@ export default class ConsoleUsersController {
82
81
  }
83
82
  /** POST {prefix}/api/users */
84
83
  async store(ctx) {
85
- const service = await ctx.containerResolver.make("authkit.server");
84
+ const service = await ctx.containerResolver.make('authkit.server');
86
85
  const cfg = service.config;
87
86
  const actorId = ctx.session?.get(ACCOUNT_SESSION_KEY) ?? null;
88
87
  const ip = ctx.request.ip?.() ?? null;
@@ -93,45 +92,45 @@ export default class ConsoleUsersController {
93
92
  name: name ?? null,
94
93
  password: password ?? null,
95
94
  invite: invite ?? false,
96
- }, { actorId, ip, source: "admin" });
95
+ }, { actorId, ip, source: 'admin' });
97
96
  if (!result.ok) {
98
- if (result.reason === "password_policy") {
99
- return ctx.response.badRequest(apiError("password_policy", cfg.messages[result.messageKey] ?? result.messageKey));
97
+ if (result.reason === 'password_policy') {
98
+ return ctx.response.badRequest(apiError('password_policy', cfg.messages[result.messageKey] ?? result.messageKey));
100
99
  }
101
- return ctx.response.conflict(apiError("email_taken", "Já existe uma conta com este e-mail."));
100
+ return ctx.response.conflict(apiError('email_taken', 'Já existe uma conta com este e-mail.'));
102
101
  }
103
102
  ctx.response.status(201);
104
103
  return { ...userDto(result.account), invited: result.invited };
105
104
  }
106
105
  /** PATCH {prefix}/api/users/:id/roles */
107
106
  async updateRoles(ctx) {
108
- const service = await ctx.containerResolver.make("authkit.server");
107
+ const service = await ctx.containerResolver.make('authkit.server');
109
108
  const cfg = service.config;
110
- const id = ctx.request.param("id");
109
+ const id = ctx.request.param('id');
111
110
  const account = await cfg.accountStore.findById(id);
112
111
  if (!account)
113
- return ctx.response.notFound(apiError("not_found", "Usuário não encontrado."));
112
+ return ctx.response.notFound(apiError('not_found', 'Usuário não encontrado.'));
114
113
  const actorId = ctx.session?.get(ACCOUNT_SESSION_KEY) ?? null;
115
114
  const { roles: rolesInput } = await ctx.request.validateUsing(adminUserRolesValidator);
116
115
  const roles = Array.from(new Set((rolesInput ?? []).map((r) => r.trim()).filter(Boolean)));
117
116
  const users = new AdminUsersService(cfg);
118
117
  // Proteções de escalonamento/lockout: último admin + auto-rebaixamento.
119
118
  const guard = await users.guardGlobalRolesChange(id, roles, actorId);
120
- if (guard === "last_admin") {
119
+ if (guard === 'last_admin') {
121
120
  return ctx.response
122
121
  .status(409)
123
- .send(apiError("last_admin", "Não é possível remover a última conta com a role de administrador."));
122
+ .send(apiError('last_admin', 'Não é possível remover a última conta com a role de administrador.'));
124
123
  }
125
- if (guard === "cannot_self_demote") {
124
+ if (guard === 'cannot_self_demote') {
126
125
  return ctx.response
127
126
  .status(409)
128
- .send(apiError("cannot_self_demote", "Você não pode remover a sua própria role de administrador."));
127
+ .send(apiError('cannot_self_demote', 'Você não pode remover a sua própria role de administrador.'));
129
128
  }
130
129
  // Resolve RuntimeSettings para validação contra catálogo (fail-safe).
131
130
  const runtimeSettings = await resolveRuntimeSettings(ctx);
132
131
  const errorKey = await users.setGlobalRolesValidated(id, roles, runtimeSettings);
133
132
  if (errorKey) {
134
- return ctx.response.badRequest(apiError("invalid_role", cfg.messages[errorKey] ?? errorKey));
133
+ return ctx.response.badRequest(apiError('invalid_role', cfg.messages[errorKey] ?? errorKey));
135
134
  }
136
135
  const updated = await cfg.accountStore.findById(id);
137
136
  const disabled = await users.isDisabled(id);
@@ -146,24 +145,24 @@ export default class ConsoleUsersController {
146
145
  return this.#setStatus(ctx, false);
147
146
  }
148
147
  async #setStatus(ctx, disable) {
149
- const service = await ctx.containerResolver.make("authkit.server");
148
+ const service = await ctx.containerResolver.make('authkit.server');
150
149
  const cfg = service.config;
151
150
  const actorId = ctx.session?.get(ACCOUNT_SESSION_KEY) ?? null;
152
151
  const ip = ctx.request.ip?.() ?? null;
153
- const id = ctx.request.param("id");
152
+ const id = ctx.request.param('id');
154
153
  const account = await cfg.accountStore.findById(id);
155
154
  if (!account)
156
- return ctx.response.notFound(apiError("not_found", "Usuário não encontrado."));
155
+ return ctx.response.notFound(apiError('not_found', 'Usuário não encontrado.'));
157
156
  const users = new AdminUsersService(cfg);
158
157
  const applied = await users.setStatus(id, disable, {
159
158
  actorId,
160
159
  ip,
161
- source: "admin",
160
+ source: 'admin',
162
161
  });
163
162
  if (!applied) {
164
163
  return ctx.response
165
164
  .status(409)
166
- .send(apiError("capability_unsupported", "O store não suporta habilitar/desabilitar contas."));
165
+ .send(apiError('capability_unsupported', 'O store não suporta habilitar/desabilitar contas.'));
167
166
  }
168
167
  const updated = await cfg.accountStore.findById(id);
169
168
  const disabled = await users.isDisabled(id);
@@ -171,41 +170,41 @@ export default class ConsoleUsersController {
171
170
  }
172
171
  /** POST {prefix}/api/users/:id/reset-password */
173
172
  async resetPassword(ctx) {
174
- const service = await ctx.containerResolver.make("authkit.server");
173
+ const service = await ctx.containerResolver.make('authkit.server');
175
174
  const cfg = service.config;
176
175
  const actorId = ctx.session?.get(ACCOUNT_SESSION_KEY) ?? null;
177
176
  const ip = ctx.request.ip?.() ?? null;
178
- const id = ctx.request.param("id");
177
+ const id = ctx.request.param('id');
179
178
  const users = new AdminUsersService(cfg);
180
179
  const account = await users.resetPassword(ctx, id, {
181
180
  actorId,
182
181
  ip,
183
- source: "admin",
182
+ source: 'admin',
184
183
  });
185
184
  if (!account)
186
- return ctx.response.notFound(apiError("not_found", "Usuário não encontrado."));
185
+ return ctx.response.notFound(apiError('not_found', 'Usuário não encontrado.'));
187
186
  return { ok: true, email: account.email };
188
187
  }
189
188
  /** DELETE {prefix}/api/users/:id */
190
189
  async destroy(ctx) {
191
- const service = await ctx.containerResolver.make("authkit.server");
190
+ const service = await ctx.containerResolver.make('authkit.server');
192
191
  const cfg = service.config;
193
192
  const actorId = ctx.session?.get(ACCOUNT_SESSION_KEY) ?? null;
194
193
  const ip = ctx.request.ip?.() ?? null;
195
- const id = ctx.request.param("id");
194
+ const id = ctx.request.param('id');
196
195
  const users = new AdminUsersService(cfg);
197
196
  // OPT-IN durável: passa o enqueue (cascade async); senão delete() roda síncrono.
198
197
  const enqueue = cfg.accountLifecycle?.durable
199
- ? (await import("../durable/index.js")).enqueueDeletionVia(ctx.containerResolver)
198
+ ? (await import('../durable/index.js')).enqueueDeletionVia(ctx.containerResolver)
200
199
  : undefined;
201
- const outcome = await users.delete(service, id, { actorId, ip, source: "admin" }, enqueue);
200
+ const outcome = await users.delete(service, id, { actorId, ip, source: 'admin' }, enqueue);
202
201
  if (!outcome.ok) {
203
- if (outcome.reason === "not_found") {
204
- return ctx.response.notFound(apiError("not_found", "Usuário não encontrado."));
202
+ if (outcome.reason === 'not_found') {
203
+ return ctx.response.notFound(apiError('not_found', 'Usuário não encontrado.'));
205
204
  }
206
205
  return ctx.response
207
206
  .status(409)
208
- .send(apiError("capability_unsupported", "O store não suporta deleção de contas."));
207
+ .send(apiError('capability_unsupported', 'O store não suporta deleção de contas.'));
209
208
  }
210
209
  return { ok: true, deleted: id };
211
210
  }
@@ -22,7 +22,7 @@ let _prefix = DEFAULT_ADMIN_PREFIX;
22
22
  export function normalizeAdminPrefix(raw) {
23
23
  let p = raw.trim();
24
24
  if (!p.startsWith('/'))
25
- p = '/' + p;
25
+ p = `/${p}`;
26
26
  p = p.replace(/\/+$/, '');
27
27
  return p || '/';
28
28
  }
@@ -53,7 +53,7 @@ let _apiPrefix = DEFAULT_ADMIN_API_PREFIX;
53
53
  export function normalizeAdminApiPrefix(raw) {
54
54
  let p = raw.trim();
55
55
  if (!p.startsWith('/'))
56
- p = '/' + p;
56
+ p = `/${p}`;
57
57
  p = p.replace(/\/+$/, '');
58
58
  return p || '/';
59
59
  }
@@ -230,9 +230,7 @@ export class AdminSessionsService {
230
230
  //
231
231
  // Sem sessão preservada (exceptSessionId não encontrado / sem loginTs), caímos
232
232
  // no default (`now`) — não há sessão nova a proteger nesse caminho.
233
- const cutoff = typeof preserved?.loginTs === 'number'
234
- ? new Date((preserved.loginTs - 1) * 1000)
235
- : undefined;
233
+ const cutoff = typeof preserved?.loginTs === 'number' ? new Date((preserved.loginTs - 1) * 1000) : undefined;
236
234
  await this.recordSubRevocation(accountId, cutoff);
237
235
  return {
238
236
  sessions: sessionsToRevoke.length,
@@ -1,6 +1,6 @@
1
1
  import type { HttpContext } from '@adonisjs/core/http';
2
- import type { ResolvedServerConfig } from '../define_config.js';
3
2
  import type { AuthAccount } from '../accounts/account_store.js';
3
+ import type { ResolvedServerConfig } from '../define_config.js';
4
4
  /**
5
5
  * Sincroniza `ctx.auth` (`@adonisjs/auth`) com um login bem-sucedido no console
6
6
  * de conta do authkit. Ver `adonisAuth` em `define_config.ts` pro porquê: sem
@@ -1,5 +1,5 @@
1
- import type { ConfigProvider } from '@adonisjs/core/types';
2
1
  import type { SessionUserProviderContract } from '@adonisjs/auth/types/session';
2
+ import type { ConfigProvider } from '@adonisjs/core/types';
3
3
  import type { AuthAccount } from '../accounts/account_store.js';
4
4
  /**
5
5
  * User provider de `@adonisjs/auth` (session guard) apoiado no `accountStore`
@@ -4,7 +4,7 @@ import { RuntimeException } from '@adonisjs/core/exceptions';
4
4
  * LAZY do `register()`) para o erro de `appKey` ausente — um só lugar para
5
5
  * editar o texto, e garante que os dois caminhos falem exatamente a mesma coisa.
6
6
  */
7
- export const MISSING_APP_KEY_MESSAGE = 'APP_KEY ausente: defina `export const appKey = new Secret(env.get(\'APP_KEY\'))` em config/app.ts. ' +
7
+ export const MISSING_APP_KEY_MESSAGE = "APP_KEY ausente: defina `export const appKey = new Secret(env.get('APP_KEY'))` em config/app.ts. " +
8
8
  'O @adonis-agora/authkit-server precisa dele para assinar os cookies do oidc-provider (NÃO usa config/encryption.ts).';
9
9
  /**
10
10
  * Lê e valida `app.appKey` (usado pelo oidc-provider para assinar cookies via
@@ -43,9 +43,7 @@ let mediaModulePromise;
43
43
  async function loadMedia() {
44
44
  if (!mediaModulePromise) {
45
45
  const specifier = '@adonis-agora/media/single-file';
46
- mediaModulePromise = import(__rewriteRelativeImportExtension(specifier))
47
- .then((mod) => mod ?? null)
48
- .catch(() => null);
46
+ mediaModulePromise = import(__rewriteRelativeImportExtension(specifier)).then((mod) => mod ?? null).catch(() => null);
49
47
  }
50
48
  return mediaModulePromise;
51
49
  }
@@ -48,9 +48,7 @@ export class SettingLockedError extends Error {
48
48
  code = 'E_SETTING_LOCKED';
49
49
  key;
50
50
  constructor(key) {
51
- super(`A setting "${key}" foi definida via defineConfig() e está travada — ` +
52
- `não pode ser alterada em runtime (console/Admin API). ` +
53
- `Remova-a do defineConfig para liberar a edição pela UI.`);
51
+ super(`A setting "${key}" foi definida via defineConfig() e está travada — não pode ser alterada em runtime (console/Admin API). Remova-a do defineConfig para liberar a edição pela UI.`);
54
52
  this.name = 'SettingLockedError';
55
53
  this.key = key;
56
54
  }
@@ -1,5 +1,5 @@
1
- import { ACCOUNT_SESSION_KEY } from './middleware/account_auth.js';
2
1
  import { getAccountLoginUrl } from './account_login_url.js';
2
+ import { ACCOUNT_SESSION_KEY } from './middleware/account_auth.js';
3
3
  /**
4
4
  * Helpers públicos para integrar a sessão do console do AuthKit com
5
5
  * qualquer coisa fora do pacote (ex.: proteger o dashboard do
@@ -1,6 +1,7 @@
1
1
  import '../augmentations.js';
2
- import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
2
+ import { accountPath } from '../account_paths.js';
3
3
  import { AdminSessionsService } from '../admin_sessions_service.js';
4
+ import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
4
5
  /**
5
6
  * Self-service de consentimento ("apps com acesso") no console de conta. Lista os
6
7
  * Grants da própria conta agrupados por client (resolvendo o nome do client da
@@ -56,6 +57,6 @@ export default class AccountAppsController {
56
57
  },
57
58
  });
58
59
  ctx.session.flash('appRevoked', cfg.messages['account.apps.revoked'] ?? 'account.apps.revoked');
59
- return ctx.response.redirect('/account/apps');
60
+ return ctx.response.redirect(accountPath('apps'));
60
61
  }
61
62
  }
@@ -8,7 +8,7 @@
8
8
  * A tela está atrás do `accountGuard` (requer sessão de conta ativa).
9
9
  */
10
10
  import '../augmentations.js';
11
- import { resolveAvailableMethods, configuredSudoMethods, isSudoMethodMounted, sudoContextFrom, LAST_METHOD_SESSION_KEY, } from '../sudo/runtime.js';
11
+ import { LAST_METHOD_SESSION_KEY, configuredSudoMethods, isSudoMethodMounted, resolveAvailableMethods, sudoContextFrom, } from '../sudo/runtime.js';
12
12
  /**
13
13
  * Reexport de compatibilidade. O construtor canônico do `SudoContext` vive em
14
14
  * `sudo/runtime.ts` (é runtime do SPI, não detalhe da tela); este caminho
@@ -23,7 +23,6 @@ export default class AccountConfirmController {
23
23
  if (!methods.length) {
24
24
  // Nenhum método disponível é erro de CONFIGURAÇÃO do host, não usuário
25
25
  // preso: a tela informa e o log aponta o problema.
26
- ;
27
26
  ctx.logger?.error({ accountId: c.accountId }, 'authkit: nenhum método de sudo disponível para a conta — verifique config.sudo.methods');
28
27
  }
29
28
  // FLAG-DRIFT: `config.sudo.methods` decide o que a tela OFERECE, mas as
@@ -35,10 +34,7 @@ export default class AccountConfirmController {
35
34
  // `configuredSudoMethods` devolve a própria lista montada.
36
35
  for (const m of methods) {
37
36
  if (!isSudoMethodMounted(m.id)) {
38
- ;
39
- ctx.logger?.warn({ method: m.id }, `authkit: método de sudo "${m.id}" está em config.sudo.methods mas não teve ` +
40
- 'rotas montadas por registerAuthHost — a tela vai oferecer uma opção cujo ' +
41
- 'endpoint não existe');
37
+ ctx.logger?.warn({ method: m.id }, `authkit: método de sudo "${m.id}" está em config.sudo.methods mas não teve rotas montadas por registerAuthHost — a tela vai oferecer uma opção cujo endpoint não existe`);
42
38
  }
43
39
  }
44
40
  return c.cfg.render(ctx, 'account/confirm', {