@adonis-agora/authkit-server 0.86.0 → 0.87.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 (37) hide show
  1. package/README.md +2 -2
  2. package/build/index.d.ts +1 -2
  3. package/build/index.js +0 -1
  4. package/build/src/agents/config.d.ts +1 -1
  5. package/build/src/agents/delegation_service.js +1 -1
  6. package/build/src/agents/poppy/client_registry.d.ts +5 -0
  7. package/build/src/agents/poppy/client_registry.js +35 -1
  8. package/build/src/agents/poppy/config.d.ts +111 -80
  9. package/build/src/agents/poppy/config.js +55 -35
  10. package/build/src/agents/poppy/dpop.d.ts +2 -2
  11. package/build/src/agents/poppy/dpop.js +3 -3
  12. package/build/src/agents/poppy/email_code_sign_in.d.ts +4 -4
  13. package/build/src/agents/poppy/email_code_sign_in.js +5 -5
  14. package/build/src/agents/poppy/errors.d.ts +7 -2
  15. package/build/src/agents/poppy/errors.js +5 -2
  16. package/build/src/agents/poppy/resource.d.ts +30 -25
  17. package/build/src/agents/poppy/resource.js +24 -20
  18. package/build/src/agents/poppy/safe_fetch.js +8 -2
  19. package/build/src/agents/poppy/service.d.ts +69 -62
  20. package/build/src/agents/poppy/service.js +540 -546
  21. package/build/src/agents/poppy/session_jwt.d.ts +30 -0
  22. package/build/src/agents/poppy/session_jwt.js +133 -0
  23. package/build/src/agents/poppy/store.d.ts +17 -22
  24. package/build/src/agents/poppy/store.js +22 -30
  25. package/build/src/agents/poppy/web_session.d.ts +23 -16
  26. package/build/src/agents/poppy/web_session.js +42 -24
  27. package/build/src/host/admin_sessions_service.js +3 -3
  28. package/build/src/host/controllers/account_apps_controller.js +1 -1
  29. package/build/src/host/controllers/poppy_consent_controller.d.ts +2 -2
  30. package/build/src/host/controllers/poppy_consent_controller.js +2 -2
  31. package/build/src/host/controllers/poppy_controller.d.ts +19 -11
  32. package/build/src/host/controllers/poppy_controller.js +93 -68
  33. package/build/src/host/csrf.d.ts +2 -4
  34. package/build/src/host/csrf.js +2 -3
  35. package/build/src/host/register_auth_host.js +10 -5
  36. package/build/src/schema/ensure.js +14 -9
  37. package/package.json +3 -3
