@every-app/sdk 0.3.0-rc.8 → 0.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.
Files changed (146) hide show
  1. package/README.md +75 -74
  2. package/dist/cloudflare/catalogSettings.generated.d.ts +20 -6
  3. package/dist/cloudflare/catalogSettings.generated.d.ts.map +1 -1
  4. package/dist/cloudflare/catalogSettings.generated.js +45 -14
  5. package/dist/cloudflare/index.d.ts +1 -1
  6. package/dist/cloudflare/index.d.ts.map +1 -1
  7. package/dist/cloudflare/sentinel.d.ts +3 -0
  8. package/dist/cloudflare/sentinel.d.ts.map +1 -1
  9. package/dist/cloudflare/sentinel.js +10 -0
  10. package/dist/cloudflare/worker.d.ts +67 -23
  11. package/dist/cloudflare/worker.d.ts.map +1 -1
  12. package/dist/cloudflare/worker.js +68 -32
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/internal/aiDefault.d.ts +36 -79
  16. package/dist/internal/aiDefault.d.ts.map +1 -1
  17. package/dist/internal/aiDefault.js +47 -149
  18. package/dist/internal/aiProviders.d.ts +1 -1
  19. package/dist/internal/aiProviders.d.ts.map +1 -1
  20. package/dist/internal/aiProviders.js +2 -2
  21. package/dist/internal/appSettings.d.ts +140 -89
  22. package/dist/internal/appSettings.d.ts.map +1 -1
  23. package/dist/internal/appSettings.js +264 -156
  24. package/dist/internal/capabilities.d.ts +145 -503
  25. package/dist/internal/capabilities.d.ts.map +1 -1
  26. package/dist/internal/capabilities.js +29 -550
  27. package/dist/internal/catalog/commerce.js +1 -1
  28. package/dist/internal/catalog/comms.d.ts +37 -0
  29. package/dist/internal/catalog/comms.d.ts.map +1 -1
  30. package/dist/internal/catalog/comms.js +43 -0
  31. package/dist/internal/catalog/index.d.ts +72 -0
  32. package/dist/internal/catalog/index.d.ts.map +1 -1
  33. package/dist/internal/catalog/infra.d.ts +35 -0
  34. package/dist/internal/catalog/infra.d.ts.map +1 -1
  35. package/dist/internal/catalog/infra.js +65 -0
  36. package/dist/internal/devProviders.d.ts +1 -19
  37. package/dist/internal/devProviders.d.ts.map +1 -1
  38. package/dist/internal/devProviders.js +7 -1
  39. package/dist/internal/events.d.ts +52 -1
  40. package/dist/internal/events.d.ts.map +1 -1
  41. package/dist/internal/events.js +66 -2
  42. package/dist/internal/gatewaySettings.d.ts +6 -16
  43. package/dist/internal/gatewaySettings.d.ts.map +1 -1
  44. package/dist/internal/gatewaySettings.js +6 -24
  45. package/dist/internal/index.d.ts +1 -0
  46. package/dist/internal/index.d.ts.map +1 -1
  47. package/dist/internal/index.js +1 -0
  48. package/dist/internal/mcpOAuth.d.ts +210 -0
  49. package/dist/internal/mcpOAuth.d.ts.map +1 -0
  50. package/dist/internal/mcpOAuth.js +735 -0
  51. package/dist/internal/oauthClient.d.ts +7 -47
  52. package/dist/internal/oauthClient.d.ts.map +1 -1
  53. package/dist/internal/oauthClient.js +1 -115
  54. package/dist/internal/oauthPresets.d.ts +356 -20
  55. package/dist/internal/oauthPresets.d.ts.map +1 -1
  56. package/dist/internal/oauthPresets.js +183 -861
  57. package/dist/internal/oauthScopes.d.ts +43 -155
  58. package/dist/internal/oauthScopes.d.ts.map +1 -1
  59. package/dist/internal/oauthScopes.js +82 -475
  60. package/dist/internal/oauthSpec.d.ts +28 -71
  61. package/dist/internal/oauthSpec.d.ts.map +1 -1
  62. package/dist/internal/oauthSpec.js +172 -448
  63. package/dist/internal/protocol.d.ts +39 -15
  64. package/dist/internal/protocol.d.ts.map +1 -1
  65. package/dist/internal/protocol.js +40 -7
  66. package/dist/internal/providerApps.d.ts +2 -2
  67. package/dist/internal/providerApps.js +2 -2
  68. package/dist/internal/providerRegistry.d.ts +5 -64
  69. package/dist/internal/providerRegistry.d.ts.map +1 -1
  70. package/dist/internal/providerRegistry.js +19 -118
  71. package/dist/internal/providerSpec.d.ts.map +1 -1
  72. package/dist/internal/providerSpec.js +14 -36
  73. package/dist/internal/remoteMcp.d.ts +191 -47
  74. package/dist/internal/remoteMcp.d.ts.map +1 -1
  75. package/dist/internal/remoteMcp.js +338 -133
  76. package/dist/internal/signInProviders.d.ts +1 -1
  77. package/dist/internal/signInProviders.d.ts.map +1 -1
  78. package/dist/internal/tools.d.ts +15 -8
  79. package/dist/internal/tools.d.ts.map +1 -1
  80. package/dist/internal/tools.js +9 -8
  81. package/dist/manifest.d.ts +96 -28
  82. package/dist/manifest.d.ts.map +1 -1
  83. package/dist/manifest.js +1 -1
  84. package/dist/server/ai.d.ts +1 -93
  85. package/dist/server/ai.d.ts.map +1 -1
  86. package/dist/server/ai.js +17 -111
  87. package/dist/server/attribution.d.ts +10 -1
  88. package/dist/server/attribution.d.ts.map +1 -1
  89. package/dist/server/attribution.js +7 -1
  90. package/dist/server/connectUrl.d.ts +4 -9
  91. package/dist/server/connectUrl.d.ts.map +1 -1
  92. package/dist/server/connectUrl.js +17 -14
  93. package/dist/server/context.d.ts +12 -14
  94. package/dist/server/context.d.ts.map +1 -1
  95. package/dist/server/context.js +23 -25
  96. package/dist/server/emit.d.ts.map +1 -1
  97. package/dist/server/emit.js +2 -2
  98. package/dist/server/env.d.ts +3 -0
  99. package/dist/server/env.d.ts.map +1 -1
  100. package/dist/server/eventsEndpoint.d.ts +48 -0
  101. package/dist/server/eventsEndpoint.d.ts.map +1 -0
  102. package/dist/server/eventsEndpoint.js +145 -0
  103. package/dist/server/everyApp.d.ts +16 -26
  104. package/dist/server/everyApp.d.ts.map +1 -1
  105. package/dist/server/everyApp.js +22 -46
  106. package/dist/server/gatewayFetch.d.ts +19 -1
  107. package/dist/server/gatewayFetch.d.ts.map +1 -1
  108. package/dist/server/gatewayFetch.js +45 -3
  109. package/dist/server/index.d.ts +6 -9
  110. package/dist/server/index.d.ts.map +1 -1
  111. package/dist/server/index.js +4 -8
  112. package/dist/server/integrationFetch.d.ts +60 -72
  113. package/dist/server/integrationFetch.d.ts.map +1 -1
  114. package/dist/server/integrationFetch.js +124 -397
  115. package/dist/server/listMembers.d.ts.map +1 -1
  116. package/dist/server/listMembers.js +2 -2
  117. package/dist/server/refusal.d.ts +0 -9
  118. package/dist/server/refusal.d.ts.map +1 -1
  119. package/dist/server/refusal.js +0 -22
  120. package/dist/server/sendEmail.d.ts.map +1 -1
  121. package/dist/server/sendEmail.js +2 -2
  122. package/dist/server/tools.d.ts +17 -6
  123. package/dist/server/tools.d.ts.map +1 -1
  124. package/dist/server/tools.js +14 -4
  125. package/dist/server/toolsEndpoint.d.ts +2 -1
  126. package/dist/server/toolsEndpoint.d.ts.map +1 -1
  127. package/dist/server/toolsEndpoint.js +4 -3
  128. package/dist/server/webhooks.d.ts +56 -0
  129. package/dist/server/webhooks.d.ts.map +1 -0
  130. package/dist/server/webhooks.js +205 -0
  131. package/dist/testing/index.d.ts +2 -3
  132. package/dist/testing/index.d.ts.map +1 -1
  133. package/dist/testing/index.js +2 -6
  134. package/package.json +6 -1
  135. package/dist/server/aiBinding.d.ts +0 -68
  136. package/dist/server/aiBinding.d.ts.map +0 -1
  137. package/dist/server/aiBinding.js +0 -294
  138. package/dist/server/authorizeUrl.d.ts +0 -43
  139. package/dist/server/authorizeUrl.d.ts.map +0 -1
  140. package/dist/server/authorizeUrl.js +0 -106
  141. package/dist/server/emailBinding.d.ts +0 -72
  142. package/dist/server/emailBinding.d.ts.map +0 -1
  143. package/dist/server/emailBinding.js +0 -124
  144. package/dist/server/fromMcpTools.d.ts +0 -89
  145. package/dist/server/fromMcpTools.d.ts.map +0 -1
  146. package/dist/server/fromMcpTools.js +0 -192
