@every-app/sdk 0.3.0-rc.2 → 0.3.0-rc.4

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 (110) hide show
  1. package/README.md +1 -1
  2. package/dist/cloudflare/index.d.ts +2 -2
  3. package/dist/cloudflare/index.d.ts.map +1 -1
  4. package/dist/cloudflare/index.js +1 -1
  5. package/dist/cloudflare/sentinel.d.ts +57 -2
  6. package/dist/cloudflare/sentinel.d.ts.map +1 -1
  7. package/dist/cloudflare/sentinel.js +27 -2
  8. package/dist/cloudflare/worker.d.ts +297 -5
  9. package/dist/cloudflare/worker.d.ts.map +1 -1
  10. package/dist/cloudflare/worker.js +279 -12
  11. package/dist/dev/index.d.ts +1 -1
  12. package/dist/dev/index.d.ts.map +1 -1
  13. package/dist/dev/index.js +1 -1
  14. package/dist/dev/keypair.d.ts +2 -0
  15. package/dist/dev/keypair.d.ts.map +1 -1
  16. package/dist/dev/keypair.js +2 -0
  17. package/dist/internal/aiDefault.d.ts +141 -0
  18. package/dist/internal/aiDefault.d.ts.map +1 -0
  19. package/dist/internal/aiDefault.js +204 -0
  20. package/dist/internal/aiProviders.d.ts +4 -1
  21. package/dist/internal/aiProviders.d.ts.map +1 -1
  22. package/dist/internal/aiProviders.js +5 -1
  23. package/dist/internal/appSettings.d.ts +20 -2
  24. package/dist/internal/appSettings.d.ts.map +1 -1
  25. package/dist/internal/appSettings.js +53 -7
  26. package/dist/internal/audit.d.ts +108 -0
  27. package/dist/internal/audit.d.ts.map +1 -0
  28. package/dist/internal/audit.js +235 -0
  29. package/dist/internal/capabilities.d.ts +276 -7
  30. package/dist/internal/capabilities.d.ts.map +1 -1
  31. package/dist/internal/capabilities.js +111 -0
  32. package/dist/internal/catalog/index.d.ts +39 -2
  33. package/dist/internal/catalog/index.d.ts.map +1 -1
  34. package/dist/internal/catalog/inference.d.ts +39 -2
  35. package/dist/internal/catalog/inference.d.ts.map +1 -1
  36. package/dist/internal/catalog/inference.js +36 -4
  37. package/dist/internal/devProviders.d.ts +2 -2
  38. package/dist/internal/devProviders.d.ts.map +1 -1
  39. package/dist/internal/devProviders.js +19 -1
  40. package/dist/internal/events.d.ts +13 -2
  41. package/dist/internal/events.d.ts.map +1 -1
  42. package/dist/internal/events.js +42 -4
  43. package/dist/internal/identity.d.ts +29 -3
  44. package/dist/internal/identity.d.ts.map +1 -1
  45. package/dist/internal/identity.js +37 -9
  46. package/dist/internal/index.d.ts +5 -1
  47. package/dist/internal/index.d.ts.map +1 -1
  48. package/dist/internal/index.js +5 -1
  49. package/dist/internal/members.d.ts +3 -2
  50. package/dist/internal/members.d.ts.map +1 -1
  51. package/dist/internal/oauthPresets.d.ts +29 -0
  52. package/dist/internal/oauthPresets.d.ts.map +1 -0
  53. package/dist/internal/oauthPresets.js +534 -0
  54. package/dist/internal/oauthScopes.d.ts +56 -1
  55. package/dist/internal/oauthScopes.d.ts.map +1 -1
  56. package/dist/internal/oauthScopes.js +98 -4
  57. package/dist/internal/oauthSpec.d.ts +59 -0
  58. package/dist/internal/oauthSpec.d.ts.map +1 -0
  59. package/dist/internal/oauthSpec.js +676 -0
  60. package/dist/internal/protocol.d.ts +36 -1
  61. package/dist/internal/protocol.d.ts.map +1 -1
  62. package/dist/internal/protocol.js +30 -1
  63. package/dist/internal/providerRegistry.d.ts +17 -6
  64. package/dist/internal/providerRegistry.d.ts.map +1 -1
  65. package/dist/internal/providerRegistry.js +47 -2
  66. package/dist/internal/providerSpec.d.ts +11 -7
  67. package/dist/internal/providerSpec.d.ts.map +1 -1
  68. package/dist/internal/providerSpec.js +134 -37
  69. package/dist/internal/signInProviders.d.ts.map +1 -1
  70. package/dist/internal/signInProviders.js +11 -4
  71. package/dist/server/ai.d.ts +45 -0
  72. package/dist/server/ai.d.ts.map +1 -0
  73. package/dist/server/ai.js +40 -0
  74. package/dist/server/attribution.d.ts +9 -5
  75. package/dist/server/attribution.d.ts.map +1 -1
  76. package/dist/server/attribution.js +12 -4
  77. package/dist/server/connectUrl.d.ts +21 -0
  78. package/dist/server/connectUrl.d.ts.map +1 -0
  79. package/dist/server/connectUrl.js +37 -0
  80. package/dist/server/context.d.ts +68 -0
  81. package/dist/server/context.d.ts.map +1 -0
  82. package/dist/server/context.js +117 -0
  83. package/dist/server/emit.d.ts +1 -1
  84. package/dist/server/emit.d.ts.map +1 -1
  85. package/dist/server/emit.js +4 -4
  86. package/dist/server/everyApp.d.ts +27 -7
  87. package/dist/server/everyApp.d.ts.map +1 -1
  88. package/dist/server/everyApp.js +106 -5
  89. package/dist/server/fromMcpTools.d.ts +89 -0
  90. package/dist/server/fromMcpTools.d.ts.map +1 -0
  91. package/dist/server/fromMcpTools.js +192 -0
  92. package/dist/server/gatewayFetch.d.ts +8 -6
  93. package/dist/server/gatewayFetch.d.ts.map +1 -1
  94. package/dist/server/gatewayFetch.js +78 -11
  95. package/dist/server/index.d.ts +7 -3
  96. package/dist/server/index.d.ts.map +1 -1
  97. package/dist/server/index.js +6 -2
  98. package/dist/server/integrationFetch.d.ts +55 -8
  99. package/dist/server/integrationFetch.d.ts.map +1 -1
  100. package/dist/server/integrationFetch.js +198 -18
  101. package/dist/server/listMembers.d.ts +1 -1
  102. package/dist/server/listMembers.d.ts.map +1 -1
  103. package/dist/server/listMembers.js +5 -8
  104. package/dist/server/sendEmail.d.ts +1 -1
  105. package/dist/server/sendEmail.d.ts.map +1 -1
  106. package/dist/server/sendEmail.js +4 -4
  107. package/dist/server/toolsEndpoint.d.ts.map +1 -1
  108. package/dist/server/toolsEndpoint.js +11 -5
  109. package/package.json +13 -14
  110. package/LICENSE +0 -21
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,eAAe,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,GAClC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,wBAAwB,GAC9B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,SAAS,EACT,WAAW,EACX,UAAU,EACV,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,OAAO,GACb,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,OAAO,EACP,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,OAAO,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,WAAW,EACX,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EACL,WAAW,EACX,UAAU,EACV,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,eAAe,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,EAAE,EAAE,mBAAmB,EAAE,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,GAClC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,wBAAwB,GAC9B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,SAAS,EACT,WAAW,EACX,UAAU,EACV,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,OAAO,GACb,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACL,YAAY,EACZ,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,mBAAmB,CAAC"}
@@ -3,13 +3,17 @@
3
3
  *
