@every-app/sdk 0.3.0-rc.10 → 0.3.0-rc.11
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 +62 -64
- package/dist/cloudflare/catalogSettings.generated.d.ts +7 -4
- package/dist/cloudflare/catalogSettings.generated.d.ts.map +1 -1
- package/dist/cloudflare/catalogSettings.generated.js +7 -6
- package/dist/cloudflare/index.d.ts +1 -1
- package/dist/cloudflare/index.d.ts.map +1 -1
- package/dist/cloudflare/worker.d.ts +35 -1
- package/dist/cloudflare/worker.d.ts.map +1 -1
- package/dist/cloudflare/worker.js +31 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/internal/aiDefault.d.ts +4 -3
- package/dist/internal/aiDefault.d.ts.map +1 -1
- package/dist/internal/aiDefault.js +6 -5
- package/dist/internal/aiProviders.d.ts.map +1 -1
- package/dist/internal/aiProviders.js +2 -2
- package/dist/internal/capabilities.d.ts +97 -481
- package/dist/internal/capabilities.d.ts.map +1 -1
- package/dist/internal/capabilities.js +47 -548
- package/dist/internal/catalog/index.d.ts +35 -0
- package/dist/internal/catalog/index.d.ts.map +1 -1
- package/dist/internal/catalog/infra.d.ts +35 -0
- package/dist/internal/catalog/infra.d.ts.map +1 -1
- package/dist/internal/catalog/infra.js +65 -0
- package/dist/internal/events.d.ts +52 -1
- package/dist/internal/events.d.ts.map +1 -1
- package/dist/internal/events.js +65 -3
- package/dist/internal/oauthBuiltIns.d.ts +101 -0
- package/dist/internal/oauthBuiltIns.d.ts.map +1 -0
- package/dist/internal/oauthBuiltIns.js +122 -0
- package/dist/internal/oauthClient.d.ts +7 -47
- package/dist/internal/oauthClient.d.ts.map +1 -1
- package/dist/internal/oauthClient.js +1 -115
- package/dist/internal/oauthPresets.d.ts +14 -15
- package/dist/internal/oauthPresets.d.ts.map +1 -1
- package/dist/internal/oauthPresets.js +42 -853
- package/dist/internal/oauthScopes.d.ts +43 -155
- package/dist/internal/oauthScopes.d.ts.map +1 -1
- package/dist/internal/oauthScopes.js +82 -475
- package/dist/internal/oauthSpec.d.ts +72 -71
- package/dist/internal/oauthSpec.d.ts.map +1 -1
- package/dist/internal/oauthSpec.js +178 -447
- package/dist/internal/protocol.d.ts +42 -13
- package/dist/internal/protocol.d.ts.map +1 -1
- package/dist/internal/protocol.js +45 -7
- package/dist/internal/providerRegistry.d.ts +1 -61
- package/dist/internal/providerRegistry.d.ts.map +1 -1
- package/dist/internal/providerRegistry.js +8 -115
- package/dist/internal/providerSpec.d.ts.map +1 -1
- package/dist/internal/providerSpec.js +14 -36
- package/dist/internal/remoteMcp.d.ts.map +1 -1
- package/dist/internal/remoteMcp.js +1 -5
- package/dist/internal/tools.d.ts +5 -4
- package/dist/internal/tools.d.ts.map +1 -1
- package/dist/internal/tools.js +4 -3
- package/dist/manifest.d.ts +34 -5
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +1 -1
- package/dist/server/attribution.d.ts +9 -0
- package/dist/server/attribution.d.ts.map +1 -1
- package/dist/server/attribution.js +7 -1
- package/dist/server/connectUrl.d.ts +4 -9
- package/dist/server/connectUrl.d.ts.map +1 -1
- package/dist/server/connectUrl.js +17 -14
- package/dist/server/eventsEndpoint.d.ts +48 -0
- package/dist/server/eventsEndpoint.d.ts.map +1 -0
- package/dist/server/eventsEndpoint.js +145 -0
- package/dist/server/everyApp.d.ts +15 -6
- package/dist/server/everyApp.d.ts.map +1 -1
- package/dist/server/everyApp.js +12 -3
- package/dist/server/index.d.ts +4 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/integrationFetch.d.ts +59 -71
- package/dist/server/integrationFetch.d.ts.map +1 -1
- package/dist/server/integrationFetch.js +117 -392
- package/dist/server/tools.d.ts +7 -2
- package/dist/server/tools.d.ts.map +1 -1
- package/dist/server/tools.js +2 -1
- package/dist/server/toolsEndpoint.d.ts +3 -1
- package/dist/server/toolsEndpoint.d.ts.map +1 -1
- package/dist/server/toolsEndpoint.js +9 -3
- package/dist/server/webhooks.d.ts +56 -0
- package/dist/server/webhooks.d.ts.map +1 -0
- package/dist/server/webhooks.js +205 -0
- package/package.json +1 -1
- package/dist/server/authorizeUrl.d.ts +0 -43
- package/dist/server/authorizeUrl.d.ts.map +0 -1
- package/dist/server/authorizeUrl.js +0 -106
|
@@ -40,16 +40,14 @@ export declare const GATEWAY_ERROR_HEADER = "x-everyapp-error";
|
|
|
40
40
|
*/
|
|
41
41
|
export declare const ORG_HEADER = "x-everyapp-org";
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* `
|
|
48
|
-
*
|
|
43
|
+
* On background work's call to an OAuth provider's API: the member whose
|
|
44
|
+
* connection to this app the call uses. Set by `for: { background: true,
|
|
45
|
+
* userId }`; the gateway reads it on the held-token branch only, for an
|
|
46
|
+
* organization's own app, and the perimeter strips it, with every
|
|
47
|
+
* `x-everyapp-*`, from browsers. It addresses a connection; it is not a
|
|
48
|
+
* permission: connecting in the app already lets the app use it.
|
|
49
49
|
*/
|
|
50
|
-
export declare const
|
|
51
|
-
/** The values {@link ACCOUNT_HEADER} may carry. */
|
|
52
|
-
export type ConnectionAccount = "user" | "organization";
|
|
50
|
+
export declare const USER_HEADER = "x-everyapp-user";
|
|
53
51
|
/** 120-second lifetime — caps revocation staleness while surviving clock skew. */
|
|
54
52
|
export declare const IDENTITY_TTL_SECONDS = 120;
|
|
55
53
|
/** System tokens are minted per call and live at most a minute. */
|
|
@@ -105,9 +103,17 @@ export declare const LINKED_DEV_HEADER = "x-everyapp-linked-dev";
|
|
|
105
103
|
/** Where the gateway-lite serves the forwarder, under the app's own host. */
|
|
106
104
|
export declare const LINKED_DEV_FORWARD_PATH = "/__everyapp/gateway";
|
|
107
105
|
export type IdentityChannel = "web" | "api" | "mcp" | "agent";
|
|
106
|
+
/**
|
|
107
|
+
* The channels a tool call arrives on: `mcp` for an AI client's MCP
|
|
108
|
+
* connection, `agent` for an agent principal the Gateway runs a call for.
|
|
109
|
+
* Only the ToolBus mints either with a `tc` claim.
|
|
110
|
+
*/
|
|
111
|
+
export declare const TOOL_CALL_CHANNELS: readonly IdentityChannel[];
|
|
112
|
+
/** `act.sub` of an agent principal: `agent:<agt_id>`; `sub` stays its sponsor. */
|
|
113
|
+
export declare const AGENT_ACTOR_PREFIX = "agent:";
|
|
108
114
|
export type IdentityTokenType = "user" | "public" | "system";
|
|
109
115
|
/** What a system token may open. One purpose per token. */
|
|
110
|
-
export type SystemTokenPurpose = "tools.list";
|
|
116
|
+
export type SystemTokenPurpose = "tools.list" | "events.deliver";
|
|
111
117
|
/** The actor on whose behalf the request is made (user, MCP client, agent). */
|
|
112
118
|
export interface IdentityActor {
|
|
113
119
|
sub: string;
|
|
@@ -135,6 +141,16 @@ export declare function toOrgRole(role: unknown): OrgRole;
|
|
|
135
141
|
export declare function isAdmin(user: {
|
|
136
142
|
orgRole: OrgRole | string;
|
|
137
143
|
}): boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Whether an agent principal made this call: `chan: "agent"` with
|
|
146
|
+
* `act.sub` `agent:<agt_id>`. `user.id` is still the sponsoring member (the
|
|
147
|
+
* person accountable for the agent), so key rows by it as for anyone;
|
|
148
|
+
* `user.actor.sub` names the agent.
|
|
149
|
+
*/
|
|
150
|
+
export declare function isAgentCall(user: {
|
|
151
|
+
channel: IdentityChannel;
|
|
152
|
+
actor: IdentityActor;
|
|
153
|
+
}): boolean;
|
|
138
154
|
export interface EveryAppUser {
|
|
139
155
|
/** User id (the `sub` claim). */
|
|
140
156
|
id: string;
|
|
@@ -149,13 +165,17 @@ export interface EveryAppUser {
|
|
|
149
165
|
*/
|
|
150
166
|
orgName?: string;
|
|
151
167
|
channel: IdentityChannel;
|
|
152
|
-
/**
|
|
168
|
+
/**
|
|
169
|
+
* The acting principal: the user id, the credential acting for them
|
|
170
|
+
* (`pat:<id>`, `oauth:<id>`, `access:<email>`), or an agent
|
|
171
|
+
* (`agent:<agt_id>`, on `channel: "agent"`; {@link isAgentCall}).
|
|
172
|
+
*/
|
|
153
173
|
actor: IdentityActor;
|
|
154
174
|
scopes: string[];
|
|
155
175
|
jti: string;
|
|
156
176
|
/**
|
|
157
|
-
* Set only on
|
|
158
|
-
* identity was minted for.
|
|
177
|
+
* Set only on a tool call (`channel: "mcp"` or `"agent"`): the one call
|
|
178
|
+
* this identity was minted for.
|
|
159
179
|
*/
|
|
160
180
|
toolCall?: ToolCallClaim;
|
|
161
181
|
}
|
|
@@ -177,6 +197,11 @@ export interface SystemClaims extends JWTPayload {
|
|
|
177
197
|
typ: "system";
|
|
178
198
|
purpose: SystemTokenPurpose;
|
|
179
199
|
jti: string;
|
|
200
|
+
/**
|
|
201
|
+
* `events.deliver` only: the SHA-256 (base64url) of the request body the
|
|
202
|
+
* token was minted for, so it opens that one delivery and nothing else.
|
|
203
|
+
*/
|
|
204
|
+
bh?: string;
|
|
180
205
|
}
|
|
181
206
|
export interface PublicMarkerClaims extends JWTPayload {
|
|
182
207
|
typ: "public";
|
|
@@ -248,7 +273,11 @@ export interface MintSystemTokenOptions {
|
|
|
248
273
|
now?: number;
|
|
249
274
|
/** Header kid. Defaults to the production kid; dev mints with the dev kid. */
|
|
250
275
|
keyId?: string;
|
|
276
|
+
/** `events.deliver`: the body's SHA-256, base64url ({@link bodyHash}). */
|
|
277
|
+
bodyHash?: string;
|
|
251
278
|
}
|
|
279
|
+
/** SHA-256 of a request body, base64url: what an `events.deliver` token's `bh` names. */
|
|
280
|
+
export declare function bodyHash(body: string): Promise<string>;
|
|
252
281
|
/**
|
|
253
282
|
* Mint the gateway's system token for `x-everyapp-system`: no user, one
|
|
254
283
|
* purpose, one app, one minute. The SDK only accepts it on the endpoint its
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/internal/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAwB,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,eAAO,MAAM,YAAY,UAAU,CAAC;AACpC,eAAO,MAAM,eAAe,sBAAsB,CAAC;AACnD,eAAO,MAAM,mBAAmB,0BAA0B,CAAC;AAC3D;;;;GAIG;AACH,eAAO,MAAM,UAAU,kCAAkC,CAAC;AAC1D,eAAO,MAAM,eAAe,wBAAwB,CAAC;AACrD,eAAO,MAAM,aAAa,sBAAsB,CAAC;AACjD;;;;GAIG;AACH,eAAO,MAAM,aAAa,sBAAsB,CAAC;AACjD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,qBAAqB,CAAC;AACvD;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,mBAAmB,CAAC;AAC3C;;;;;;;GAOG;AACH,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/internal/protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,14 +39,14 @@ export const GATEWAY_ERROR_HEADER = "x-everyapp-error";
|
|
|
39
39
|
*/
|
|
40
40
|
export const ORG_HEADER = "x-everyapp-org";
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* `
|
|
47
|
-
*
|
|
42
|
+
* On background work's call to an OAuth provider's API: the member whose
|
|
43
|
+
* connection to this app the call uses. Set by `for: { background: true,
|
|
44
|
+
* userId }`; the gateway reads it on the held-token branch only, for an
|
|
45
|
+
* organization's own app, and the perimeter strips it, with every
|
|
46
|
+
* `x-everyapp-*`, from browsers. It addresses a connection; it is not a
|
|
47
|
+
* permission: connecting in the app already lets the app use it.
|
|
48
48
|
*/
|
|
49
|
-
export const
|
|
49
|
+
export const USER_HEADER = "x-everyapp-user";
|
|
50
50
|
/** 120-second lifetime — caps revocation staleness while surviving clock skew. */
|
|
51
51
|
export const IDENTITY_TTL_SECONDS = 120;
|
|
52
52
|
/** System tokens are minted per call and live at most a minute. */
|
|
@@ -101,6 +101,14 @@ export const LINKED_DEV_NONCE_ENV = "EVERYAPP_LINKED_DEV_NONCE";
|
|
|
101
101
|
export const LINKED_DEV_HEADER = "x-everyapp-linked-dev";
|
|
102
102
|
/** Where the gateway-lite serves the forwarder, under the app's own host. */
|
|
103
103
|
export const LINKED_DEV_FORWARD_PATH = "/__everyapp/gateway";
|
|
104
|
+
/**
|
|
105
|
+
* The channels a tool call arrives on: `mcp` for an AI client's MCP
|
|
106
|
+
* connection, `agent` for an agent principal the Gateway runs a call for.
|
|
107
|
+
* Only the ToolBus mints either with a `tc` claim.
|
|
108
|
+
*/
|
|
109
|
+
export const TOOL_CALL_CHANNELS = ["mcp", "agent"];
|
|
110
|
+
/** `act.sub` of an agent principal: `agent:<agt_id>`; `sub` stays its sponsor. */
|
|
111
|
+
export const AGENT_ACTOR_PREFIX = "agent:";
|
|
104
112
|
/** `role` as an {@link OrgRole}: `owner` and `admin` as they are, anything else `member`. */
|
|
105
113
|
export function toOrgRole(role) {
|
|
106
114
|
return role === "owner" || role === "admin" ? role : "member";
|
|
@@ -109,6 +117,17 @@ export function toOrgRole(role) {
|
|
|
109
117
|
export function isAdmin(user) {
|
|
110
118
|
return user.orgRole === "owner" || user.orgRole === "admin";
|
|
111
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Whether an agent principal made this call: `chan: "agent"` with
|
|
122
|
+
* `act.sub` `agent:<agt_id>`. `user.id` is still the sponsoring member (the
|
|
123
|
+
* person accountable for the agent), so key rows by it as for anyone;
|
|
124
|
+
* `user.actor.sub` names the agent.
|
|
125
|
+
*/
|
|
126
|
+
export function isAgentCall(user) {
|
|
127
|
+
return (user.channel === "agent" &&
|
|
128
|
+
user.actor.sub.startsWith(AGENT_ACTOR_PREFIX) &&
|
|
129
|
+
user.actor.sub.length > AGENT_ACTOR_PREFIX.length);
|
|
130
|
+
}
|
|
112
131
|
export class ProtocolClaimsError extends Error {
|
|
113
132
|
constructor(message) {
|
|
114
133
|
super(message);
|
|
@@ -208,6 +227,10 @@ export function assertSystemClaims(payload, purpose) {
|
|
|
208
227
|
payload.exp - payload.iat > SYSTEM_TOKEN_TTL_SECONDS) {
|
|
209
228
|
throw new ProtocolClaimsError(`system token must expire within ${SYSTEM_TOKEN_TTL_SECONDS}s of issue`);
|
|
210
229
|
}
|
|
230
|
+
if (purpose === "events.deliver" &&
|
|
231
|
+
(typeof payload.bh !== "string" || payload.bh.length === 0)) {
|
|
232
|
+
throw new ProtocolClaimsError("an events.deliver token must name the body it was minted for");
|
|
233
|
+
}
|
|
211
234
|
return payload;
|
|
212
235
|
}
|
|
213
236
|
let cachedPrivateKey = null;
|
|
@@ -269,6 +292,17 @@ export async function mintPublicMarkerJwt(privateKeyPem, opts) {
|
|
|
269
292
|
.setExpirationTime(nowSec + ttl)
|
|
270
293
|
.sign(key);
|
|
271
294
|
}
|
|
295
|
+
/** SHA-256 of a request body, base64url: what an `events.deliver` token's `bh` names. */
|
|
296
|
+
export async function bodyHash(body) {
|
|
297
|
+
const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(body)));
|
|
298
|
+
let binary = "";
|
|
299
|
+
for (const byte of digest)
|
|
300
|
+
binary += String.fromCharCode(byte);
|
|
301
|
+
return btoa(binary)
|
|
302
|
+
.replace(/\+/g, "-")
|
|
303
|
+
.replace(/\//g, "_")
|
|
304
|
+
.replace(/=+$/, "");
|
|
305
|
+
}
|
|
272
306
|
/**
|
|
273
307
|
* Mint the gateway's system token for `x-everyapp-system`: no user, one
|
|
274
308
|
* purpose, one app, one minute. The SDK only accepts it on the endpoint its
|
|
@@ -281,10 +315,14 @@ export async function mintSystemJwt(privateKeyPem, opts) {
|
|
|
281
315
|
}
|
|
282
316
|
const key = await loadPrivateKey(privateKeyPem);
|
|
283
317
|
const nowSec = Math.floor((opts.now ?? Date.now()) / 1000);
|
|
318
|
+
if (opts.purpose === "events.deliver" && !opts.bodyHash) {
|
|
319
|
+
throw new RangeError("an events.deliver token needs the body's hash");
|
|
320
|
+
}
|
|
284
321
|
const claims = {
|
|
285
322
|
typ: "system",
|
|
286
323
|
purpose: opts.purpose,
|
|
287
324
|
jti: crypto.randomUUID(),
|
|
325
|
+
...(opts.bodyHash ? { bh: opts.bodyHash } : {}),
|
|
288
326
|
};
|
|
289
327
|
return new SignJWT(claims)
|
|
290
328
|
.setProtectedHeader({
|
|
@@ -19,19 +19,8 @@
|
|
|
19
19
|
* an IP literal, localhost, or a `.local`, `.internal` or `.arpa` name)
|
|
20
20
|
* and not one the gateway serves itself (`refuseHost`, which knows the
|
|
21
21
|
* gateway's own host and `APP_BASE_DOMAIN`).
|
|
22
|
-
*
|
|
23
|
-
* A second kind of row, a scope-set overlay (`provider_scope_sets`,
|
|
24
|
-
* `everyapp provider scope-set add`), adds a named scope set to a
|
|
25
|
-
* built-in OAuth client that has scope sets (Google, Microsoft, Slack):
|
|
26
|
-
* its scopes, and the routes on the client's own API hosts it unlocks,
|
|
27
|
-
* checked by the rules a built-in set is checked by
|
|
28
|
-
* (`providers.scope-set-overlay-within-client`). An overlay never replaces
|
|
29
|
-
* one of the client's own sets, never names a host outside the client's
|
|
30
|
-
* `api`, and never applies to a registered row (an operator replaces the
|
|
31
|
-
* row's spec instead). Apps list an overlay set under `scopes` as they
|
|
32
|
-
* list a built-in one.
|
|
33
22
|
*/
|
|
34
|
-
import { type Capability, type CapabilityLookup
|
|
23
|
+
import { type Capability, type CapabilityLookup } from "./capabilities.js";
|
|
35
24
|
import { type RegistrableCapability } from "./providerSpec.js";
|
|
36
25
|
/** A `providers` row as the gateway or the CLI read it. */
|
|
37
26
|
export interface ProviderRow {
|
|
@@ -50,33 +39,6 @@ export interface ProviderRow {
|
|
|
50
39
|
/** When, in epoch milliseconds. */
|
|
51
40
|
addedAt?: number | null;
|
|
52
41
|
}
|
|
53
|
-
/** A `provider_scope_sets` row as the gateway or the CLI read it. */
|
|
54
|
-
export interface ScopeSetRow {
|
|
55
|
-
/** The built-in OAuth client the set belongs to (`google-workspace`). */
|
|
56
|
-
providerId: string;
|
|
57
|
-
/** The set's name, what an app lists under `scopes` (`gmail.send`). */
|
|
58
|
-
name: string;
|
|
59
|
-
/** The set's spec, as JSON text or already parsed (`parseScopeSetOverlay`'s shape). */
|
|
60
|
-
spec: unknown;
|
|
61
|
-
addedBy?: string | null;
|
|
62
|
-
addedAt?: number | null;
|
|
63
|
-
}
|
|
64
|
-
/** One overlay the registry serves, as `provider show` reports it. */
|
|
65
|
-
export interface RegisteredScopeSet {
|
|
66
|
-
providerId: string;
|
|
67
|
-
name: string;
|
|
68
|
-
set: OAuthScopeSet;
|
|
69
|
-
addedBy: string | null;
|
|
70
|
-
addedAt: number | null;
|
|
71
|
-
}
|
|
72
|
-
export type ScopeSetRefusalCode = "SCOPE_SET_INVALID" | "SCOPE_SET_PROVIDER_UNKNOWN" | "SCOPE_SET_BUILTIN";
|
|
73
|
-
/** Why an overlay row is not a scope set on this gateway. */
|
|
74
|
-
export interface ScopeSetRefusal {
|
|
75
|
-
providerId: string;
|
|
76
|
-
name: string;
|
|
77
|
-
code: ScopeSetRefusalCode;
|
|
78
|
-
message: string;
|
|
79
|
-
}
|
|
80
42
|
/**
|
|
81
43
|
* The part of a row a key is set for: its hosts, its host setting and its
|
|
82
44
|
* auth, as one canonical string (sorted keys, sorted hosts), so that
|
|
@@ -123,12 +85,6 @@ export interface ProviderRegistry extends CapabilityLookup {
|
|
|
123
85
|
rows(): readonly RegisteredProvider[];
|
|
124
86
|
/** The rows this registry left out, each with why. */
|
|
125
87
|
readonly rejected: readonly RowRefusal[];
|
|
126
|
-
/** The scope-set overlays this registry applied to built-in clients, in row order. */
|
|
127
|
-
scopeSets(): readonly RegisteredScopeSet[];
|
|
128
|
-
/** Where a client's scope set comes from: its catalog entry, an overlay row, or nowhere. */
|
|
129
|
-
scopeSetSource(providerId: string, name: string): "catalog" | "row" | undefined;
|
|
130
|
-
/** The overlay rows this registry left out, each with why. */
|
|
131
|
-
readonly rejectedScopeSets: readonly ScopeSetRefusal[];
|
|
132
88
|
}
|
|
133
89
|
export interface ProviderRegistryOptions {
|
|
134
90
|
/**
|
|
@@ -137,8 +93,6 @@ export interface ProviderRegistryOptions {
|
|
|
137
93
|
* the rest (IP literals, localhost, `.internal`).
|
|
138
94
|
*/
|
|
139
95
|
refuseHost?: (host: string) => string | null;
|
|
140
|
-
/** The scope-set overlays (`provider_scope_sets`), applied to the catalog's OAuth clients. */
|
|
141
|
-
scopeSets?: readonly ScopeSetRow[];
|
|
142
96
|
}
|
|
143
97
|
/** The prefix a provider's own Gateway settings carry: `stripe` → `STRIPE_`, `tiktok-business` → `TIKTOK_BUSINESS_`. */
|
|
144
98
|
export declare function providerSettingPrefix(id: string): string;
|
|
@@ -194,20 +148,6 @@ export declare function resolveProviderRow(row: ProviderRow, context: {
|
|
|
194
148
|
ok: false;
|
|
195
149
|
refusal: RowRefusal;
|
|
196
150
|
};
|
|
197
|
-
/**
|
|
198
|
-
* The built-in OAuth client an overlay may extend: a catalog entry of mode
|
|
199
|
-
* `oauth_client` with a scope policy. Null for anything else (an API-key
|
|
200
|
-
* entry, a client without sets, a registered row, an unknown id).
|
|
201
|
-
*/
|
|
202
|
-
export declare function overlayableClient(providerId: string): OAuthClientCapability | null;
|
|
203
|
-
/** An overlay row's spec parsed and checked against its client: the set, or the refusal. */
|
|
204
|
-
export declare function resolveScopeSetRow(row: ScopeSetRow): {
|
|
205
|
-
ok: true;
|
|
206
|
-
set: OAuthScopeSet;
|
|
207
|
-
} | {
|
|
208
|
-
ok: false;
|
|
209
|
-
refusal: ScopeSetRefusal;
|
|
210
|
-
};
|
|
211
151
|
/**
|
|
212
152
|
* The catalog and `rows` as one registry. Rows are taken in order; a row
|
|
213
153
|
* whose settings another earlier row holds is the one refused.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providerRegistry.d.ts","sourceRoot":"","sources":["../../src/internal/providerRegistry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"providerRegistry.d.ts","sourceRoot":"","sources":["../../src/internal/providerRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,21 +19,9 @@
|
|
|
19
19
|
* an IP literal, localhost, or a `.local`, `.internal` or `.arpa` name)
|
|
20
20
|
* and not one the gateway serves itself (`refuseHost`, which knows the
|
|
21
21
|
* gateway's own host and `APP_BASE_DOMAIN`).
|
|
22
|
-
*
|
|
23
|
-
* A second kind of row, a scope-set overlay (`provider_scope_sets`,
|
|
24
|
-
* `everyapp provider scope-set add`), adds a named scope set to a
|
|
25
|
-
* built-in OAuth client that has scope sets (Google, Microsoft, Slack):
|
|
26
|
-
* its scopes, and the routes on the client's own API hosts it unlocks,
|
|
27
|
-
* checked by the rules a built-in set is checked by
|
|
28
|
-
* (`providers.scope-set-overlay-within-client`). An overlay never replaces
|
|
29
|
-
* one of the client's own sets, never names a host outside the client's
|
|
30
|
-
* `api`, and never applies to a registered row (an operator replaces the
|
|
31
|
-
* row's spec instead). Apps list an overlay set under `scopes` as they
|
|
32
|
-
* list a built-in one.
|
|
33
22
|
*/
|
|
34
23
|
import { CAPABILITIES, CAPABILITY_IDS, capabilitySettings, } from "./capabilities.js";
|
|
35
24
|
import { isDevOnlyGatewaySetting, isInstallOwnedGatewaySetting, isReservedAppSecretName, isSettableGatewaySetting, } from "./gatewaySettings.js";
|
|
36
|
-
import { parseScopeSetOverlay, withScopeSets } from "./oauthSpec.js";
|
|
37
25
|
import { isSignInSettingName } from "./signInProviders.js";
|
|
38
26
|
import { describeSpecProblems, parseProviderSpec, PROVIDER_ID, } from "./providerSpec.js";
|
|
39
27
|
/**
|
|
@@ -59,10 +47,10 @@ export function providerBindingKey(capability) {
|
|
|
59
47
|
if (capability.mode === "oauth_client") {
|
|
60
48
|
return JSON.stringify({
|
|
61
49
|
kind: "oauth2-user",
|
|
62
|
-
authorizeUrl: capability.
|
|
63
|
-
tokenUrl: capability.flow
|
|
64
|
-
revokeUrl: capability.flow
|
|
65
|
-
inject: capability.
|
|
50
|
+
authorizeUrl: capability.flow.authorizeUrl,
|
|
51
|
+
tokenUrl: capability.flow.tokenUrl,
|
|
52
|
+
revokeUrl: capability.flow.revokeUrl ?? null,
|
|
53
|
+
inject: capability.flow.inject,
|
|
66
54
|
clientId: capability.secrets.clientId,
|
|
67
55
|
clientSecret: capability.secrets.clientSecret ?? null,
|
|
68
56
|
hosts: [...capability.api].sort(),
|
|
@@ -207,10 +195,10 @@ export function registrableHosts(capability) {
|
|
|
207
195
|
return [new URL(capability.origin).hostname.toLowerCase()];
|
|
208
196
|
const hosts = [...capability.api];
|
|
209
197
|
const urls = [
|
|
210
|
-
capability.
|
|
211
|
-
capability.flow
|
|
212
|
-
capability.flow
|
|
213
|
-
capability.flow
|
|
198
|
+
capability.flow.authorizeUrl,
|
|
199
|
+
capability.flow.tokenUrl,
|
|
200
|
+
capability.flow.revokeUrl,
|
|
201
|
+
capability.flow.identity?.url,
|
|
214
202
|
];
|
|
215
203
|
for (const url of urls) {
|
|
216
204
|
if (!url)
|
|
@@ -270,92 +258,12 @@ export function resolveProviderRow(row, context) {
|
|
|
270
258
|
? { ok: false, refusal }
|
|
271
259
|
: { ok: true, capability: parsed.capability };
|
|
272
260
|
}
|
|
273
|
-
/**
|
|
274
|
-
* The built-in OAuth client an overlay may extend: a catalog entry of mode
|
|
275
|
-
* `oauth_client` with a scope policy. Null for anything else (an API-key
|
|
276
|
-
* entry, a client without sets, a registered row, an unknown id).
|
|
277
|
-
*/
|
|
278
|
-
export function overlayableClient(providerId) {
|
|
279
|
-
if (!CAPABILITY_IDS.includes(providerId))
|
|
280
|
-
return null;
|
|
281
|
-
const capability = CAPABILITIES[providerId];
|
|
282
|
-
return capability.mode === "oauth_client" && capability.scopePolicy
|
|
283
|
-
? capability
|
|
284
|
-
: null;
|
|
285
|
-
}
|
|
286
|
-
/** An overlay row's spec parsed and checked against its client: the set, or the refusal. */
|
|
287
|
-
export function resolveScopeSetRow(row) {
|
|
288
|
-
const refuse = (code, message) => ({
|
|
289
|
-
ok: false,
|
|
290
|
-
refusal: { providerId: row.providerId, name: row.name, code, message },
|
|
291
|
-
});
|
|
292
|
-
const client = overlayableClient(row.providerId);
|
|
293
|
-
if (!client) {
|
|
294
|
-
return refuse("SCOPE_SET_PROVIDER_UNKNOWN", `${row.providerId} isn't a built-in OAuth client with scope sets (google-workspace, microsoft-365, slack); a registered provider's sets are in its spec`);
|
|
295
|
-
}
|
|
296
|
-
if (Object.hasOwn(client.scopePolicy.sets, row.name)) {
|
|
297
|
-
return refuse("SCOPE_SET_BUILTIN", `${row.name} is one of ${row.providerId}'s own sets; an overlay adds a set, never replaces one`);
|
|
298
|
-
}
|
|
299
|
-
let spec = row.spec;
|
|
300
|
-
if (typeof spec === "string") {
|
|
301
|
-
try {
|
|
302
|
-
spec = JSON.parse(spec);
|
|
303
|
-
}
|
|
304
|
-
catch {
|
|
305
|
-
return refuse("SCOPE_SET_INVALID", "the stored spec isn't JSON");
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
const parsed = parseScopeSetOverlay(typeof spec === "object" && spec !== null && !Array.isArray(spec)
|
|
309
|
-
? { ...spec, name: row.name }
|
|
310
|
-
: spec, { id: row.providerId, capability: client });
|
|
311
|
-
if (!parsed.ok) {
|
|
312
|
-
return refuse("SCOPE_SET_INVALID", describeSpecProblems(parsed.problems));
|
|
313
|
-
}
|
|
314
|
-
return { ok: true, set: parsed.set };
|
|
315
|
-
}
|
|
316
261
|
/**
|
|
317
262
|
* The catalog and `rows` as one registry. Rows are taken in order; a row
|
|
318
263
|
* whose settings another earlier row holds is the one refused.
|
|
319
264
|
*/
|
|
320
265
|
export function providerRegistry(rows = [], options = {}) {
|
|
321
266
|
const catalog = new Map(CAPABILITY_IDS.map((id) => [id, CAPABILITIES[id]]));
|
|
322
|
-
// Scope-set overlays on the catalog's OAuth clients, before any row is
|
|
323
|
-
// looked at: a row never shadows the catalog, with or without overlays.
|
|
324
|
-
const overlays = [];
|
|
325
|
-
const rejectedScopeSets = [];
|
|
326
|
-
const overlaySets = new Map();
|
|
327
|
-
for (const row of options.scopeSets ?? []) {
|
|
328
|
-
if (overlays.some((each) => each.providerId === row.providerId && each.name === row.name)) {
|
|
329
|
-
rejectedScopeSets.push({
|
|
330
|
-
providerId: row.providerId,
|
|
331
|
-
name: row.name,
|
|
332
|
-
code: "SCOPE_SET_INVALID",
|
|
333
|
-
message: "listed twice",
|
|
334
|
-
});
|
|
335
|
-
continue;
|
|
336
|
-
}
|
|
337
|
-
const resolved = resolveScopeSetRow(row);
|
|
338
|
-
if (!resolved.ok) {
|
|
339
|
-
rejectedScopeSets.push(resolved.refusal);
|
|
340
|
-
continue;
|
|
341
|
-
}
|
|
342
|
-
overlays.push({
|
|
343
|
-
providerId: row.providerId,
|
|
344
|
-
name: row.name,
|
|
345
|
-
set: resolved.set,
|
|
346
|
-
addedBy: row.addedBy ?? null,
|
|
347
|
-
addedAt: row.addedAt ?? null,
|
|
348
|
-
});
|
|
349
|
-
const sets = overlaySets.get(row.providerId) ?? {};
|
|
350
|
-
sets[row.name] = resolved.set;
|
|
351
|
-
overlaySets.set(row.providerId, sets);
|
|
352
|
-
}
|
|
353
|
-
for (const [id, sets] of overlaySets) {
|
|
354
|
-
const client = catalog.get(id);
|
|
355
|
-
if (client?.mode === "oauth_client") {
|
|
356
|
-
catalog.set(id, withScopeSets(client, sets));
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
267
|
const accepted = new Map();
|
|
360
268
|
const rejected = [];
|
|
361
269
|
const rowSettings = new Set();
|
|
@@ -411,21 +319,6 @@ export function providerRegistry(rows = [], options = {}) {
|
|
|
411
319
|
},
|
|
412
320
|
rows: () => [...accepted.values()],
|
|
413
321
|
rejected,
|
|
414
|
-
scopeSets: () => [...overlays],
|
|
415
|
-
scopeSetSource: (providerId, name) => {
|
|
416
|
-
if (overlays.some((each) => each.providerId === providerId && each.name === name)) {
|
|
417
|
-
return "row";
|
|
418
|
-
}
|
|
419
|
-
const capability = CAPABILITY_IDS.includes(providerId)
|
|
420
|
-
? CAPABILITIES[providerId]
|
|
421
|
-
: undefined;
|
|
422
|
-
return capability?.mode === "oauth_client" &&
|
|
423
|
-
capability.scopePolicy &&
|
|
424
|
-
Object.hasOwn(capability.scopePolicy.sets, name)
|
|
425
|
-
? "catalog"
|
|
426
|
-
: undefined;
|
|
427
|
-
},
|
|
428
|
-
rejectedScopeSets,
|
|
429
322
|
};
|
|
430
323
|
}
|
|
431
324
|
/** The catalog alone, as a registry: what every surface reads without a gateway's rows. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providerSpec.d.ts","sourceRoot":"","sources":["../../src/internal/providerSpec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAGL,KAAK,oBAAoB,EAEzB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAM3B,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"providerSpec.d.ts","sourceRoot":"","sources":["../../src/internal/providerSpec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAGL,KAAK,oBAAoB,EAEzB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAM3B,MAAM,mBAAmB,CAAC;AAO3B,oEAAoE;AACpE,eAAO,MAAM,WAAW,QAA2B,CAAC;AACpD,kFAAkF;AAClF,eAAO,MAAM,oBAAoB,QAA2B,CAAC;AAC7D,0FAA0F;AAC1F,eAAO,MAAM,aAAa,QACoD,CAAC;AA4C/E,kGAAkG;AAClG,eAAO,MAAM,kBAAkB,yBAAyB,CAAC;AACzD,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AAkEzD,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,0HAA0H;AAC1H,MAAM,MAAM,qBAAqB,GAC7B,gBAAgB,GAChB,qBAAqB,GACrB,oBAAoB,CAAC;AAEzB,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,qBAAqB,CAAA;CAAE,GAC3D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,mBAAmB,EAAE,CAAA;CAAE,CAAC;AA+iBnD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAsNpE;AAkOD,wFAAwF;AACxF,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,SAAS,mBAAmB,EAAE,GACvC,MAAM,CAIR;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,qBAAqB,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA+FzB;AAED,kGAAkG;AAClG,wBAAgB,cAAc,CAC5B,UAAU,EAAE,qBAAqB,GAChC,SAAS,MAAM,EAAE,CAKnB"}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* registry's (./providerRegistry.ts), run after this parse.
|
|
22
22
|
*/
|
|
23
23
|
import { DEFAULT_WRITE_METHODS, authSettingNames, } from "./capabilities.js";
|
|
24
|
-
import { oauthSpecOf, parseOAuthUserSpec } from "./oauthSpec.js";
|
|
24
|
+
import { REMOVED_OAUTH_FIELDS, oauthSpecOf, parseOAuthUserSpec, } from "./oauthSpec.js";
|
|
25
25
|
/** A provider id: lowercase, a letter first, 2 to 40 characters. */
|
|
26
26
|
export const PROVIDER_ID = /^[a-z][a-z0-9-]{1,39}$/;
|
|
27
27
|
/** A Gateway setting name a provider may hold: upper case, 3 to 64 characters. */
|
|
@@ -96,10 +96,6 @@ const KNOWN_FIELDS = new Set([
|
|
|
96
96
|
"example",
|
|
97
97
|
"verified",
|
|
98
98
|
"tags",
|
|
99
|
-
// An `oauth2-user` spec's own (./oauthSpec.ts).
|
|
100
|
-
"scopeSets",
|
|
101
|
-
"alwaysRequested",
|
|
102
|
-
"tolerated",
|
|
103
99
|
// An `ai` spec's own.
|
|
104
100
|
"baseUrl",
|
|
105
101
|
"models",
|
|
@@ -128,11 +124,7 @@ const NOT_AI_FIELDS = [
|
|
|
128
124
|
"readMethods",
|
|
129
125
|
"writeMethods",
|
|
130
126
|
"accountWidePaths",
|
|
131
|
-
...OAUTH_ONLY_FIELDS_LIST(),
|
|
132
127
|
];
|
|
133
|
-
function OAUTH_ONLY_FIELDS_LIST() {
|
|
134
|
-
return ["scopeSets", "alwaysRequested", "tolerated"];
|
|
135
|
-
}
|
|
136
128
|
/** Fields an API-key spec has that an `oauth2-user` spec does not. */
|
|
137
129
|
const API_KEY_ONLY_FIELDS = [
|
|
138
130
|
"hostSetting",
|
|
@@ -144,11 +136,6 @@ const API_KEY_ONLY_FIELDS = [
|
|
|
144
136
|
"rate",
|
|
145
137
|
"verified",
|
|
146
138
|
];
|
|
147
|
-
const OAUTH_ONLY_FIELDS = [
|
|
148
|
-
"scopeSets",
|
|
149
|
-
"alwaysRequested",
|
|
150
|
-
"tolerated",
|
|
151
|
-
];
|
|
152
139
|
function isRecord(value) {
|
|
153
140
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
154
141
|
}
|
|
@@ -656,7 +643,11 @@ export function parseProviderSpec(input) {
|
|
|
656
643
|
problems: [{ path: "(root)", message: "must be a JSON object" }],
|
|
657
644
|
};
|
|
658
645
|
}
|
|
646
|
+
const oauthSpec = isRecord(input["auth"]) && input["auth"]["kind"] === "oauth2-user";
|
|
659
647
|
for (const field of Object.keys(input)) {
|
|
648
|
+
// An OAuth spec's removed fields get their own message below.
|
|
649
|
+
if (oauthSpec && Object.hasOwn(REMOVED_OAUTH_FIELDS, field))
|
|
650
|
+
continue;
|
|
660
651
|
if (!KNOWN_FIELDS.has(field)) {
|
|
661
652
|
problems.push({ path: field, message: "unknown field" });
|
|
662
653
|
}
|
|
@@ -715,7 +706,12 @@ export function parseProviderSpec(input) {
|
|
|
715
706
|
return parseAiSpec(input, problems, { id, name, description, docs, api });
|
|
716
707
|
}
|
|
717
708
|
if (isOAuth) {
|
|
718
|
-
|
|
709
|
+
// Fields an OAuth spec had before scopes moved to each app's config,
|
|
710
|
+
// each refused with what to write instead.
|
|
711
|
+
for (const [field, message] of Object.entries(REMOVED_OAUTH_FIELDS)) {
|
|
712
|
+
if (input[field] !== undefined)
|
|
713
|
+
problems.push({ path: field, message });
|
|
714
|
+
}
|
|
719
715
|
const hint = text(input["hint"], "hint", problems, { max: 500 });
|
|
720
716
|
const example = text(input["example"], "example", problems, { max: 200 });
|
|
721
717
|
const tags = tagList(input["tags"], problems);
|
|
@@ -746,11 +742,6 @@ export function parseProviderSpec(input) {
|
|
|
746
742
|
hosts,
|
|
747
743
|
...(description === undefined ? {} : { description }),
|
|
748
744
|
...(api === undefined ? {} : { reference: api }),
|
|
749
|
-
...(access === undefined
|
|
750
|
-
? {}
|
|
751
|
-
: { access: access }),
|
|
752
|
-
...(readMethods === undefined ? {} : { readMethods }),
|
|
753
|
-
...(writeMethods === undefined ? {} : { writeMethods }),
|
|
754
745
|
...(hint === undefined ? {} : { hint }),
|
|
755
746
|
...(example === undefined ? {} : { example }),
|
|
756
747
|
...(tags === undefined ? {} : { tags }),
|
|
@@ -761,14 +752,6 @@ export function parseProviderSpec(input) {
|
|
|
761
752
|
}
|
|
762
753
|
return { ok: true, id, capability: parsed.capability };
|
|
763
754
|
}
|
|
764
|
-
for (const field of OAUTH_ONLY_FIELDS) {
|
|
765
|
-
if (input[field] !== undefined) {
|
|
766
|
-
problems.push({
|
|
767
|
-
path: field,
|
|
768
|
-
message: "only an oauth2-user spec has it",
|
|
769
|
-
});
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
755
|
const hostSetting = input["hostSetting"] === undefined
|
|
773
756
|
? undefined
|
|
774
757
|
: secretName(input["hostSetting"], "hostSetting", problems);
|
|
@@ -1048,13 +1031,8 @@ export function describeSpecProblems(problems) {
|
|
|
1048
1031
|
* gives the entry back.
|
|
1049
1032
|
*/
|
|
1050
1033
|
export function providerSpecOf(id, capability) {
|
|
1051
|
-
if (capability.mode === "oauth_client")
|
|
1052
|
-
|
|
1053
|
-
if (!spec) {
|
|
1054
|
-
throw new Error(`${id} is a catalog OAuth client without a Gateway-owned flow: it has no spec`);
|
|
1055
|
-
}
|
|
1056
|
-
return spec;
|
|
1057
|
-
}
|
|
1034
|
+
if (capability.mode === "oauth_client")
|
|
1035
|
+
return oauthSpecOf(id, capability);
|
|
1058
1036
|
if (capability.mode === "ai") {
|
|
1059
1037
|
if (!capability.chat || !capability.models) {
|
|
1060
1038
|
throw new Error(`${id} is a catalog AI entry without a model list: it has no spec`);
|
|
@@ -1149,6 +1127,6 @@ export function providerSpecOf(id, capability) {
|
|
|
1149
1127
|
}
|
|
1150
1128
|
/** The methods an app with `access: "write"` may use on `capability` besides its read methods. */
|
|
1151
1129
|
export function writeMethodsOf(capability) {
|
|
1152
|
-
return ((capability.mode === "
|
|
1130
|
+
return ((capability.mode === "api_key" ? capability.writeMethods : undefined) ??
|
|
1153
1131
|
DEFAULT_WRITE_METHODS);
|
|
1154
1132
|
}
|