@@ -16,18 +16,15 @@
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`: a provider's OAuth client (Google's, Microsoft's,
20
- * Slack's), held the same way. The gateway completes the token endpoint
21
- * calls only, putting the client on them; the app builds the authorize
22
- * URL from the public client id (`integrationStatus()`), sends people
23
- * back to a callback its manifest entry lists (`redirectPaths`), keeps
24
- * the user tokens and calls the provider's API with them itself. Other
25
- * providers' clients (GitHub, the social networks) are presets
26
- * (./oauthPresets.ts): rows only once an operator adds one. A client shared by apps
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 whose client the gateway holds and
20
+ * whose flow it runs. None is in the catalog: each is a registered row,
21
+ * written from a preset (./oauthPresets.ts: Google, Microsoft, Slack,
22
+ * GitHub and the rest) or an operator's spec. A person connects in an app,
23
+ * for exactly the provider scopes the app's manifest entry lists
24
+ * (`scopes`); the gateway keeps the tokens and puts the person's token
25
+ * on the app's calls to the provider's `api` hosts. Each provider is a
26
+ * spec (./oauthSpec.ts), its differences data; ./oauthScopes.ts holds
27
+ * the one set of scope rules.
31
28
  * - `service`: something the gateway does itself, with no upstream host
32
29
  * an app names (sending email, listing the organization's members). An
33
30
  * app lists it the same way and calls its routes,
@@ -70,8 +67,8 @@ export const CAPABILITIES = {
70
67
  "/v1/images/variations",
71
68
  ],
72
69
  unstoredRoutes: ["/v1/responses", "/v1/chat/completions"],
73
- // More than inference needs both the operator (AI_PROXY_EXTRA_ROUTES)
74
- // and the app's manifest (`ai.routes`): OpenAI paths only.
70
+ // More than inference needs the app's manifest (`ai.routes`): OpenAI
71
+ // paths only.
75
72
  extraRoutes: true,
76
73
  // Tool calling on chat completions needs `reasoning_effort: "none"`
77
74
  // on the GPT-6 family (the responses route takes tools as it is).
@@ -296,518 +293,6 @@ export const CAPABILITIES = {
296
293
  settings: [],
297
294
  optionalSettings: [],
298
295
  },
299
- slack: {
300
- mode: "oauth_client",
301
- label: "Slack",
302
- secrets: {
303
- clientId: "SLACK_CLIENT_ID",
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
- },
811
296
  // The first fifty beyond the entries above (catalog/*.ts, PR 3 of the
812
297
  // provider registry), after them so the derived lists keep their order.
813
298
  ...CATALOG_ENTRIES,
@@ -831,7 +316,12 @@ export function capabilitySettings(capability) {
831
316
  ...(capability.hostSetting ? [capability.hostSetting] : []),
832
317
  ];
833
318
  case "ai":
834
- return [capability.auth.secret, ...(capability.alsoNeeds ?? [])];
319
+ // Every setting `auth` names, as for an API-key provider: a Basic
320
+ // username held as a setting is checked, bound and listed like the key.
321
+ return [
322
+ ...authSettingNames(capability.auth),
323
+ ...(capability.alsoNeeds ?? []),
324
+ ];
835
325
  case "service":
836
326
  return [...capability.settings, ...capability.optionalSettings];
837
327
  case "oauth_client":
@@ -864,7 +354,13 @@ export function capabilityIdsOf(lookup) {
864
354
  * to encode, or taken as already encoded when it holds no colon.
865
355
  */
866
356
  export function authorizationFor(capability, settings) {
867
- return authorizationOf(capability.auth, settings);
357
+ // Only the settings the entry declares are visible: whatever `auth` reads
358
+ // beyond them (a setting no row check saw) is unset, and the call fails closed.
359
+ const declared = {};
360
+ for (const name of capabilitySettings(capability)) {
361
+ declared[name] = settings[name];
362
+ }
363
+ return authorizationOf(capability.auth, declared);
868
364
  }
869
365
  /** {@link authorizationFor} for an `auth` block alone (the SDK's AI fallback holds the block, not the entry). */
870
366
  export function authorizationOf(auth, settings) {
@@ -959,9 +455,8 @@ export function serviceRoutePath(id, route) {
959
455
  /**
960
456
  * The capability call an AppGateway path names, or null when the path names
961
457
  * 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 path
963
- * that isn't one of an OAuth client's token endpoints, or a route a service
964
- * capability doesn't declare. `settings` resolves an API-key provider's
458
+ * host outside the provider's, a path that could leave that host, or a
459
+ * route a service capability doesn't declare. `settings` resolves an API-key provider's
965
460
  * `hostSetting` (a Shopify store's host); `lookup` is where the id is found,
966
461
  * the catalog alone by default.
967
462
  */
@@ -986,13 +481,12 @@ export function parseIntegrationProxyPath(pathname, search, settings, lookup = C
986
481
  };
987
482
  }
988
483
  if (capability.mode === "oauth_client") {
989
- const upstream = capability.token.some((rule) => rule.host === host)
484
+ const upstream = capability.api.includes(host)
990
485
  ? httpsUpstream(host, path ?? "/", search)
991
486
  : null;
992
- const endpoint = upstream && tokenEndpointFor(capability, upstream);
993
- if (!upstream || !endpoint)
487
+ if (!upstream)
994
488
  return null;
995
- return { kind: "oauth_client", id, capability, upstream, endpoint };
489
+ return { kind: "oauth_client", id, capability, upstream };
996
490
  }
997
491
  if (capability.mode !== "api_key")
998
492
  return null;
@@ -1013,21 +507,6 @@ function httpsUpstream(host, path, search) {
1013
507
  return null;
1014
508
  return upstream;
1015
509
  }
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
510
  /**
1032
511
  * The command that gives the gateway `capability`'s client:
1033
512
  * `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, TODO.md).
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",