@every-app/sdk 0.3.0-rc.5 → 0.3.0-rc.6

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 (76) hide show
  1. package/dist/cloudflare/catalogSettings.generated.d.ts +1 -16
  2. package/dist/cloudflare/catalogSettings.generated.d.ts.map +1 -1
  3. package/dist/cloudflare/catalogSettings.generated.js +0 -49
  4. package/dist/cloudflare/worker.d.ts +14 -0
  5. package/dist/cloudflare/worker.d.ts.map +1 -1
  6. package/dist/cloudflare/worker.js +19 -6
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/internal/aiDefault.d.ts +70 -7
  10. package/dist/internal/aiDefault.d.ts.map +1 -1
  11. package/dist/internal/aiDefault.js +145 -15
  12. package/dist/internal/aiProviders.d.ts +3 -1
  13. package/dist/internal/aiProviders.d.ts.map +1 -1
  14. package/dist/internal/aiProviders.js +12 -3
  15. package/dist/internal/appSettings.d.ts +65 -5
  16. package/dist/internal/appSettings.d.ts.map +1 -1
  17. package/dist/internal/appSettings.js +141 -23
  18. package/dist/internal/capabilities.d.ts +52 -433
  19. package/dist/internal/capabilities.d.ts.map +1 -1
  20. package/dist/internal/capabilities.js +25 -558
  21. package/dist/internal/catalog/index.d.ts +6 -6
  22. package/dist/internal/catalog/inference.d.ts +6 -6
  23. package/dist/internal/catalog/inference.d.ts.map +1 -1
  24. package/dist/internal/catalog/inference.js +9 -6
  25. package/dist/internal/events.d.ts.map +1 -1
  26. package/dist/internal/events.js +1 -0
  27. package/dist/internal/gatewaySettings.d.ts +0 -6
  28. package/dist/internal/gatewaySettings.d.ts.map +1 -1
  29. package/dist/internal/gatewaySettings.js +1 -14
  30. package/dist/internal/identity.d.ts +12 -1
  31. package/dist/internal/identity.d.ts.map +1 -1
  32. package/dist/internal/identity.js +11 -1
  33. package/dist/internal/oauthClient.d.ts +10 -12
  34. package/dist/internal/oauthClient.d.ts.map +1 -1
  35. package/dist/internal/oauthClient.js +20 -81
  36. package/dist/internal/oauthPresets.d.ts +7 -3
  37. package/dist/internal/oauthPresets.d.ts.map +1 -1
  38. package/dist/internal/oauthPresets.js +533 -3
  39. package/dist/internal/oauthSpec.d.ts +44 -1
  40. package/dist/internal/oauthSpec.d.ts.map +1 -1
  41. package/dist/internal/oauthSpec.js +147 -34
  42. package/dist/internal/protocol.d.ts +14 -0
  43. package/dist/internal/protocol.d.ts.map +1 -1
  44. package/dist/internal/protocol.js +7 -0
  45. package/dist/internal/providerRegistry.d.ts +61 -1
  46. package/dist/internal/providerRegistry.d.ts.map +1 -1
  47. package/dist/internal/providerRegistry.js +127 -6
  48. package/dist/internal/providerSpec.d.ts +14 -7
  49. package/dist/internal/providerSpec.d.ts.map +1 -1
  50. package/dist/internal/providerSpec.js +306 -7
  51. package/dist/manifest.d.ts +25 -4
  52. package/dist/manifest.d.ts.map +1 -1
  53. package/dist/server/ai.d.ts +45 -0
  54. package/dist/server/ai.d.ts.map +1 -1
  55. package/dist/server/ai.js +77 -1
  56. package/dist/server/aiBinding.d.ts.map +1 -1
  57. package/dist/server/aiBinding.js +3 -3
  58. package/dist/server/authorizeUrl.d.ts +1 -1
  59. package/dist/server/authorizeUrl.d.ts.map +1 -1
  60. package/dist/server/authorizeUrl.js +2 -6
  61. package/dist/server/emailBinding.js +1 -1
  62. package/dist/server/emit.js +1 -1
  63. package/dist/server/gatewayFetch.d.ts.map +1 -1
  64. package/dist/server/gatewayFetch.js +20 -7
  65. package/dist/server/index.d.ts +3 -2
  66. package/dist/server/index.d.ts.map +1 -1
  67. package/dist/server/index.js +3 -2
  68. package/dist/server/integrationFetch.d.ts +4 -31
  69. package/dist/server/integrationFetch.d.ts.map +1 -1
  70. package/dist/server/integrationFetch.js +44 -42
  71. package/dist/server/listMembers.js +1 -1
  72. package/dist/server/refusal.d.ts +55 -0
  73. package/dist/server/refusal.d.ts.map +1 -0
  74. package/dist/server/refusal.js +193 -0
  75. package/dist/server/sendEmail.js +1 -1
  76. package/package.json +1 -1