4
4
  * There is intentionally no client-side export.
5
5
  */
6
- export { ConfigurationError, IdentityError, everyApp, getEveryAppUser, hasScope, requireEveryAppUser, } from "./everyApp.js";
6
+ export { ConfigurationError, IdentityError, everyApp, getEveryAppUser, hasScope, isAdmin, requireCurrentUser, requireEveryAppUser, } from "./everyApp.js";
7
+ export { OrganizationMismatchError, RequestContextError, currentUser, withOrganization, } from "./context.js";
7
8
  export { AttributionError } from "./attribution.js";
8
9
  export { authorizeUrl } from "./authorizeUrl.js";
10
+ export { connectPath, connectUrl, } from "./connectUrl.js";
9
11
  export { createGatewayFetch, } from "./gatewayFetch.js";
10
- export { GatewayRefusalError, gatewayRefusal, integrationFetch, integrationStatus, } from "./integrationFetch.js";
12
+ export { ai, AI_DEFAULT_BASE_URL } from "./ai.js";
13
+ export { GatewayRefusalError, gatewayRefusal, devAccessTokenName, integrationFetch, integrationStatus, } from "./integrationFetch.js";
11
14
  export { nodeServerHandler, } from "./nodeServer.js";
12
15
  export { sendEmail } from "./sendEmail.js";
13
16
  export { listMembers } from "./listMembers.js";
14
17
  export { emit } from "./emit.js";
15
18
  export { ToolError, defineTools, toolResult, } from "./tools.js";
19
+ export { fromMcpTools, } from "./fromMcpTools.js";
@@ -1,4 +1,4 @@
1
- import { type ApiKeyCapabilityId, type CapabilityId, type EmailCapabilityStatus, type OAuthClientCapabilityId } from "../internal/index.js";
1
+ import { type ApiKeyCapabilityId, type CapabilityId, type ConnectionAccount, type EmailCapabilityStatus, type OAuthClientCapabilityId } from "../internal/index.js";
2
2
  import { type GatewayCallFor } from "./attribution.js";
3
3
  export interface IntegrationFetchOptions {
4
4
  /**
@@ -17,13 +17,22 @@ export interface IntegrationFetchOptions {
17
17
  */
18
18
  provider: ApiKeyCapabilityId | OAuthClientCapabilityId | (string & {});
19
19
  /**
20
- * Whom the call is for: the inbound request (its user), or
21
- * `{ background: true, organizationId }` for work no person started
22
- * (crons, Workflows, queues). An organization's own app may omit it for
23
- * background work, which is then the app's; a shared app's Worker must
24
- * pass one or the other ({@link AttributionError}).
20
+ * Whom the call is for. Left out, the request `everyApp()` is serving
21
+ * (its user, while the identity is good) or the organization
22
+ * `withOrganization()` named; outside both, `RequestContextError`.
23
+ * Explicitly: the inbound request, or `{ background: true,
24
+ * organizationId }` for work no person started (crons, Workflows,
25
+ * queues). A shared app's Worker must end up with one or the other
26
+ * ({@link AttributionError}).
25
27
  */
26
28
  for?: GatewayCallFor;
29
+ /**
30
+ * For an OAuth provider the gateway holds connections for: whose
31
+ * connection the call uses, the person's (`user`, the default when a
32
+ * person is behind the call) or the organization's (`organization`,
33
+ * the default for background work). Sent as `x-everyapp-account`.
34
+ */
35
+ account?: ConnectionAccount;
27
36
  }
28
37
  /**
29
38
  * A `fetch` for one of the gateway's capabilities. Call the provider's real
@@ -47,7 +56,14 @@ export interface IntegrationFetchOptions {
47
56
  * provider show <id> --save` writes it), put on the call as the gateway's
48
57
  * spec says.
49
58
  */
