@kya-os/mcp-i-cloudflare 1.16.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +11 -6
  2. package/dist/adapter.d.ts.map +1 -1
  3. package/dist/adapter.js +9 -0
  4. package/dist/adapter.js.map +1 -1
  5. package/dist/agent.d.ts.map +1 -1
  6. package/dist/agent.js +5 -0
  7. package/dist/agent.js.map +1 -1
  8. package/dist/delegation-http/bearer-retry.d.ts.map +1 -1
  9. package/dist/delegation-http/bearer-retry.js +5 -3
  10. package/dist/delegation-http/bearer-retry.js.map +1 -1
  11. package/dist/delegation-http/native-oauth.d.ts.map +1 -1
  12. package/dist/delegation-http/native-oauth.js +10 -2
  13. package/dist/delegation-http/native-oauth.js.map +1 -1
  14. package/dist/helpers/env-mapper.js +2 -2
  15. package/dist/helpers/env-mapper.js.map +1 -1
  16. package/dist/runtime/amount-limit-refusal.d.ts +3 -0
  17. package/dist/runtime/amount-limit-refusal.d.ts.map +1 -0
  18. package/dist/runtime/amount-limit-refusal.js +7 -0
  19. package/dist/runtime/amount-limit-refusal.js.map +1 -0
  20. package/dist/runtime/oauth-handler.d.ts.map +1 -1
  21. package/dist/runtime/oauth-handler.js +16 -4
  22. package/dist/runtime/oauth-handler.js.map +1 -1
  23. package/dist/runtime.d.ts.map +1 -1
  24. package/dist/runtime.js +11 -4
  25. package/dist/runtime.js.map +1 -1
  26. package/dist/services/delegation-trust.d.ts +22 -9
  27. package/dist/services/delegation-trust.d.ts.map +1 -1
  28. package/dist/services/delegation-trust.js +16 -26
  29. package/dist/services/delegation-trust.js.map +1 -1
  30. package/dist/services/delegation.service.d.ts +9 -12
  31. package/dist/services/delegation.service.d.ts.map +1 -1
  32. package/dist/services/delegation.service.js +17 -22
  33. package/dist/services/delegation.service.js.map +1 -1
  34. package/dist/services/proof.service.d.ts +10 -0
  35. package/dist/services/proof.service.d.ts.map +1 -1
  36. package/dist/services/proof.service.js +28 -6
  37. package/dist/services/proof.service.js.map +1 -1
  38. package/dist/services/resource-audience.d.ts +53 -0
  39. package/dist/services/resource-audience.d.ts.map +1 -0
  40. package/dist/services/resource-audience.js +83 -0
  41. package/dist/services/resource-audience.js.map +1 -0
  42. package/dist/types.d.ts +5 -4
  43. package/dist/types.d.ts.map +1 -1
  44. package/dist/utils/oauth-profile.d.ts +19 -0
  45. package/dist/utils/oauth-profile.d.ts.map +1 -1
  46. package/dist/utils/oauth-profile.js +54 -1
  47. package/dist/utils/oauth-profile.js.map +1 -1
  48. package/package.json +3 -3
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Resource audience: the one `aud` a delegation must name for this request.
3
+ *
4
+ * A worker can be routed under several hosts (apex and www,
5
+ * `<script>.kya-os.ai` plus a custom domain), each its own resource with its
6
+ * own `did:web:<host>`. `KYA_OS_RESOURCE_DIDS`, a JSON array of did:web DIDs
7
+ * provisioned by Checkpoint, lists them. A delegation must name exactly
8
+ * `did:web:<the host this request was routed for>`, and that DID must be
9
+ * listed: a token for one host is refused at another.
10
+ *
11
+ * The routed host must be authentic: the host of the request the edge
12
+ * delivered (Workers for Platforms dispatch forwards the original request),
13
+ * never a client-controllable forwarding header. Callers pass it in.
14
+ *
15
+ * Unset, empty or malformed configuration, a routed host that is not listed,
16
+ * or no routed host at all accepts nothing.
17
+ *
18
+ * Pure: no I/O. One implementation, shared by every verifier in this package.
19
+ */
20
+ /** The error each refusal reports; every credential is refused. */
21
+ export const RESOURCE_REFUSALS = Object.freeze({
22
+ resources_unconfigured: "KYA_OS_RESOURCE_DIDS is unset, empty or malformed: this worker has no resource DID, so no delegation can name it",
23
+ no_routed_host: "No routed host for this verification: the expected audience is did:web:<request Host>",
24
+ host_not_a_resource: "The routed host is not one of this worker's resources (KYA_OS_RESOURCE_DIDS)",
25
+ });
26
+ const DID_WEB_PATTERN = /^did:web:[a-z0-9.-]+(?:%3A[0-9]{1,5})?(?::[^\s:#?/]+)*$/;
27
+ /**
28
+ * `KYA_OS_RESOURCE_DIDS`: a non-empty JSON array of `did:web` DIDs. Anything
29
+ * else (unset, empty, not JSON, not an array, a non-did:web entry) is null,
30
+ * so every credential is refused.
31
+ */
32
+ export function parseResourceDids(raw) {
33
+ if (typeof raw !== "string" || !raw.trim())
34
+ return null;
35
+ let parsed;
36
+ try {
37
+ parsed = JSON.parse(raw);
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ return Array.isArray(parsed) &&
43
+ parsed.length > 0 &&
44
+ parsed.every((did) => typeof did === "string" && DID_WEB_PATTERN.test(did))
45
+ ? parsed
46
+ : null;
47
+ }
48
+ /** did:web for a URL host (`host[:port]`), port colon percent-encoded. */
49
+ export function didWebForHost(host) {
50
+ const value = host.trim().toLowerCase();
51
+ if (!/^[a-z0-9.-]+(?::[0-9]{1,5})?$/.test(value))
52
+ return undefined;
53
+ return "did:web:" + value.replace(":", "%3A");
54
+ }
55
+ /**
56
+ * The resource DID a delegation must name for a request routed for
57
+ * `routedHost`, given the `KYA_OS_RESOURCE_DIDS` setting.
58
+ */
59
+ export function routedResource(resourceDids, routedHost) {
60
+ const resources = parseResourceDids(resourceDids);
61
+ if (!resources)
62
+ return { refusal: "resources_unconfigured" };
63
+ const routed = routedHost === undefined ? undefined : didWebForHost(routedHost);
64
+ if (!routed)
65
+ return { refusal: "no_routed_host" };
66
+ if (!resources.includes(routed))
67
+ return { refusal: "host_not_a_resource" };
68
+ return { resourceDid: routed };
69
+ }
70
+ /**
71
+ * RFC 7519 §4.1.3: `aud` must be exactly the expected resource DID (a string,
72
+ * or an array holding only that value). A multi-valued `aud` is refused, so
73
+ * no token is accepted at more than one host.
74
+ */
75
+ export function audienceNamesResource(aud, resourceDid) {
76
+ if (aud === undefined)
77
+ return "missing";
78
+ const value = Array.isArray(aud) && aud.length === 1 ? aud[0] : aud;
79
+ return resourceDid !== undefined && value === resourceDid
80
+ ? "accepted"
81
+ : "unmatched";
82
+ }
83
+ //# sourceMappingURL=resource-audience.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-audience.js","sourceRoot":"","sources":["../../src/services/resource-audience.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAWH,mEAAmE;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAC5B,MAAM,CAAC,MAAM,CAAC;IACZ,sBAAsB,EACpB,kHAAkH;IACpH,cAAc,EACZ,uFAAuF;IACzF,mBAAmB,EACjB,8EAA8E;CACjF,CAAC,CAAC;AAOL,MAAM,eAAe,GACnB,yDAAyD,CAAC;AAE5D;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;QAAE,OAAO,IAAI,CAAC;IACxD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAC1B,MAAM,CAAC,MAAM,GAAG,CAAC;QACjB,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3E,CAAC,CAAE,MAAmB;QACtB,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACxC,IAAI,CAAC,+BAA+B,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACnE,OAAO,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,YAAqB,EACrB,UAA8B;IAE9B,MAAM,SAAS,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;IAClD,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC;IAC7D,MAAM,MAAM,GACV,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAClD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC;IAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,GAAY,EACZ,WAA+B;IAE/B,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACpE,OAAO,WAAW,KAAK,SAAS,IAAI,KAAK,KAAK,WAAW;QACvD,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,WAAW,CAAC;AAClB,CAAC"}
package/dist/types.d.ts CHANGED
@@ -62,11 +62,12 @@ export interface CloudflareEnv {
62
62
  */
63
63
  KYA_OS_TRUSTED_DELEGATION_ISSUERS?: string;
64
64
  /**
65
- * Comma- or whitespace-separated `aud` values this worker accepts on
66
- * delegation VC-JWTs, in addition to its own DID, CHECKPOINT_PROJECT_ID and
67
- * the native issuer binding's org DID and project. Read by DelegationService.
65
+ * This worker's resources: a JSON array of `did:web:<host>`, one per host it
66
+ * is routed under, provisioned by Checkpoint. A delegation's `aud` must be
67
+ * `did:web:<the request's Host>` and be in this list. Unset, empty or
68
+ * malformed, every delegation is refused. Read by DelegationService.
68
69
  */
69
- KYA_OS_DELEGATION_AUDIENCES?: string;
70
+ KYA_OS_RESOURCE_DIDS?: string;
70
71
  /**
71
72
  * "1"/"true" accepts legacy (non VC-JWT) delegation tokens unchecked when no
72
73
  * CHECKPOINT_API_KEY is configured. Local development only; never cached.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -4,4 +4,23 @@ export declare function oauthProfileString(value: unknown): string | undefined;
4
4
  export declare function normalizeOAuthSubject(value: unknown): string | undefined;
5
5
  /** Use provider identifiers; an email alone is not a provider subject. */
6
6
  export declare function oauthProfileSubject(profile: unknown): string | undefined;
7
+ /**
8
+ * The email to send for identity linking, and whether the provider verified it.
9
+ *
10
+ * GitHub's /user has no verification flag, so for a profile read from the
11
+ * GitHub API the only verified email is the primary one on /user/emails (needs
12
+ * the `user:email` scope). A missing scope, an error or an unverified primary
13
+ * leaves the profile email unverified. The token only goes to the API that
14
+ * already served the profile. Other providers keep their explicit boolean claim.
15
+ */
16
+ export declare function resolveOAuthEmail(params: {
17
+ profile: Record<string, unknown>;
18
+ userInfoUrl: string;
19
+ accessToken: string;
20
+ fetchImpl: typeof fetch;
21
+ userAgent: string;
22
+ }): Promise<{
23
+ email?: string;
24
+ emailVerified: boolean;
25
+ }>;
7
26
  //# sourceMappingURL=oauth-profile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-profile.d.ts","sourceRoot":"","sources":["../../src/utils/oauth-profile.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAIrE;AAED,8EAA8E;AAC9E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAKxE;AAED,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAUxE"}
1
+ {"version":3,"file":"oauth-profile.d.ts","sourceRoot":"","sources":["../../src/utils/oauth-profile.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAIrE;AAED,8EAA8E;AAC9E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOxE;AAED,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAUxE;AAmBD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE;IAC9C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,KAAK,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,OAAO,CAAA;CAAE,CAAC,CA2BtD"}
@@ -7,7 +7,9 @@ export function oauthProfileString(value) {
7
7
  /** GitHub subjects are numeric IDs; preserve them as exact scalar strings. */
8
8
  export function normalizeOAuthSubject(value) {
9
9
  if (typeof value === "number") {
10
- return Number.isSafeInteger(value) && value >= 0 ? String(value) : undefined;
10
+ return Number.isSafeInteger(value) && value >= 0
11
+ ? String(value)
12
+ : undefined;
11
13
  }
12
14
  return oauthProfileString(value);
13
15
  }
@@ -21,4 +23,55 @@ export function oauthProfileSubject(profile) {
21
23
  normalizeOAuthSubject(claims.id) ??
22
24
  oauthProfileString(claims.login));
23
25
  }
26
+ const GITHUB_API_ORIGIN = "https://api.github.com";
27
+ /** The primary address from GitHub's /user/emails, only when GitHub verified it. */
28
+ function githubVerifiedPrimaryEmail(emails) {
29
+ if (!Array.isArray(emails))
30
+ return undefined;
31
+ const primary = emails.find((entry) => !!entry &&
32
+ typeof entry === "object" &&
33
+ "primary" in entry &&
34
+ entry.primary === true);
35
+ return primary?.verified === true
36
+ ? oauthProfileString(primary.email)
37
+ : undefined;
38
+ }
39
+ /**
40
+ * The email to send for identity linking, and whether the provider verified it.
41
+ *
42
+ * GitHub's /user has no verification flag, so for a profile read from the
43
+ * GitHub API the only verified email is the primary one on /user/emails (needs
44
+ * the `user:email` scope). A missing scope, an error or an unverified primary
45
+ * leaves the profile email unverified. The token only goes to the API that
46
+ * already served the profile. Other providers keep their explicit boolean claim.
47
+ */
48
+ export async function resolveOAuthEmail(params) {
49
+ const profileEmail = oauthProfileString(params.profile.email);
50
+ if (new URL(params.userInfoUrl).origin !== GITHUB_API_ORIGIN) {
51
+ return {
52
+ email: profileEmail,
53
+ emailVerified: params.profile.email_verified === true,
54
+ };
55
+ }
56
+ // Unbound: Workers throws "Illegal invocation" for fetch called as a method.
57
+ const { fetchImpl } = params;
58
+ try {
59
+ const response = await fetchImpl(`${GITHUB_API_ORIGIN}/user/emails`, {
60
+ headers: {
61
+ Authorization: `Bearer ${params.accessToken}`,
62
+ Accept: "application/vnd.github+json",
63
+ "User-Agent": params.userAgent,
64
+ },
65
+ });
66
+ const verified = response.ok
67
+ ? githubVerifiedPrimaryEmail(await response.json())
68
+ : undefined;
69
+ return verified
70
+ ? { email: verified, emailVerified: true }
71
+ : { email: profileEmail, emailVerified: false };
72
+ }
73
+ catch {
74
+ return { email: profileEmail, emailVerified: false };
75
+ }
76
+ }
24
77
  //# sourceMappingURL=oauth-profile.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-profile.js","sourceRoot":"","sources":["../../src/utils/oauth-profile.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;QACzD,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/E,CAAC;IACD,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACtE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,MAAM,GAAG,OAAkC,CAAC;IAClD,OAAO,CACL,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC;QAC9B,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CACjC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"oauth-profile.js","sourceRoot":"","sources":["../../src/utils/oauth-profile.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kya-os/mcp-i-cloudflare",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "description": "Cloudflare Workers adapter for MCP-I framework",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -31,8 +31,8 @@
31
31
  "prepublishOnly": "npm run build && node ../create-mcpi-app/scripts/validate-no-workspace.js"
32
32
  },
33
33
  "dependencies": {
34
- "@kya-os/consent": "^0.1.50",
35
- "@kya-os/contracts": "^1.13.1",
34
+ "@kya-os/consent": "^0.2.0",
35
+ "@kya-os/contracts": "^1.14.0",
36
36
  "@kya-os/mcp": "1.16.0",
37
37
  "@kya-os/mcp-i-core": "^1.9.4",
38
38
  "@kya-os/mcp-i-runtime": "^1.3.1",