@@ -16,11 +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`: a provider's OAuth client (a social network's), held
20
- * the same way. The gateway completes the token endpoint calls only,
21
- * putting the client on them; the app builds the authorize URL from the
22
- * public client id (`integrationStatus()`), keeps the user tokens and
23
- * calls the provider's API with them itself. A client shared by apps
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
24
27
  * with different needs carries a `scopePolicy`: named scope sets an app
25
28
  * lists in its manifest entry's `scopes`, which ./oauthScopes.ts turns
26
29
  * into what the app may ask the provider for and what a token it is
@@ -72,8 +75,8 @@ export const CAPABILITIES = {
72
75
  extraRoutes: true,
73
76
  // Tool calling on chat completions needs `reasoning_effort: "none"`
74
77
  // on the GPT-6 family (the responses route takes tools as it is).
75
- chat: { path: "/v1/chat/completions", model: "gpt-6-luna" },
76
- embeddings: { path: "/v1/embeddings", model: "text-embedding-3-small" },
78
+ chat: { path: "/v1/chat/completions", seedModel: "gpt-6-luna" },
79
+ embeddings: { path: "/v1/embeddings", seedModel: "text-embedding-3-small" },
77
80
  // AI Gateway's OpenAI endpoint takes the path without `/v1`.
78
81
  aig: { slug: "openai", trim: "/v1" },
79
82
  hint: "A secret key from the API keys page; the Gateway puts it on every call as a bearer token.",
@@ -98,11 +101,11 @@ export const CAPABILITIES = {
98
101
  ],
99
102
  chat: {
100
103
  path: "/api/v1/chat/completions",
101
- model: "anthropic/claude-haiku-5.5",
104
+ seedModel: "anthropic/claude-haiku-5.5",
102
105
  },
103
106
  embeddings: {
104
107
  path: "/api/v1/embeddings",
105
- model: "openai/text-embedding-3-small",
108
+ seedModel: "openai/text-embedding-3-small",
106
109
  },
107
110
  // AI Gateway's OpenRouter endpoint takes the path without `/api`.
108
111
  aig: { slug: "openrouter", trim: "/api" },
@@ -140,9 +143,9 @@ export const CAPABILITIES = {
140
143
  normalize: "workers-ai",
141
144
  chat: {
142
145
  path: "/v1/chat/completions",
143
- model: "@cf/meta/llama-4-scout-17b-16e-instruct",
146
+ seedModel: "@cf/meta/llama-4-scout-17b-16e-instruct",
144
147
  },
145
- embeddings: { path: "/v1/embeddings", model: "@cf/baai/bge-m3" },
148
+ embeddings: { path: "/v1/embeddings", seedModel: "@cf/baai/bge-m3" },
146
149
  // Workers AI's REST API is AI Gateway's own host: the URL stays and
147
150
  // `cf-aig-gateway-id` names the gateway.
148
151
  aig: { slug: "workers-ai", header: true },
@@ -293,359 +296,6 @@ export const CAPABILITIES = {
293
296
  settings: [],
294
297
  optionalSettings: [],
295
298
  },
296
- // Social networks' OAuth clients (docs/capabilities.md "OAuth clients"):
297
- // the gateway completes their token endpoints only. Postiz connects its
298
- // channels with them; one client serves every organization on the gateway.
299
- linkedin: {
300
- mode: "oauth_client",
301
- label: "LinkedIn",
302
- secrets: {
303
- clientId: "LINKEDIN_CLIENT_ID",
304
- clientSecret: "LINKEDIN_CLIENT_SECRET",
305
- },
306
- token: [
307
- {
308
- host: "www.linkedin.com",
309
- path: "/oauth/v2/accessToken",
310
- methods: ["POST"],
311
- inject: "form",
312
- },
313
- ],
314
- access: ["write"],
315
- console: "https://www.linkedin.com/developers/apps",
316
- authorize: {
317
- url: "https://www.linkedin.com/oauth/v2/authorization",
318
- scopes: [
319
- "openid",
320
- "profile",
321
- "w_member_social",
322
- "r_basicprofile",
323
- "rw_organization_admin",
324
- "w_organization_social",
325
- "r_organization_social",
326
- ],
327
- },
328
- api: ["api.linkedin.com"],
329
- // Profiles and pages: both callbacks complete on the one client.
330
- redirectPaths: [
331
- "/integrations/social/linkedin",
332
- "/integrations/social/linkedin-page",
333
- ],
334
- },
335
- facebook: {
336
- mode: "oauth_client",
337
- label: "Facebook",
338
- secrets: {
339
- clientId: "FACEBOOK_APP_ID",
340
- clientSecret: "FACEBOOK_APP_SECRET",
341
- },
342
- token: [
343
- {
344
- // The code exchange and the long-lived token exchange, both on a
345
- // versioned path (/v25.0/oauth/access_token).
346
- host: "graph.facebook.com",
347
- path: /^\/v\d+\.\d+\/oauth\/access_token$/,
348
- methods: ["GET", "POST"],
349
- inject: "query",
350
- },
351
- ],
352
- access: ["write"],
353
- console: "https://developers.facebook.com/apps",
354
- authorize: {
355
- url: "https://www.facebook.com/v25.0/dialog/oauth",
356
- // Facebook pages, and Instagram business accounts through them.
357
- scopes: [
358
- "pages_show_list",
359
- "business_management",
360
- "pages_manage_posts",
361
- "pages_manage_engagement",
362
- "pages_read_engagement",
363
- "read_insights",
364
- "instagram_basic",
365
- "instagram_content_publish",
366
- "instagram_manage_comments",
367
- "instagram_manage_insights",
368
- ],
369
- },
370
- api: ["graph.facebook.com", "graph.instagram.com"],
371
- redirectPaths: [
372
- "/integrations/social/facebook",
373
- "/integrations/social/instagram",
374
- ],
375
- },
376
- instagram: {
377
- mode: "oauth_client",
378
- label: "Instagram",
379
- secrets: {
380
- clientId: "INSTAGRAM_APP_ID",
381
- clientSecret: "INSTAGRAM_APP_SECRET",
382
- },
383
- token: [
384
- // The code exchange, then the long-lived token exchange.
385
- {
386
- host: "api.instagram.com",
387
- path: "/oauth/access_token",
388
- methods: ["POST"],
389
- inject: "form",
390
- },
391
- {
392
- host: "graph.instagram.com",
393
- path: "/access_token",
394
- methods: ["GET"],
395
- inject: "query",
396
- },
397
- ],
398
- access: ["write"],
399
- console: "https://developers.facebook.com/apps",
400
- authorize: {
401
- url: "https://www.instagram.com/oauth/authorize",
402
- scopes: [
403
- "instagram_business_basic",
404
- "instagram_business_content_publish",
405
- "instagram_business_manage_comments",
406
- "instagram_business_manage_insights",
407
- ],
408
- },
409
- api: ["graph.instagram.com"],
410
- redirectPaths: ["/integrations/social/instagram-standalone"],
411
- },
412
- threads: {
413
- mode: "oauth_client",
414
- label: "Threads",
415
- secrets: { clientId: "THREADS_APP_ID", clientSecret: "THREADS_APP_SECRET" },
416
- token: [
417
- // The code exchange, then the long-lived token exchange.
418
- {
419
- host: "graph.threads.net",
420
- path: "/oauth/access_token",
421
- methods: ["GET", "POST"],
422
- inject: "query",
423
- },
424
- {
425
- host: "graph.threads.net",
426
- path: "/access_token",
427
- methods: ["GET"],
428
- inject: "query",
429
- },
430
- ],
431
- access: ["write"],
432
- console: "https://developers.facebook.com/apps",
433
- authorize: {
434
- url: "https://threads.net/oauth/authorize",
435
- scopes: [
436
- "threads_basic",
437
- "threads_content_publish",
438
- "threads_manage_replies",
439
- "threads_manage_insights",
440
- ],
441
- },
442
- api: ["graph.threads.net"],
443
- redirectPaths: ["/integrations/social/threads"],
444
- },
445
- youtube: {
446
- mode: "oauth_client",
447
- label: "YouTube",
448
- secrets: {
449
- clientId: "YOUTUBE_CLIENT_ID",
450
- clientSecret: "YOUTUBE_CLIENT_SECRET",
451
- },
452
- token: [
453
- {
454
- host: "oauth2.googleapis.com",
455
- path: "/token",
456
- methods: ["POST"],
457
- inject: "form",
458
- },
459
- ],
460
- access: ["write"],
461
- console: "https://console.cloud.google.com/apis/credentials",
462
- setup: "setup/google.md",
463
- authorize: {
464
- url: "https://accounts.google.com/o/oauth2/v2/auth",
465
- // YouTube channels, and Google Business Profiles on the same client.
466
- scopes: [
467
- "https://www.googleapis.com/auth/userinfo.profile",
468
- "https://www.googleapis.com/auth/userinfo.email",
469
- "https://www.googleapis.com/auth/youtube",
470
- "https://www.googleapis.com/auth/youtube.force-ssl",
471
- "https://www.googleapis.com/auth/youtube.readonly",
472
- "https://www.googleapis.com/auth/youtube.upload",
473
- "https://www.googleapis.com/auth/youtubepartner",
474
- "https://www.googleapis.com/auth/yt-analytics.readonly",
475
- "https://www.googleapis.com/auth/business.manage",
476
- ],
477
- },
478
- api: [
479
- "www.googleapis.com",
480
- "youtubeanalytics.googleapis.com",
481
- "mybusinessaccountmanagement.googleapis.com",
482
- "mybusinessbusinessinformation.googleapis.com",
483
- "mybusiness.googleapis.com",
484
- "businessprofileperformance.googleapis.com",
485
- ],
486
- redirectPaths: ["/integrations/social/youtube", "/integrations/social/gmb"],
487
- },
488
- tiktok: {
489
- mode: "oauth_client",
490
- label: "TikTok",
491
- secrets: {
492
- clientId: "TIKTOK_CLIENT_ID",
493
- clientSecret: "TIKTOK_CLIENT_SECRET",
494
- },
495
- token: [
496
- {
497
- host: "open.tiktokapis.com",
498
- path: "/v2/oauth/token/",
499
- methods: ["POST"],
500
- inject: "form",
501
- // TikTok calls the client id its client key.
502
- params: { clientId: "client_key" },
503
- },
504
- ],
505
- access: ["write"],
506
- console: "https://developers.tiktok.com/apps",
507
- authorize: {
508
- url: "https://www.tiktok.com/v2/auth/authorize/",
509
- scopes: [
510
- "video.list",
511
- "user.info.basic",
512
- "video.publish",
513
- "video.upload",
514
- "user.info.profile",
515
- "user.info.stats",
516
- ],
517
- },
518
- api: ["open.tiktokapis.com"],
519
- redirectPaths: ["/integrations/social/tiktok"],
520
- },
521
- "tiktok-business": {
522
- mode: "oauth_client",
523
- label: "TikTok Business",
524
- secrets: {
525
- clientId: "TIKTOK_BUSINESS_CLIENT_ID",
526
- clientSecret: "TIKTOK_BUSINESS_CLIENT_SECRET",
527
- },
528
- token: [
529
- {
530
- host: "business-api.tiktok.com",
531
- path: "/open_api/v1.3/tt_user/oauth2/token/",
532
- methods: ["POST"],
533
- inject: "json",
534
- },
535
- {
536
- host: "business-api.tiktok.com",
537
- path: "/open_api/v1.3/tt_user/oauth2/refresh_token/",
538
- methods: ["POST"],
539
- inject: "json",
540
- },
541
- ],
542
- access: ["write"],
543
- console: "https://business-api.tiktok.com/portal/apps",
544
- authorize: {
545
- url: "https://www.tiktok.com/v2/auth/authorize/",
546
- scopes: [
547
- "user.info.basic",
548
- "user.info.username",
549
- "user.info.stats",
550
- "video.list",
551
- "video.upload",
552
- "video.publish",
553
- ],
554
- },
555
- api: ["business-api.tiktok.com"],
556
- // TikTok Business wants the trailing slash.
557
- redirectPaths: ["/integrations/social/tiktok-business/"],
558
- },
559
- reddit: {
560
- mode: "oauth_client",
561
- label: "Reddit",
562
- secrets: {
563
- clientId: "REDDIT_CLIENT_ID",
564
- clientSecret: "REDDIT_CLIENT_SECRET",
565
- },
566
- token: [
567
- {
568
- host: "www.reddit.com",
569
- path: "/api/v1/access_token",
570
- methods: ["POST"],
571
- inject: "basic",
572
- },
573
- ],
574
- access: ["write"],
575
- console: "https://www.reddit.com/prefs/apps",
576
- authorize: {
577
- url: "https://www.reddit.com/api/v1/authorize",
578
- scopes: ["read", "identity", "submit", "flair"],
579
- },
580
- api: ["oauth.reddit.com"],
581
- redirectPaths: ["/integrations/social/reddit"],
582
- },
583
- pinterest: {
584
- mode: "oauth_client",
585
- label: "Pinterest",
586
- secrets: {
587
- clientId: "PINTEREST_CLIENT_ID",
588
- clientSecret: "PINTEREST_CLIENT_SECRET",
589
- },
590
- token: [
591
- {
592
- host: "api.pinterest.com",
593
- path: "/v5/oauth/token",
594
- methods: ["POST"],
595
- inject: "basic",
596
- },
597
- ],
598
- access: ["write"],
599
- console: "https://developers.pinterest.com/apps/",
600
- authorize: {
601
- url: "https://www.pinterest.com/oauth/",
602
- scopes: [
603
- "boards:read",
604
- "boards:write",
605
- "pins:read",
606
- "pins:write",
607
- "user_accounts:read",
608
- ],
609
- },
610
- api: ["api.pinterest.com"],
611
- redirectPaths: ["/integrations/social/pinterest"],
612
- },
613
- discord: {
614
- mode: "oauth_client",
615
- label: "Discord",
616
- secrets: {
617
- clientId: "DISCORD_CLIENT_ID",
618
- clientSecret: "DISCORD_CLIENT_SECRET",
619
- },
620
- token: [
621
- {
622
- host: "discord.com",
623
- path: "/api/oauth2/token",
624
- methods: ["POST"],
625
- inject: "basic",
626
- },
627
- ],
628
- access: ["write"],
629
- console: "https://discord.com/developers/applications",
630
- // The server install; posting uses the bot's token, an app secret.
631
- authorize: {
632
- url: "https://discord.com/oauth2/authorize",
633
- scopes: ["bot", "identify", "guilds"],
634
- },
635
- api: ["discord.com"],
636
- redirectPaths: ["/integrations/social/discord"],
637
- flow: {
638
- tokenUrl: "https://discord.com/api/oauth2/token",
639
- revokeUrl: "https://discord.com/api/oauth2/token/revoke",
640
- pkce: true,
641
- scopeDialect: "space",
642
- identity: {
643
- url: "https://discord.com/api/users/@me",
644
- label: "username",
645
- id: "id",
646
- },
647
- },
648
- },
649
299
  slack: {
650
300
  mode: "oauth_client",
651
301
  label: "Slack",
@@ -855,10 +505,6 @@ export const CAPABILITIES = {
855
505
  },
856
506
  },
857
507
  api: ["slack.com"],
858
- redirectPaths: [
859
- "/integrations/social/slack",
860
- "/integrations/slack/callback",
861
- ],
862
508
  // Slack refuses `code_challenge`; `auth.test` names the workspace and
863
509
  // the installing person.
864
510
  flow: {
@@ -873,131 +519,12 @@ export const CAPABILITIES = {
873
519
  },
874
520
  },
875
521
  },
876
- mastodon: {
877
- mode: "oauth_client",
878
- label: "Mastodon",
879
- secrets: {
880
- clientId: "MASTODON_CLIENT_ID",
881
- clientSecret: "MASTODON_CLIENT_SECRET",
882
- },
883
- // On the instance the operator registered the client on.
884
- token: [{ path: "/oauth/token", methods: ["POST"], inject: "form" }],
885
- hostSetting: "MASTODON_URL",
886
- defaultOrigin: "https://mastodon.social",
887
- access: ["write"],
888
- console: "/settings/applications",
889
- authorize: {
890
- url: "/oauth/authorize",
891
- scopes: ["write:statuses", "profile", "write:media"],
892
- },
893
- api: [],
894
- redirectPaths: ["/integrations/social/mastodon"],
895
- },
896
- kick: {
897
- mode: "oauth_client",
898
- label: "Kick",
899
- secrets: { clientId: "KICK_CLIENT_ID", clientSecret: "KICK_CLIENT_SECRET" },
900
- token: [
901
- {
902
- host: "id.kick.com",
903
- path: "/oauth/token",
904
- methods: ["POST"],
905
- inject: "form",
906
- },
907
- ],
908
- access: ["write"],
909
- console: "https://kick.com/settings/developer",
910
- authorize: {
911
- url: "https://id.kick.com/oauth/authorize",
912
- scopes: ["chat:write", "user:read", "channel:read"],
913
- },
914
- api: ["api.kick.com"],
915
- redirectPaths: ["/integrations/social/kick"],
916
- },
917
- twitch: {
918
- mode: "oauth_client",
919
- label: "Twitch",
920
- secrets: {
921
- clientId: "TWITCH_CLIENT_ID",
922
- clientSecret: "TWITCH_CLIENT_SECRET",
923
- },
924
- token: [
925
- {
926
- host: "id.twitch.tv",
927
- path: "/oauth2/token",
928
- methods: ["POST"],
929
- inject: "form",
930
- },
931
- ],
932
- access: ["write"],
933
- console: "https://dev.twitch.tv/console/apps",
934
- authorize: {
935
- url: "https://id.twitch.tv/oauth2/authorize",
936
- scopes: [
937
- "user:write:chat",
938
- "user:read:chat",
939
- "moderator:manage:announcements",
940
- ],
941
- },
942
- // Helix also wants the public client id, as Client-Id, on every call.
943
- api: ["api.twitch.tv"],
944
- redirectPaths: ["/integrations/social/twitch"],
945
- },
946
- tumblr: {
947
- mode: "oauth_client",
948
- label: "Tumblr",
949
- secrets: {
950
- clientId: "TUMBLR_CLIENT_ID",
951
- clientSecret: "TUMBLR_CLIENT_SECRET",
952
- },
953
- token: [
954
- {
955
- host: "api.tumblr.com",
956
- path: "/v2/oauth2/token",
957
- methods: ["POST"],
958
- inject: "form",
959
- },
960
- ],
961
- access: ["write"],
962
- console: "https://www.tumblr.com/oauth/apps",
963
- authorize: {
964
- url: "https://www.tumblr.com/oauth2/authorize",
965
- scopes: ["write", "offline_access"],
966
- },
967
- api: ["api.tumblr.com"],
968
- redirectPaths: ["/integrations/social/tumblr"],
969
- },
970
- dribbble: {
971
- mode: "oauth_client",
972
- label: "Dribbble",
973
- secrets: {
974
- clientId: "DRIBBBLE_CLIENT_ID",
975
- clientSecret: "DRIBBBLE_CLIENT_SECRET",
976
- },
977
- token: [
978
- {
979
- // A POST that takes the client in its query string.
980
- host: "dribbble.com",
981
- path: "/oauth/token",
982
- methods: ["POST"],
983
- inject: "query",
984
- },
985
- ],
986
- access: ["write"],
987
- console: "https://dribbble.com/account/applications",
988
- authorize: {
989
- url: "https://dribbble.com/oauth/authorize",
990
- scopes: ["public", "upload"],
991
- },
992
- api: ["api.dribbble.com"],
993
- redirectPaths: ["/integrations/social/dribbble"],
994
- },
995
522
  // Clients several apps share with different needs, so each app lists the
996
523
  // scope sets it uses: Open CRM reads a member's own mailbox and calendar
997
524
  // (`gmail.read`, `calendar.read`; `identity`, `mail.read`), OpenSEO reads
998
525
  // a site's Search Console and Analytics (`identity`, `search-console.read`,
999
526
  // `analytics.read`). Every set is read-only. Google's is one Cloud project
1000
- // apart from YouTube's; Gmail's read scope is restricted and needs
527
+ // apart from the YouTube preset's; Gmail's read scope is restricted and needs
1001
528
  // Google's verification, and whether Search Console and Analytics share
1002
529
  // that consent screen with it is the operator's choice when verifying.
1003
530
  "google-workspace": {
@@ -1161,7 +688,6 @@ export const CAPABILITIES = {
1161
688
  "analyticsadmin.googleapis.com",
1162
689
  "openidconnect.googleapis.com",
1163
690
  ],
1164
- redirectPaths: ["/integrations/google/callback"],
1165
691
  // The Gateway-owned flow: a refresh token needs `access_type=offline`,
1166
692
  // and `prompt=consent` makes Google issue one on every connect. No
1167
693
  // revoke: Google's `/revoke` is per person per client and would also
@@ -1271,7 +797,6 @@ export const CAPABILITIES = {
1271
797
  },
1272
798
  },
1273
799
  api: ["graph.microsoft.com"],
1274
- redirectPaths: ["/integrations/microsoft/callback"],
1275
800
  flow: {
1276
801
  tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
1277
802
  pkce: true,
@@ -1315,7 +840,6 @@ export function capabilitySettings(capability) {
1315
840
  ...(capability.secrets.clientSecret
1316
841
  ? [capability.secrets.clientSecret]
1317
842
  : []),
1318
- ...(capability.hostSetting ? [capability.hostSetting] : []),
1319
843
  ];
1320
844
  }
1321
845
  }
@@ -1437,8 +961,8 @@ export function serviceRoutePath(id, route) {
1437
961
  * an unknown capability (or an AI provider, which has its own route), a
1438
962
  * host outside the provider's, a path that could leave that host, a path
1439
963
  * that isn't one of an OAuth client's token endpoints, or a route a service
1440
- * capability doesn't declare. `settings` resolves an OAuth client's
1441
- * `hostSetting` (Mastodon's instance); `lookup` is where the id is found,
964
+ * capability doesn't declare. `settings` resolves an API-key provider's
965
+ * `hostSetting` (a Shopify store's host); `lookup` is where the id is found,
1442
966
  * the catalog alone by default.
1443
967
  */
1444
968
  export function parseIntegrationProxyPath(pathname, search, settings, lookup = CATALOG) {
@@ -1462,10 +986,10 @@ export function parseIntegrationProxyPath(pathname, search, settings, lookup = C
1462
986
  };
1463
987
  }
1464
988
  if (capability.mode === "oauth_client") {
1465
- const upstream = oauthClientHosts(capability, settings).includes(host)
989
+ const upstream = capability.token.some((rule) => rule.host === host)
1466
990
  ? httpsUpstream(host, path ?? "/", search)
1467
991
  : null;
1468
- const endpoint = upstream && tokenEndpointFor(capability, upstream, settings);
992
+ const endpoint = upstream && tokenEndpointFor(capability, upstream);
1469
993
  if (!upstream || !endpoint)
1470
994
  return null;
1471
995
  return { kind: "oauth_client", id, capability, upstream, endpoint };
@@ -1490,80 +1014,23 @@ function httpsUpstream(host, path, search) {
1490
1014
  return upstream;
1491
1015
  }
1492
1016
  /**
1493
- * The origin an OAuth client's `hostSetting` names (its default when the
1494
- * setting is unset), or null for a client with a fixed host or a setting
1495
- * that isn't an https origin. A bare host is taken as https.
1496
- */
1497
- export function oauthClientOrigin(capability, settings) {
1498
- if (!capability.hostSetting)
1499
- return null;
1500
- const set = settings?.[capability.hostSetting];
1501
- const value = typeof set === "string" && set.trim()
1502
- ? set.trim()
1503
- : capability.defaultOrigin;
1504
- if (!value)
1505
- return null;
1506
- let url;
1507
- try {
1508
- url = new URL(/^[a-z][a-z0-9+.-]*:\/\//i.test(value) ? value : `https://${value}`);
1509
- }
1510
- catch {
1511
- return null;
1512
- }
1513
- // An origin and nothing else: the paths are the provider's own.
1514
- const bare = url.pathname === "/" &&
1515
- !url.search &&
1516
- !url.hash &&
1517
- !url.username &&
1518
- !url.password;
1519
- return url.protocol === "https:" && bare ? url.origin : null;
1520
- }
1521
- /** The host an OAuth client's `hostSetting` names, or null. */
1522
- function settingHost(capability, settings) {
1523
- const origin = oauthClientOrigin(capability, settings);
1524
- return origin ? new URL(origin).host : null;
1525
- }
1526
- /** The hosts an OAuth client's token endpoints are on. */
1527
- function oauthClientHosts(capability, settings) {
1528
- const fromSetting = settingHost(capability, settings);
1529
- return [
1530
- ...new Set(capability.token.flatMap(({ host }) => {
1531
- const resolved = host ?? fromSetting;
1532
- return resolved ? [resolved] : [];
1533
- })),
1534
- ];
1535
- }
1536
- /**
1537
- * The token endpoint `upstream` is, by its exact host and path (a RegExp
1538
- * for a versioned one), or null. Its method is the caller's to check.
1017
+ * The token endpoint `upstream` is, by its exact host and path, or null.
1018
+ * Its method is the caller's to check.
1539
1019
  */