50
- export declare function integrationFetch({ env, provider, for: target, }: IntegrationFetchOptions): typeof fetch;
59
+ export declare function integrationFetch({ env, provider, for: explicitTarget, account, }: IntegrationFetchOptions): typeof fetch;
60
+ /**
61
+ * The `.dev.vars` name of a held token for `provider` in local dev
62
+ * (`GOOGLE_WORKSPACE_ACCESS_TOKEN`, `GITHUB_ACCESS_TOKEN`): a token the
63
+ * developer obtained themselves, standing in for the connection the
64
+ * gateway would hold. Dev-only: the gateway never reads it.
65
+ */
66
+ export declare function devAccessTokenName(provider: string): string;
51
67
  export interface IntegrationStatus {
52
68
  /** The app's manifest lists the capability. */
53
69
  requested: boolean;
@@ -92,6 +108,29 @@ export interface OAuthClientIntegrationStatus extends IntegrationStatus {
92
108
  scopes?: readonly string[];
93
109
  /** Slack's `user_scope` strings, when the sets name any. */
94
110
  userScopes?: readonly string[];
111
+ /**
112
+ * Which flows the client supports: `app` (the app runs authorize and
113
+ * callback itself and keeps the tokens, the social networks), `gateway`
114
+ * (the Gateway holds the connection; API calls go through
115
+ * `integrationFetch` with the token injected) or `both` (Google,
116
+ * Microsoft, Slack, Discord and every registered OAuth provider).
117
+ */
118
+ flow?: "app" | "gateway" | "both";
119
+ /** Where a person connects on the Gateway: `/connect/<id>`; see `connectUrl()`. */
120
+ connectPath?: string;
121
+ /**
122
+ * The connection the caller's account would use (the person's, or the
123
+ * organization's for background work), or null when there is none yet;
124
+ * `reconnect` when it exists but lacks a set the app declares or has
125
+ * expired, so the person has to connect again.
126
+ */
127
+ connection?: {
128
+ account: ConnectionAccount;
129
+ label: string | null;
130
+ scopeSets: readonly string[];
131
+ ready: boolean;
132
+ reconnect?: boolean;
133
+ } | null;
95
134
  }
96
135
  /** The status of a capability: email's carries its senders, an OAuth client's its id. */
97
136
  export type IntegrationStatusOf<P extends string> = P extends "email" ? EmailIntegrationStatus : P extends OAuthClientCapabilityId ? OAuthClientIntegrationStatus : IntegrationStatus;
@@ -101,9 +140,17 @@ export type IntegrationStatusOf<P extends string> = P extends "email" ? EmailInt
101
140
  * set up") up front instead of failing mid-task. An OAuth client's status
102
141
  * carries its public `clientId` for the authorize URL.
103
142
  */
104
- export declare function integrationStatus<P extends CapabilityId | (string & {})>({ env, provider, }: {
143
+ export declare function integrationStatus<P extends CapabilityId | (string & {})>({ env, provider, for: explicitTarget, }: {
105
144
  env: object;
106
145
  provider: P;
146
+ /**
147
+ * Whom the status is for: the request being served (its person), so an
148
+ * OAuth provider's `connection` is that person's; background work
149
+ * (`withOrganization()`) its organization, whose own connection is then
150
+ * reported. Explicitly the inbound request or `{ background: true,
151
+ * organizationId }`, as on every call.
152
+ */
153
+ for?: GatewayCallFor;
107
154
  }): Promise<IntegrationStatusOf<P>>;
108
155
  /** A refusal the AppGateway binding made itself, not the provider. */
109
156
  export interface GatewayRefusal {
@@ -1 +1 @@
1
- {"version":3,"file":"integrationFetch.d.ts","sourceRoot":"","sources":["../../src/server/integrationFetch.ts"],"names":[],"mappings":"AAAA,OAAO,EA2BL,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAE1B,KAAK,uBAAuB,EAO7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAO1B,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;OAOG;IACH,QAAQ,EAAE,kBAAkB,GAAG,uBAAuB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACvE;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,cAAc,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,GAAG,EACH,QAAQ,EACR,GAAG,EAAE,MAAM,GACZ,EAAE,uBAAuB,GAAG,OAAO,KAAK,CAkGxC;AA+XD,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,UAAU,EAAE,OAAO,CAAC;IACpB,8BAA8B;IAC9B,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG,iBAAiB,GACpD,IAAI,CAAC,qBAAqB,EAAE,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC,CAAC;AAEjE;;;;GAIG;AACH,MAAM,WAAW,4BAA6B,SAAQ,iBAAiB;IACrE,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,4DAA4D;IAC5D,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,yFAAyF;AACzF,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,OAAO,GACjE,sBAAsB,GACtB,CAAC,SAAS,uBAAuB,GAC/B,4BAA4B,GAC5B,iBAAiB,CAAC;AAExB;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,CAAC,SAAS,YAAY,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,EACtC,EACA,GAAG,EACH,QAAQ,GACT,EAAE;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,CAAC,CAAC;CACb,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAoElC;AA2FD,sEAAsE;AACtE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,qBAAa,mBAAoB,SAAQ,KAAM,YAAW,cAAc;IACtE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,cAAc;CAMtD;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAWhC"}
1
+ {"version":3,"file":"integrationFetch.d.ts","sourceRoot":"","sources":["../../src/server/integrationFetch.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { CATALOG, ConfigurationError, GATEWAY_ERROR_HEADER, INTEGRATION_PROXY_PREFIX, OAUTH_TOKEN_BODY_LIMIT, allowedScopes, apiKeyHosts, authorizationFor, capabilitySettings, carriesToken, declaredScopeSets, describeTokenEndpoints, devProviderFile, grantedScopes, injectClientCredentials, integrationProxyPath, oauthClientCredentials, oauthClientOrigin, requestedScopes, requestedTokenScopes, resolveDevProvider, rewriteTokenRequestScope, scopeExcess, tokenEndpointFor, tokenGrantType, EMAIL_SENDERS_ENV, chooseEmailProvider, parseEmailList, parseEmailSender, } from "../internal/index.js";
2
- import { applyAttribution, checkAttribution, } from "./attribution.js";
1
+ import { ACCOUNT_HEADER, CATALOG, ConfigurationError, GATEWAY_ERROR_HEADER, INTEGRATION_PROXY_PREFIX, OAUTH_TOKEN_BODY_LIMIT, allowedScopes, apiKeyHosts, authorizationFor, capabilitySettings, carriesToken, declaredScopeSets, describeTokenEndpoints, devProviderFile, grantedScopes, heldTokenCallAllowed, injectClientCredentials, integrationProxyPath, oauthClientCredentials, oauthClientOrigin, oauthReadMethods, oauthWriteMethods, providerSettingPrefix, requestedScopes, requestedTokenScopes, resolveDevProvider, rewriteTokenRequestScope, scopeExcess, tokenEndpointFor, tokenGrantType, EMAIL_SENDERS_ENV, chooseEmailProvider, parseEmailList, parseEmailSender, } from "../internal/index.js";
2
+ import { applyAttribution, attributionFor, } from "./attribution.js";
3
3
  import { BINDING_ORIGIN, streamingRequest, } from "./gatewayFetch.js";
4
4
  /**
5
5
  * A `fetch` for one of the gateway's capabilities. Call the provider's real
@@ -23,9 +23,12 @@ import { BINDING_ORIGIN, streamingRequest, } from "./gatewayFetch.js";
23
23
  * provider show <id> --save` writes it), put on the call as the gateway's
24
24
  * spec says.
25
25
  */
26
- export function integrationFetch({ env, provider, for: target, }) {
26
+ export function integrationFetch({ env, provider, for: explicitTarget, account, }) {
27
27
  const catalogEntry = fetchableCapability(provider);
28
- checkAttribution(env, target, `integrationFetch("${provider}")`);
28
+ const what = `integrationFetch("${provider}")`;
29
+ // Checked now, so a call nobody's fails where the fetch is made; and
30
+ // again per call, where an identity may since have neared its expiry.
31
+ attributionFor(env, explicitTarget, what);
29
32
  const values = env;
30
33
  const binding = values["EVERY_APP_GATEWAY"];
31
34
  if (binding && typeof binding.fetch !== "function") {
@@ -36,10 +39,26 @@ export function integrationFetch({ env, provider, for: target, }) {
36
39
  const integration = catalogEntry ??
37
40
  (binding ? undefined : devRegisteredProvider(provider, values));
38
41
  const local = binding || !integration ? null : localCredentials(integration, values);
39
- if (!binding && !local && integration) {
40
- throw new ConfigurationError(`${integration.label} is unavailable: deploy with the EVERY_APP_GATEWAY binding, or set ${capabilitySettings(integration).join(", ")} in .dev.vars for local development.`);
42
+ // In dev an OAuth provider with a held token in `.dev.vars` serves API
43
+ // calls without the client (the token stands in for a connection).
44
+ const devToken = !binding && integration?.mode === "oauth_client" && integration.flow
45
+ ? stringValue(values[devAccessTokenName(provider)])
46
+ : undefined;
47
+ // An OAuth provider with a Gateway-owned flow answers an API call
48
+ // without the client (`integration_not_connected`, below); a token
49
+ // endpoint call without the client throws when it is made.
50
+ const decidesLater = integration?.mode === "oauth_client" && integration.flow !== undefined;
51
+ if (!binding && !local && !devToken && integration && !decidesLater) {
52
+ const names = [
53
+ ...capabilitySettings(integration),
54
+ ...(integration.mode === "oauth_client" && integration.flow
55
+ ? [devAccessTokenName(provider)]
56
+ : []),
57
+ ];
58
+ throw new ConfigurationError(`${integration.label} is unavailable: deploy with the EVERY_APP_GATEWAY binding, or set ${names.join(", ")} in .dev.vars for local development.`);
41
59
  }
42
60
  return async (input, init) => {
61
+ const target = attributionFor(env, explicitTarget, what);
43
62
  const outbound = new Request(input, init);
44
63
  const upstream = new URL(outbound.url);
45
64
  const headers = new Headers(outbound.headers);
@@ -55,6 +74,30 @@ export function integrationFetch({ env, provider, for: target, }) {
55
74
  return binding.fetch(streamingRequest(`${BINDING_ORIGIN}${integrationProxyPath(provider, upstream)}`, outbound, headers));
56
75
  }
57
76
  if (integration.mode === "oauth_client") {
77
+ // A call to the provider's API with the token the gateway holds
78
+ // (docs/design/2026-10-oauth-providers.md section 7), for an entry
79
+ // that supports the Gateway-owned flow; a token endpoint stays the
80
+ // app-driven call it always was.
81
+ const toApi = integration.flow !== undefined &&
82
+ upstream.protocol === "https:" &&
83
+ integration.api.includes(upstream.host) &&
84
+ !tokenEndpointFor(integration, upstream, binding && integration.hostSetting ? undefined : values);
85
+ if (toApi) {
86
+ if (binding) {
87
+ if (account)
88
+ headers.set(ACCOUNT_HEADER, account);
89
+ applyAttribution(headers, target);
90
+ return binding.fetch(streamingRequest(`${BINDING_ORIGIN}${integrationProxyPath(provider, upstream)}`, outbound, headers));
91
+ }
92
+ return devHeldTokenCall({
93
+ provider,
94
+ capability: integration,
95
+ outbound,
96
+ upstream,
97
+ headers,
98
+ values,
99
+ });
100
+ }
58
101
  return oauthClientCall({
59
102
  provider: provider,
60
103
  capability: integration,
@@ -92,6 +135,93 @@ export function integrationFetch({ env, provider, for: target, }) {
92
135
  return fetch(streamingRequest(upstream.toString(), outbound, headers));
93
136
  };
94
137
  }
138
+ /**
139
+ * The `.dev.vars` name of a held token for `provider` in local dev
140
+ * (`GOOGLE_WORKSPACE_ACCESS_TOKEN`, `GITHUB_ACCESS_TOKEN`): a token the
141
+ * developer obtained themselves, standing in for the connection the
142
+ * gateway would hold. Dev-only: the gateway never reads it.
143
+ */
144
+ export function devAccessTokenName(provider) {
145
+ return `${providerSettingPrefix(provider)}ACCESS_TOKEN`;
146
+ }
147
+ /**
148
+ * An app's call to an OAuth provider's API in local dev, with no
149
+ * gateway: the gateway's held-token checks in its order (the app's
150
+ * declared sets, the method, the route), then the developer's own token
151
+ * from `.dev.vars` as the bearer, straight to the provider.
152
+ */
153
+ async function devHeldTokenCall({ provider, capability, outbound, upstream, headers, values, }) {
154
+ const token = stringValue(values[devAccessTokenName(provider)]);
155
+ if (!token) {
156
+ return devRefusal(409, "integration_not_connected", `${capability.label} isn't connected here. In local dev, set ${devAccessTokenName(provider)} in .dev.vars to a token you obtained yourself; deployed, the person connects at /connect/${provider}.`, { connectPath: `/connect/${provider}`, reconnect: false });
157
+ }
158
+ const policy = capability.scopePolicy;
159
+ const grant = policy
160
+ ? devScopeSets(policy, provider, capability.label, values, "any")
161
+ : null;
162
+ if (grant && "problem" in grant) {
163
+ return devRefusal(403, grant.code, grant.problem);
164
+ }
165
+ const method = outbound.method.toUpperCase();
166
+ const reads = oauthReadMethods(capability).includes(method);
167
+ const writes = !reads &&
168
+ capability.access.includes("write") &&
169
+ oauthWriteMethods(capability).includes(method) &&
170
+ devDeclaredAccess(provider, values) === "write";
171
+ if (policy && grant) {
172
+ const allowed = heldTokenCallAllowed({
173
+ policy,
174
+ declaredSets: grant.sets,
175
+ // The developer's token stands for a connection granted every set.
176
+ connectionSets: grant.sets,
177
+ hosts: capability.api,
178
+ method,
179
+ upstream,
180
+ readMethods: oauthReadMethods(capability),
181
+ writes,
182
+ });
183
+ if (!allowed.ok) {
184
+ const status = {
185
+ integration_not_connected: 409,
186
+ integration_method_not_allowed: 405,
187
+ integration_scope_not_allowed: 403,
188
+ }[allowed.code];
189
+ return devRefusal(status, allowed.code, allowed.code === "integration_not_connected"
190
+ ? `${capability.label} is connected without ${allowed.missingSets.join(", ")}.`
191
+ : allowed.message);
192
+ }
193
+ }
194
+ else if (!reads && !writes) {
195
+ return devRefusal(405, "integration_method_not_allowed", `${capability.label} calls may use ${oauthReadMethods(capability).join(" or ")} with access: "read"; ${method} needs access: "write" in the app's capabilities entry, on a provider that offers it.`);
196
+ }
197
+ applyAttribution(headers, undefined);
198
+ headers.set("authorization", `Bearer ${token}`);
199
+ for (const name of ["access_token", "token"]) {
200
+ upstream.searchParams.delete(name);
201
+ }
202
+ headers.delete("x-http-method-override");
203
+ return fetch(new Request(upstream.toString(), {
204
+ method,
205
+ headers,
206
+ body: method === "GET" || method === "HEAD" ? null : outbound.body,
207
+ signal: outbound.signal,
208
+ // As the gateway: the token never follows a redirect.
209
+ redirect: "manual",
210
+ ...(method === "GET" || method === "HEAD" ? {} : { duplex: "half" }),
211
+ }));
212
+ }
213
+ /** The `access` the manifest entry for `provider` declares in dev (EVERYAPP_DEV_CAPABILITIES), or null. */
214
+ function devDeclaredAccess(provider, values) {
215
+ const raw = values["EVERYAPP_DEV_CAPABILITIES"];
216
+ try {
217
+ const capabilities = typeof raw === "string" ? jsonRecord(JSON.parse(raw)) : undefined;
218
+ const entry = jsonRecord(capabilities?.[provider]);
219
+ return typeof entry?.["access"] === "string" ? entry["access"] : null;
220
+ }
221
+ catch {
222
+ return null;
223
+ }
224
+ }
95
225
  /**
96
226
  * The developer's own key or client from `.dev.vars` (with EVERYAPP_DEV
97
227
  * set), under the gateway's names; null until every setting it needs is.
@@ -125,6 +255,9 @@ async function oauthClientCall({ provider, capability, outbound, upstream, heade
125
255
  return binding.fetch(streamingRequest(`${BINDING_ORIGIN}${integrationProxyPath(provider, upstream)}`, outbound, headers));
126
256
  }
127
257
  applyAttribution(headers, undefined);
258
+ if (!client) {
259
+ throw new ConfigurationError(`${capability.label}'s token endpoints need the client in .dev.vars for local development: set ${capabilitySettings(capability).join(", ")}.`);
260
+ }
128
261
  // The gateway's scope checks, in its order, answering its refusals: an
129
262
  // app sees in `everyapp dev` what the gateway will say.
130
263
  const policy = capability.scopePolicy;
@@ -173,13 +306,15 @@ async function oauthClientCall({ provider, capability, outbound, upstream, heade
173
306
  * `x-everyapp-error`) from the local-dev twin, so {@link gatewayRefusal}
174
307
  * reads it the same way.
175
308
  */
176
- function devRefusal(status, code, message) {
309
+ function devRefusal(status, code, message, extra = {}) {
177
310
  const labels = {
178
311
  400: "Bad Request",
179
312
  403: "Forbidden",
313
+ 405: "Method Not Allowed",
314
+ 409: "Conflict",
180
315
  502: "Bad Gateway",
181
316
  };
182
- return Response.json({ error: labels[status] ?? "Error", code, message }, { status, headers: { [GATEWAY_ERROR_HEADER]: code } });
317
+ return Response.json({ error: labels[status] ?? "Error", code, message, ...extra }, { status, headers: { [GATEWAY_ERROR_HEADER]: code } });
183
318
  }
184
319
  /**
185
320
  * The scope sets the manifest declares for `id`, read from
@@ -191,7 +326,9 @@ function devRefusal(status, code, message) {
191
326
  * doesn't offer). Fails closed like the gateway: a hand-rolled dev harness
192
327
  * that passes no capabilities gets nothing.
193
328
  */
194
- function devScopeSets(policy, id, label, values) {
329
+ function devScopeSets(policy, id, label, values,
330
+ /** The grant the entry needs: `write` for a token-endpoint call (the app-driven flow), `any` for a held-token call. */
331
+ grant = "write") {
195
332
  const offered = Object.keys(policy.sets).join(", ");
196
333
  const raw = values["EVERYAPP_DEV_CAPABILITIES"];
197
334
  let capabilities;
@@ -211,11 +348,16 @@ function devScopeSets(policy, id, label, values) {
211
348
  const entry = Object.hasOwn(capabilities, id)
212
349
  ? jsonRecord(capabilities[id])
213
350
  : undefined;
214
- // The gateway's check 2: listing the client for writing is the grant.
215
- if (entry?.["access"] !== "write") {
351
+ // The gateway's check 2: listing the client for writing is the grant
352
+ // of the app-driven flow; a held-token call takes any listing.
353
+ const access = entry?.["access"];
354
+ if (!entry ||
355
+ (grant === "write"
356
+ ? access !== "write"
357
+ : access !== "read" && access !== "write")) {
216
358
  return {
217
359
  code: "capability_not_requested",
218
- problem: `This app doesn't list ${label} in its capabilities. Add capabilities: { ${JSON.stringify(id)}: { access: "write" } } to everyapp.config.ts and start everyapp dev again.`,
360
+ problem: `This app doesn't list ${label} in its capabilities. Add capabilities: { ${JSON.stringify(id)}: { access: "${grant === "write" ? "write" : "read"}" } } to everyapp.config.ts and start everyapp dev again.`,
219
361
  };
220
362
  }
221
363
  const sets = declaredScopeSets(policy, entry);
@@ -315,6 +457,8 @@ async function checkTokenResponse(policy, capability, sets, response) {
315
457
  google: "Ask for only the scopes integrationStatus() returns, without include_granted_scopes, and connect again; if the app needs more, add the scope set to everyapp.config.ts and deploy.",
316
458
  microsoft: "On a shared Microsoft client a token carries everything the person consented to this client: have them remove this app's consent at https://myapplications.microsoft.com and connect again, or add the scope set to everyapp.config.ts and deploy.",
317
459
  slack: "Slack scopes add up per workspace installation: reinstall the app in the workspace with only the status's scopes, or add the scope set to everyapp.config.ts and deploy.",
460
+ space: "Ask for only the scopes integrationStatus() returns and connect again, or add the scope set to everyapp.config.ts and deploy.",
461
+ comma: "Ask for only the scopes integrationStatus() returns and connect again, or add the scope set to everyapp.config.ts and deploy.",
318
462
  }[policy.dialect];
319
463
  return devRefusal(403, "integration_scope_exceeded", `${capability.label} granted scopes this app doesn't declare: ${excess.join(", ")}. It declares ${sets.join(", ")} (${requestedScopes(policy, sets).scopes.join(", ")}). Nothing was passed on. ${remedy}`);
320
464
  }
@@ -361,7 +505,8 @@ function stringValue(value) {
361
505
  * set up") up front instead of failing mid-task. An OAuth client's status
362
506
  * carries its public `clientId` for the authorize URL.
363
507
  */
364
- export async function integrationStatus({ env, provider, }) {
508
+ export async function integrationStatus({ env, provider, for: explicitTarget, }) {
509
+ const target = attributionFor(env, explicitTarget, `integrationStatus("${String(provider)}")`);
365
510
  const values = env;
366
511
  const binding = values["EVERY_APP_GATEWAY"];
367
512
  // A provider registered on the gateway is the gateway's to answer for;
@@ -389,7 +534,18 @@ export async function integrationStatus({ env, provider, }) {
389
534
  ready: false,
390
535
  });
391
536
  if (binding && typeof binding.fetch === "function") {
392
- const response = await binding.fetch(`${BINDING_ORIGIN}${INTEGRATION_PROXY_PREFIX}/${provider}`);
537
+ const statusUrl = `${BINDING_ORIGIN}${INTEGRATION_PROXY_PREFIX}/${provider}`;
538
+ let response;
539
+ if (target === undefined) {
540
+ response = await binding.fetch(statusUrl);
541
+ }
542
+ else {
543
+ // Whose status: the person's identity (their OAuth connection) or the
544
+ // organization's, as a call would carry it.
545
+ const headers = new Headers();
546
+ applyAttribution(headers, target);
547
+ response = await binding.fetch(statusUrl, { headers });
548
+ }
393
549
  if (!response.ok)
394
550
  return unavailable();
395
551
  return (await response.json());
@@ -431,9 +587,31 @@ function devOAuthClientStatus(id, capability, values) {
431
587
  : null;
432
588
  const origin = oauthClientOrigin(capability, values);
433
589
  const policy = capability.scopePolicy;
590
+ // An entry with a Gateway-owned flow is listed for reading or writing;
591
+ // the app-driven flow alone needs the write grant.
434
592
  const grant = policy
435
- ? devScopeSets(policy, id, capability.label, values)
593
+ ? devScopeSets(policy, id, capability.label, values, capability.flow ? "any" : "write")
436
594
  : null;
595
+ // The Gateway-owned flow's fields, in dev: a token in `.dev.vars`
596
+ // stands for a connection granted every declared set.
597
+ const flow = capability.flow ? "both" : "app";
598
+ const devToken = capability.flow
599
+ ? stringValue(values[devAccessTokenName(id)])
600
+ : undefined;
601
+ const gateway = (sets) => capability.flow
602
+ ? {
603
+ flow,
604
+ connectPath: `/connect/${id}`,
605
+ connection: devToken
606
+ ? {
607
+ account: "user",
608
+ label: devAccessTokenName(id),
609
+ scopeSets: sets,
610
+ ready: true,
611
+ }
612
+ : null,
613
+ }
614
+ : { flow };
437
615
  if (grant && "problem" in grant) {
438
616
  if (grant.code === "capability_not_requested") {
439
617
  return { requested: false, configured: false, ready: false };
@@ -443,16 +621,17 @@ function devOAuthClientStatus(id, capability, values) {
443
621
  configured: Boolean(client),
444
622
  ready: false,
445
623
  scopeSets: [],
624
+ ...gateway([]),
446
625
  };
447
626
  }
448
627
  const asked = policy && grant ? requestedScopes(policy, grant.sets) : null;
449
628
  return {
450
629
  requested: true,
451
630
  configured: Boolean(client),
452
- ready: Boolean(client),
631
+ ready: Boolean(client) || Boolean(devToken),
453
632
  ...(client ? { clientId: client.clientId } : {}),
454
633
  ...(client && origin ? { origin } : {}),
455
- ...(client && grant && asked
634
+ ...((client || devToken) && grant && asked
456
635
  ? {
457
636
  scopeSets: grant.sets,
458
637
  scopes: asked.scopes,
@@ -461,6 +640,7 @@ function devOAuthClientStatus(id, capability, values) {
461
640
  : {}),
462
641
  }
463
642
  : {}),
643
+ ...gateway(grant?.sets ?? []),
464
644
  };
465
645
  }
466
646
  /**
@@ -521,6 +701,6 @@ export async function gatewayRefusal(response) {
521
701
  typeof body === "object" &&
522
702
  typeof body.message === "string"
523
703
  ? body.message
524
- : `The Every App gateway refused the call (${code}).`;
704
+ : `The EveryApp gateway refused the call (${code}).`;
525
705
  return { status: response.status, code, message };
526
706
  }
@@ -28,5 +28,5 @@ export interface ListMembersOptions {
28
28
  * for a request answers its signed-in user alone, and background work
29
29
  * answers no one.
30
30
  */
31
- export declare function listMembers({ env, for: target, }: ListMembersOptions): Promise<ListMembersResult>;
31
+ export declare function listMembers({ env, for: explicitTarget, }: ListMembersOptions): Promise<ListMembersResult>;
32
32
  //# sourceMappingURL=listMembers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"listMembers.d.ts","sourceRoot":"","sources":["../../src/server/listMembers.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,iBAAiB,EAEvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAK1B,MAAM,WAAW,kBAAkB;IACjC,8FAA8F;IAC9F,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,cAAc,CAAC;CACtB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,WAAW,CAAC,EAChC,GAAG,EACH,GAAG,EAAE,MAAM,GACZ,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAoBjD"}
1
+ {"version":3,"file":"listMembers.d.ts","sourceRoot":"","sources":["../../src/server/listMembers.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAK1B,MAAM,WAAW,kBAAkB;IACjC,8FAA8F;IAC9F,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,cAAc,CAAC;CACtB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,WAAW,CAAC,EAChC,GAAG,EACH,GAAG,EAAE,cAAc,GACpB,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAoBjD"}
@@ -1,5 +1,5 @@
1
1
  import { ConfigurationError, serviceRoutePath, } from "../internal/index.js";
2
- import { applyAttribution, checkAttribution, isRequest, } from "./attribution.js";
2
+ import { applyAttribution, attributionFor, isRequest, } from "./attribution.js";
3
3
  import { getEveryAppUser } from "./everyApp.js";
4
4
  import { BINDING_ORIGIN } from "./gatewayFetch.js";
5
5
  import { GatewayRefusalError, gatewayRefusal } from "./integrationFetch.js";
@@ -19,8 +19,8 @@ import { GatewayRefusalError, gatewayRefusal } from "./integrationFetch.js";
19
19
  * for a request answers its signed-in user alone, and background work
20
20
  * answers no one.
21
21
  */
22
- export async function listMembers({ env, for: target, }) {
23
- checkAttribution(env, target, "listMembers");
22
+ export async function listMembers({ env, for: explicitTarget, }) {
23
+ const target = attributionFor(env, explicitTarget, "listMembers");
24
24
  const values = env;
25
25
  const binding = values["EVERY_APP_GATEWAY"];
26
26
  if (binding) {
@@ -48,7 +48,7 @@ async function listThroughGateway(binding, target) {
48
48
  throw new GatewayRefusalError({
49
49
  status: response.status,
50
50
  code: "members_list_failed",
51
- message: `The Every App gateway answered ${response.status} to the members list.`,
51
+ message: `The EveryApp gateway answered ${response.status} to the members list.`,
52
52
  });
53
53
  }
54
54
  return (await response.json());
@@ -64,11 +64,8 @@ async function listInDev(env, target) {
64
64
  id: user.id,
65
65
  email: user.email,
66
66
  name: "",
67
- role: memberRole(user.orgRole),
67
+ role: user.orgRole,
68
68
  },
69
69
  ],
70
70
  };
71
71
  }
72
- function memberRole(role) {
73
- return role === "owner" || role === "admin" ? role : "member";
74
- }
@@ -35,5 +35,5 @@ export interface SendEmailOptions {
35
35
  * `.dev.vars` it goes out for real through Email Sending's REST API, from
36
36
  * the developer's own account.
37
37
  */
38
- export declare function sendEmail({ env, for: target, message, }: SendEmailOptions): Promise<SendEmailResult>;
38
+ export declare function sendEmail({ env, for: explicitTarget, message, }: SendEmailOptions): Promise<SendEmailResult>;
39
39
  //# sourceMappingURL=sendEmail.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sendEmail.d.ts","sourceRoot":"","sources":["../../src/server/sendEmail.ts"],"names":[],"mappings":"AAAA,OAAO,EAeL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAI1B,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,SAAS,CAAC,EAC9B,GAAG,EACH,GAAG,EAAE,MAAM,EACX,OAAO,GACR,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAoB7C"}
1
+ {"version":3,"file":"sendEmail.d.ts","sourceRoot":"","sources":["../../src/server/sendEmail.ts"],"names":[],"mappings":"AAAA,OAAO,EAeL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAI1B,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,SAAS,CAAC,EAC9B,GAAG,EACH,GAAG,EAAE,cAAc,EACnB,OAAO,GACR,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAoB7C"}
@@ -1,5 +1,5 @@
1
1
  import { ConfigurationError, EMAIL_SENDERS_ENV, emailDomain, emailProviderRefusal, emailRestBody, emailRestUrl, emailSenderRefusal, parseEmailList, parseEmailSender, parseSendEmailMessage, readEmailRestResponse, senderAllowed, serviceRoutePath, } from "../internal/index.js";
2
- import { applyAttribution, checkAttribution, } from "./attribution.js";
2
+ import { applyAttribution, attributionFor, } from "./attribution.js";
3
3
  import { BINDING_ORIGIN } from "./gatewayFetch.js";
4
4
  import { GatewayRefusalError, gatewayRefusal } from "./integrationFetch.js";
5
5
  /**
@@ -19,8 +19,8 @@ import { GatewayRefusalError, gatewayRefusal } from "./integrationFetch.js";
19
19
  * `.dev.vars` it goes out for real through Email Sending's REST API, from
20
20
  * the developer's own account.
21
21
  */
22
- export async function sendEmail({ env, for: target, message, }) {
23
- checkAttribution(env, target, "sendEmail");
22
+ export async function sendEmail({ env, for: explicitTarget, message, }) {
23
+ const target = attributionFor(env, explicitTarget, "sendEmail");
24
24
  const values = env;
25
25
  const binding = values["EVERY_APP_GATEWAY"];
26
26
  if (binding) {
@@ -49,7 +49,7 @@ async function sendThroughGateway(binding, target, message) {
49
49
  throw new GatewayRefusalError({
50
50
  status: response.status,
51
51
  code: "email_send_failed",
52
- message: `The Every App gateway answered ${response.status} to the send.`,
52
+ message: `The EveryApp gateway answered ${response.status} to the send.`,
53
53
  });
54
54
  }
55
55
  return (await response.json());
@@ -1 +1 @@
1
- {"version":3,"file":"toolsEndpoint.d.ts","sourceRoot":"","sources":["../../src/server/toolsEndpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAcL,KAAK,sBAAsB,EAO5B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAOL,KAAK,OAAO,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,QAAQ,EAAE,sBAAsB,CAAC;CAClC;AAoFD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,oBAAoB,EACzB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAyB1B"}
1
+ {"version":3,"file":"toolsEndpoint.d.ts","sourceRoot":"","sources":["../../src/server/toolsEndpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAcL,KAAK,sBAAsB,EAO5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAOL,KAAK,OAAO,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,QAAQ,EAAE,sBAAsB,CAAC;CAClC;AAoFD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,oBAAoB,EACzB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAyB1B"}
@@ -14,7 +14,8 @@
14
14
  * The perimeter also refuses these paths from outside and strips inbound
15
15
  * `x-everyapp-*` headers, so only the gateway's ToolBus ever reaches them.
16
16
  */
17
- import { ConfigurationError, IDENTITY_HEADER, IdentityError, SYSTEM_HEADER, TOOLS_CALL_PATH, TOOLS_LIST_PATH, TOOLS_PROTOCOL_VERSION, catalogHash, requiredScopeForRisk, resolveVerifyOptions, verifyIdentityJwt, verifySystemJwt, } from "../internal/index.js";
17
+ import { ConfigurationError, IDENTITY_HEADER, IdentityError, SYSTEM_HEADER, TOOLS_CALL_PATH, TOOLS_LIST_PATH, TOOLS_PROTOCOL_VERSION, assertOrganizationPin, catalogHash, requiredScopeForRisk, resolveVerifyOptions, verifyIdentity, verifySystemJwt, } from "../internal/index.js";
18
+ import { serveRequest } from "./context.js";
18
19
  import { SDK_VERSION, ToolError, toToolResult, toolSetInternals, validateWithSchema, } from "./tools.js";
19
20
  function toolsJson(status, body, headers = {}) {
20
21
  return Response.json(body, {
@@ -148,9 +149,12 @@ function parseCallRequest(body) {
148
149
  return { v: TOOLS_PROTOCOL_VERSION, name, arguments: args, callId };
149
150
  }
150
151
  async function callTool(request, env, ctx, verify, options) {
151
- let user;
152
+ let user, expiresAt;
152
153
  try {
153
- user = await verifyIdentityJwt(request.headers.get(IDENTITY_HEADER) ?? "", verify);
154
+ ({ user, expiresAt } = await verifyIdentity(request.headers.get(IDENTITY_HEADER) ?? "", verify));
155
+ // The same pin as the handler path: a call for another organization's
156
+ // install never runs a tool here.
157
+ assertOrganizationPin(user, options.identity.organizationId);
154
158
  }
155
159
  catch (error) {
156
160
  if (error instanceof IdentityError) {
@@ -194,13 +198,15 @@ async function callTool(request, env, ctx, verify, options) {
194
198
  });
195
199
  let result;
196
200
  try {
197
- const value = await tool.handler(input.value, {
201
+ // The call runs in the request context like a page would: currentUser()
202
+ // is the caller, and its Gateway calls are attributed to them.
203
+ const value = await serveRequest({ request, user, expiresAt }, () => tool.handler(input.value, {
198
204
  user,
199
205
  env: env,
200
206
  ctx,
201
207
  request,
202
208
  callId: call.callId,
203
- });
209
+ }));
204
210
  result = await toToolResult(tool, value);
205
211
  }
206
212
  catch (error) {