@every-app/sdk 0.3.0-rc.10 → 0.3.0-rc.12
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 +67 -67
- 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 +36 -2
- package/dist/cloudflare/worker.d.ts.map +1 -1
- package/dist/cloudflare/worker.js +32 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/internal/aiDefault.d.ts +36 -79
- package/dist/internal/aiDefault.d.ts.map +1 -1
- package/dist/internal/aiDefault.js +47 -149
- package/dist/internal/aiProviders.d.ts.map +1 -1
- package/dist/internal/aiProviders.js +2 -2
- package/dist/internal/appSettings.d.ts +14 -17
- package/dist/internal/appSettings.d.ts.map +1 -1
- package/dist/internal/appSettings.js +2 -16
- package/dist/internal/capabilities.d.ts +106 -489
- package/dist/internal/capabilities.d.ts.map +1 -1
- package/dist/internal/capabilities.js +49 -550
- package/dist/internal/catalog/commerce.js +1 -1
- 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/gatewaySettings.d.ts +2 -2
- package/dist/internal/gatewaySettings.d.ts.map +1 -1
- package/dist/internal/gatewaySettings.js +0 -6
- 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 +24 -14
- package/dist/internal/protocol.d.ts.map +1 -1
- package/dist/internal/protocol.js +26 -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 +4 -6
- package/dist/internal/remoteMcp.d.ts.map +1 -1
- package/dist/internal/remoteMcp.js +8 -15
- package/dist/internal/tools.d.ts +12 -7
- package/dist/internal/tools.d.ts.map +1 -1
- package/dist/internal/tools.js +9 -8
- package/dist/manifest.d.ts +41 -28
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +1 -1
- package/dist/server/ai.d.ts +1 -93
- package/dist/server/ai.d.ts.map +1 -1
- package/dist/server/ai.js +17 -111
- package/dist/server/attribution.d.ts +10 -1
- 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/context.d.ts +12 -14
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/context.js +23 -25
- 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 +16 -26
- package/dist/server/everyApp.d.ts.map +1 -1
- package/dist/server/everyApp.js +22 -46
- package/dist/server/gatewayFetch.d.ts +1 -1
- package/dist/server/gatewayFetch.js +1 -1
- package/dist/server/index.d.ts +6 -9
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +4 -8
- package/dist/server/integrationFetch.d.ts +60 -72
- package/dist/server/integrationFetch.d.ts.map +1 -1
- package/dist/server/integrationFetch.js +117 -392
- package/dist/server/refusal.d.ts +0 -9
- package/dist/server/refusal.d.ts.map +1 -1
- package/dist/server/refusal.js +0 -22
- package/dist/server/tools.d.ts +13 -5
- package/dist/server/tools.d.ts.map +1 -1
- package/dist/server/tools.js +10 -3
- package/dist/server/toolsEndpoint.d.ts +2 -1
- package/dist/server/toolsEndpoint.d.ts.map +1 -1
- package/dist/server/toolsEndpoint.js +4 -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/dist/testing/index.d.ts +2 -3
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +2 -6
- package/package.json +1 -1
- package/dist/server/aiBinding.d.ts +0 -68
- package/dist/server/aiBinding.d.ts.map +0 -1
- package/dist/server/aiBinding.js +0 -294
- package/dist/server/authorizeUrl.d.ts +0 -43
- package/dist/server/authorizeUrl.d.ts.map +0 -1
- package/dist/server/authorizeUrl.js +0 -106
- package/dist/server/emailBinding.d.ts +0 -72
- package/dist/server/emailBinding.d.ts.map +0 -1
- package/dist/server/emailBinding.js +0 -124
- package/dist/server/fromMcpTools.d.ts +0 -89
- package/dist/server/fromMcpTools.d.ts.map +0 -1
- package/dist/server/fromMcpTools.js +0 -192
|
@@ -16,18 +16,14 @@
|
|
|
16
16
|
* proxy's rules: inference routes only, the model allowlist, the usage
|
|
17
17
|
* tap. Never a capability: its key would reach the account's credits
|
|
18
18
|
* and keys on the same host.
|
|
19
|
-
* - `oauth_client`:
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* the
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* with different needs carries a `scopePolicy`: named scope sets an app
|
|
28
|
-
* lists in its manifest entry's `scopes`, which ./oauthScopes.ts turns
|
|
29
|
-
* into what the app may ask the provider for and what a token it is
|
|
30
|
-
* handed may carry.
|
|
19
|
+
* - `oauth_client`: an OAuth provider (Google, Microsoft, Slack built
|
|
20
|
+
* in; GitHub and others as presets, ./oauthPresets.ts) whose client the
|
|
21
|
+
* gateway holds and whose flow it runs. A person connects in an app,
|
|
22
|
+
* for exactly the provider scopes the app's manifest entry lists
|
|
23
|
+
* (`scopes`); the gateway keeps the tokens and puts the person's token
|
|
24
|
+
* on the app's calls to the provider's `api` hosts. Each provider is a
|
|
25
|
+
* spec (./oauthSpec.ts), its differences data; ./oauthScopes.ts holds
|
|
26
|
+
* the one set of scope rules.
|
|
31
27
|
* - `service`: something the gateway does itself, with no upstream host
|
|
32
28
|
* an app names (sending email, listing the organization's members). An
|
|
33
29
|
* app lists it the same way and calls its routes,
|
|
@@ -47,6 +43,22 @@ export const DEFAULT_WRITE_METHODS = [
|
|
|
47
43
|
"DELETE",
|
|
48
44
|
];
|
|
49
45
|
import { CATALOG_ENTRIES } from "./catalog/index.js";
|
|
46
|
+
import { BUILT_IN_OAUTH_SPECS } from "./oauthBuiltIns.js";
|
|
47
|
+
import { oauthCapabilityFromSpec } from "./oauthSpec.js";
|
|
48
|
+
/**
|
|
49
|
+
* A built-in OAuth provider's catalog entry from its spec, its setting
|
|
50
|
+
* names kept literal so `CapabilitySecret` names them.
|
|
51
|
+
*/
|
|
52
|
+
function builtInOAuth(spec, setup) {
|
|
53
|
+
return {
|
|
54
|
+
...oauthCapabilityFromSpec(spec),
|
|
55
|
+
secrets: {
|
|
56
|
+
clientId: spec.auth.clientId,
|
|
57
|
+
clientSecret: spec.auth.clientSecret,
|
|
58
|
+
},
|
|
59
|
+
setup,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
50
62
|
export const CAPABILITIES = {
|
|
51
63
|
// The AI providers, in the order the AI proxy's table had them.
|
|
52
64
|
openai: {
|
|
@@ -70,8 +82,8 @@ export const CAPABILITIES = {
|
|
|
70
82
|
"/v1/images/variations",
|
|
71
83
|
],
|
|
72
84
|
unstoredRoutes: ["/v1/responses", "/v1/chat/completions"],
|
|
73
|
-
// More than inference needs
|
|
74
|
-
//
|
|
85
|
+
// More than inference needs the app's manifest (`ai.routes`): OpenAI
|
|
86
|
+
// paths only.
|
|
75
87
|
extraRoutes: true,
|
|
76
88
|
// Tool calling on chat completions needs `reasoning_effort: "none"`
|
|
77
89
|
// on the GPT-6 family (the responses route takes tools as it is).
|
|
@@ -296,518 +308,11 @@ export const CAPABILITIES = {
|
|
|
296
308
|
settings: [],
|
|
297
309
|
optionalSettings: [],
|
|
298
310
|
},
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
clientSecret: "SLACK_CLIENT_SECRET",
|
|
305
|
-
},
|
|
306
|
-
token: [
|
|
307
|
-
{
|
|
308
|
-
host: "slack.com",
|
|
309
|
-
path: "/api/oauth.v2.access",
|
|
310
|
-
methods: ["POST"],
|
|
311
|
-
inject: "form",
|
|
312
|
-
},
|
|
313
|
-
],
|
|
314
|
-
access: ["write"],
|
|
315
|
-
console: "https://api.slack.com/apps",
|
|
316
|
-
setup: "setup/slack.md",
|
|
317
|
-
authorize: {
|
|
318
|
-
url: "https://slack.com/oauth/v2/authorize",
|
|
319
|
-
// The sets' union: the bot scopes in set order, then the one user
|
|
320
|
-
// scope no bot set carries. Postiz lists `channels.read`,
|
|
321
|
-
// `users.read`, `messages.write`, `channels.join` and `files.write`
|
|
322
|
-
// (it posts to channels it joins and uploads images); Open CRM adds
|
|
323
|
-
// `users.email`, `channels.manage` and `user-channels.manage` (its
|
|
324
|
-
// team agents match members to Slack users by email, create and
|
|
325
|
-
// manage the channels they post to, open DMs, and the installing
|
|
326
|
-
// person invites the bot to private channels).
|
|
327
|
-
scopes: [
|
|
328
|
-
"channels:read",
|
|
329
|
-
"groups:read",
|
|
330
|
-
"users:read",
|
|
331
|
-
"users:read.email",
|
|
332
|
-
"chat:write",
|
|
333
|
-
"chat:write.public",
|
|
334
|
-
"chat:write.customize",
|
|
335
|
-
"channels:join",
|
|
336
|
-
"channels:manage",
|
|
337
|
-
"groups:write",
|
|
338
|
-
"channels:write.invites",
|
|
339
|
-
"groups:write.invites",
|
|
340
|
-
"im:write",
|
|
341
|
-
"files:write",
|
|
342
|
-
"channels:write",
|
|
343
|
-
],
|
|
344
|
-
},
|
|
345
|
-
scopePolicy: {
|
|
346
|
-
dialect: "slack",
|
|
347
|
-
// `oauth.v2.access` takes `code` with no `grant_type`; an app that
|
|
348
|
-
// opts into token rotation refreshes with `refresh_token`.
|
|
349
|
-
grantTypes: [null, "refresh_token"],
|
|
350
|
-
// Slack reads no `scope` on the token leg (the installation's scopes
|
|
351
|
-
// were fixed on the authorize URL), so the request goes as sent.
|
|
352
|
-
requestScope: "keep",
|
|
353
|
-
alwaysRequested: [],
|
|
354
|
-
tolerated: [],
|
|
355
|
-
deniedSegments: [],
|
|
356
|
-
// Slack authorizes by method name, not verb, and every method is one
|
|
357
|
-
// exact `/api/<method>` path on the host that also serves the token
|
|
358
|
-
// endpoint (which no set lists). A read set names its methods in
|
|
359
|
-
// `paths` (GET) and `posts` (POST) alike; a write set in `posts`
|
|
360
|
-
// only, with the one listing among them in `paths` too.
|
|
361
|
-
sets: {
|
|
362
|
-
"channels.read": {
|
|
363
|
-
label: "Channels (read-only)",
|
|
364
|
-
access: "read",
|
|
365
|
-
scopes: ["channels:read", "groups:read"],
|
|
366
|
-
routes: [
|
|
367
|
-
{
|
|
368
|
-
host: "slack.com",
|
|
369
|
-
paths: [
|
|
370
|
-
"/api/conversations.list",
|
|
371
|
-
"/api/conversations.info",
|
|
372
|
-
"/api/conversations.members",
|
|
373
|
-
"/api/users.conversations",
|
|
374
|
-
],
|
|
375
|
-
posts: [
|
|
376
|
-
/^\/api\/conversations\.(list|info|members)$/,
|
|
377
|
-
/^\/api\/users\.conversations$/,
|
|
378
|
-
],
|
|
379
|
-
},
|
|
380
|
-
],
|
|
381
|
-
},
|
|
382
|
-
"users.read": {
|
|
383
|
-
label: "Members (read-only)",
|
|
384
|
-
access: "read",
|
|
385
|
-
scopes: ["users:read"],
|
|
386
|
-
routes: [
|
|
387
|
-
{
|
|
388
|
-
host: "slack.com",
|
|
389
|
-
paths: [
|
|
390
|
-
"/api/users.list",
|
|
391
|
-
"/api/users.info",
|
|
392
|
-
"/api/users.getPresence",
|
|
393
|
-
"/api/bots.info",
|
|
394
|
-
],
|
|
395
|
-
posts: [
|
|
396
|
-
/^\/api\/users\.(list|info|getPresence)$/,
|
|
397
|
-
/^\/api\/bots\.info$/,
|
|
398
|
-
],
|
|
399
|
-
},
|
|
400
|
-
],
|
|
401
|
-
},
|
|
402
|
-
"users.email": {
|
|
403
|
-
// Slack grants it only beside `users:read`: declare both sets.
|
|
404
|
-
label: "Members' email addresses (read-only)",
|
|
405
|
-
access: "read",
|
|
406
|
-
scopes: ["users:read.email"],
|
|
407
|
-
routes: [
|
|
408
|
-
{
|
|
409
|
-
host: "slack.com",
|
|
410
|
-
paths: ["/api/users.lookupByEmail"],
|
|
411
|
-
posts: [/^\/api\/users\.lookupByEmail$/],
|
|
412
|
-
},
|
|
413
|
-
],
|
|
414
|
-
},
|
|
415
|
-
"messages.write": {
|
|
416
|
-
label: "Messages (post as the app)",
|
|
417
|
-
access: "write",
|
|
418
|
-
scopes: ["chat:write", "chat:write.public", "chat:write.customize"],
|
|
419
|
-
routes: [
|
|
420
|
-
{
|
|
421
|
-
host: "slack.com",
|
|
422
|
-
// The scheduled-messages listing is the one read among them.
|
|
423
|
-
paths: ["/api/chat.scheduledMessages.list"],
|
|
424
|
-
posts: [
|
|
425
|
-
/^\/api\/chat\.(postMessage|postEphemeral|update|delete|scheduleMessage|deleteScheduledMessage|scheduledMessages\.list)$/,
|
|
426
|
-
],
|
|
427
|
-
},
|
|
428
|
-
],
|
|
429
|
-
},
|
|
430
|
-
"channels.join": {
|
|
431
|
-
label: "Channels (join public ones)",
|
|
432
|
-
access: "write",
|
|
433
|
-
scopes: ["channels:join"],
|
|
434
|
-
routes: [
|
|
435
|
-
{
|
|
436
|
-
host: "slack.com",
|
|
437
|
-
paths: [],
|
|
438
|
-
posts: [/^\/api\/conversations\.join$/],
|
|
439
|
-
},
|
|
440
|
-
],
|
|
441
|
-
},
|
|
442
|
-
"channels.manage": {
|
|
443
|
-
label: "Channels (create, manage and invite to; open DMs)",
|
|
444
|
-
access: "write",
|
|
445
|
-
scopes: [
|
|
446
|
-
"channels:manage",
|
|
447
|
-
"groups:write",
|
|
448
|
-
"channels:write.invites",
|
|
449
|
-
"groups:write.invites",
|
|
450
|
-
"im:write",
|
|
451
|
-
],
|
|
452
|
-
routes: [
|
|
453
|
-
{
|
|
454
|
-
host: "slack.com",
|
|
455
|
-
paths: [],
|
|
456
|
-
posts: [
|
|
457
|
-
/^\/api\/conversations\.(create|rename|archive|unarchive|invite|open|kick|leave|setTopic|setPurpose|mark)$/,
|
|
458
|
-
],
|
|
459
|
-
},
|
|
460
|
-
],
|
|
461
|
-
},
|
|
462
|
-
"files.write": {
|
|
463
|
-
label: "Files (upload)",
|
|
464
|
-
access: "write",
|
|
465
|
-
scopes: ["files:write"],
|
|
466
|
-
routes: [
|
|
467
|
-
{
|
|
468
|
-
host: "slack.com",
|
|
469
|
-
paths: [],
|
|
470
|
-
// The external upload flow; the retired `files.upload` stays off.
|
|
471
|
-
posts: [
|
|
472
|
-
/^\/api\/files\.(getUploadURLExternal|completeUploadExternal)$/,
|
|
473
|
-
],
|
|
474
|
-
},
|
|
475
|
-
],
|
|
476
|
-
},
|
|
477
|
-
"user-channels.manage": {
|
|
478
|
-
label: "Channels (as the installing person: read, manage, invite to)",
|
|
479
|
-
access: "write",
|
|
480
|
-
scopes: [],
|
|
481
|
-
// Slack's `user_scope`: issued to the person's own token, which
|
|
482
|
-
// Open CRM uses to invite the bot to private channels.
|
|
483
|
-
userScopes: [
|
|
484
|
-
"channels:read",
|
|
485
|
-
"channels:write",
|
|
486
|
-
"groups:read",
|
|
487
|
-
"groups:write",
|
|
488
|
-
],
|
|
489
|
-
routes: [
|
|
490
|
-
{
|
|
491
|
-
host: "slack.com",
|
|
492
|
-
paths: [
|
|
493
|
-
"/api/conversations.list",
|
|
494
|
-
"/api/conversations.info",
|
|
495
|
-
"/api/conversations.members",
|
|
496
|
-
"/api/users.conversations",
|
|
497
|
-
],
|
|
498
|
-
posts: [
|
|
499
|
-
/^\/api\/conversations\.(list|info|members|create|rename|archive|unarchive|invite|kick|leave|setTopic|setPurpose|mark)$/,
|
|
500
|
-
/^\/api\/users\.conversations$/,
|
|
501
|
-
],
|
|
502
|
-
},
|
|
503
|
-
],
|
|
504
|
-
},
|
|
505
|
-
},
|
|
506
|
-
},
|
|
507
|
-
api: ["slack.com"],
|
|
508
|
-
// Slack refuses `code_challenge`; `auth.test` names the workspace and
|
|
509
|
-
// the installing person.
|
|
510
|
-
flow: {
|
|
511
|
-
tokenUrl: "https://slack.com/api/oauth.v2.access",
|
|
512
|
-
revokeUrl: "https://slack.com/api/auth.revoke",
|
|
513
|
-
pkce: false,
|
|
514
|
-
scopeDialect: "slack",
|
|
515
|
-
identity: {
|
|
516
|
-
url: "https://slack.com/api/auth.test",
|
|
517
|
-
label: "team",
|
|
518
|
-
id: "user_id",
|
|
519
|
-
},
|
|
520
|
-
},
|
|
521
|
-
},
|
|
522
|
-
// Clients several apps share with different needs, so each app lists the
|
|
523
|
-
// scope sets it uses: Open CRM reads a member's own mailbox and calendar
|
|
524
|
-
// (`gmail.read`, `calendar.read`; `identity`, `mail.read`), OpenSEO reads
|
|
525
|
-
// a site's Search Console and Analytics (`identity`, `search-console.read`,
|
|
526
|
-
// `analytics.read`). Every set is read-only. Google's is one Cloud project
|
|
527
|
-
// apart from the YouTube preset's; Gmail's read scope is restricted and needs
|
|
528
|
-
// Google's verification, and whether Search Console and Analytics share
|
|
529
|
-
// that consent screen with it is the operator's choice when verifying.
|
|
530
|
-
"google-workspace": {
|
|
531
|
-
mode: "oauth_client",
|
|
532
|
-
label: "Google (Gmail, Calendar, Search Console and Analytics)",
|
|
533
|
-
secrets: {
|
|
534
|
-
clientId: "GOOGLE_WORKSPACE_CLIENT_ID",
|
|
535
|
-
clientSecret: "GOOGLE_WORKSPACE_CLIENT_SECRET",
|
|
536
|
-
},
|
|
537
|
-
token: [
|
|
538
|
-
{
|
|
539
|
-
host: "oauth2.googleapis.com",
|
|
540
|
-
path: "/token",
|
|
541
|
-
methods: ["POST"],
|
|
542
|
-
inject: "form",
|
|
543
|
-
},
|
|
544
|
-
],
|
|
545
|
-
access: ["write"],
|
|
546
|
-
console: "https://console.cloud.google.com/apis/credentials",
|
|
547
|
-
setup: "setup/google.md",
|
|
548
|
-
authorize: {
|
|
549
|
-
url: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
550
|
-
scopes: [
|
|
551
|
-
"openid",
|
|
552
|
-
"email",
|
|
553
|
-
"profile",
|
|
554
|
-
"https://www.googleapis.com/auth/gmail.readonly",
|
|
555
|
-
"https://www.googleapis.com/auth/calendar.readonly",
|
|
556
|
-
"https://www.googleapis.com/auth/webmasters.readonly",
|
|
557
|
-
"https://www.googleapis.com/auth/analytics.readonly",
|
|
558
|
-
],
|
|
559
|
-
},
|
|
560
|
-
scopePolicy: {
|
|
561
|
-
dialect: "google",
|
|
562
|
-
// Google documents no scope on either token leg: the response's
|
|
563
|
-
// `scope` is where the gateway learns what a token holds.
|
|
564
|
-
grantTypes: ["authorization_code", "refresh_token"],
|
|
565
|
-
requestScope: "drop",
|
|
566
|
-
alwaysRequested: [],
|
|
567
|
-
// Both spellings: Google documents `email`/`profile` and the userinfo
|
|
568
|
-
// URLs as the same grants, and echoes the URLs.
|
|
569
|
-
tolerated: [
|
|
570
|
-
"openid",
|
|
571
|
-
"email",
|
|
572
|
-
"profile",
|
|
573
|
-
"https://www.googleapis.com/auth/userinfo.email",
|
|
574
|
-
"https://www.googleapis.com/auth/userinfo.profile",
|
|
575
|
-
],
|
|
576
|
-
// Gmail's and Calendar's `/batch/<api>/<version>` carry whole requests
|
|
577
|
-
// inside; Analytics' measurement protocol secrets are readable under
|
|
578
|
-
// the read-only scope.
|
|
579
|
-
deniedSegments: ["batch", "measurementProtocolSecrets"],
|
|
580
|
-
sets: {
|
|
581
|
-
identity: {
|
|
582
|
-
label: "Google account (who you are)",
|
|
583
|
-
access: "read",
|
|
584
|
-
scopes: ["openid", "email", "profile"],
|
|
585
|
-
routes: [
|
|
586
|
-
{ host: "openidconnect.googleapis.com", paths: ["/v1/userinfo"] },
|
|
587
|
-
{
|
|
588
|
-
host: "www.googleapis.com",
|
|
589
|
-
paths: [
|
|
590
|
-
"/oauth2/v2/userinfo",
|
|
591
|
-
"/oauth2/v3/userinfo",
|
|
592
|
-
"/userinfo/v2/me",
|
|
593
|
-
],
|
|
594
|
-
},
|
|
595
|
-
],
|
|
596
|
-
},
|
|
597
|
-
"gmail.read": {
|
|
598
|
-
label: "Gmail (read-only)",
|
|
599
|
-
access: "read",
|
|
600
|
-
scopes: ["https://www.googleapis.com/auth/gmail.readonly"],
|
|
601
|
-
routes: [
|
|
602
|
-
{
|
|
603
|
-
host: "gmail.googleapis.com",
|
|
604
|
-
paths: ["/gmail/v1/users/"],
|
|
605
|
-
// Push notifications start and stop; `messages/send`, drafts
|
|
606
|
-
// and `modify` are the other POSTs under the same prefix.
|
|
607
|
-
posts: [/^\/gmail\/v1\/users\/[^/]+\/(watch|stop)$/],
|
|
608
|
-
},
|
|
609
|
-
],
|
|
610
|
-
},
|
|
611
|
-
"calendar.read": {
|
|
612
|
-
label: "Google Calendar (read-only)",
|
|
613
|
-
access: "read",
|
|
614
|
-
scopes: ["https://www.googleapis.com/auth/calendar.readonly"],
|
|
615
|
-
routes: [
|
|
616
|
-
{
|
|
617
|
-
host: "www.googleapis.com",
|
|
618
|
-
paths: ["/calendar/v3/"],
|
|
619
|
-
posts: [
|
|
620
|
-
/^\/calendar\/v3\/freeBusy$/,
|
|
621
|
-
/^\/calendar\/v3\/calendars\/[^/]+\/events\/watch$/,
|
|
622
|
-
/^\/calendar\/v3\/users\/me\/calendarList\/watch$/,
|
|
623
|
-
/^\/calendar\/v3\/channels\/stop$/,
|
|
624
|
-
],
|
|
625
|
-
},
|
|
626
|
-
],
|
|
627
|
-
},
|
|
628
|
-
"search-console.read": {
|
|
629
|
-
label: "Search Console (read-only)",
|
|
630
|
-
access: "read",
|
|
631
|
-
scopes: ["https://www.googleapis.com/auth/webmasters.readonly"],
|
|
632
|
-
// The v3 paths answer on both hosts; URL inspection is v1 only.
|
|
633
|
-
// A site is one segment, `https%3A%2F%2Fexample.com%2F` or
|
|
634
|
-
// `sc-domain%3Aexample.com`, which is why routes match the raw path.
|
|
635
|
-
routes: [
|
|
636
|
-
{
|
|
637
|
-
host: "www.googleapis.com",
|
|
638
|
-
paths: ["/webmasters/v3/"],
|
|
639
|
-
posts: [
|
|
640
|
-
/^\/webmasters\/v3\/sites\/[^/]+\/searchAnalytics\/query$/,
|
|
641
|
-
],
|
|
642
|
-
},
|
|
643
|
-
{
|
|
644
|
-
host: "searchconsole.googleapis.com",
|
|
645
|
-
paths: ["/webmasters/v3/"],
|
|
646
|
-
posts: [
|
|
647
|
-
/^\/webmasters\/v3\/sites\/[^/]+\/searchAnalytics\/query$/,
|
|
648
|
-
/^\/v1\/urlInspection\/index:inspect$/,
|
|
649
|
-
],
|
|
650
|
-
},
|
|
651
|
-
],
|
|
652
|
-
},
|
|
653
|
-
"analytics.read": {
|
|
654
|
-
label: "Google Analytics (read-only)",
|
|
655
|
-
access: "read",
|
|
656
|
-
scopes: ["https://www.googleapis.com/auth/analytics.readonly"],
|
|
657
|
-
routes: [
|
|
658
|
-
{
|
|
659
|
-
// Reports are POSTed queries.
|
|
660
|
-
host: "analyticsdata.googleapis.com",
|
|
661
|
-
paths: ["/v1beta/properties/"],
|
|
662
|
-
posts: [
|
|
663
|
-
/^\/v1beta\/properties\/[^/]+:(runReport|batchRunReports|runPivotReport|batchRunPivotReports|runRealtimeReport|checkCompatibility)$/,
|
|
664
|
-
],
|
|
665
|
-
},
|
|
666
|
-
{
|
|
667
|
-
// Reads only: accounts, properties and what hangs off them
|
|
668
|
-
// (data streams, key events, enhanced measurement settings).
|
|
669
|
-
host: "analyticsadmin.googleapis.com",
|
|
670
|
-
paths: [
|
|
671
|
-
"/v1beta/accountSummaries",
|
|
672
|
-
"/v1beta/accounts",
|
|
673
|
-
"/v1beta/accounts/",
|
|
674
|
-
"/v1beta/properties",
|
|
675
|
-
"/v1beta/properties/",
|
|
676
|
-
"/v1alpha/properties/",
|
|
677
|
-
],
|
|
678
|
-
},
|
|
679
|
-
],
|
|
680
|
-
},
|
|
681
|
-
},
|
|
682
|
-
},
|
|
683
|
-
api: [
|
|
684
|
-
"gmail.googleapis.com",
|
|
685
|
-
"www.googleapis.com",
|
|
686
|
-
"searchconsole.googleapis.com",
|
|
687
|
-
"analyticsdata.googleapis.com",
|
|
688
|
-
"analyticsadmin.googleapis.com",
|
|
689
|
-
"openidconnect.googleapis.com",
|
|
690
|
-
],
|
|
691
|
-
// The Gateway-owned flow: a refresh token needs `access_type=offline`,
|
|
692
|
-
// and `prompt=consent` makes Google issue one on every connect. No
|
|
693
|
-
// revoke: Google's `/revoke` is per person per client and would also
|
|
694
|
-
// kill the tokens an app-driven OpenSEO holds under the same client.
|
|
695
|
-
flow: {
|
|
696
|
-
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
697
|
-
pkce: true,
|
|
698
|
-
scopeDialect: "google",
|
|
699
|
-
authorizeParams: { access_type: "offline", prompt: "consent" },
|
|
700
|
-
identity: {
|
|
701
|
-
url: "https://openidconnect.googleapis.com/v1/userinfo",
|
|
702
|
-
label: "email",
|
|
703
|
-
id: "sub",
|
|
704
|
-
},
|
|
705
|
-
},
|
|
706
|
-
},
|
|
707
|
-
"microsoft-365": {
|
|
708
|
-
mode: "oauth_client",
|
|
709
|
-
label: "Microsoft 365 (Outlook mail and calendar)",
|
|
710
|
-
secrets: {
|
|
711
|
-
clientId: "MICROSOFT_365_CLIENT_ID",
|
|
712
|
-
clientSecret: "MICROSOFT_365_CLIENT_SECRET",
|
|
713
|
-
},
|
|
714
|
-
token: [
|
|
715
|
-
{
|
|
716
|
-
// The multi-tenant endpoint: register the client for accounts in
|
|
717
|
-
// any organization and personal accounts. A single-tenant client
|
|
718
|
-
// answers only on its tenant's path, which this does not complete.
|
|
719
|
-
host: "login.microsoftonline.com",
|
|
720
|
-
path: "/common/oauth2/v2.0/token",
|
|
721
|
-
methods: ["POST"],
|
|
722
|
-
inject: "form",
|
|
723
|
-
},
|
|
724
|
-
],
|
|
725
|
-
access: ["write"],
|
|
726
|
-
console: "https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade",
|
|
727
|
-
setup: "setup/microsoft-365.md",
|
|
728
|
-
authorize: {
|
|
729
|
-
url: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
730
|
-
scopes: ["offline_access", "User.Read", "Mail.Read", "Calendars.Read"],
|
|
731
|
-
},
|
|
732
|
-
scopePolicy: {
|
|
733
|
-
dialect: "microsoft",
|
|
734
|
-
grantTypes: ["authorization_code", "refresh_token"],
|
|
735
|
-
// The token leg's `scope` is Microsoft's extension for naming the
|
|
736
|
-
// resource; the gateway sets it to the app's list so a token covers
|
|
737
|
-
// Graph alone.
|
|
738
|
-
requestScope: "replace",
|
|
739
|
-
// Refresh tokens; Entra never echoes it in a response's `scope`.
|
|
740
|
-
alwaysRequested: ["offline_access"],
|
|
741
|
-
// Compared case-insensitively, as Microsoft spells them both ways.
|
|
742
|
-
tolerated: ["openid", "profile", "email", "offline_access", "User.Read"],
|
|
743
|
-
// `$batch` carries whole requests inside; `beta` is another API.
|
|
744
|
-
deniedSegments: ["$batch", "beta"],
|
|
745
|
-
// `/v1.0/me/…` only: `/v1.0/users/<id>/…` reaches shared mailboxes
|
|
746
|
-
// and calendars under the same permissions.
|
|
747
|
-
sets: {
|
|
748
|
-
identity: {
|
|
749
|
-
label: "Microsoft account (who you are)",
|
|
750
|
-
access: "read",
|
|
751
|
-
scopes: ["User.Read"],
|
|
752
|
-
routes: [
|
|
753
|
-
{
|
|
754
|
-
host: "graph.microsoft.com",
|
|
755
|
-
paths: ["/v1.0/me", "/oidc/userinfo"],
|
|
756
|
-
},
|
|
757
|
-
],
|
|
758
|
-
},
|
|
759
|
-
"mail.read": {
|
|
760
|
-
label: "Outlook mail (read-only)",
|
|
761
|
-
access: "read",
|
|
762
|
-
scopes: ["Mail.Read"],
|
|
763
|
-
routes: [
|
|
764
|
-
{
|
|
765
|
-
host: "graph.microsoft.com",
|
|
766
|
-
paths: [
|
|
767
|
-
"/v1.0/me/messages",
|
|
768
|
-
"/v1.0/me/messages/",
|
|
769
|
-
"/v1.0/me/mailFolders",
|
|
770
|
-
"/v1.0/me/mailFolders/",
|
|
771
|
-
],
|
|
772
|
-
},
|
|
773
|
-
],
|
|
774
|
-
},
|
|
775
|
-
"calendar.read": {
|
|
776
|
-
label: "Outlook calendar (read-only)",
|
|
777
|
-
access: "read",
|
|
778
|
-
scopes: ["Calendars.Read"],
|
|
779
|
-
routes: [
|
|
780
|
-
{
|
|
781
|
-
host: "graph.microsoft.com",
|
|
782
|
-
paths: [
|
|
783
|
-
"/v1.0/me/calendar",
|
|
784
|
-
"/v1.0/me/calendar/",
|
|
785
|
-
"/v1.0/me/calendars",
|
|
786
|
-
"/v1.0/me/calendars/",
|
|
787
|
-
"/v1.0/me/events",
|
|
788
|
-
"/v1.0/me/events/",
|
|
789
|
-
"/v1.0/me/calendarView",
|
|
790
|
-
"/v1.0/me/calendarView/",
|
|
791
|
-
],
|
|
792
|
-
// Free/busy is a POSTed query.
|
|
793
|
-
posts: [/^\/v1\.0\/me\/calendar\/getSchedule$/],
|
|
794
|
-
},
|
|
795
|
-
],
|
|
796
|
-
},
|
|
797
|
-
},
|
|
798
|
-
},
|
|
799
|
-
api: ["graph.microsoft.com"],
|
|
800
|
-
flow: {
|
|
801
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
802
|
-
pkce: true,
|
|
803
|
-
scopeDialect: "microsoft",
|
|
804
|
-
identity: {
|
|
805
|
-
url: "https://graph.microsoft.com/v1.0/me",
|
|
806
|
-
label: "userPrincipalName",
|
|
807
|
-
id: "id",
|
|
808
|
-
},
|
|
809
|
-
},
|
|
810
|
-
},
|
|
311
|
+
// The OAuth providers every Gateway has built in, from their JSON specs
|
|
312
|
+
// (./oauthBuiltIns.ts): what differs between them is data there.
|
|
313
|
+
slack: builtInOAuth(BUILT_IN_OAUTH_SPECS.slack, "setup/slack.md"),
|
|
314
|
+
"google-workspace": builtInOAuth(BUILT_IN_OAUTH_SPECS["google-workspace"], "setup/google.md"),
|
|
315
|
+
"microsoft-365": builtInOAuth(BUILT_IN_OAUTH_SPECS["microsoft-365"], "setup/microsoft-365.md"),
|
|
811
316
|
// The first fifty beyond the entries above (catalog/*.ts, PR 3 of the
|
|
812
317
|
// provider registry), after them so the derived lists keep their order.
|
|
813
318
|
...CATALOG_ENTRIES,
|
|
@@ -831,7 +336,12 @@ export function capabilitySettings(capability) {
|
|
|
831
336
|
...(capability.hostSetting ? [capability.hostSetting] : []),
|
|
832
337
|
];
|
|
833
338
|
case "ai":
|
|
834
|
-
|
|
339
|
+
// Every setting `auth` names, as for an API-key provider: a Basic
|
|
340
|
+
// username held as a setting is checked, bound and listed like the key.
|
|
341
|
+
return [
|
|
342
|
+
...authSettingNames(capability.auth),
|
|
343
|
+
...(capability.alsoNeeds ?? []),
|
|
344
|
+
];
|
|
835
345
|
case "service":
|
|
836
346
|
return [...capability.settings, ...capability.optionalSettings];
|
|
837
347
|
case "oauth_client":
|
|
@@ -864,7 +374,13 @@ export function capabilityIdsOf(lookup) {
|
|
|
864
374
|
* to encode, or taken as already encoded when it holds no colon.
|
|
865
375
|
*/
|
|
866
376
|
export function authorizationFor(capability, settings) {
|
|
867
|
-
|
|
377
|
+
// Only the settings the entry declares are visible: whatever `auth` reads
|
|
378
|
+
// beyond them (a setting no row check saw) is unset, and the call fails closed.
|
|
379
|
+
const declared = {};
|
|
380
|
+
for (const name of capabilitySettings(capability)) {
|
|
381
|
+
declared[name] = settings[name];
|
|
382
|
+
}
|
|
383
|
+
return authorizationOf(capability.auth, declared);
|
|
868
384
|
}
|
|
869
385
|
/** {@link authorizationFor} for an `auth` block alone (the SDK's AI fallback holds the block, not the entry). */
|
|
870
386
|
export function authorizationOf(auth, settings) {
|
|
@@ -959,9 +475,8 @@ export function serviceRoutePath(id, route) {
|
|
|
959
475
|
/**
|
|
960
476
|
* The capability call an AppGateway path names, or null when the path names
|
|
961
477
|
* an unknown capability (or an AI provider, which has its own route), a
|
|
962
|
-
* host outside the provider's, a path that could leave that host, a
|
|
963
|
-
*
|
|
964
|
-
* capability doesn't declare. `settings` resolves an API-key provider's
|
|
478
|
+
* host outside the provider's, a path that could leave that host, or a
|
|
479
|
+
* route a service capability doesn't declare. `settings` resolves an API-key provider's
|
|
965
480
|
* `hostSetting` (a Shopify store's host); `lookup` is where the id is found,
|
|
966
481
|
* the catalog alone by default.
|
|
967
482
|
*/
|
|
@@ -986,13 +501,12 @@ export function parseIntegrationProxyPath(pathname, search, settings, lookup = C
|
|
|
986
501
|
};
|
|
987
502
|
}
|
|
988
503
|
if (capability.mode === "oauth_client") {
|
|
989
|
-
const upstream = capability.
|
|
504
|
+
const upstream = capability.api.includes(host)
|
|
990
505
|
? httpsUpstream(host, path ?? "/", search)
|
|
991
506
|
: null;
|
|
992
|
-
|
|
993
|
-
if (!upstream || !endpoint)
|
|
507
|
+
if (!upstream)
|
|
994
508
|
return null;
|
|
995
|
-
return { kind: "oauth_client", id, capability, upstream
|
|
509
|
+
return { kind: "oauth_client", id, capability, upstream };
|
|
996
510
|
}
|
|
997
511
|
if (capability.mode !== "api_key")
|
|
998
512
|
return null;
|
|
@@ -1013,21 +527,6 @@ function httpsUpstream(host, path, search) {
|
|
|
1013
527
|
return null;
|
|
1014
528
|
return upstream;
|
|
1015
529
|
}
|
|
1016
|
-
/**
|
|
1017
|
-
* The token endpoint `upstream` is, by its exact host and path, or null.
|
|
1018
|
-
* Its method is the caller's to check.
|
|
1019
|
-
*/
|
|
1020
|
-
export function tokenEndpointFor(capability, upstream) {
|
|
1021
|
-
if (upstream.protocol !== "https:")
|
|
1022
|
-
return null;
|
|
1023
|
-
return (capability.token.find(({ host, path }) => host === upstream.host && path === upstream.pathname) ?? null);
|
|
1024
|
-
}
|
|
1025
|
-
/** An OAuth client's token endpoints, as `POST https://host/path` lines for messages. */
|
|
1026
|
-
export function describeTokenEndpoints(capability) {
|
|
1027
|
-
return capability.token
|
|
1028
|
-
.map(({ host, path, methods }) => `${methods.join("/")} https://${host}${path}`)
|
|
1029
|
-
.join(", ");
|
|
1030
|
-
}
|
|
1031
530
|
/**
|
|
1032
531
|
* The command that gives the gateway `capability`'s client:
|
|
1033
532
|
* `pnpm everyapp secret set <ID> <SECRET>`.
|
|
@@ -146,7 +146,7 @@ export const COMMERCE = {
|
|
|
146
146
|
},
|
|
147
147
|
tags: ["payments", "billing"],
|
|
148
148
|
},
|
|
149
|
-
// Legacy admin custom apps only: Shopify no longer lets a store create one, and Dev Dashboard tokens expire daily (the hint says so; shipping it is Ben's call
|
|
149
|
+
// Legacy admin custom apps only: Shopify no longer lets a store create one, and Dev Dashboard tokens expire daily (the hint says so; shipping it is Ben's call).
|
|
150
150
|
shopify: {
|
|
151
151
|
mode: "api_key",
|
|
152
152
|
label: "Shopify",
|