@adonis-agora/authkit-server 0.56.0 → 0.57.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,7 +31,7 @@ node ace add @adonis-agora/authkit-server
31
31
  # ou: pnpm add @adonis-agora/authkit-server && node ace configure @adonis-agora/authkit-server
32
32
  ```
33
33
 
34
- O `configure` publica `config/authkit_server.ts`, o model `app/models/auth_user.ts`,
34
+ O `configure` publica `config/authkit.ts`, o model `app/models/auth_user.ts`,
35
35
  o controller de interactions (`app/controllers/auth_interaction_controller.ts`) e
36
36
  registra o provider.
37
37
 
@@ -89,7 +89,7 @@ Em todos os presets o controller ejetado é **casca**: a lógica vive em
89
89
  `details(ctx)`, `login(ctx, { email, password })` e `consent(ctx)`. Você edita só a parte de
90
90
  render/redirect.
91
91
 
92
- Quem decide se as credenciais valem é o `verifyCredentials` do `config/authkit_server.ts`
92
+ Quem decide se as credenciais valem é o `verifyCredentials` do `config/authkit.ts`
93
93
  — é o que o `service.interactions.login` chama. O default consulta o `AuthUser` por e-mail e
94
94
  usa `verifyPassword`; sobrescreva para plugar sua própria base de usuários.
95
95
 
@@ -105,7 +105,7 @@ router.post('/auth/interaction/:uid/consent', [AuthInteractionController, 'conse
105
105
 
106
106
  ## Persistência
107
107
 
108
- Escolha o backend no `config/authkit_server.ts`:
108
+ Escolha o backend no `config/authkit.ts`:
109
109
  - `adapters.redis({ connection })` — requer `@adonisjs/redis` configurado.
110
110
  - `adapters.database({ connection? })` — Lucid; rode a migração `authkit_oidc_payloads`.
111
111
 
@@ -116,7 +116,7 @@ de resolve) e as expõe de forma opt-in.
116
116
 
117
117
  ### Configuração
118
118
 
119
- No `config/authkit_server.ts`, use a chave `observability`:
119
+ No `config/authkit.ts`, use a chave `observability`:
120
120
 
121
121
  ```ts
122
122
  observability: {
package/build/index.d.ts CHANGED
@@ -129,7 +129,7 @@ export { resolveRegistration } from './src/define_config.js';
129
129
  export type { RegistrationConfigInput, ResolvedRegistrationConfig, } from './src/define_config.js';
130
130
  export { getAccountId, realAccountId, hasAccountSession, consoleLoginUrl, } from './src/host/console_session.js';
131
131
  export { ACCOUNT_SESSION_KEY } from './src/host/middleware/account_auth.js';
132
- export { rememberAccessToken, startImpersonation, impersonationState, stopImpersonation, } from './src/host/impersonation_session.js';
132
+ export { rememberAccessToken, rememberRefreshToken, refreshAccessToken, startImpersonation, impersonationState, stopImpersonation, } from './src/host/impersonation_session.js';
133
133
  export type { StartImpersonationParams, ImpersonationState, } from './src/host/impersonation_session.js';
134
134
  export { SUDO_SESSION_KEY, SUDO_ACCOUNT_SESSION_KEY, SUDO_MODE_DEFAULTS, requireSudo, isSudoActive, markSudo, resolveEffectiveSudoMode, } from './src/host/sudo_mode.js';
135
135
  export type { SudoModeSetting, ResolvedSudoModeSetting, } from './src/host/sudo_mode.js';
package/build/index.js CHANGED
@@ -91,7 +91,7 @@ export { ACCOUNT_SESSION_KEY } from './src/host/middleware/account_auth.js';
91
91
  // Session impersonation — RP-side glue that routes through the IdP's RFC 8693
92
92
  // token-exchange (the IdP validates the admin role + audits). See
93
93
  // src/host/impersonation_session.ts.
94
- export { rememberAccessToken, startImpersonation, impersonationState, stopImpersonation, } from './src/host/impersonation_session.js';
94
+ export { rememberAccessToken, rememberRefreshToken, refreshAccessToken, startImpersonation, impersonationState, stopImpersonation, } from './src/host/impersonation_session.js';
95
95
  // Sudo mode — helpers for host controllers that require step-up authentication.
96
96
  export { SUDO_SESSION_KEY, SUDO_ACCOUNT_SESSION_KEY, SUDO_MODE_DEFAULTS, requireSudo, isSudoActive, markSudo, resolveEffectiveSudoMode, } from './src/host/sudo_mode.js';
97
97
  // SPI de métodos de confirmação de identidade (sudo mode).
@@ -131,6 +131,19 @@ export interface MailHooks {
131
131
  unlockUrl: string;
132
132
  token: string;
133
133
  }) => Promise<void>;