1540
- export function tokenEndpointFor(capability, upstream, settings) {
1020
+ export function tokenEndpointFor(capability, upstream) {
1541
1021
  if (upstream.protocol !== "https:")
1542
1022
  return null;
1543
- const fromSetting = settingHost(capability, settings);
1544
- return (capability.token.find(({ host, path }) => (host ?? fromSetting) === upstream.host &&
1545
- (typeof path === "string"
1546
- ? path === upstream.pathname
1547
- : path.test(upstream.pathname))) ?? null);
1023
+ return (capability.token.find(({ host, path }) => host === upstream.host && path === upstream.pathname) ?? null);
1548
1024
  }
1549
1025
  /** An OAuth client's token endpoints, as `POST https://host/path` lines for messages. */
1550
1026
  export function describeTokenEndpoints(capability) {
1551
1027
  return capability.token
1552
- .map(({ host, path, methods }) => `${methods.join("/")} https://${host ?? `<${capability.hostSetting}>`}${tokenPathText(path)}`)
1028
+ .map(({ host, path, methods }) => `${methods.join("/")} https://${host}${path}`)
1553
1029
  .join(", ");
1554
1030
  }
1555
- /** A token endpoint's path as people read it: a versioned one as `/v<version>/oauth/access_token`. */
1556
- export function tokenPathText(path) {
1557
- if (typeof path === "string")
1558
- return path;
1559
- return path.source
1560
- .replace(/^\^|\$$/g, "")
1561
- .replace(/v\\d\+\\\.\\d\+/g, "v<version>")
1562
- .replace(/\\(.)/g, "$1");
1563
- }
1564
1031
  /**
1565
1032
  * The command that gives the gateway `capability`'s client:
1566
- * `pnpm everyapp secret set <ID> <SECRET> [<HOST SETTING>]`.
1033
+ * `pnpm everyapp secret set <ID> <SECRET>`.
1567
1034
  */
1568
1035
  export function oauthClientSecretSetCommand(capability) {
1569
1036
  return `pnpm everyapp secret set ${capabilitySettings(capability).join(" ")}`;