@adonis-agora/authkit-server 0.85.1 → 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.
- package/README.md +2 -2
- package/build/index.d.ts +1 -2
- package/build/index.js +0 -1
- package/build/src/agents/config.d.ts +1 -1
- package/build/src/agents/delegation_service.js +1 -1
- package/build/src/agents/poppy/client_registry.d.ts +5 -0
- package/build/src/agents/poppy/client_registry.js +35 -1
- package/build/src/agents/poppy/config.d.ts +111 -80
- package/build/src/agents/poppy/config.js +55 -35
- package/build/src/agents/poppy/dpop.d.ts +2 -2
- package/build/src/agents/poppy/dpop.js +3 -3
- package/build/src/agents/poppy/email_code_sign_in.d.ts +4 -4
- package/build/src/agents/poppy/email_code_sign_in.js +5 -5
- package/build/src/agents/poppy/errors.d.ts +7 -2
- package/build/src/agents/poppy/errors.js +5 -2
- package/build/src/agents/poppy/resource.d.ts +30 -25
- package/build/src/agents/poppy/resource.js +24 -20
- package/build/src/agents/poppy/safe_fetch.js +8 -2
- package/build/src/agents/poppy/service.d.ts +69 -62
- package/build/src/agents/poppy/service.js +540 -546
- package/build/src/agents/poppy/session_jwt.d.ts +30 -0
- package/build/src/agents/poppy/session_jwt.js +133 -0
- package/build/src/agents/poppy/store.d.ts +17 -22
- package/build/src/agents/poppy/store.js +22 -30
- package/build/src/agents/poppy/web_session.d.ts +23 -16
- package/build/src/agents/poppy/web_session.js +42 -24
- package/build/src/host/admin_sessions_service.js +3 -3
- package/build/src/host/controllers/account_apps_controller.js +1 -1
- package/build/src/host/controllers/poppy_consent_controller.d.ts +2 -2
- package/build/src/host/controllers/poppy_consent_controller.js +2 -2
- package/build/src/host/controllers/poppy_controller.d.ts +19 -11
- package/build/src/host/controllers/poppy_controller.js +93 -68
- package/build/src/host/csrf.d.ts +2 -4
- package/build/src/host/csrf.js +2 -3
- package/build/src/host/register_auth_host.d.ts +53 -0
- package/build/src/host/register_auth_host.js +66 -22
- package/build/src/schema/ensure.js +14 -9
- 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,
|
|
21
|
-
⚠️ **Experimental** — tracks the spec's Draft 0.
|
|
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.
|
|
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 (
|
|
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.
|
|
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.
|
|
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
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
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
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
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 (
|
|
21
|
+
/** Um campo de credencial do Mediated Sign-In (extensão Mediated Sign-In). */
|
|
29
22
|
export interface PoppyMediatedField {
|
|
30
|
-
/**
|
|
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 —
|
|
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
|
|
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 `
|
|
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.
|
|
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 (
|
|
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
|
|
88
|
-
scopes
|
|
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 `
|
|
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, §
|
|
99
|
+
/** Uma entrada de `agent.protocols` (§3.1, §8.1). */
|
|
108
100
|
export interface PoppyAgentProtocolEntry {
|
|
109
|
-
/** `'poppy'` para as conversas deste protocolo (§
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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 (§
|
|
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
|
|
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 (
|
|
135
|
-
* provas DPoP
|
|
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.
|
|
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`)
|
|
152
|
-
*
|
|
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.
|
|
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
|
|
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 `
|
|
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
|
|
177
|
-
* Default: os de `personalAgents.delegation.scopes`, quando houver — um
|
|
178
|
-
*
|
|
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
|
-
/**
|
|
182
|
-
|
|
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 (§
|
|
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
|
|
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 (§
|
|
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
|
|
227
|
-
|
|
228
|
-
/** Vida do
|
|
229
|
-
|
|
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
|
|
248
|
+
/** Vida máxima das client assertions (`exp - iat`), em segundos. Default: 300. */
|
|
239
249
|
assertionMaxLifetime?: number;
|
|
240
|
-
/**
|
|
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,
|
|
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
|
-
/**
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
|
|
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
|
-
/**
|
|
330
|
+
/** Os scopes oferecidos, `id → descrição`. */
|
|
308
331
|
scopes: Record<string, string>;
|
|
309
|
-
|
|
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
|
-
|
|
342
|
-
|
|
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;
|