134
+ /**
135
+ * Disparado pelo `authkit:expire-scan` quando uma conta está prestes a ser
136
+ * desativada por inatividade. Substitui o e-mail default de aviso quando
137
+ * fornecido. Best-effort, fire-and-forget; deduplicado pela janela de
138
+ * `warnDays` da setting `account_expiration`, então cada conta recebe no
139
+ * máximo um aviso por janela.
140
+ */
141
+ onAccountExpirationWarning?: (data: {
142
+ /** E-mail da conta que será desativada. */
143
+ email: string;
144
+ /** Dias restantes até a desativação. */
145
+ expiresInDays: number;
146
+ }) => Promise<void>;
134
147
  /**
135
148
  * Disparado após um evento de segurança (senha alterada, MFA habilitado/desabilitado,
136
149
  * passkey adicionada/removida, e-mail alterado). Substitui o e-mail default quando
@@ -888,15 +901,21 @@ export interface AuthServerConfigInput {
888
901
  */
889
902
  accessTokens?: AccessTokensConfig;
890
903
  /**
891
- * Console admin do IdP (B6). Default: desligado. Quando ligado, o host também
892
- * deve passar `admin: true` em {@link AuthHostOptions} no registro de rotas
893
- * (a montagem das rotas acontece antes do config resolver).
904
+ * Console admin do IdP (B6). Default: desligado.
905
+ *
906
+ * Declarar esta chave TRAVA o liga/desliga: `registerAuthHost(router, { admin })`
907
+ * passa a ser ignorado (ver `deriveLockedRouteOptions`). Não repita o
908
+ * `enabled` no `start/routes.ts` — no máximo passe `admin: { prefix }`, que é
909
+ * estrutural e continua valendo.
894
910
  */
895
911
  admin?: AdminConfigInput;
896
912
  /**
897
- * Admin REST API (R6). Default: desligada. Quando ligada, o host também deve
898
- * passar `adminApi: true` em {@link AuthHostOptions} no registro de rotas (a
899
- * montagem das rotas acontece antes do config resolver). Autenticação por API key.
913
+ * Admin REST API (R6). Default: desligada. Autenticação por API key.
914
+ *
915
+ * Declarar esta chave TRAVA o liga/desliga: `registerAuthHost(router, { adminApi })`
916
+ * passa a ser ignorado (ver `deriveLockedRouteOptions`). Não repita o
917
+ * `enabled` no `start/routes.ts` — no máximo passe `adminApi: { prefix }`, que
918
+ * é estrutural e continua valendo.
900
919
  */
901
920
  adminApi?: AdminApiConfigInput;
902
921
  /**
@@ -913,8 +932,16 @@ export interface AuthServerConfigInput {
913
932
  */
914
933
  resolveGeo?: ResolveGeo;
