@every-app/sdk 0.3.0-rc.10 → 0.3.0-rc.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +62 -64
  2. package/dist/cloudflare/catalogSettings.generated.d.ts +7 -4
  3. package/dist/cloudflare/catalogSettings.generated.d.ts.map +1 -1
  4. package/dist/cloudflare/catalogSettings.generated.js +7 -6
  5. package/dist/cloudflare/index.d.ts +1 -1
  6. package/dist/cloudflare/index.d.ts.map +1 -1
  7. package/dist/cloudflare/worker.d.ts +35 -1
  8. package/dist/cloudflare/worker.d.ts.map +1 -1
  9. package/dist/cloudflare/worker.js +31 -4
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/internal/aiDefault.d.ts +4 -3
  13. package/dist/internal/aiDefault.d.ts.map +1 -1
  14. package/dist/internal/aiDefault.js +6 -5
  15. package/dist/internal/aiProviders.d.ts.map +1 -1
  16. package/dist/internal/aiProviders.js +2 -2
  17. package/dist/internal/capabilities.d.ts +97 -481
  18. package/dist/internal/capabilities.d.ts.map +1 -1
  19. package/dist/internal/capabilities.js +47 -548
  20. package/dist/internal/catalog/index.d.ts +35 -0
  21. package/dist/internal/catalog/index.d.ts.map +1 -1
  22. package/dist/internal/catalog/infra.d.ts +35 -0
  23. package/dist/internal/catalog/infra.d.ts.map +1 -1
  24. package/dist/internal/catalog/infra.js +65 -0
  25. package/dist/internal/events.d.ts +52 -1
  26. package/dist/internal/events.d.ts.map +1 -1
  27. package/dist/internal/events.js +65 -3
  28. package/dist/internal/oauthBuiltIns.d.ts +101 -0
  29. package/dist/internal/oauthBuiltIns.d.ts.map +1 -0
  30. package/dist/internal/oauthBuiltIns.js +122 -0
  31. package/dist/internal/oauthClient.d.ts +7 -47
  32. package/dist/internal/oauthClient.d.ts.map +1 -1
  33. package/dist/internal/oauthClient.js +1 -115
  34. package/dist/internal/oauthPresets.d.ts +14 -15
  35. package/dist/internal/oauthPresets.d.ts.map +1 -1
  36. package/dist/internal/oauthPresets.js +42 -853
  37. package/dist/internal/oauthScopes.d.ts +43 -155
  38. package/dist/internal/oauthScopes.d.ts.map +1 -1
  39. package/dist/internal/oauthScopes.js +82 -475
  40. package/dist/internal/oauthSpec.d.ts +72 -71
  41. package/dist/internal/oauthSpec.d.ts.map +1 -1
  42. package/dist/internal/oauthSpec.js +178 -447
  43. package/dist/internal/protocol.d.ts +42 -13
  44. package/dist/internal/protocol.d.ts.map +1 -1
  45. package/dist/internal/protocol.js +45 -7
  46. package/dist/internal/providerRegistry.d.ts +1 -61
  47. package/dist/internal/providerRegistry.d.ts.map +1 -1
  48. package/dist/internal/providerRegistry.js +8 -115
  49. package/dist/internal/providerSpec.d.ts.map +1 -1
  50. package/dist/internal/providerSpec.js +14 -36
  51. package/dist/internal/remoteMcp.d.ts.map +1 -1
  52. package/dist/internal/remoteMcp.js +1 -5
  53. package/dist/internal/tools.d.ts +5 -4
  54. package/dist/internal/tools.d.ts.map +1 -1
  55. package/dist/internal/tools.js +4 -3
  56. package/dist/manifest.d.ts +34 -5
  57. package/dist/manifest.d.ts.map +1 -1
  58. package/dist/manifest.js +1 -1
  59. package/dist/server/attribution.d.ts +9 -0
  60. package/dist/server/attribution.d.ts.map +1 -1
  61. package/dist/server/attribution.js +7 -1
  62. package/dist/server/connectUrl.d.ts +4 -9
  63. package/dist/server/connectUrl.d.ts.map +1 -1
  64. package/dist/server/connectUrl.js +17 -14
  65. package/dist/server/eventsEndpoint.d.ts +48 -0
  66. package/dist/server/eventsEndpoint.d.ts.map +1 -0
  67. package/dist/server/eventsEndpoint.js +145 -0
  68. package/dist/server/everyApp.d.ts +15 -6
  69. package/dist/server/everyApp.d.ts.map +1 -1
  70. package/dist/server/everyApp.js +12 -3
  71. package/dist/server/index.d.ts +4 -3
  72. package/dist/server/index.d.ts.map +1 -1
  73. package/dist/server/index.js +2 -2
  74. package/dist/server/integrationFetch.d.ts +59 -71
  75. package/dist/server/integrationFetch.d.ts.map +1 -1
  76. package/dist/server/integrationFetch.js +117 -392
  77. package/dist/server/tools.d.ts +7 -2
  78. package/dist/server/tools.d.ts.map +1 -1
  79. package/dist/server/tools.js +2 -1
  80. package/dist/server/toolsEndpoint.d.ts +3 -1
  81. package/dist/server/toolsEndpoint.d.ts.map +1 -1
  82. package/dist/server/toolsEndpoint.js +9 -3
  83. package/dist/server/webhooks.d.ts +56 -0
  84. package/dist/server/webhooks.d.ts.map +1 -0
  85. package/dist/server/webhooks.js +205 -0
  86. package/package.json +1 -1
  87. package/dist/server/authorizeUrl.d.ts +0 -43
  88. package/dist/server/authorizeUrl.d.ts.map +0 -1
  89. package/dist/server/authorizeUrl.js +0 -106
