melchizedek-agents 1.2.0 → 1.3.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/.env.example +9 -0
- package/CHANGELOG.md +141 -0
- package/DOCUMENTATION.md +107 -10
- package/ONBOARDING.md +50 -11
- package/QUICKSTART.md +1 -1
- package/README.md +22 -2
- package/config/agents/examples/connectors.yaml +82 -0
- package/config/agents/syndicate.schema.json +324 -26
- package/dist/lib/a2a/app.js +3 -0
- package/dist/lib/a2a/oauthSetup.js +20 -5
- package/dist/lib/chatgpt/adapter.d.ts +50 -0
- package/dist/lib/chatgpt/adapter.js +107 -0
- package/dist/lib/chatgpt/cli.d.ts +23 -0
- package/dist/lib/chatgpt/cli.js +77 -0
- package/dist/lib/chatgpt/oauth.d.ts +103 -0
- package/dist/lib/chatgpt/oauth.js +448 -0
- package/dist/lib/chatgpt/state.d.ts +98 -0
- package/dist/lib/chatgpt/state.js +145 -0
- package/dist/lib/chatgpt/store.d.ts +24 -0
- package/dist/lib/chatgpt/store.js +94 -0
- package/dist/lib/compile.js +40 -25
- package/dist/lib/dispatch.js +6 -2
- package/dist/lib/doctor.d.ts +34 -3
- package/dist/lib/doctor.js +63 -5
- package/dist/lib/loadSyndicate.d.ts +6 -0
- package/dist/lib/mcp/server.d.ts +195 -0
- package/dist/lib/mcp/server.js +564 -0
- package/dist/lib/memory/supabaseMemoryService.js +2 -2
- package/dist/lib/models/adapterResolver.js +6 -1
- package/dist/lib/models/gateway.d.ts +1 -1
- package/dist/lib/models/gateway.js +4 -2
- package/dist/lib/onboarding.d.ts +4 -3
- package/dist/lib/onboarding.js +48 -9
- package/dist/lib/runtime/syndicateTurn.js +30 -16
- package/dist/lib/syndicateSchema.d.ts +146 -8
- package/dist/lib/syndicateSchema.js +118 -11
- package/dist/lib/tools/credentialUses.d.ts +7 -1
- package/dist/lib/tools/credentialUses.js +10 -2
- package/dist/lib/tools/generateImageTool.js +2 -1
- package/dist/lib/tools/inspectImageTool.js +1 -1
- package/dist/lib/tools/mcpToolFactory.d.ts +29 -1
- package/dist/lib/tools/mcpToolFactory.js +71 -25
- package/dist/lib/tools/mcpTransports.d.ts +12 -0
- package/dist/lib/tools/mcpTransports.js +11 -0
- package/dist/lib/tools/oauthConsent.d.ts +18 -3
- package/dist/lib/tools/oauthConsent.js +49 -14
- package/dist/lib/tools/oauthDiscovery.d.ts +202 -0
- package/dist/lib/tools/oauthDiscovery.js +616 -0
- package/dist/lib/tools/oauthTools.d.ts +44 -12
- package/dist/lib/tools/oauthTools.js +79 -22
- package/dist/lib/tools/xApiSearchTool.js +2 -2
- package/dist/scripts/a2a_server.js +8 -0
- package/dist/scripts/assistant_worker.js +11 -1
- package/dist/scripts/doctor.d.ts +1 -1
- package/dist/scripts/doctor.js +1 -1
- package/dist/scripts/mcp_server.d.ts +12 -0
- package/dist/scripts/mcp_server.js +345 -0
- package/dist/scripts/setup.d.ts +2 -0
- package/dist/scripts/setup.js +27 -0
- package/dist/scripts/syndicate_chat.js +12 -3
- package/package.json +5 -2
- package/skills/README.md +2 -2
- package/skills/briefs/skills-readme.md +1 -1
- package/skills/melchizedek-onboard/SKILL.md +28 -6
- package/skills/melchizedek-onboard-keys/SKILL.md +17 -5
|
@@ -85,7 +85,9 @@ export class ConsentError extends Error {
|
|
|
85
85
|
? `The authorization at ${p} could not be completed.`
|
|
86
86
|
: code === 'store_failed'
|
|
87
87
|
? `The authorization at ${p} could not be saved.`
|
|
88
|
-
:
|
|
88
|
+
: code === 'registration_failed'
|
|
89
|
+
? `The authorization at ${p} could not be set up.`
|
|
90
|
+
: `No OAuth client is configured for ${p}.`);
|
|
89
91
|
this.name = 'ConsentError';
|
|
90
92
|
this.code = code;
|
|
91
93
|
if (provider !== undefined)
|
|
@@ -120,7 +122,21 @@ function checkEndpoint(value, what) {
|
|
|
120
122
|
throw new Error(`${what} must not carry credentials.`);
|
|
121
123
|
return url;
|
|
122
124
|
}
|
|
123
|
-
const RESERVED_PARAMS = new Set(['state', 'redirect_uri', 'code_challenge', 'code_challenge_method', 'client_id', 'response_type', 'scope']);
|
|
125
|
+
const RESERVED_PARAMS = new Set(['state', 'redirect_uri', 'code_challenge', 'code_challenge_method', 'client_id', 'response_type', 'scope', 'resource']);
|
|
126
|
+
/** A client's configuration, checked: the endpoints, the client id, the parameters. Throws, naming the provider. */
|
|
127
|
+
function checkClient(name, client) {
|
|
128
|
+
checkEndpoint(client.authorizationUrl, `${name}: authorizationUrl`);
|
|
129
|
+
checkEndpoint(client.tokenUrl, `${name}: tokenUrl`);
|
|
130
|
+
if (typeof client.clientId !== 'string' || !client.clientId)
|
|
131
|
+
throw new Error(`${name}: clientId is required.`);
|
|
132
|
+
for (const key of Object.keys(client.authorizationParams ?? {})) {
|
|
133
|
+
if (RESERVED_PARAMS.has(key))
|
|
134
|
+
throw new Error(`${name}: authorizationParams may not set "${key}".`);
|
|
135
|
+
}
|
|
136
|
+
if (client.resource !== undefined)
|
|
137
|
+
checkEndpoint(client.resource, `${name}: resource`);
|
|
138
|
+
return { ...client, scopes: [...(client.scopes ?? [])] };
|
|
139
|
+
}
|
|
124
140
|
/** The consent manager over a credential store. Validates the configuration at once: a bad URL throws here, at boot. */
|
|
125
141
|
export function oauthConsent(options) {
|
|
126
142
|
const redirect = checkEndpoint(options.redirectUri, 'The OAuth redirect URI');
|
|
@@ -130,16 +146,23 @@ export function oauthConsent(options) {
|
|
|
130
146
|
for (const [name, client] of Object.entries(options.providers)) {
|
|
131
147
|
if (!PROVIDER_NAME.test(name))
|
|
132
148
|
throw new Error(`OAuth provider "${name.slice(0, 64)}" must match ${PROVIDER_NAME}.`);
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (typeof client.clientId !== 'string' || !client.clientId)
|
|
136
|
-
throw new Error(`${name}: clientId is required.`);
|
|
137
|
-
for (const key of Object.keys(client.authorizationParams ?? {})) {
|
|
138
|
-
if (RESERVED_PARAMS.has(key))
|
|
139
|
-
throw new Error(`${name}: authorizationParams may not set "${key}".`);
|
|
140
|
-
}
|
|
141
|
-
providers.set(name, { ...client, scopes: [...(client.scopes ?? [])] });
|
|
149
|
+
// A source is checked each time it answers; a configured client here, at boot.
|
|
150
|
+
providers.set(name, typeof client === 'function' ? client : checkClient(name, client));
|
|
142
151
|
}
|
|
152
|
+
/** The provider's client now, or undefined; a source that fails is a ConsentError('registration_failed'). */
|
|
153
|
+
const clientOf = async (name) => {
|
|
154
|
+
const entry = providers.get(name);
|
|
155
|
+
if (typeof entry !== 'function')
|
|
156
|
+
return entry;
|
|
157
|
+
try {
|
|
158
|
+
return checkClient(name, await entry());
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
// A discovery refusal names roles and hosts, never a value (lib/tools/oauthDiscovery.ts); anything else is named by kind only.
|
|
162
|
+
console.warn(`[OAuth] ${name}: the client could not be set up: ${err instanceof Error && err.name === 'OAuthDiscoveryError' ? err.message : err instanceof Error ? err.name : 'unknown error'}`);
|
|
163
|
+
throw new ConsentError('registration_failed', name);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
143
166
|
const states = options.states ?? memoryConsentStates({ ...(options.now ? { now: options.now } : {}) });
|
|
144
167
|
const ttlMs = options.ttlMs ?? 10 * 60_000;
|
|
145
168
|
const now = options.now ?? Date.now;
|
|
@@ -193,6 +216,8 @@ export function oauthConsent(options) {
|
|
|
193
216
|
client_id: client.clientId,
|
|
194
217
|
code_verifier: flow.codeVerifier,
|
|
195
218
|
});
|
|
219
|
+
if (client.resource)
|
|
220
|
+
body.set('resource', client.resource);
|
|
196
221
|
if (client.clientSecret) {
|
|
197
222
|
// The secret goes only to a host the operator binds its variable to (ADR 0122), checked now:
|
|
198
223
|
// the allowlist can change after boot. Refused, nothing is sent.
|
|
@@ -238,9 +263,9 @@ export function oauthConsent(options) {
|
|
|
238
263
|
redirectUri: options.redirectUri,
|
|
239
264
|
has: (provider) => typeof provider === 'string' && providers.has(provider),
|
|
240
265
|
async begin(binding) {
|
|
241
|
-
|
|
242
|
-
if (!client)
|
|
266
|
+
if (!providers.has(binding.provider))
|
|
243
267
|
throw new ConsentError('unknown_provider', PROVIDER_NAME.test(binding.provider) ? binding.provider : undefined);
|
|
268
|
+
const client = (await clientOf(binding.provider));
|
|
244
269
|
for (const field of ['appName', 'userId', 'sessionId', 'functionCallId']) {
|
|
245
270
|
if (typeof binding[field] !== 'string' || !binding[field])
|
|
246
271
|
throw new Error(`A consent flow needs the paused call's ${field}.`);
|
|
@@ -269,6 +294,8 @@ export function oauthConsent(options) {
|
|
|
269
294
|
url.searchParams.set('state', state);
|
|
270
295
|
url.searchParams.set('code_challenge', s256Challenge(codeVerifier));
|
|
271
296
|
url.searchParams.set('code_challenge_method', 'S256');
|
|
297
|
+
if (client.resource)
|
|
298
|
+
url.searchParams.set('resource', client.resource);
|
|
272
299
|
const authUri = url.toString();
|
|
273
300
|
const authConfig = {
|
|
274
301
|
credentialKey: binding.provider,
|
|
@@ -314,7 +341,15 @@ export function oauthConsent(options) {
|
|
|
314
341
|
const code = input.code;
|
|
315
342
|
if (typeof code !== 'string' || !CODE_FORMAT.test(code))
|
|
316
343
|
fail('invalid_request');
|
|
317
|
-
|
|
344
|
+
if (!providers.has(flow.provider))
|
|
345
|
+
fail('unknown_provider');
|
|
346
|
+
let client;
|
|
347
|
+
try {
|
|
348
|
+
client = await clientOf(flow.provider);
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
return fail('registration_failed');
|
|
352
|
+
}
|
|
318
353
|
if (!client)
|
|
319
354
|
fail('unknown_provider');
|
|
320
355
|
let tokens;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/tools/oauthDiscovery.ts — an MCP server's authorization server,
|
|
3
|
+
* discovered, and this deployment registered at it as an OAuth client
|
|
4
|
+
* (ADR 0124).
|
|
5
|
+
*
|
|
6
|
+
* WHY this file exists:
|
|
7
|
+
* The official remote MCP servers (an issue tracker's, a wiki's, a code
|
|
8
|
+
* host's) take each user's own OAuth token, and most issue no client id in
|
|
9
|
+
* advance: the MCP authorization spec has a client find the authorization
|
|
10
|
+
* server from the MCP server (protected-resource metadata, RFC 9728; then
|
|
11
|
+
* authorization-server metadata, RFC 8414 or OpenID discovery) and register
|
|
12
|
+
* itself (dynamic client registration, RFC 7591). A YAML says so with
|
|
13
|
+
* `client_registration: dynamic` on the server's `oauth2` grant; this module
|
|
14
|
+
* does the discovery and the registration, and keeps the registered client.
|
|
15
|
+
*
|
|
16
|
+
* WHAT IT GUARANTEES:
|
|
17
|
+
* - The MCP server is asked first, as the MCP authorization spec has a
|
|
18
|
+
* client do: an unauthenticated initialize request, and on a 401 the
|
|
19
|
+
* Bearer challenge's `resource_metadata` (and `scope`) parameters in its
|
|
20
|
+
* WWW-Authenticate header (RFC 9728 5.1). The URL it names is read first;
|
|
21
|
+
* the well-known URLs are the fallback. The header is read by a linear,
|
|
22
|
+
* length-bounded tokenizer (no regular expression), and never logged.
|
|
23
|
+
* - Discovery never widens the operator's OAuth host allowlist (ADR 0114):
|
|
24
|
+
* every URL it fetches (the MCP server's challenge, the metadata
|
|
25
|
+
* documents, including one the header names, the registration
|
|
26
|
+
* endpoint) and every endpoint it returns (authorization, token) must be
|
|
27
|
+
* a host the allowlist binds to the provider, checked before the request
|
|
28
|
+
* and again whenever the client is used. A discovered host outside it is
|
|
29
|
+
* refused by name, not skipped.
|
|
30
|
+
* - Every request passes the transport rule (https, or http to a loopback
|
|
31
|
+
* host) and the SSRF guard (lib/net/addressGuard.ts) unless private hosts
|
|
32
|
+
* are allowed (ALLOW_PRIVATE_MCP), follows no redirect, has a time limit,
|
|
33
|
+
* and reads a bounded JSON body.
|
|
34
|
+
* - The authorization server must advertise PKCE S256; one that does not is
|
|
35
|
+
* refused (MCP authorization spec). The client registers as a public
|
|
36
|
+
* client (`token_endpoint_auth_method: none`) for the one configured
|
|
37
|
+
* redirect URI, with the authorization_code and refresh_token grants.
|
|
38
|
+
* - The registered client is kept per provider, MCP server and redirect URI
|
|
39
|
+
* in the credential store's rows, sealed by its cipher
|
|
40
|
+
* (MELCHIZEDEK_CREDENTIAL_KEY), under an app name no run can have (it
|
|
41
|
+
* carries `:`, which a memory namespace cannot), so no tool call can read
|
|
42
|
+
* it as a token. A row this key cannot open, an expired client secret, or
|
|
43
|
+
* endpoints that moved are registered again.
|
|
44
|
+
* - No client secret, metadata body or server error text reaches a log
|
|
45
|
+
* line, an error message or a result: refusals name roles and hosts.
|
|
46
|
+
*/
|
|
47
|
+
import type { CredentialKey } from './auth.ts';
|
|
48
|
+
import type { CredentialCipher } from './credentialCipher.ts';
|
|
49
|
+
import type { CredentialRows } from './credentialStore.ts';
|
|
50
|
+
import type { OAuthHostAllowlist } from './oauthHosts.ts';
|
|
51
|
+
import type { OAuthClientSource } from './oauthConsent.ts';
|
|
52
|
+
/** A discovery or registration that cannot proceed. The message names roles and hosts, never a value. */
|
|
53
|
+
export declare class OAuthDiscoveryError extends Error {
|
|
54
|
+
readonly provider: string;
|
|
55
|
+
constructor(provider: string, message: string);
|
|
56
|
+
}
|
|
57
|
+
/** What discovery found: the MCP server as a resource, and its authorization server's endpoints. */
|
|
58
|
+
export interface DiscoveredAuthorization {
|
|
59
|
+
/** The MCP server's canonical URI, sent as the RFC 8707 `resource` parameter. */
|
|
60
|
+
resource: string;
|
|
61
|
+
/** The authorization server's issuer identifier. */
|
|
62
|
+
issuer: string;
|
|
63
|
+
authorizationEndpoint: string;
|
|
64
|
+
tokenEndpoint: string;
|
|
65
|
+
registrationEndpoint: string;
|
|
66
|
+
/**
|
|
67
|
+
* The scopes the MCP server's 401 challenge named (its `scope` parameter),
|
|
68
|
+
* when it named any: the MCP spec's first choice when the grant names none.
|
|
69
|
+
*/
|
|
70
|
+
challengeScopes?: string[];
|
|
71
|
+
}
|
|
72
|
+
export interface DiscoveryOptions {
|
|
73
|
+
/** The provider the grant names: the allowlist is read for it. */
|
|
74
|
+
provider: string;
|
|
75
|
+
/** Private and loopback hosts pass the SSRF guard (ALLOW_PRIVATE_MCP). The allowlist still applies. */
|
|
76
|
+
allowPrivate?: boolean;
|
|
77
|
+
/** The allowlist; default the one in force (`null`: none configured, which refuses). */
|
|
78
|
+
allowlist?: OAuthHostAllowlist | null;
|
|
79
|
+
/** Each request's time limit, ms. Default 10 s. */
|
|
80
|
+
timeoutMs?: number;
|
|
81
|
+
/** For tests. */
|
|
82
|
+
fetch?: typeof fetch;
|
|
83
|
+
}
|
|
84
|
+
/** The MCP server's canonical URI (RFC 8707, MCP authorization spec): no fragment, no trailing slash on a path. */
|
|
85
|
+
export declare function canonicalResource(serverUrl: string): string;
|
|
86
|
+
/** A WWW-Authenticate header longer than this is ignored whole. */
|
|
87
|
+
export declare const MAX_CHALLENGE_HEADER: number;
|
|
88
|
+
/** What a Bearer challenge tells a client that has no token yet. */
|
|
89
|
+
export interface BearerChallenge {
|
|
90
|
+
/** The `resource_metadata` parameter: the protected-resource metadata URL (RFC 9728 5.1), unparsed. */
|
|
91
|
+
resourceMetadata?: string;
|
|
92
|
+
/** The `scope` parameter, split, each a valid scope token (RFC 6750 3). */
|
|
93
|
+
scopes?: string[];
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The first Bearer challenge's parameters in a WWW-Authenticate header, or
|
|
97
|
+
* undefined (no Bearer challenge, or a header that is too long or malformed:
|
|
98
|
+
* either is ignored whole, and discovery falls back to the well-known URLs).
|
|
99
|
+
* One pass over the header, each step advancing: linear in its length, with
|
|
100
|
+
* no regular expression. Several challenges in one header, quoted-string
|
|
101
|
+
* values with escapes, case-insensitive scheme and parameter names, and a
|
|
102
|
+
* token68 credential on another scheme are understood. A parameter given
|
|
103
|
+
* twice in the Bearer challenge makes it ambiguous, and malformed.
|
|
104
|
+
*/
|
|
105
|
+
export declare function parseBearerChallenge(header: string | null | undefined): BearerChallenge | undefined;
|
|
106
|
+
/** RFC 9728 3.1: the protected-resource metadata URLs for a server, path-specific first. */
|
|
107
|
+
export declare function protectedResourceMetadataUrls(serverUrl: string): URL[];
|
|
108
|
+
/** RFC 8414 3.1 and OpenID discovery, in the order the MCP authorization spec gives. */
|
|
109
|
+
export declare function authorizationServerMetadataUrls(issuer: string): URL[];
|
|
110
|
+
/**
|
|
111
|
+
* The MCP server's authorization server, as the MCP authorization spec finds
|
|
112
|
+
* it: the protected-resource metadata URL named by the server's 401 challenge
|
|
113
|
+
* (WWW-Authenticate, RFC 9728 5.1), then the well-known URLs (RFC 9728 3.1);
|
|
114
|
+
* the metadata names the authorization server (a server with none is its
|
|
115
|
+
* own, as the 2025-03-26 revision had it), and its own metadata (RFC 8414, or
|
|
116
|
+
* OpenID discovery) names the endpoints. Every host involved, the one the
|
|
117
|
+
* header names included, passes the provider's allowlist before any request;
|
|
118
|
+
* PKCE S256 and a registration endpoint are required. Throws
|
|
119
|
+
* OAuthDiscoveryError.
|
|
120
|
+
*/
|
|
121
|
+
export declare function discoverAuthorization(serverUrl: string, options: DiscoveryOptions): Promise<DiscoveredAuthorization>;
|
|
122
|
+
/** A client this deployment registered at an authorization server. */
|
|
123
|
+
export interface RegisteredClient {
|
|
124
|
+
clientId: string;
|
|
125
|
+
/** A confidential client's secret, when the server issued one anyway. */
|
|
126
|
+
clientSecret?: string;
|
|
127
|
+
/** Epoch ms after which the secret stops working; absent when it does not expire. */
|
|
128
|
+
secretExpiresAt?: number;
|
|
129
|
+
}
|
|
130
|
+
export interface RegistrationOptions extends DiscoveryOptions {
|
|
131
|
+
/** The consent callback, exactly as every authorization will send it. */
|
|
132
|
+
redirectUri: string;
|
|
133
|
+
/** Shown to the person on the provider's consent screen. Default "Melchizedek agents". */
|
|
134
|
+
clientName?: string;
|
|
135
|
+
scopes?: string[];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Registers this deployment at the authorization server (RFC 7591) as a
|
|
139
|
+
* public PKCE client for the one redirect URI. Throws OAuthDiscoveryError,
|
|
140
|
+
* never the server's text.
|
|
141
|
+
*/
|
|
142
|
+
export declare function registerOAuthClient(discovered: DiscoveredAuthorization, options: RegistrationOptions): Promise<RegisteredClient>;
|
|
143
|
+
/**
|
|
144
|
+
* The app name registered clients are filed under. It carries `:`, which a
|
|
145
|
+
* memory namespace (the app a run pins, `[A-Za-z0-9._-]`) cannot, so no
|
|
146
|
+
* run's credential key ever reaches one of these rows.
|
|
147
|
+
*/
|
|
148
|
+
export declare const REGISTERED_CLIENTS_APP = "oauth-client:dcr";
|
|
149
|
+
/** The row a provider's registered client is kept in: one per MCP server (resource) and redirect URI. */
|
|
150
|
+
export declare function registeredClientKey(provider: string, resource: string, redirectUri: string): CredentialKey;
|
|
151
|
+
/** What a sealed registration holds. */
|
|
152
|
+
interface StoredRegistration {
|
|
153
|
+
v: 1;
|
|
154
|
+
clientId: string;
|
|
155
|
+
clientSecret?: string;
|
|
156
|
+
issuer: string;
|
|
157
|
+
authorizationEndpoint: string;
|
|
158
|
+
tokenEndpoint: string;
|
|
159
|
+
resource: string;
|
|
160
|
+
redirectUri: string;
|
|
161
|
+
}
|
|
162
|
+
export interface OAuthClientRegistry {
|
|
163
|
+
/** The registration kept for this key, or undefined (none, unreadable under this key, or its secret expired). */
|
|
164
|
+
get(key: CredentialKey): Promise<(StoredRegistration & {
|
|
165
|
+
secretExpiresAt?: number;
|
|
166
|
+
}) | undefined>;
|
|
167
|
+
put(key: CredentialKey, registration: Omit<StoredRegistration, 'v'>, secretExpiresAt?: number): Promise<void>;
|
|
168
|
+
}
|
|
169
|
+
/** Registered clients over the credential store's rows, sealed by its cipher (the same key as every user's tokens). */
|
|
170
|
+
export declare function oauthClientRegistry(options: {
|
|
171
|
+
rows: CredentialRows;
|
|
172
|
+
cipher: CredentialCipher;
|
|
173
|
+
now?: () => number;
|
|
174
|
+
}): OAuthClientRegistry;
|
|
175
|
+
/** A dynamic grant as a served YAML declares it (lib/tools/oauthTools.ts dynamicOAuthGrantsFor). */
|
|
176
|
+
export interface DynamicOAuthGrant {
|
|
177
|
+
provider: string;
|
|
178
|
+
/** The MCP server the grant is for. */
|
|
179
|
+
server: string;
|
|
180
|
+
scopes: string[];
|
|
181
|
+
authorizationParams?: Record<string, string>;
|
|
182
|
+
}
|
|
183
|
+
export interface DynamicClientOptions {
|
|
184
|
+
/** The consent callback, as configured (OAUTH_REDIRECT_URI). */
|
|
185
|
+
redirectUri: string;
|
|
186
|
+
/** Where registrations are kept; without one, each process registers once in memory. */
|
|
187
|
+
registry?: OAuthClientRegistry;
|
|
188
|
+
allowPrivate?: boolean;
|
|
189
|
+
clientName?: string;
|
|
190
|
+
timeoutMs?: number;
|
|
191
|
+
fetch?: typeof fetch;
|
|
192
|
+
/** For tests. */
|
|
193
|
+
allowlist?: OAuthHostAllowlist | null;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* The consent step's client for a dynamic grant (oauthConsent and
|
|
197
|
+
* oauthRefreshProviders take it in place of a fixed config): discovered and
|
|
198
|
+
* registered on first use, kept, and re-checked against the allowlist in
|
|
199
|
+
* force on every use. A failure is not cached; the next use tries again.
|
|
200
|
+
*/
|
|
201
|
+
export declare function dynamicOAuthClient(grant: DynamicOAuthGrant, options: DynamicClientOptions): OAuthClientSource;
|
|
202
|
+
export {};
|