915
934
  /**
916
- * Gestão automática do schema das tabelas do authkit (`authkit_oidc_payloads`,
917
- * `auth_settings`, `auth_password_history` e as três de organizations).
935
+ * Gestão automática do schema das OITO tabelas do authkit:
936
+ * `authkit_oidc_payloads`, `auth_settings`, `auth_password_history`,
937
+ * `auth_mfa`, `auth_session_revocations` e as três de organizations
938
+ * (`auth_organizations`, `auth_organization_members`,
939
+ * `auth_organization_invitations`). Ver `TABLES` em `schema/ensure.ts` — a
940
+ * lista aqui existe para o leitor, mas quem manda é aquele array.
941
+ *
942
+ * FORA desta gestão: `authkit_keystore`, criada sob demanda pelo
943
+ * `LucidKeystoreVault` na primeira escrita, e as tabelas do MODEL do host
944
+ * (`auth_users` etc.), que são migrations do app.
918
945
  *
919
946
  * - `autoManage` (default `true`): no boot, cria as tabelas que faltam e
920
947
  * adiciona colunas novas (aditivo — nunca dropa nem altera tipos).
@@ -138,9 +138,11 @@ export declare function checkEmailChange(input: DoctorInput): Finding | null;
138
138
  */
139
139
  export declare function checkSecurityNotifications(input: DoctorInput): Finding | null;
140
140
  /**
141
- * Verifica a capability de histórico de senhas.
142
- * - Informa se a tabela `auth_password_history` está presente.
143
- * - Avisa quando pepper está configurado como string (não array) rotation recomendada.
141
+ * Verifica o pepper de senha (`accountStore.password.pepper`).
142
+ * - Silencioso quando não pepper configurado.
143
+ * - Reporta o pepper como string e sugere a forma `[novo, antigo]`, que permite
144
+ * rotação sem downtime (lazy re-hash no verify).
145
+ * - Reporta quantos peppers a rotação tem quando já é array.
144
146
  */
145
147
  export declare function checkPasswordPepper(input: DoctorInput): Finding | null;
146
148
  /**
@@ -573,9 +573,11 @@ export function checkSecurityNotifications(input) {
573
573
  return null; // Silencioso quando tudo está ok (não-obrigatório).
574
574
  }
575
575
  /**
576
- * Verifica a capability de histórico de senhas.
577
- * - Informa se a tabela `auth_password_history` está presente.
578
- * - Avisa quando pepper está configurado como string (não array) rotation recomendada.
576
+ * Verifica o pepper de senha (`accountStore.password.pepper`).
577
+ * - Silencioso quando não pepper configurado.
578
+ * - Reporta o pepper como string e sugere a forma `[novo, antigo]`, que permite
579
+ * rotação sem downtime (lazy re-hash no verify).
580
+ * - Reporta quantos peppers a rotação tem quando já é array.
579
581
  */