@@ -17,7 +17,8 @@
17
17
  *
18
18
  * Apps never speak MCP. The gateway snapshots this catalog at deploy, serves
19
19
  * MCP clients from the snapshot, and calls a tool over the internal tools
20
- * contract (../internal/tools.ts) with a verified `chan: "mcp"` identity.
20
+ * contract (../internal/tools.ts) with a verified `chan: "mcp"` or
21
+ * `chan: "agent"` identity.
21
22
  *
22
23
  * `input` and `output` accept any validator implementing Standard Schema and
23
24
  * Standard JSON Schema (zod >= 4.2 does both), or a plain
@@ -81,7 +82,11 @@ export interface PlainToolSchema<Output = unknown> {
81
82
  export type ToolSchema<Output = unknown> = StandardSchemaWithJSON<unknown, Output> | PlainToolSchema<Output>;
82
83
  /** What a tool handler receives besides its validated input. */
83
84
  export interface ToolContext<TEnv = Cloudflare.Env> {
84
- /** The verified caller. `channel` is "mcp"; `toolCall` names this call. */
85
+ /**
86
+ * The verified caller. `channel` is "mcp" (an AI client) or "agent" (an
87
+ * agent principal: `isAgentCall(user)`, `actor.sub` `agent:<id>`, `id`
88
+ * its sponsor); `toolCall` names this call.
89
+ */
85
90
  user: EveryAppUser;
86
91
  env: TEnv;
87
92
  ctx: ExecutionContextLike;
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/server/tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/server/tools.ts"],"names":[],"mappings":"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"}
@@ -17,7 +17,8 @@
17
17
  *
18
18
  * Apps never speak MCP. The gateway snapshots this catalog at deploy, serves
19
19
  * MCP clients from the snapshot, and calls a tool over the internal tools
20
- * contract (../internal/tools.ts) with a verified `chan: "mcp"` identity.
20
+ * contract (../internal/tools.ts) with a verified `chan: "mcp"` or
21
+ * `chan: "agent"` identity.
21
22
  *
22
23
  * `input` and `output` accept any validator implementing Standard Schema and
23
24
  * Standard JSON Schema (zod >= 4.2 does both), or a plain
@@ -7,7 +7,9 @@
7
7
  * - `/__everyapp/tools/list` needs the gateway's system token for this app
8
8
  * (purpose "tools.list"). It describes tools; it never runs them.
9
9
  * - `/__everyapp/tools/call` needs an identity token minted for this exact
10
- * call: `chan: "mcp"` plus a `tc` claim naming the tool and call id. The
10
+ * call: `chan: "mcp"` (an AI client's MCP connection) or `chan: "agent"`
11
+ * (an agent principal, `act.sub` `agent:<id>`, with its sponsor as `sub`),
12
+ * plus a `tc` claim naming the tool and call id. The
11
13
  * token's scopes must include the scope the tool's risk requires; `*` does
12
14
  * not count, because the ToolBus only ever mints explicit scopes.
13
15
  *
@@ -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;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"}
1
+ {"version":3,"file":"toolsEndpoint.d.ts","sourceRoot":"","sources":["../../src/server/toolsEndpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAgBL,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"}
@@ -7,14 +7,16 @@
7
7
  * - `/__everyapp/tools/list` needs the gateway's system token for this app
8
8
  * (purpose "tools.list"). It describes tools; it never runs them.
9
9
  * - `/__everyapp/tools/call` needs an identity token minted for this exact
10
- * call: `chan: "mcp"` plus a `tc` claim naming the tool and call id. The
10
+ * call: `chan: "mcp"` (an AI client's MCP connection) or `chan: "agent"`
11
+ * (an agent principal, `act.sub` `agent:<id>`, with its sponsor as `sub`),
12
+ * plus a `tc` claim naming the tool and call id. The
11
13
  * token's scopes must include the scope the tool's risk requires; `*` does
12
14
  * not count, because the ToolBus only ever mints explicit scopes.
13
15
  *
14
16
  * The perimeter also refuses these paths from outside and strips inbound
15
17
  * `x-everyapp-*` headers, so only the gateway's ToolBus ever reaches them.
16
18
  */
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";
19
+ import { ConfigurationError, IDENTITY_HEADER, IdentityError, SYSTEM_HEADER, TOOL_CALL_CHANNELS, TOOLS_CALL_PATH, TOOLS_LIST_PATH, TOOLS_PROTOCOL_VERSION, assertOrganizationPin, catalogHash, isAgentCall, requiredScopeForRisk, resolveVerifyOptions, verifyIdentity, verifySystemJwt, } from "../internal/index.js";
18
20
  import { serveRequest } from "./context.js";
19
21
  import { SDK_VERSION, ToolError, toToolResult, toolSetInternals, validateWithSchema, } from "./tools.js";
20
22
  function toolsJson(status, body, headers = {}) {
@@ -162,7 +164,11 @@ async function callTool(request, env, ctx, verify, options) {
162
164
  }
163
165
  throw error;
164
166
  }
165
- if (user.channel !== "mcp" || !user.toolCall) {
167
+ if (!TOOL_CALL_CHANNELS.includes(user.channel) ||
168
+ !user.toolCall ||
169
+ // An agent call names its agent; a `chan: "agent"` token without one
170
+ // is not something the ToolBus mints.
171
+ (user.channel === "agent" && !isAgentCall(user))) {
166
172
  return toolsError(403, "forbidden", "Tool calls need an identity the gateway minted for this call.");
167
173
  }
168
174
  const call = parseCallRequest(await readJsonBody(request));
@@ -0,0 +1,56 @@
1
+ export type WebhookProvider = "slack" | "github" | "everyapp";
2
+ export interface VerifyWebhookOptions {
3
+ provider: WebhookProvider;
4
+ /** The signing secret, or several while one rotates. Empty ones are ignored. */
5
+ secret: string | readonly string[];
6
+ /** How far a signed timestamp may be from now (Slack, EveryApp). Default 300 s. */
7
+ toleranceSeconds?: number;
8
+ /** The largest body read before giving up. Default 5 MiB. */
9
+ maxBytes?: number;
10
+ /** The clock, for tests. */
11
+ now?: Date;
12
+ }
13
+ export type WebhookRefusalReason =
14
+ /** No usable secret was passed: a configuration fault, never the sender's. */
15
+ "no_secret"
16
+ /** The provider's signature header is absent. */
17
+ | "missing_signature"
18
+ /** A signature or timestamp header that isn't the provider's shape. */
19
+ | "malformed"
20
+ /** The signed timestamp is outside the tolerance. */
21
+ | "expired"
22
+ /** The body is larger than `maxBytes`. */
23
+ | "too_large"
24
+ /** The body was already read, or its stream failed mid-read. */
25
+ | "unreadable"
26
+ /** No secret verifies the signature. */
27
+ | "mismatch";
28
+ export type WebhookVerification = {
29
+ ok: true;
30
+ /** The body exactly as signed. The request's own body is consumed: parse this. */
31
+ body: string;
32
+ /** The provider's id for this delivery, for deduplication; null when it sends none. */
33
+ deliveryId: string | null;
34
+ /** The signed timestamp in seconds; null for GitHub, which signs none. */
35
+ timestamp: number | null;
36
+ } | {
37
+ ok: false;
38
+ reason: WebhookRefusalReason;
39
+ };
40
+ /** The default body limit: well above Slack's payloads and most of GitHub's (whose cap is 25 MB). */
41
+ export declare const WEBHOOK_MAX_BYTES_DEFAULT: number;
42
+ /**
43
+ * Verify `request` as a `provider` webhook signed with `secret`. Reads the
44
+ * body (at most `maxBytes`) and returns it on success; never throws for a
45
+ * bad delivery, so a handler answers `401` on `{ ok: false }`. Throws a
46
+ * `TypeError` only for a programming error: an unknown `provider`, or a
47
+ * `toleranceSeconds` or `maxBytes` that is negative, NaN or infinite.
48
+ *
49
+ * ```ts
50
+ * const check = await verifyWebhook(request, { provider: "slack", secret: env.SLACK_SIGNING_SECRET });
51
+ * if (!check.ok) return new Response(null, { status: 401 });
52
+ * const params = new URLSearchParams(check.body);
53
+ * ```
54
+ */
55
+ export declare function verifyWebhook(request: Request, options: VerifyWebhookOptions): Promise<WebhookVerification>;
56
+ //# sourceMappingURL=webhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../src/server/webhooks.ts"],"names":[],"mappings":"AAiCA,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,eAAe,CAAC;IAC1B,gFAAgF;IAChF,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IACnC,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,MAAM,MAAM,oBAAoB;AAC9B,8EAA8E;AAC5E,WAAW;AACb,iDAAiD;GAC/C,mBAAmB;AACrB,uEAAuE;GACrE,WAAW;AACb,qDAAqD;GACnD,SAAS;AACX,0CAA0C;GACxC,WAAW;AACb,gEAAgE;GAC9D,YAAY;AACd,wCAAwC;GACtC,UAAU,CAAC;AAEf,MAAM,MAAM,mBAAmB,GAC3B;IACE,EAAE,EAAE,IAAI,CAAC;IACT,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,0EAA0E;IAC1E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAEhD,qGAAqG;AACrG,eAAO,MAAM,yBAAyB,QAAkB,CAAC;AAMzD;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CA4D9B"}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * `verifyWebhook()`: check an inbound provider webhook on a route the
3
+ * manifest declares `public`, the way the provider signs it.
4
+ *
5
+ * The Gateway forwards a public route's body and headers untouched and
6
+ * verifies nothing (landing-page/content/agent/manifest.md, "Why a route is
7
+ * public"): the app checks the provider's signature itself, with the signing
8
+ * secret it declares in `secrets`. Every app that takes a webhook would
9
+ * otherwise write this HMAC code again, and the easy mistakes (a `===`
10
+ * compare, no timestamp window, verifying a re-serialized body, reading an
11
+ * unbounded body first) are the ones that matter. Proposed in
12
+ * docs/design/2026-11-birds-forcing-function.md (limitation 6).
13
+ *
14
+ * Supported signing schemes:
15
+ * - `slack`: `X-Slack-Signature: v0=<hex>` over `v0:<timestamp>:<body>`,
16
+ * with `X-Slack-Request-Timestamp` inside the tolerance;
17
+ * - `github`: `X-Hub-Signature-256: sha256=<hex>` over the body. GitHub
18
+ * signs no timestamp, so a replay is the receiver's to drop: dedupe on
19
+ * `deliveryId` (`X-GitHub-Delivery`);
20
+ * - `everyapp`: a Gateway's own event delivery, `X-EveryApp-Signature:
21
+ * t=<seconds>,v1=<hex>` over `<t>.<body>` (the same check as the
22
+ * Gateway's `verifyEventSignature`), deduped on `X-EveryApp-Event-Id`.
23
+ *
24
+ * WebCrypto only. The compare is `crypto.subtle.verify`, constant time.
25
+ * Several secrets may be given, so a secret rotates without a gap.
26
+ */
27
+ import { EVENT_HEADERS, EVENT_SIGNATURE_TOLERANCE_SECONDS, eventSigningInput, parseEventSignature, } from "../internal/events.js";
28
+ /** The default body limit: well above Slack's payloads and most of GitHub's (whose cap is 25 MB). */
29
+ export const WEBHOOK_MAX_BYTES_DEFAULT = 5 * 1024 * 1024;
30
+ const HEX_SHA256 = /^[0-9a-f]{64}$/i;
31
+ const MAX_EVENT_SIGNATURES = 4;
32
+ const encoder = new TextEncoder();
33
+ /**
34
+ * Verify `request` as a `provider` webhook signed with `secret`. Reads the
35
+ * body (at most `maxBytes`) and returns it on success; never throws for a
36
+ * bad delivery, so a handler answers `401` on `{ ok: false }`. Throws a
37
+ * `TypeError` only for a programming error: an unknown `provider`, or a
38
+ * `toleranceSeconds` or `maxBytes` that is negative, NaN or infinite.
39
+ *
40
+ * ```ts
41
+ * const check = await verifyWebhook(request, { provider: "slack", secret: env.SLACK_SIGNING_SECRET });
42
+ * if (!check.ok) return new Response(null, { status: 401 });
43
+ * const params = new URLSearchParams(check.body);
44
+ * ```
45
+ */
46
+ export async function verifyWebhook(request, options) {
47
+ const secrets = (typeof options.secret === "string" ? [options.secret] : options.secret).filter((secret) => typeof secret === "string" && secret.length > 0);
48
+ if (secrets.length === 0)
49
+ return refused("no_secret");
50
+ // A NaN or infinite tolerance or limit would quietly turn the window or the
51
+ // read bound off (every comparison with NaN is false): refuse the call.
52
+ const tolerance = checkedOption("toleranceSeconds", options.toleranceSeconds, EVENT_SIGNATURE_TOLERANCE_SECONDS);
53
+ const maxBytes = checkedOption("maxBytes", options.maxBytes, WEBHOOK_MAX_BYTES_DEFAULT);
54
+ const signed = readSignature(request.headers, options.provider);
55
+ if (!signed.ok)
56
+ return signed;
57
+ if (signed.timestamp !== null) {
58
+ const nowSeconds = Math.floor((options.now ?? new Date()).getTime() / 1000);
59
+ if (Math.abs(nowSeconds - signed.timestamp) > tolerance) {
60
+ return refused("expired");
61
+ }
62
+ }
63
+ const bytes = await readBody(request, maxBytes);
64
+ if (bytes === "unreadable")
65
+ return refused("unreadable");
66
+ if (bytes === null)
67
+ return refused("too_large");
68
+ // The HMAC runs over the bytes received, never a decoded and re-encoded copy.
69
+ const prefix = encoder.encode(signed.prefix);
70
+ const data = new Uint8Array(new ArrayBuffer(prefix.byteLength + bytes.byteLength));
71
+ data.set(prefix, 0);
72
+ data.set(bytes, prefix.byteLength);
73
+ for (const secret of secrets) {
74
+ const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["verify"]);
75
+ for (const candidate of signed.digests) {
76
+ if (await crypto.subtle.verify("HMAC", key, fromHex(candidate), data)) {
77
+ return {
78
+ ok: true,
79
+ body: new TextDecoder().decode(bytes),
80
+ deliveryId: signed.deliveryId,
81
+ timestamp: signed.timestamp,
82
+ };
83
+ }
84
+ }
85
+ }
86
+ return refused("mismatch");
87
+ }
88
+ function readSignature(headers, provider) {
89
+ switch (provider) {
90
+ case "slack": {
91
+ const header = headers.get("x-slack-signature");
92
+ if (!header)
93
+ return refused("missing_signature");
94
+ const rawTimestamp = headers.get("x-slack-request-timestamp");
95
+ const digest = header.startsWith("v0=") ? header.slice(3) : "";
96
+ if (!HEX_SHA256.test(digest) ||
97
+ !rawTimestamp ||
98
+ !/^\d{1,12}$/.test(rawTimestamp)) {
99
+ return refused("malformed");
100
+ }
101
+ return {
102
+ ok: true,
103
+ digests: [digest.toLowerCase()],
104
+ timestamp: Number(rawTimestamp),
105
+ deliveryId: null,
106
+ prefix: `v0:${rawTimestamp}:`,
107
+ };
108
+ }
109
+ case "github": {
110
+ const header = headers.get("x-hub-signature-256");
111
+ if (!header)
112
+ return refused("missing_signature");
113
+ const digest = header.startsWith("sha256=") ? header.slice(7) : "";
114
+ if (!HEX_SHA256.test(digest))
115
+ return refused("malformed");
116
+ return {
117
+ ok: true,
118
+ digests: [digest.toLowerCase()],
119
+ timestamp: null,
120
+ deliveryId: headers.get("x-github-delivery"),
121
+ prefix: "",
122
+ };
123
+ }
124
+ case "everyapp": {
125
+ const header = headers.get(EVENT_HEADERS.signature);
126
+ if (!header)
127
+ return refused("missing_signature");
128
+ const parsed = parseEventSignature(header);
129
+ // The Gateway sends one v1 (two while a secret rotates): a header with
130
+ // many isn't one it sent, and each would cost an HMAC per secret.
131
+ if (!parsed || parsed.v1.length > MAX_EVENT_SIGNATURES) {
132
+ return refused("malformed");
133
+ }
134
+ return {
135
+ ok: true,
136
+ digests: parsed.v1,
137
+ timestamp: parsed.timestamp,
138
+ deliveryId: headers.get(EVENT_HEADERS.eventId),
139
+ prefix: eventSigningInput(parsed.timestamp, ""),
140
+ };
141
+ }
142
+ default: {
143
+ const unknown = provider;
144
+ throw new TypeError(`verifyWebhook: unknown provider "${String(unknown)}"`);
145
+ }
146
+ }
147
+ }
148
+ /** A finite, non-negative option, or its default when not given. */
149
+ function checkedOption(name, value, fallback) {
150
+ if (value === undefined)
151
+ return fallback;
152
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
153
+ throw new TypeError(`verifyWebhook: ${name} must be a finite number of at least 0`);
154
+ }
155
+ return value;
156
+ }
157
+ /**
158
+ * The body's bytes; null once it passes `maxBytes` (read no further);
159
+ * "unreadable" when it was already consumed or its stream fails.
160
+ */
161
+ async function readBody(request, maxBytes) {
162
+ const declared = Number(request.headers.get("content-length"));
163
+ if (Number.isFinite(declared) && declared > maxBytes)
164
+ return null;
165
+ if (request.bodyUsed)
166
+ return "unreadable";
167
+ if (!request.body)
168
+ return new Uint8Array(new ArrayBuffer(0));
169
+ const chunks = [];
170
+ let total = 0;
171
+ try {
172
+ const reader = request.body.getReader();
173
+ for (;;) {
174
+ const { done, value } = await reader.read();
175
+ if (done)
176
+ break;
177
+ total += value.byteLength;
178
+ if (total > maxBytes) {
179
+ await reader.cancel().catch(() => undefined);
180
+ return null;
181
+ }
182
+ chunks.push(value);
183
+ }
184
+ }
185
+ catch {
186
+ return "unreadable";
187
+ }
188
+ const bytes = new Uint8Array(new ArrayBuffer(total));
189
+ let offset = 0;
190
+ for (const chunk of chunks) {
191
+ bytes.set(chunk, offset);
192
+ offset += chunk.byteLength;
193
+ }
194
+ return bytes;
195
+ }
196
+ function fromHex(hex) {
197
+ const bytes = new Uint8Array(new ArrayBuffer(hex.length / 2));
198
+ for (let index = 0; index < bytes.length; index += 1) {
199
+ bytes[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);
200
+ }
201
+ return bytes;
202
+ }
203
+ function refused(reason) {
204
+ return { ok: false, reason };
205
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@every-app/sdk",
3
- "version": "0.3.0-rc.10",
3
+ "version": "0.3.0-rc.11",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,43 +0,0 @@
1
- import { type OAuthClientCapabilityId } from "../internal/index.js";
2
- import type { OAuthClientIntegrationStatus } from "./integrationFetch.js";
3
- export interface AuthorizeUrlOptions {
4
- /** The OAuth client, as listed in the manifest's `capabilities`. */
5
- provider: OAuthClientCapabilityId;
6
- /** What `integrationStatus()` answered for it, ready and with its `clientId`. */
7
- status: OAuthClientIntegrationStatus;
8
- /** One of the redirect URIs the operator registered on the client. */
9
- redirectUri: string;
10
- /** The app's own anti-forgery value, checked when the person comes back. */
11
- state: string;
12
- /** PKCE: the S256 challenge of the verifier the app keeps for the exchange. */
13
- codeChallenge?: string;
14
- /**
15
- * The provider's extras (`prompt`, `login_hint`, Google's `hd`). Never
16
- * one of the parameters this helper sets (PKCE's and the provider's own
17
- * included), nor Google's `include_granted_scopes`.
18
- */
19
- params?: Record<string, string>;
20
- }
21
- /**
22
- * The provider's authorize URL to send a person to, for a client with
23
- * scope sets (`google-workspace`, `microsoft-365`, `slack`), built from the
24
- * capability's status: the registry's authorize endpoint (or the instance
25
- * the status names), `client_id`, `response_type=code`, `redirect_uri`,
26
- * `state`, and the scopes the status allows this app, which are exactly
27
- * what the gateway will let the token carry. Each provider's own needs
28
- * are added: Google's `access_type=offline` (a refresh token), Microsoft's
29
- * `response_mode=query`, Slack's comma-joined `scope` and its `user_scope`
30
- * (the status's `userScopes`, when the app's sets include a user set). With
31
- * `codeChallenge`, PKCE as S256. The app keeps its `state` and verifier
32
- * for the callback.
33
- *
34
- * A client without scope sets is refused: the
35
- * registry's checklist for one isn't what the gateway holds a token to,
36
- * so an app builds that URL itself from the status's `clientId`.
37
- *
38
- * Throws a `TypeError` naming the fix when the client has no scope sets,
39
- * when the status isn't ready or has no `clientId`, when the status lacks
40
- * `scopes`, or when `params` names a parameter the helper sets.
41
- */
42
- export declare function authorizeUrl({ provider, status, redirectUri, state, codeChallenge, params, }: AuthorizeUrlOptions): URL;
43
- //# sourceMappingURL=authorizeUrl.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"authorizeUrl.d.ts","sourceRoot":"","sources":["../../src/server/authorizeUrl.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,uBAAuB,EAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAE1E,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,QAAQ,EAAE,uBAAuB,CAAC;IAClC,iFAAiF;IACjF,MAAM,EAAE,4BAA4B,CAAC;IACrC,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAgCD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,MAAM,EACN,WAAW,EACX,KAAK,EACL,aAAa,EACb,MAAM,GACP,EAAE,mBAAmB,GAAG,GAAG,CAqD3B"}
@@ -1,106 +0,0 @@
1
- import { CAPABILITIES, ConfigurationError, } from "../internal/index.js";
2
- /**
3
- * Parameters the helper owns: the status decides the scopes, the caller's
4
- * other arguments decide the rest (PKCE from `codeChallenge`, always as
5
- * S256), each provider's own are fixed (Google's `access_type=offline` is
6
- * what gets a refresh token, Microsoft's `response_mode=query` is what
7
- * the callback reads), and Google's `include_granted_scopes` would widen
8
- * the token to every scope the person ever granted this client, which the
9
- * gateway refuses (`integration_scope_exceeded`).
10
- */
11
- const RESERVED_PARAMS = [
12
- "scope",
13
- "user_scope",
14
- "client_id",
15
- "redirect_uri",
16
- "state",
17
- "response_type",
18
- "code_challenge",
19
- "code_challenge_method",
20
- "access_type",
21
- "response_mode",
22
- "include_granted_scopes",
23
- ];
24
- /** The OAuth clients with scope sets: the ones this helper builds for. */
25
- function scopedClientIds() {
26
- return Object.entries(CAPABILITIES)
27
- .filter(([, found]) => found.mode === "oauth_client" && found.scopePolicy)
28
- .map(([id]) => id);
29
- }
30
- /**
31
- * The provider's authorize URL to send a person to, for a client with
32
- * scope sets (`google-workspace`, `microsoft-365`, `slack`), built from the
33
- * capability's status: the registry's authorize endpoint (or the instance
34
- * the status names), `client_id`, `response_type=code`, `redirect_uri`,
35
- * `state`, and the scopes the status allows this app, which are exactly
36
- * what the gateway will let the token carry. Each provider's own needs
37
- * are added: Google's `access_type=offline` (a refresh token), Microsoft's
38
- * `response_mode=query`, Slack's comma-joined `scope` and its `user_scope`
39
- * (the status's `userScopes`, when the app's sets include a user set). With
40
- * `codeChallenge`, PKCE as S256. The app keeps its `state` and verifier
41
- * for the callback.
42
- *
43
- * A client without scope sets is refused: the
44
- * registry's checklist for one isn't what the gateway holds a token to,
45
- * so an app builds that URL itself from the status's `clientId`.
46
- *
47
- * Throws a `TypeError` naming the fix when the client has no scope sets,
48
- * when the status isn't ready or has no `clientId`, when the status lacks
49
- * `scopes`, or when `params` names a parameter the helper sets.
50
- */
51
- export function authorizeUrl({ provider, status, redirectUri, state, codeChallenge, params, }) {
52
- const capability = oauthClientCapability(provider);
53
- if (!capability.scopePolicy) {
54
- throw new TypeError(`authorizeUrl() builds URLs for clients with scope sets (${scopedClientIds().join(", ")}); build ${capability.label}'s authorize URL yourself from the status's clientId.`);
55
- }
56
- if (!status.ready || !status.clientId) {
57
- throw new TypeError(`authorizeUrl(${JSON.stringify(provider)}) needs a ready status with a clientId, and integrationStatus() answered ready: ${String(status.ready)}. Show ${capability.label} as not available instead: its operator sets the client up on the gateway, and an app lists the scope sets it uses in everyapp.config.ts.`);
58
- }
59
- if (!status.scopes) {
60
- throw new TypeError(`authorizeUrl(${JSON.stringify(provider)}) takes ${capability.label}'s scopes from integrationStatus().scopes, which this status lacks: pass the status as the gateway (or everyapp dev) answered it.`);
61
- }
62
- for (const name of Object.keys(params ?? {})) {
63
- if (!RESERVED_PARAMS.includes(name))
64
- continue;
65
- throw new TypeError(name === "include_granted_scopes"
66
- ? `authorizeUrl(${JSON.stringify(provider)}): include_granted_scopes would widen the token to every scope the person granted this client, which the gateway refuses (integration_scope_exceeded); leave it out of params.`
67
- : `authorizeUrl(${JSON.stringify(provider)}) sets ${name} itself; leave it out of params.`);
68
- }
69
- const url = new URL(capability.authorize.url);
70
- // The status speaks for the gateway: its scopes are the token's ceiling.
71
- const scopes = status.scopes;
72
- const slack = url.host === "slack.com";
73
- url.searchParams.set("client_id", status.clientId);
74
- url.searchParams.set("response_type", "code");
75
- url.searchParams.set("redirect_uri", redirectUri);
76
- url.searchParams.set("state", state);
77
- url.searchParams.set("scope", scopes.join(slack ? "," : " "));
78
- if (status.userScopes && status.userScopes.length > 0) {
79
- url.searchParams.set("user_scope", status.userScopes.join(","));
80
- }
81
- if (codeChallenge) {
82
- url.searchParams.set("code_challenge", codeChallenge);
83
- url.searchParams.set("code_challenge_method", "S256");
84
- }
85
- if (url.host === "accounts.google.com") {
86
- // Without it Google issues no refresh token.
87
- url.searchParams.set("access_type", "offline");
88
- }
89
- else if (url.host === "login.microsoftonline.com") {
90
- url.searchParams.set("response_mode", "query");
91
- }
92
- for (const [name, value] of Object.entries(params ?? {})) {
93
- url.searchParams.set(name, value);
94
- }
95
- return url;
96
- }
97
- /** The OAuth client `provider` names, from plain JavaScript or a stale type too. */
98
- function oauthClientCapability(provider) {
99
- const found = Object.hasOwn(CAPABILITIES, provider)
100
- ? CAPABILITIES[provider]
101
- : undefined;
102
- if (found?.mode !== "oauth_client") {
103
- throw new ConfigurationError(`${JSON.stringify(String(provider))} isn't an OAuth client the gateway holds.`);
104
- }
105
- return found;
106
- }