package/README.md CHANGED
@@ -17,8 +17,8 @@ wrapper around [`oidc-provider`](https://github.com/panva/node-oidc-provider).
17
17
  (JWKS, no shared secrets) and user-approved, revocable delegation with scopes you define,
18
18
  over a pluggable protocol adapter ([PACT](https://openpactprotocol.org) built in).
19
19
  Plus the [Personal Agent Protocol ("Poppy")](https://personalagentprotocol.org/docs/spec):
20
- discovery, DPoP-bound agent sessions, Direct/Device/Mediated sign-in, MCP and browser sessions.
21
- ⚠️ **Experimental** — tracks the spec's Draft 0.1 and will change (possibly breaking, outside
20
+ discovery, signed `Poppy-Session` agent sessions, Direct/Device/Mediated sign-in, MCP and browser sessions.
21
+ ⚠️ **Experimental** — tracks the spec's Draft 0.3 and will change (possibly breaking, outside
22
22
  semver majors) while the spec is a draft.
23
23
  - **Native apps** — RFC 8252 native clients (`authkit:clients:create --native`: private-use
24
24
  scheme / claimed https / loopback redirects, always public + PKCE) and the `@adonisjs/auth`
package/build/index.d.ts CHANGED
@@ -16,8 +16,7 @@ export type { PersonalAgentDelegationConfigInput, PersonalAgentRegistration, Per
16
16
  export type { DelegationContext, DelegationGrantSummary, DelegationReceipt, } from './src/agents/delegation_service.js';
17
17
  export type { PersonalAgentAuthOptions, PersonalAgentRequestContext, } from './src/agents/middleware.js';
18
18
  export { personalAgentAuth, personalAgentOf, personalAgentReceipt, personalAgentSecurity, personalAgentStepUp, } from './src/agents/middleware.js';
19
- export type { PoppyAgentProtocolEntry, PoppyApiEntry, PoppyBrowserLogin, PoppyClientsConfigInput, PoppyConfigInput, PoppyLimiter, PoppyMediatedConfigInput, PoppyMediatedField, PoppyMediatedResult, PoppyMediatedVerifyInput, PoppyPrincipalBase, PoppyReplayStore, ResolvedPoppyConfig, } from './src/agents/poppy/config.js';
20
- export { POPPY_READ, POPPY_WRITE } from './src/agents/poppy/config.js';
19
+ export type { PoppyAgentProtocolEntry, PoppyApiEntry, PoppyBrowserLogin, PoppyClientsConfigInput, PoppyConfigInput, PoppyLimiter, PoppyMediatedConfigInput, PoppyMediatedField, PoppyMediatedResult, PoppyMediatedVerifyInput, PoppyPrincipalBase, PoppyReplayStore, PoppyScopeHint, ResolvedPoppyConfig, } from './src/agents/poppy/config.js';
21
20
  export { accessTokenHash, type DpopNonceSource, type DpopResult, hmacNonceSource, type VerifyDpopInput, verifyDpopProof, } from './src/agents/poppy/dpop.js';
22
21
  export { maskEmail, type PoppyEmailCodeSignInOptions, poppyEmailCodeSignIn, } from './src/agents/poppy/email_code_sign_in.js';
23
22
  export { PoppyError, type PoppyErrorCode } from './src/agents/poppy/errors.js';
package/build/index.js CHANGED
@@ -9,7 +9,6 @@ export { AuthOrganization, AuthOrganizationInvitation, AuthOrganizationMember, d
9
9
  export { lucidStores } from './src/accounts/lucid_stores.js';
10
10
  export { PersonalAgentVerifier } from './src/agents/agent_identity.js';
11
11
  export { personalAgentAuth, personalAgentOf, personalAgentReceipt, personalAgentSecurity, personalAgentStepUp, } from './src/agents/middleware.js';
12
- export { POPPY_READ, POPPY_WRITE } from './src/agents/poppy/config.js';
13
12
  export { accessTokenHash, hmacNonceSource, verifyDpopProof, } from './src/agents/poppy/dpop.js';
14
13
  export { maskEmail, poppyEmailCodeSignIn, } from './src/agents/poppy/email_code_sign_in.js';
15
14
  export { PoppyError } from './src/agents/poppy/errors.js';
@@ -83,7 +83,7 @@ export interface PersonalAgentsConfigInput {
83
83
  * segundo protocolo, ao lado do PACT. Um app pode servir os dois. Ver
84
84
  * `poppy/config.ts`.
85
85
  *
86
- * @experimental Poppy (Personal Agent Protocol) Draft 0.1 — acompanha a spec em desenvolvimento e PODE MUDAR
86
+ * @experimental Poppy (Personal Agent Protocol) Draft 0.3 — acompanha a spec em desenvolvimento e PODE MUDAR
87
87
  * de forma incompatível fora de majors enquanto ela for draft.
88
88
  */
89
89
  poppy?: PoppyConfigInput;
@@ -31,7 +31,7 @@ function newUserCode() {
31
31
  return `${code.slice(0, 4)}-${code.slice(4)}`;
32
32
  }
33
33
  /**
34
- * A tabela de grants é compartilhada com o Poppy (Account Tokens, `pgrant_`):
34
+ * A tabela de grants é compartilhada com o Poppy (refresh tokens, `pgrant_`):
35
35
  * o PACT só enxerga os dele.
36
36
  */
37
37
  function isPactGrant(id) {
@@ -18,6 +18,11 @@ export interface PoppyClient {
18
18
  /** Chaves públicas do `jwks_uri`. */
19
19
  keys: JWTVerifyGetKey;
20
20
  }
21
+ /**
22
+ * `redirect_uri` igual a uma entrada de `redirect_uris`; numa loopback redirect URI a porta não
23
+ * conta (§4.2, RFC 8252 §7.3).
24
+ */
25
+ export declare function redirectUriAllowed(registered: string[], redirectUri: string): boolean;
21
26
  /** Valida um documento de metadata e devolve os campos usados. Lança `invalid_client`. */
22
27
  export declare function validateClientMetadata(fetchedFrom: string, doc: unknown, options?: {
23
28
  allowHttp?: boolean;
@@ -34,6 +34,38 @@ function isHttpsUrl(value, allowHttp = false) {
34
34
  return false;
35
35
  }
36
36
  }
37
+ /** Loopback redirect URI (RFC 8252 §7.3): `http`, IP de loopback literal, sem fragmento. */
38
+ function isLoopbackRedirect(value) {
39
+ if (typeof value !== 'string')
40
+ return false;
41
+ try {
42
+ const url = new URL(value);
43
+ return (url.protocol === 'http:' &&
44
+ (url.hostname === '127.0.0.1' || url.hostname === '[::1]') &&
45
+ !url.username &&
46
+ !url.password &&
47
+ !url.hash);
48
+ }
49
+ catch {
50
+ return false;
51
+ }
52
+ }
53
+ /**
54
+ * `redirect_uri` igual a uma entrada de `redirect_uris`; numa loopback redirect URI a porta não
55
+ * conta (§4.2, RFC 8252 §7.3).
56
+ */
57
+ export function redirectUriAllowed(registered, redirectUri) {
58
+ if (registered.includes(redirectUri))
59
+ return true;
60
+ if (!isLoopbackRedirect(redirectUri))
61
+ return false;
62
+ const withoutPort = (value) => {
63
+ const url = new URL(value);
64
+ url.port = '';
65
+ return url.toString();
66
+ };
67
+ return registered.some((r) => isLoopbackRedirect(r) && withoutPort(r) === withoutPort(redirectUri));
68
+ }
37
69
  function ttlFrom(maxAge) {
38
70
  if (maxAge === null)
39
71
  return DEFAULT_TTL_MS;
@@ -62,8 +94,10 @@ export function validateClientMetadata(fetchedFrom, doc, options = {}) {
62
94
  if (!Array.isArray(redirects))
63
95
  throw bad('redirect_uris must be an array');
64
96
  for (const uri of redirects) {
97
+ if (isLoopbackRedirect(uri))
98
+ continue;
65
99
  if (!isHttpsUrl(uri, allowHttp) || hostOf(uri) !== host) {
66
- throw bad('every redirect_uri must be an HTTPS URL on the same domain as client_id');
100
+ throw bad('every redirect_uri must be an HTTPS URL on the same domain as client_id, or a loopback URI');
67
101
  }
68
102
  }
69
103
  if (d.token_endpoint_auth_method !== 'private_key_jwt') {
@@ -1,33 +1,26 @@
1
1
  /**
2
- * @experimental Draft 0.1 da spec (https://personalagentprotocol.org/docs/spec) — pode mudar de forma
2
+ * @experimental Draft 0.3 da spec (https://personalagentprotocol.org/docs/spec) — pode mudar de forma
3
3
  * incompatível fora de majors enquanto a spec for draft.
4
4
  *
5
- * Personal Agent Protocol ("Poppy", Draft 0.1 — https://personalagentprotocol.org) — config.
5
+ * Personal Agent Protocol ("Poppy", Draft 0.3 — https://personalagentprotocol.org) — config.
6
6
  *
7
- * Poppy é o segundo protocolo de personal agents ao lado do PACT. O modelo é
8
- * outro: em vez de um JWT do agente em cada request + um token de delegação, a
9
- * empresa (este app) roda um authorization server OAuth com SESSÕES — o agente
10
- * se identifica pelo `client_id` (uma URL HTTPS com o documento de metadata
11
- * dele), começa uma Session deslogada com uma asserção JWT, e o usuário entra
12
- * na conta por Direct (código + PKCE), Device (RFC 8628) ou Mediated Sign-In.
13
- * Os tokens de sessão são opacos e presos a uma chave por DPoP (RFC 9449);
14
- * Bearer só no MCP.
7
+ * Poppy é o segundo protocolo de personal agents ao lado do PACT. O agente se identifica pelo
8
+ * `client_id` (uma URL HTTPS com o documento de metadata dele) e declara a Session em cada request
9
+ * com o header `Poppy-Session`, um JWT assinado com uma chave delegada. O acesso à conta é OAuth
10
+ * puro e separado: este app roda o authorization server, e o usuário entra por Direct (código +
11
+ * PKCE), Device (RFC 8628) ou pela extensão Mediated Sign-In. Prender os access tokens com DPoP é
12
+ * opcional (RFC 9449).
15
13
  *
16
- * Reaproveita o núcleo de delegação: o Account Token é um grant na tabela de
17
- * grants de personal agents (`auth_agent_grants`) — lista e revogação no console
18
- * de conta são as mesmas do PACT — e os scopes aprovados viram os `scopes` do
19
- * principal (que o `@adonis-agora/agent` mapeia para roles `scope:<id>`).
14
+ * Reaproveita o núcleo de delegação: o refresh token é um grant na tabela de grants de personal
15
+ * agents (`auth_agent_grants`) — lista e revogação no console de conta são as mesmas do PACT — e os
16
+ * scopes aprovados viram os `scopes` do principal (que o `@adonis-agora/agent` mapeia para roles
17
+ * `scope:<id>`).
20
18
  */
21
19
  import type { HttpContext } from '@adonisjs/core/http';
22
- /** Scopes amplos definidos pelo protocolo (§4.4). */
23
- export declare const POPPY_READ = "poppy:read";
24
- export declare const POPPY_WRITE = "poppy:write";
25
- /** Descrições default dos scopes do protocolo — o que a tela de consentimento mostra. */
26
- export declare const POPPY_SCOPE_DESCRIPTIONS: Record<string, string>;
27
20
  export type PoppySignInType = 'direct' | 'device' | 'mediated';
28
- /** Um campo de credencial do Mediated Sign-In (§4.7). */
21
+ /** Um campo de credencial do Mediated Sign-In (extensão Mediated Sign-In). */
29
22
  export interface PoppyMediatedField {
30
- /** Chave que o agente manda em `credentials`. */
23
+ /** Parâmetro que o agente manda no token endpoint. */
31
24
  name: string;
32
25
  /** O que pedir ao usuário. */
33
26
  label: string;
@@ -41,27 +34,25 @@ export interface PoppyMediatedVerifyInput {
41
34
  scopes: string[];
42
35
  /** `client_id` do personal agent. */
43
36
  clientId: string;
44
- /** User ID que o agente deu ao usuário (opaco). */
45
- userId: string;
46
- sessionId: string;
47
37
  ctx: HttpContext;
48
38
  }
49
39
  /**
50
40
  * Resultado do callback de credenciais. Nunca devolva as credenciais.
51
41
  *
52
- * - `complete`: credenciais certas, nada mais a fazer — a Session entra na conta.
42
+ * - `complete`: credenciais certas, nada mais a fazer — o agente recebe os tokens.
53
43
  * - `code_required`: o app MANDOU um código de uso único (SMS, e-mail, WhatsApp…)
54
44
  * e o agente precisa submetê-lo. Ou devolve o `code` que mandou (a lib guarda
55
45
  * só o hash e confere), ou deixa sem `code` e implementa `verifyCode` (ex.: um
56
46
  * serviço de OTP que confere do lado dele). `state` é opaco e volta no
57
47
  * `verifyCode`.
58
- * - `failed`: senha errada, conta bloqueada…
48
+ * - `failed`: senha errada… (`invalid_grant`).
49
+ * - `denied`: a empresa recusa este sign-in (`access_denied`).
59
50
  *
60
51
  * **Sem enumeração de contas.** Num fluxo só de identificador (e-mail/telefone + código), `failed`
61
52
  * para um identificador desconhecido conta ao agente quem tem conta. Devolva então `code_required`
62
53
  * com `accountId: null` (e o mesmo `sentTo` que uma conta real teria) e NÃO mande código: a lib
63
54
  * responde igual a uma conta real e recusa qualquer código como um código errado (mesmas
64
- * tentativas, mesmo `failed` no fim). Faça o mesmo trabalho nos dois caminhos (ex.: enfileire o
55
+ * tentativas, mesmo `invalid_grant` no fim). Faça o mesmo trabalho nos dois caminhos (ex.: enfileire o
65
56
  * e-mail em vez de mandar na hora) para o tempo de resposta não denunciar.
66
57
  */
67
58
  export type PoppyMediatedResult = {
@@ -77,15 +68,17 @@ export type PoppyMediatedResult = {
77
68
  state?: unknown;
78
69
  } | {
79
70
  status: 'failed';
71
+ } | {
72
+ status: 'denied';
80
73
  };
81
74
  /**
82
- * @experimental Poppy (Personal Agent Protocol) Draft 0.1 — pode mudar de forma incompatível enquanto a spec for draft.
75
+ * @experimental Poppy (Personal Agent Protocol) Draft 0.3 — pode mudar de forma incompatível enquanto a spec for draft.
83
76
  */
84
77
  export interface PoppyMediatedConfigInput {
85
- /** Campos pedidos (§4.7). Ex.: `[{ name: 'email', … }, { name: 'password', secret: true, … }]`. */
78
+ /** Campos pedidos (extensão Mediated Sign-In). Ex.: `[{ name: 'email', … }, { name: 'password', secret: true, … }]`. */
86
79
  fields: PoppyMediatedField[];
87
- /** Scopes que o Mediated Sign-In pode conceder. Default: `['poppy:read']`. */
88
- scopes?: string[];
80
+ /** Scopes que o Mediated Sign-In pode conceder (`scopes` da extensão). */
81
+ scopes: string[];
89
82
  /** Confere as credenciais (e, se for o caso, manda o código). */
90
83
  verify: (input: PoppyMediatedVerifyInput) => Promise<PoppyMediatedResult>;
91
84
  /**
@@ -97,45 +90,54 @@ export interface PoppyMediatedConfigInput {
97
90
  accountId: string;
98
91
  state: unknown;
99
92
  clientId: string;
100
- userId: string;
101
93
  }) => Promise<boolean>;
102
94
  /** Validade do sign-in pendente de código, em segundos. Default: 600. */
103
95
  codeTtl?: number;
104
- /** Tentativas de código antes de `failed`. Default: 5. */
96
+ /** Tentativas de código antes de `invalid_grant`. Default: 5. */
105
97
  maxCodeAttempts?: number;
106
98
  }
107
- /** Uma entrada de `agent.protocols` (§3.1, §7.1). */
99
+ /** Uma entrada de `agent.protocols` (§3.1, §8.1). */
108
100
  export interface PoppyAgentProtocolEntry {
109
- /** `'poppy'` para as conversas deste protocolo (§7). */
101
+ /** `'poppy'` para as conversas deste protocolo (§8). */
110
102
  type: string;
111
103
  /** URL HTTPS do endpoint de conversas. */
112
104
  endpoint: string;
113
- /** Exige tokens emitidos para este `resource` (§4.3). */
105
+ /** A interface precisa da conta desde o início (§3.2). Default: `session`. */
106
+ access?: 'session' | 'signed_in';
107
+ /**
108
+ * Só aceita tokens emitidos para este `resource` (§4.5). Não sai no `poppy.json`: publique a
109
+ * protected resource metadata do serviço (RFC 9728) com este `resource`.
110
+ */
114
111
  resource?: string;
115
112
  }
116
- /** Uma entrada de `apis` (§3.1, §6). */
113
+ /** Hints de um scope (§4.7): a ação de maior consequência que o exige. */
114
+ export interface PoppyScopeHint {
115
+ changes: 'none' | 'reversible' | 'irreversible';
116
+ personal_data: boolean;
117
+ }
118
+ /** Uma entrada de `apis` (§3.1, §7). */
117
119
  export interface PoppyApiEntry {
118
120
  type: 'openapi' | 'mcp' | (string & {});
119
121
  url: string;
120
122
  description: string;
121
- /** Exige tokens emitidos para este `resource` (§4.3). MCP sempre exige o próprio `url`. */
123
+ /** Como em `agent.protocols`. MCP sempre exige o próprio `url` (§7). */
122
124
  resource?: string;
123
125
  }
124
- /** Hook de login do navegador do agente (§5) para apps com sessão de login própria. */
126
+ /** Hook de login do navegador do agente (§6) para apps com sessão de login própria. */
125
127
  export type PoppyBrowserLogin = (ctx: HttpContext, input: {
126
128
  sessionId: string;
127
129
  clientId: string;
128
130
  userId: string;
129
- /** Conta da Session quando ela está logada; `null` = Session deslogada. */
131
+ /** Conta autorizada na entrada do navegador; `null` = entrada sem access token. */
130
132
  accountId: string | null;
131
133
  scopes: string[];
132
134
  }) => Promise<void>;
133
135
  /**
134
- * Onde o protocolo guarda os `jti` já vistos (asserções, client assertions,
135
- * provas DPoP, asserções de navegador) até expirarem. `claim` devolve `true` na
136
+ * Onde o protocolo guarda os `jti` já vistos (client assertions, Session JWTs,
137
+ * provas DPoP) até expirarem. `claim` devolve `true` na
136
138
  * primeira vez que vê a chave e `false` num replay.
137
139
  *
138
- * @experimental Poppy (Personal Agent Protocol) Draft 0.1 — acompanha a spec em desenvolvimento e PODE MUDAR
140
+ * @experimental Poppy (Personal Agent Protocol) Draft 0.3 — acompanha a spec em desenvolvimento e PODE MUDAR
139
141
  * de forma incompatível fora de majors enquanto ela for draft.
140
142
  */
141
143
  export interface PoppyReplayStore {
@@ -148,8 +150,8 @@ export type PoppyLimiter = (input: {
148
150
  }) => Promise<number | null>;
149
151
  export interface PoppyClientsConfigInput {
150
152
  /**
151
- * `true` = só agentes registrados (`registered`) iniciam Sessions; os demais
152
- * levam `invalid_client` (§4.1). Default: false — qualquer `client_id` com um
153
+ * `true` = só agentes registrados (`registered`) são aceitos; os demais levam
154
+ * `invalid_client` ou `invalid_session` (§4.1). Default: false — qualquer `client_id` com um
153
155
  * documento de metadata válido.
154
156
  */
155
157
  requireRegistration?: boolean;
@@ -159,29 +161,27 @@ export interface PoppyClientsConfigInput {
159
161
  blocked?: string[] | ((clientId: string) => boolean | Promise<boolean>);
160
162
  }
161
163
  /**
162
- * @experimental Poppy (Personal Agent Protocol) Draft 0.1 — pode mudar de forma incompatível enquanto a spec for draft.
164
+ * @experimental Poppy (Personal Agent Protocol) Draft 0.3 — pode mudar de forma incompatível enquanto a spec for draft.
163
165
  */
164
166
  export interface PoppyConfigInput {
165
167
  /** Nome exibido e domínio (`organization` do poppy.json). */
166
168
  organization: {
167
169
  name: string;
168
- /** Domínio da empresa (sem esquema). O poppy.json só é servido nele (ignorando `www.`). */
170
+ /** Domínio da empresa (sem esquema). O poppy.json só é servido nele; `www.` redireciona. */
169
171
  domain: string;
170
- /** Outros domínios da mesma empresa (um por país…) — também vão para `poppy_domains`. */
172
+ /** Outros domínios da mesma empresa (um por país…) — também vão para `protected_resources`. */
171
173
  aliases?: string[];
172
174
  };
173
175
  /** Prefixo das rotas e path do issuer. Default: `/poppy`. */
174
176
  prefix?: string;
175
177
  /**
176
- * Scopes próprios do app (`custom_scopes`), `id → descrição para o usuário`.
177
- * Default: os de `personalAgents.delegation.scopes`, quando houver — um
178
- * catálogo só para os dois protocolos. Não podem começar com `poppy:`.
178
+ * Scopes do app (`auth.scopes`), `id → descrição`. O protocolo não define nenhum (§4.7).
179
+ * Default: os de `personalAgents.delegation.scopes`, quando houver — um catálogo só para os
180
+ * dois protocolos.
179
181
  */
180
182
  scopes?: Record<string, string>;
181
- /** Oferece os scopes amplos `poppy:read`/`poppy:write`. Default: true. */
182
- broadScopes?: boolean;
183
- /** Descrições próprias para `poppy:read`/`poppy:write` na tela de consentimento. */
184
- broadScopeDescriptions?: Partial<Record<'poppy:read' | 'poppy:write', string>>;
183
+ /** Hints de cada scope (`auth.scope_hints`, §4.7). */
184
+ scopeHints?: Record<string, PoppyScopeHint>;
185
185
  /** Tipos de sign-in. `false` desliga; um array restringe os scopes do tipo. */
186
186
  signIn?: {
187
187
  /** Default: todos os scopes. */
@@ -195,19 +195,29 @@ export interface PoppyConfigInput {
195
195
  /** Desligado por default: o app precisa conferir as credenciais. */
196
196
  mediated?: PoppyMediatedConfigInput;
197
197
  };
198
- /** Company Agent (§7) — o endpoint de conversas é implementado pelo `@adonis-agora/agent`. */
198
+ /** Company Agent (§8) — o endpoint de conversas é implementado pelo `@adonis-agora/agent`. */
199
199
  agent?: {
200
200
  protocols: PoppyAgentProtocolEntry[];
201
201
  };
202
- /** APIs do app que aceitam Session Tokens (§6). */
202
+ /** APIs do app que aceitam o header da Session (§7). */
203
203
  apis?: PoppyApiEntry[];
204
+ /** Endpoint de feedback que o app implementa (§9.3). */
205
+ feedback?: {
206
+ endpoint: string;
207
+ };
208
+ /** Documento público das tarefas que a empresa não oferece (§9.1). */
209
+ excludedTasks?: {
210
+ url: string;
211
+ };
204
212
  /**
205
- * Site (§5). Default: liga o `browser_session_endpoint`. `false` desliga. `login`
206
- * substitui o login default (sessão de conta do authkit + `adonisAuth.guard`).
213
+ * Site (§6). Default: liga o `browser_session_endpoint`. `false` desliga. `login`
214
+ * substitui o login default (sessão de conta do authkit + `adonisAuth.guard`). `redirectTo` é
215
+ * a página do site para onde o navegador vai depois de entrar (path). Default: `/`.
207
216
  */
208
217
  web?: false | {
209
218
  browserSession?: boolean;
210
219
  login?: PoppyBrowserLogin;
220
+ redirectTo?: string;
211
221
  };
212
222
  /** Extensões suportadas (§3.3), publicadas como estão. */
213
223
  extensions?: Record<string, {
@@ -223,10 +233,10 @@ export interface PoppyConfigInput {
223
233
  * `NODE_ENV=production`. Default: false.
224
234
  */
225
235
  allowInsecureClientIds?: boolean;
226
- /** Vida do Session Token, em segundos. Default: 3600 (a spec pede horas, não dias). */
227
- sessionTokenTtl?: number;
228
- /** Vida do Account Token (`refresh_token_expires_in`), em segundos. Default: 30 dias. */
229
- accountTokenTtl?: number;
236
+ /** Vida do access token, em segundos. Default: 3600. */
237
+ accessTokenTtl?: number;
238
+ /** Vida do refresh token, em segundos. Default: 30 dias. */
239
+ refreshTokenTtl?: number;
230
240
  /** Uma Session sem uso por este tempo termina (`invalid_session`). Default: 30 dias. */
231
241
  sessionTtl?: number;
232
242
  /** Vida do código de autorização (Direct), em segundos. Default: 60. */
@@ -235,10 +245,17 @@ export interface PoppyConfigInput {
235
245
  deviceCodeTtl?: number;
236
246
  /** Intervalo mínimo de polling do device flow, em segundos. Default: 5. */
237
247
  pollInterval?: number;
238
- /** Vida máxima das asserções do agente (`exp - iat`), em segundos. Default: 300. */
248
+ /** Vida máxima das client assertions (`exp - iat`), em segundos. Default: 300. */
239
249
  assertionMaxLifetime?: number;
240
- /** DPoP (§4.3). */
250
+ /** Session JWT (§5.3). */
251
+ sessionJwt?: {
252
+ /** Janela de aceitação do `iat`, em segundos. Default: 60. */
253
+ maxAge?: number;
254
+ };
255
+ /** DPoP (§4.5): prender os access tokens é escolha da empresa. */
241
256
  dpop?: {
257
+ /** Recusa pedidos de token sem prova: nenhum access token sai Bearer (MCP à parte). Default: false. */
258
+ required?: boolean;
242
259
  /** Exige `nonce` emitido pelo servidor nas provas (RFC 9449 §8). Default: false. */
243
260
  requireNonce?: boolean;
244
261
  /** Janela de aceitação do `iat` da prova, em segundos. Default: 60. */
@@ -257,7 +274,7 @@ export interface PoppyConfigInput {
257
274
  /**
258
275
  * Limites por `client_id` (in-memory, por processo) ou um limitador próprio.
259
276
  * `false` desliga. Default: 120 Sessions novas/min por agente; 10 tentativas
260
- * de Mediated Sign-In/hora por (agente, usuário).
277
+ * de Mediated Sign-In/hora por (agente, identificador).
261
278
  */
262
279
  rateLimit?: false | {
263
280
  sessionsPerMinute?: number;
@@ -270,24 +287,30 @@ export interface PoppyConfigInput {
270
287
  */
271
288
  toActor?: (principal: PoppyPrincipalBase) => unknown | Promise<unknown>;
272
289
  }
273
- /** O que um Session Token válido autoriza — sem o `actor`. *
274
- /** O que um Session Token válido autoriza — sem o `actor`. * @experimental Poppy (Personal Agent Protocol) Draft 0.1 — acompanha a spec em desenvolvimento e PODE MUDAR
275
- /** O que um Session Token válido autoriza — sem o `actor`. * de forma incompatível fora de majors enquanto ela for draft.
276
- /** O que um Session Token válido autoriza — sem o `actor`. */
290
+ /**
291
+ * O que uma request verificada autoriza — sem o `actor`.
292
+ *
293
+ * @experimental Poppy (Personal Agent Protocol) Draft 0.3 — acompanha a spec em desenvolvimento e PODE MUDAR
294
+ * de forma incompatível fora de majors enquanto ela for draft.
295
+ */
277
296
  export interface PoppyPrincipalBase {
278
297
  /** User ID que o personal agent deu ao usuário NESTE app (opaco, estável). */
279
298
  userId: string;
280
- /** Conta deste app quando a Session está logada; `null` deslogada. */
299
+ /** Agent ID opcional (§5.1): qual dos agentes do usuário é esta Session. */
300
+ agentId: string | null;
301
+ /** Conta deste app quando a request traz access token; `null` deslogada. */
281
302
  accountId: string | null;
282
303
  /** `client_id` do personal agent (URL do documento de metadata). */
283
304
  clientId: string;
284
- /** Scopes do token (`poppy:read`, `poppy:write`, próprios). Vazio deslogado. */
305
+ /** Scopes do access token. Vazio deslogado. */
285
306
  scopes: string[];
307
+ /** A Session, única por `client_id` + `sid`. */
286
308
  sessionId: string;
287
309
  signedIn: boolean;
288
310
  /** `resource` para o qual o token foi emitido (RFC 8707), ou `null`. */
289
311
  resource: string | null;
290
- tokenType: 'DPoP' | 'Bearer';
312
+ /** Esquema do access token; `null` deslogado. */
313
+ tokenType: 'DPoP' | 'Bearer' | null;
291
314
  }
292
315
  export interface ResolvedPoppyMediatedConfig {
293
316
  fields: PoppyMediatedField[];
@@ -304,10 +327,9 @@ export interface ResolvedPoppyConfig {
304
327
  aliases: string[];
305
328
  };
306
329
  prefix: string;
307
- /** Todos os scopes oferecidos, `id → descrição`. */
330
+ /** Os scopes oferecidos, `id → descrição`. */
308
331
  scopes: Record<string, string>;
309
- /** Só os próprios do app (o `custom_scopes`). */
310
- customScopes: Record<string, string>;
332
+ scopeHints: Record<string, PoppyScopeHint>;
311
333
  signIn: {
312
334
  direct: {
313
335
  scopes: string[];
@@ -321,9 +343,16 @@ export interface ResolvedPoppyConfig {
321
343
  protocols: PoppyAgentProtocolEntry[];
322
344
  } | null;
323
345
  apis: PoppyApiEntry[];
346
+ feedback: {
347
+ endpoint: string;
348
+ } | null;
349
+ excludedTasks: {
350
+ url: string;
351
+ } | null;
324
352
  web: {
325
353
  browserSession: boolean;
326
354
  login?: PoppyBrowserLogin;
355
+ redirectTo: string;
327
356
  } | null;
328
357
  extensions: Record<string, {
329
358
  version: string;
@@ -338,14 +367,18 @@ export interface ResolvedPoppyConfig {
338
367
  };
339
368
  /** Dev/teste: `client_id` http e busca sem guarda de SSRF (ver o input). */
340
369
  allowInsecureClientIds: boolean;
341
- sessionTokenTtl: number;
342
- accountTokenTtl: number;
370
+ accessTokenTtl: number;
371
+ refreshTokenTtl: number;
343
372
  sessionTtl: number;
344
373
  authorizationCodeTtl: number;
345
374
  deviceCodeTtl: number;
346
375
  pollInterval: number;
347
376
  assertionMaxLifetime: number;
377
+ sessionJwt: {
378
+ maxAge: number;
379
+ };
348
380
  dpop: {
381
+ required: boolean;
349
382
  requireNonce: boolean;
350
383
  maxAge: number;
351
384
  algorithms: string[];
@@ -359,7 +392,5 @@ export interface ResolvedPoppyConfig {
359
392
  } | PoppyLimiter;
360
393
  toActor?: PoppyConfigInput['toActor'];
361
394
  }
362
- /** `www.example.com` → `example.com`, minúsculo. */
363
- export declare function stripWww(host: string): string;
364
395
  export declare function normalizePoppyPrefix(prefix: string | undefined): string;
365
396
  export declare function resolvePoppyConfig(input: PoppyConfigInput | undefined, fallbackScopes: Record<string, string> | undefined): ResolvedPoppyConfig | undefined;