580
582
  export function checkPasswordPepper(input) {
581
583
  const store = input.authkitConfig?.accountStore;
@@ -94,7 +94,7 @@ export class SettingLockedError extends Error {
94
94
  code = 'E_SETTING_LOCKED';
95
95
  key;
96
96
  constructor(key) {
97
- super(`A setting "${key}" foi definida via defineConfig() e está travadanão pode ser alterada em runtime (console/Admin API). Remova-a do defineConfig para liberar a edição pela UI.`);
97
+ super(`The setting "${key}" is declared in defineConfig() and is therefore locked it cannot be changed at runtime through the console or the Admin API. Remove it from defineConfig to hand the key back to the UI.`);
98
98
  this.name = 'SettingLockedError';
99
99
  this.key = key;
100
100
  }
@@ -4,10 +4,16 @@ import type { HttpContext } from '@adonisjs/core/http';
4
4
  * após o login). Necessário porque o token-exchange exige o access token do admin
5
5
  * como `subject_token`, e o RP normalmente descarta os tokens após o login.
6
6
  *
7
- * Access tokens são curtos: se expirar, `startImpersonation` falha e o admin
8
- * re-loga (aceitável; refresh fica pra depoisYAGNI).
7
+ * Access tokens são curtos: se expirar, `startImpersonation` renova via refresh
8
+ * token (`rememberRefreshToken`) e tenta de novoo admin não precisa relogar.
9
9
  */
10
10
  export declare function rememberAccessToken(ctx: HttpContext, accessToken: string): void;
11
+ /**
12
+ * Guarda o refresh token do admin (do scope `offline_access`), usado para
13
+ * renovar o access token expirado antes do token-exchange. Chame no callback
14
+ * OIDC do RP junto com `rememberAccessToken`.
15
+ */
16
+ export declare function rememberRefreshToken(ctx: HttpContext, refreshToken: string): void;
11
17
  export interface StartImpersonationParams {
12
18
  /** Id do usuário-alvo a personificar. */
13
19
  targetId: string;
@@ -27,6 +33,20 @@ export interface ImpersonationState {
27
33
  /** O admin real (impersonator), quando `active`. */
28
34
  impersonatorId?: string;
29
35
  }
36
+ /**
37
+ * Renova o access token do admin via refresh grant (RFC 6749 §6), usando o
38
+ * refresh token guardado por `rememberRefreshToken`. Retorna o novo access
39
+ * token (e o refresh token rotacionado, se o IdP emitir outro), ou null se não
40
+ * houver refresh token / o refresh falhar.
41
+ *
42
+ * O IdP deste pacote roda `refresh_token` grant por default
43
+ * (`build_provider.ts`: `grant_types: ['authorization_code', 'refresh_token']`),
44
+ * então o refresh é válido na configuração padrão.
45
+ */
46
+ export declare function refreshAccessToken(ctx: HttpContext, params: Pick<StartImpersonationParams, 'issuer' | 'clientId' | 'clientSecret' | 'tokenEndpoint' | 'fetchImpl'>): Promise<{
47
+ accessToken: string;
48
+ refreshToken?: string;
49
+ } | null>;
30
50
  /**
31
51
  * Inicia a impersonation: lê o access token do admin da sessão, chama o
32
52
  * token-exchange (o IdP valida a role admin e audita) e SÓ em sucesso guarda o
@@ -27,17 +27,32 @@ const IMPERSONATOR_SESSION_KEY = 'impersonator_user_id';
27
27
  * `subject_token` do token-exchange. Interna: NÃO exporte o literal.
28
28
  */
29
29
  const ADMIN_ACCESS_TOKEN_SESSION_KEY = 'admin_access_token';
30
+ /**
31
+ * Key de sessão que guarda o refresh token do admin (do `offline_access`),
32
+ * usado para renovar o access token expirado antes do token-exchange. Interna:
33
+ * NÃO exporte o literal.
34
+ */
35
+ const ADMIN_REFRESH_TOKEN_SESSION_KEY = 'admin_refresh_token';
36
+ const REFRESH_TOKEN_GRANT = 'refresh_token';
30
37
  /**
31
38
  * Guarda o access token do admin na sessão (chame no callback OIDC do RP, logo
32
39
  * após o login). Necessário porque o token-exchange exige o access token do admin
33
40
  * como `subject_token`, e o RP normalmente descarta os tokens após o login.
34
41
  *
35
- * Access tokens são curtos: se expirar, `startImpersonation` falha e o admin
36
- * re-loga (aceitável; refresh fica pra depoisYAGNI).
42
+ * Access tokens são curtos: se expirar, `startImpersonation` renova via refresh
43
+ * token (`rememberRefreshToken`) e tenta de novoo admin não precisa relogar.
37
44
  */
38
45
  export function rememberAccessToken(ctx, accessToken) {
39
46
  ctx.session.put(ADMIN_ACCESS_TOKEN_SESSION_KEY, accessToken);
40
47
  }
48
+ /**
49
+ * Guarda o refresh token do admin (do scope `offline_access`), usado para
50
+ * renovar o access token expirado antes do token-exchange. Chame no callback
51
+ * OIDC do RP junto com `rememberAccessToken`.
52
+ */
53
+ export function rememberRefreshToken(ctx, refreshToken) {
54
+ ctx.session.put(ADMIN_REFRESH_TOKEN_SESSION_KEY, refreshToken);
55
+ }
41
56
  /**
42
57
  * POST inline do RFC 8693 token-exchange. Inline (em vez de depender de
43
58
  * `@adonis-agora/authkit-client`) porque o client NÃO é dependência do server e
@@ -68,6 +83,43 @@ async function requestTokenExchange(params, subjectToken) {
68
83
  throw new Error(`Token exchange failed: ${res.status}`);
69
84
  }
70
85
  }
86
+ /**
87
+ * Renova o access token do admin via refresh grant (RFC 6749 §6), usando o
88
+ * refresh token guardado por `rememberRefreshToken`. Retorna o novo access
89
+ * token (e o refresh token rotacionado, se o IdP emitir outro), ou null se não
90
+ * houver refresh token / o refresh falhar.
91
+ *
92
+ * O IdP deste pacote roda `refresh_token` grant por default
93
+ * (`build_provider.ts`: `grant_types: ['authorization_code', 'refresh_token']`),
94
+ * então o refresh é válido na configuração padrão.
95
+ */
96
+ export async function refreshAccessToken(ctx, params) {
97
+ const refreshToken = ctx.session.get(ADMIN_REFRESH_TOKEN_SESSION_KEY);
98
+ if (!refreshToken)
99
+ return null;
100
+ const body = new URLSearchParams({
101
+ grant_type: REFRESH_TOKEN_GRANT,
102
+ refresh_token: refreshToken,
103
+ client_id: params.clientId,
104
+ });
105
+ if (params.clientSecret)
106
+ body.set('client_secret', params.clientSecret);
107
+ const fetchImpl = params.fetchImpl ?? fetch;
108
+ const res = await fetchImpl(params.tokenEndpoint ?? `${params.issuer}/token`, {
109
+ method: 'POST',
110
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
111
+ body: body.toString(),
112
+ });
113
+ if (!res.ok)
114
+ return null;
115
+ const data = (await res.json());
116
+ if (!data.access_token)
117
+ return null;
118
+ const result = { accessToken: data.access_token };
119
+ if (data.refresh_token)
120
+ result.refreshToken = data.refresh_token;
121
+ return result;
122
+ }
71
123
  /**
72
124
  * Inicia a impersonation: lê o access token do admin da sessão, chama o
73
125
  * token-exchange (o IdP valida a role admin e audita) e SÓ em sucesso guarda o
@@ -94,7 +146,22 @@ export async function startImpersonation(ctx, params) {
94
146
  }
95
147
  // O IdP é o gatekeeper: lança se o admin não puder personificar. Chamado ANTES
96
148
  // de qualquer mutação de sessão — em caso de erro nada é trocado.
97
- await requestTokenExchange(params, adminAccessToken);
149
+ try {
150
+ await requestTokenExchange(params, adminAccessToken);
151
+ }
152
+ catch (err) {
153
+ // Access token expirado (4xx do exchange): renova via refresh token e tenta
154
+ // de novo. Sem refresh token / refresh falho → propaga o erro original.
155
+ if (!(err instanceof Error) || !/exchange failed: 4\d\d/.test(err.message))
156
+ throw err;
157
+ const refreshed = await refreshAccessToken(ctx, params);
158
+ if (!refreshed)
159
+ throw err;
160
+ rememberAccessToken(ctx, refreshed.accessToken);
161
+ if (refreshed.refreshToken)
162
+ rememberRefreshToken(ctx, refreshed.refreshToken);
163
+ await requestTokenExchange(params, refreshed.accessToken);
164
+ }
98
165
  // Anti-fixation: rotaciona o id da sessão (mantém os dados) antes de gravar a
99
166
  // nova identidade. Mesmo padrão do consumidor real no RP.
100
167
  await ctx.session.regenerate();
@@ -39,14 +39,23 @@ export interface AuthHostOptions {
39
39
  * Login social opt-in; quando presente, monta as rotas sociais (usam ctx.ally).
40
40
  * Necessário aqui (e não só no config) porque a decisão de montar as rotas é
41
41
  * tomada em tempo de registro, antes do config (lazy) resolver.
42
+ *
43
+ * POLÍTICA: se o `defineConfig` declarou `social`, ele vence e este argumento
44
+ * é IGNORADO (com `console.warn` + entrada em `overriddenByConfig`). NÃO
45
+ * espelhe o config aqui — omitir a chave já herda dele. Use este argumento só
46
+ * quando o config NÃO declara `social`.
42
47
  */
43
48
  social?: AuthSocialConfig;
44
49
  /**
45
50
  * Rate-limiting (anti-brute-force) das rotas sensíveis. Necessário aqui (e não
46
51
  * só no config) porque a aplicação do throttle acontece em tempo de registro de
47
- * rota. Ligado por default (mesma resolução do config). Espelhe o `rateLimit` de
48
- * config/authkit.ts. Se `@adonisjs/limiter` não estiver configurado no host
49
- * (config/limiter.ts), o throttle vira no-op (fail-safe).
52
+ * rota. Ligado por default (mesma resolução do config). Se `@adonisjs/limiter`
53
+ * não estiver configurado no host (config/limiter.ts), o throttle vira no-op
54
+ * (fail-safe).
55
+ *
56
+ * POLÍTICA: se o `defineConfig` declarou `rateLimit`, ele vence e este
57
+ * argumento é IGNORADO (com `console.warn` + entrada em `overriddenByConfig`).
58
+ * NÃO espelhe o config aqui — omitir a chave já herda dele.
50
59
  */
51
60
  rateLimit?: RateLimitConfigInput;
52
61
  /**
@@ -60,7 +69,12 @@ export interface AuthHostOptions {
60
69
  *
61
70
  * Necessário aqui (e não só no config) porque a decisão de montar as rotas é
62
71
  * tomada em tempo de registro, antes do config (lazy) resolver.
63
- * Espelhe o `admin.enabled` de config/authkit.ts.
72
+ *
73
+ * DOIS EIXOS: o LIGA/DESLIGA é POLÍTICA — se o `defineConfig` declarou
74
+ * `admin`, ele vence e o `true`/`false` daqui é IGNORADO (com `console.warn`
75
+ * + entrada em `overriddenByConfig`). O PREFIXO é ESTRUTURAL e o argumento
76
+ * sempre vence. Ou seja: com `admin` no config, passe no máximo
77
+ * `{ prefix: '...' }` aqui — nunca espelhe o `enabled`.
64
78
  *
65
79
  * @example
66
80
  * // Prefixo padrão
@@ -82,7 +96,11 @@ export interface AuthHostOptions {
82
96
  *
83
97
  * Necessário aqui (e não só no config) porque a decisão de montar as rotas é
84
98
  * tomada em tempo de registro, antes do config (lazy) resolver.
85
- * Espelhe o `adminApi.enabled` de config/authkit.ts.
99
+ *
100
+ * DOIS EIXOS, como `admin`: o LIGA/DESLIGA é POLÍTICA (o `defineConfig`
101
+ * vence e o argumento é IGNORADO, com `console.warn`), o PREFIXO é
102
+ * ESTRUTURAL (o argumento vence). Com `adminApi` no config, passe no máximo
103
+ * `{ prefix: '...' }` aqui.
86
104
  *
87
105
  * @example
88
106
  * // Prefixo padrão (back-compat)
@@ -98,7 +116,10 @@ export interface AuthHostOptions {
98
116
  * Métodos de sudo cujas rotas devem ser montadas. Necessário aqui (e não só
99
117
  * no config) porque a decisão de MONTAR rotas acontece em tempo de registro,
100
118
  * antes de o config lazy resolver — mesma razão de `social`/`admin`/`rateLimit`.
101
- * Espelhe o `sudo.methods` de config/authkit.ts.
119
+ *
120
+ * POLÍTICA: se o `defineConfig` declarou `sudo.methods`, ele vence e este
121
+ * argumento é IGNORADO (com `console.warn` + entrada em `overriddenByConfig`).
122
+ * NÃO espelhe o config aqui — omitir a chave já herda dele.
102
123
  *
103
124
  * SUBSTITUI os defaults, não acrescenta: a lista é do host. Quem quer manter
104
125
  * senha/passkey ao lado do método novo os inclui explicitamente
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@adonis-agora/authkit-server",
3
- "version": "0.56.0",
3
+ "version": "0.57.1",
4
4
  "description": "AdonisJS OIDC/OAuth2 provider (Identity Provider) toolkit: ejectable auth server with sessions, rate-limiting, MFA/TOTP, audit log, federated logout and OpenTelemetry metrics.",
5
5
  "license": "MIT",
6
6
  "author": "dudousxd",
7
- "homepage": "https://github.com/DavideCarvalho/adonis-authkit/tree/main/packages/authkit-server#readme",
7
+ "homepage": "https://github.com/DavideCarvalho/adonis-agora-authkit/tree/main/packages/authkit-server#readme",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/DavideCarvalho/adonis-agora-authkit.git",
11
11
  "directory": "packages/authkit-server"
12
12
  },
13
13
  "bugs": {
14
- "url": "https://github.com/DavideCarvalho/adonis-authkit/issues"
14
+ "url": "https://github.com/DavideCarvalho/adonis-agora-authkit/issues"
15
15
  },
16
16
  "keywords": [
17
17
  "adonisjs",
@@ -108,7 +108,7 @@
108
108
  "oidc-provider": "9.11.3",
109
109
  "otplib": "12.0.1",
110
110
  "qrcode": "1.5.4",
111
- "@adonis-agora/authkit-core": "0.7.0"
111
+ "@adonis-agora/authkit-core": "0.7.1"
112
112
  },
113
113
  "devDependencies": {
114
114
  "@adonis-agora/durable": "0.22.0",
@@ -150,7 +150,7 @@
150
150
  "react-error-boundary": "6.1.2",
151
151
  "nuqs": "2.9.5",
152
152
  "recharts": "3.10.1",
153
- "@adonis-agora/authkit-react": "0.18.0"
153
+ "@adonis-agora/authkit-react": "0.18.1"
154
154
  },
155
155
  "scripts": {
156
156
  "build": "node scripts/build_host_css.mjs && node scripts/build_webauthn.mjs && node scripts/build_ui.mjs && node -e \"const fs=require('node:fs');for(const d of ['build/stubs','build/host/views'])fs.rmSync(d,{recursive:true,force:true})\" && tsc && node -e \"require('node:fs').cpSync('src/host/assets','build/src/host/assets',{recursive:true})\" && node -e \"require('node:fs').cpSync('stubs','build/stubs',{recursive:true,filter:(s)=>!s.endsWith('.ts')})\" && node -e \"const fs=require('node:fs');if(fs.existsSync('assets'))fs.cpSync('assets','build/assets',{recursive:true})\" && node -e \"require('node:fs').cpSync('src/host/views','build/host/views',{recursive:true})\" && node -e \"const fs=require('node:fs');fs.mkdirSync('build/host/ui',{recursive:true});fs.readdirSync('src/host/ui').filter(f=>f.endsWith('.html')).forEach(f=>fs.copyFileSync('src/host/ui/'+f,'build/host/ui/'+f))\" && node -e \"require('node:fs').copyFileSync('commands/commands.json','build/commands/commands.json')\" && node -e \"const fs=require('node:fs');fs.mkdirSync('build/src/password',{recursive:true});fs.copyFileSync('src/password/common_passwords.txt','build/src/password/common_passwords.txt')\"",