@kya-os/mcp 1.5.0 → 1.6.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 (82) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/dist/authz/accountability.d.ts +35 -0
  3. package/dist/authz/accountability.d.ts.map +1 -0
  4. package/dist/authz/accountability.js +28 -0
  5. package/dist/authz/accountability.js.map +1 -0
  6. package/dist/authz/adapter.d.ts +47 -0
  7. package/dist/authz/adapter.d.ts.map +1 -0
  8. package/dist/authz/adapter.js +10 -0
  9. package/dist/authz/adapter.js.map +1 -0
  10. package/dist/authz/examples/inmemory-oidc.d.ts +29 -0
  11. package/dist/authz/examples/inmemory-oidc.d.ts.map +1 -0
  12. package/dist/authz/examples/inmemory-oidc.js +68 -0
  13. package/dist/authz/examples/inmemory-oidc.js.map +1 -0
  14. package/dist/authz/index.d.ts +19 -0
  15. package/dist/authz/index.d.ts.map +1 -0
  16. package/dist/authz/index.js +19 -0
  17. package/dist/authz/index.js.map +1 -0
  18. package/dist/authz/oidc/authorize.d.ts +25 -0
  19. package/dist/authz/oidc/authorize.d.ts.map +1 -0
  20. package/dist/authz/oidc/authorize.js +24 -0
  21. package/dist/authz/oidc/authorize.js.map +1 -0
  22. package/dist/authz/oidc/metadata.d.ts +43 -0
  23. package/dist/authz/oidc/metadata.d.ts.map +1 -0
  24. package/dist/authz/oidc/metadata.js +32 -0
  25. package/dist/authz/oidc/metadata.js.map +1 -0
  26. package/dist/authz/oidc/oidc-adapter.d.ts +52 -0
  27. package/dist/authz/oidc/oidc-adapter.d.ts.map +1 -0
  28. package/dist/authz/oidc/oidc-adapter.js +131 -0
  29. package/dist/authz/oidc/oidc-adapter.js.map +1 -0
  30. package/dist/authz/oidc/pkce.d.ts +20 -0
  31. package/dist/authz/oidc/pkce.d.ts.map +1 -0
  32. package/dist/authz/oidc/pkce.js +29 -0
  33. package/dist/authz/oidc/pkce.js.map +1 -0
  34. package/dist/authz/registry.d.ts +29 -0
  35. package/dist/authz/registry.d.ts.map +1 -0
  36. package/dist/authz/registry.js +48 -0
  37. package/dist/authz/registry.js.map +1 -0
  38. package/dist/authz/requirement.d.ts +38 -0
  39. package/dist/authz/requirement.d.ts.map +1 -0
  40. package/dist/authz/requirement.js +45 -0
  41. package/dist/authz/requirement.js.map +1 -0
  42. package/dist/delegation/chain-enforcement.d.ts +86 -0
  43. package/dist/delegation/chain-enforcement.d.ts.map +1 -0
  44. package/dist/delegation/chain-enforcement.js +224 -0
  45. package/dist/delegation/chain-enforcement.js.map +1 -0
  46. package/dist/delegation/holder-binding.d.ts +128 -0
  47. package/dist/delegation/holder-binding.d.ts.map +1 -0
  48. package/dist/delegation/holder-binding.js +175 -0
  49. package/dist/delegation/holder-binding.js.map +1 -0
  50. package/dist/delegation/index.d.ts +2 -0
  51. package/dist/delegation/index.d.ts.map +1 -1
  52. package/dist/delegation/index.js +2 -0
  53. package/dist/delegation/index.js.map +1 -1
  54. package/dist/errors.d.ts +1 -0
  55. package/dist/errors.d.ts.map +1 -1
  56. package/dist/errors.js +1 -0
  57. package/dist/errors.js.map +1 -1
  58. package/dist/index.d.ts +2 -1
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +2 -1
  61. package/dist/index.js.map +1 -1
  62. package/dist/middleware/with-kya-os.d.ts +35 -1
  63. package/dist/middleware/with-kya-os.d.ts.map +1 -1
  64. package/dist/middleware/with-kya-os.js +94 -192
  65. package/dist/middleware/with-kya-os.js.map +1 -1
  66. package/dist/providers/grant-store.d.ts +98 -0
  67. package/dist/providers/grant-store.d.ts.map +1 -0
  68. package/dist/providers/grant-store.js +92 -0
  69. package/dist/providers/grant-store.js.map +1 -0
  70. package/dist/providers/index.d.ts +2 -0
  71. package/dist/providers/index.d.ts.map +1 -1
  72. package/dist/providers/index.js +2 -0
  73. package/dist/providers/index.js.map +1 -1
  74. package/dist/providers/runtime-fetch.d.ts +14 -0
  75. package/dist/providers/runtime-fetch.d.ts.map +1 -1
  76. package/dist/providers/runtime-fetch.js +22 -0
  77. package/dist/providers/runtime-fetch.js.map +1 -1
  78. package/dist/providers/web-crypto.d.ts +35 -0
  79. package/dist/providers/web-crypto.d.ts.map +1 -0
  80. package/dist/providers/web-crypto.js +91 -0
  81. package/dist/providers/web-crypto.js.map +1 -0
  82. package/package.json +25 -16
@@ -0,0 +1,131 @@
1
+ import { base64url } from 'jose';
2
+ import { createNeedsAuthorizationError, } from '../../types/protocol.js';
3
+ import { requirementMatchesAdapter } from '../adapter.js';
4
+ import { buildAuthorizeUrl } from './authorize.js';
5
+ import { computeS256Challenge } from './pkce.js';
6
+ /**
7
+ * Reference generic-OIDC authorization-server adapter.
8
+ *
9
+ * Implements {@link AuthorizationServerAdapter} for a standards-only OpenID
10
+ * Connect / OAuth 2.1 provider. No named vendor identity provider appears
11
+ * here; concrete commercial providers are downstream adapters binding the same
12
+ * port. The pure pieces (authorize URL, PKCE) run inline; the single IdP HTTP
13
+ * call (token
14
+ * exchange) goes through an injectable fetch seam, so the adapter is fully
15
+ * deterministic under test with no network.
16
+ *
17
+ * The PKCE code verifier is held server-side keyed by the resume token and is
18
+ * never placed in the authorization URL — only the S256 challenge travels.
19
+ */
20
+ export class GenericOidcAdapter {
21
+ config;
22
+ type = 'oauth';
23
+ pending = new Map();
24
+ fetchImpl;
25
+ constructor(config) {
26
+ this.config = config;
27
+ this.fetchImpl = config.fetchImpl ?? ((url, init) => fetch(url, init));
28
+ }
29
+ isRequired(protection) {
30
+ return requirementMatchesAdapter(this.type, protection);
31
+ }
32
+ async initiateFlow(params) {
33
+ const requiredScopes = params.protection.requirement.type === 'oauth'
34
+ ? (params.protection.requirement.requiredScopes ?? this.config.scopes)
35
+ : this.config.scopes;
36
+ const scopes = unique([...this.config.scopes, ...requiredScopes]);
37
+ const codeVerifier = randomToken(32);
38
+ const codeChallenge = await computeS256Challenge(codeVerifier);
39
+ const resumeToken = randomToken(24);
40
+ this.pending.set(resumeToken, {
41
+ agentDid: params.agentDid,
42
+ scopes,
43
+ state: params.state,
44
+ codeVerifier,
45
+ redirectUri: params.redirectUri,
46
+ });
47
+ const authorizationUrl = buildAuthorizeUrl({
48
+ authorizationEndpoint: this.config.authorizationEndpoint,
49
+ clientId: this.config.clientId,
50
+ redirectUri: params.redirectUri,
51
+ scopes,
52
+ state: params.state,
53
+ codeChallenge,
54
+ resource: this.config.resource,
55
+ });
56
+ return createNeedsAuthorizationError({
57
+ message: `Authorization required for "${params.protection.toolName}".`,
58
+ authorizationUrl,
59
+ resumeToken,
60
+ expiresAt: nowMs() + (this.config.resumeTokenTtlMs ?? 600_000),
61
+ scopes,
62
+ });
63
+ }
64
+ async verifyAuthorization(flowState, result) {
65
+ const pending = this.pending.get(flowState);
66
+ if (!pending) {
67
+ return { valid: false, reason: 'unknown or expired resume token' };
68
+ }
69
+ const { code, state } = (result ?? {});
70
+ if (!code) {
71
+ return { valid: false, reason: 'missing authorization code' };
72
+ }
73
+ if (state !== pending.state) {
74
+ return { valid: false, reason: 'state mismatch' };
75
+ }
76
+ const body = new URLSearchParams({
77
+ grant_type: 'authorization_code',
78
+ code,
79
+ redirect_uri: pending.redirectUri,
80
+ client_id: this.config.clientId,
81
+ code_verifier: pending.codeVerifier,
82
+ });
83
+ if (this.config.resource)
84
+ body.set('resource', this.config.resource);
85
+ if (this.config.clientSecret)
86
+ body.set('client_secret', this.config.clientSecret);
87
+ let token;
88
+ try {
89
+ const response = await this.fetchImpl(this.config.tokenEndpoint, {
90
+ method: 'POST',
91
+ headers: { 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' },
92
+ body: body.toString(),
93
+ });
94
+ if (!response.ok) {
95
+ return { valid: false, reason: `token endpoint returned ${response.status}` };
96
+ }
97
+ token = (await response.json());
98
+ }
99
+ catch (error) {
100
+ return { valid: false, reason: `token exchange failed: ${error.message}` };
101
+ }
102
+ // One-time use: a resume token is consumed on verification.
103
+ this.pending.delete(flowState);
104
+ const grantedScopes = token.scope ? token.scope.split(' ') : pending.scopes;
105
+ return {
106
+ valid: true,
107
+ credential: {
108
+ agent_did: pending.agentDid,
109
+ user_did: '',
110
+ scopes: grantedScopes,
111
+ authorization: { type: 'oauth', provider: 'generic-oidc' },
112
+ },
113
+ };
114
+ }
115
+ /** Test/inspection seam: the pending code verifier for a resume token, if any. */
116
+ pendingVerifierFor(resumeToken) {
117
+ return this.pending.get(resumeToken)?.codeVerifier;
118
+ }
119
+ }
120
+ function randomToken(byteLength) {
121
+ const bytes = new Uint8Array(byteLength);
122
+ globalThis.crypto.getRandomValues(bytes);
123
+ return base64url.encode(bytes);
124
+ }
125
+ function unique(values) {
126
+ return [...new Set(values)];
127
+ }
128
+ function nowMs() {
129
+ return Date.now();
130
+ }
131
+ //# sourceMappingURL=oidc-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-adapter.js","sourceRoot":"","sources":["../../../src/authz/oidc/oidc-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * PKCE (RFC 7636), S256 only.
3
+ *
4
+ * KYA-OS mandates the S256 challenge method — `plain` is never accepted. These
5
+ * helpers are runtime-neutral and dependency-free beyond jose's base64url and
6
+ * the Web Crypto API (available in Node 20+, edge runtimes, and browsers). No
7
+ * Node-specific import, matching the package's runtime-neutral convention.
8
+ */
9
+ export type S256 = 'S256';
10
+ /** True only for the S256 challenge method. */
11
+ export declare function isS256ChallengeMethod(method: string): method is S256;
12
+ /** Compute the S256 code challenge for a verifier: BASE64URL(SHA-256(verifier)). */
13
+ export declare function computeS256Challenge(codeVerifier: string): Promise<string>;
14
+ /**
15
+ * Verify a code verifier against its S256 challenge. Returns false on any
16
+ * mismatch; never throws. The compare is length-checked and constant-time over
17
+ * the challenge string.
18
+ */
19
+ export declare function verifyS256Challenge(codeVerifier: string, codeChallenge: string): Promise<boolean>;
20
+ //# sourceMappingURL=pkce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../../../src/authz/oidc/pkce.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC;AAE1B,+CAA+C;AAC/C,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,IAAI,CAEpE;AAED,oFAAoF;AACpF,wBAAsB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhF;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,OAAO,CAAC,CAGlB"}
@@ -0,0 +1,29 @@
1
+ import { base64url } from 'jose';
2
+ /** True only for the S256 challenge method. */
3
+ export function isS256ChallengeMethod(method) {
4
+ return method === 'S256';
5
+ }
6
+ /** Compute the S256 code challenge for a verifier: BASE64URL(SHA-256(verifier)). */
7
+ export async function computeS256Challenge(codeVerifier) {
8
+ const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(codeVerifier));
9
+ return base64url.encode(new Uint8Array(digest));
10
+ }
11
+ /**
12
+ * Verify a code verifier against its S256 challenge. Returns false on any
13
+ * mismatch; never throws. The compare is length-checked and constant-time over
14
+ * the challenge string.
15
+ */
16
+ export async function verifyS256Challenge(codeVerifier, codeChallenge) {
17
+ const expected = await computeS256Challenge(codeVerifier);
18
+ return timingSafeEqual(expected, codeChallenge);
19
+ }
20
+ /** Length-checked constant-time string compare. */
21
+ function timingSafeEqual(a, b) {
22
+ if (a.length !== b.length)
23
+ return false;
24
+ let diff = 0;
25
+ for (let i = 0; i < a.length; i++)
26
+ diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
27
+ return diff === 0;
28
+ }
29
+ //# sourceMappingURL=pkce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../../src/authz/oidc/pkce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAajC,+CAA+C;AAC/C,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,OAAO,MAAM,KAAK,MAAM,CAAC;AAC3B,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,YAAoB;IAC7D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IAC7F,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,YAAoB,EACpB,aAAqB;IAErB,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAC1D,OAAO,eAAe,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AAClD,CAAC;AAED,mDAAmD;AACnD,SAAS,eAAe,CAAC,CAAS,EAAE,CAAS;IAC3C,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC7E,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { AuthorizationServerAdapter } from './adapter.js';
2
+ import type { AuthorizationRequirement, ToolProtection } from './requirement.js';
3
+ /**
4
+ * Routes a tool's protection to exactly one {@link AuthorizationServerAdapter},
5
+ * keyed by requirement type. Mirrors the provider-registry lifecycle (register
6
+ * / get / list / resolve / seal) so the authorization seam composes the same
7
+ * pluggable, sealed way the rest of the protocol does. In-memory and
8
+ * dependency-free.
9
+ */
10
+ export declare class AuthorizationServerRegistry {
11
+ private readonly adapters;
12
+ private sealed;
13
+ /** Register an adapter for its requirement type. Throws on duplicate or when sealed. */
14
+ register(adapter: AuthorizationServerAdapter): void;
15
+ /** The adapter registered for a requirement type, if any. */
16
+ get(type: AuthorizationRequirement['type']): AuthorizationServerAdapter | undefined;
17
+ /** All registered adapters, in registration order. */
18
+ list(): AuthorizationServerAdapter[];
19
+ /**
20
+ * Resolve the adapter that must run for a tool protection. Returns undefined
21
+ * when the tool needs no authorization (`type: 'none'`) or no adapter is
22
+ * registered for its requirement type.
23
+ */
24
+ resolve(protection: ToolProtection): AuthorizationServerAdapter | undefined;
25
+ /** Freeze the registry; subsequent registration throws. */
26
+ seal(): void;
27
+ isSealed(): boolean;
28
+ }
29
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/authz/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEjF;;;;;;GAMG;AACH,qBAAa,2BAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2E;IACpG,OAAO,CAAC,MAAM,CAAS;IAEvB,wFAAwF;IACxF,QAAQ,CAAC,OAAO,EAAE,0BAA0B,GAAG,IAAI;IAUnD,6DAA6D;IAC7D,GAAG,CAAC,IAAI,EAAE,wBAAwB,CAAC,MAAM,CAAC,GAAG,0BAA0B,GAAG,SAAS;IAInF,sDAAsD;IACtD,IAAI,IAAI,0BAA0B,EAAE;IAIpC;;;;OAIG;IACH,OAAO,CAAC,UAAU,EAAE,cAAc,GAAG,0BAA0B,GAAG,SAAS;IAM3E,2DAA2D;IAC3D,IAAI,IAAI,IAAI;IAIZ,QAAQ,IAAI,OAAO;CAGpB"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Routes a tool's protection to exactly one {@link AuthorizationServerAdapter},
3
+ * keyed by requirement type. Mirrors the provider-registry lifecycle (register
4
+ * / get / list / resolve / seal) so the authorization seam composes the same
5
+ * pluggable, sealed way the rest of the protocol does. In-memory and
6
+ * dependency-free.
7
+ */
8
+ export class AuthorizationServerRegistry {
9
+ adapters = new Map();
10
+ sealed = false;
11
+ /** Register an adapter for its requirement type. Throws on duplicate or when sealed. */
12
+ register(adapter) {
13
+ if (this.sealed) {
14
+ throw new Error('AuthorizationServerRegistry is sealed; cannot register further adapters.');
15
+ }
16
+ if (this.adapters.has(adapter.type)) {
17
+ throw new Error(`An adapter for type "${adapter.type}" is already registered.`);
18
+ }
19
+ this.adapters.set(adapter.type, adapter);
20
+ }
21
+ /** The adapter registered for a requirement type, if any. */
22
+ get(type) {
23
+ return this.adapters.get(type);
24
+ }
25
+ /** All registered adapters, in registration order. */
26
+ list() {
27
+ return [...this.adapters.values()];
28
+ }
29
+ /**
30
+ * Resolve the adapter that must run for a tool protection. Returns undefined
31
+ * when the tool needs no authorization (`type: 'none'`) or no adapter is
32
+ * registered for its requirement type.
33
+ */
34
+ resolve(protection) {
35
+ if (protection.requirement.type === 'none')
36
+ return undefined;
37
+ const adapter = this.adapters.get(protection.requirement.type);
38
+ return adapter?.isRequired(protection) ? adapter : undefined;
39
+ }
40
+ /** Freeze the registry; subsequent registration throws. */
41
+ seal() {
42
+ this.sealed = true;
43
+ }
44
+ isSealed() {
45
+ return this.sealed;
46
+ }
47
+ }
48
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/authz/registry.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,OAAO,2BAA2B;IACrB,QAAQ,GAAG,IAAI,GAAG,EAAgE,CAAC;IAC5F,MAAM,GAAG,KAAK,CAAC;IAEvB,wFAAwF;IACxF,QAAQ,CAAC,OAAmC;QAC1C,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAC9F,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,CAAC,IAAI,0BAA0B,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,6DAA6D;IAC7D,GAAG,CAAC,IAAsC;QACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,sDAAsD;IACtD,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,UAA0B;QAChC,IAAI,UAAU,CAAC,WAAW,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,SAAS,CAAC;QAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC/D,OAAO,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/D,CAAC;IAED,2DAA2D;IAC3D,IAAI;QACF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF"}
@@ -0,0 +1,38 @@
1
+ import { z } from 'zod';
2
+ export declare const AuthorizationRequirementSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3
+ type: z.ZodLiteral<"oauth">;
4
+ provider: z.ZodString;
5
+ requiredScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
6
+ }, z.core.$strip>, z.ZodObject<{
7
+ type: z.ZodLiteral<"mdl">;
8
+ }, z.core.$strip>, z.ZodObject<{
9
+ type: z.ZodLiteral<"idv">;
10
+ }, z.core.$strip>, z.ZodObject<{
11
+ type: z.ZodLiteral<"credential">;
12
+ }, z.core.$strip>, z.ZodObject<{
13
+ type: z.ZodLiteral<"none">;
14
+ }, z.core.$strip>], "type">;
15
+ export type AuthorizationRequirement = z.infer<typeof AuthorizationRequirementSchema>;
16
+ /**
17
+ * Binds a tool to the authorization it requires. The PEP consults the
18
+ * requirement before dispatching a tool, and an adapter turns an unmet
19
+ * requirement into a `needs_authorization` challenge.
20
+ */
21
+ export declare const ToolProtectionSchema: z.ZodObject<{
22
+ toolName: z.ZodString;
23
+ requirement: z.ZodDiscriminatedUnion<[z.ZodObject<{
24
+ type: z.ZodLiteral<"oauth">;
25
+ provider: z.ZodString;
26
+ requiredScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
27
+ }, z.core.$strip>, z.ZodObject<{
28
+ type: z.ZodLiteral<"mdl">;
29
+ }, z.core.$strip>, z.ZodObject<{
30
+ type: z.ZodLiteral<"idv">;
31
+ }, z.core.$strip>, z.ZodObject<{
32
+ type: z.ZodLiteral<"credential">;
33
+ }, z.core.$strip>, z.ZodObject<{
34
+ type: z.ZodLiteral<"none">;
35
+ }, z.core.$strip>], "type">;
36
+ }, z.core.$strip>;
37
+ export type ToolProtection = z.infer<typeof ToolProtectionSchema>;
38
+ //# sourceMappingURL=requirement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirement.d.ts","sourceRoot":"","sources":["../../src/authz/requirement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA+BxB,eAAO,MAAM,8BAA8B;;;;;;;;;;;;2BAMzC,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAEtF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;iBAG/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Authorization requirement vocabulary.
4
+ *
5
+ * An {@link AuthorizationRequirement} describes *what kind* of authorization a
6
+ * tool needs, independent of any concrete authorization server. It is the
7
+ * neutral input an {@link AuthorizationServerAdapter} dispatches on — the same
8
+ * separation the policy layer draws between a neutral request and a pluggable
9
+ * engine. Concrete adapters (a generic-OIDC reference adapter ships in this
10
+ * package; vendor adapters live downstream) implement the behavior for a given
11
+ * `type`.
12
+ *
13
+ * The variants mirror the authorization methods the protocol anticipates:
14
+ * `oauth` (an authorization-code/OIDC flow), `mdl` (an ISO mDL presentation),
15
+ * `idv` (an identity-verification flow), `credential` (a directly held
16
+ * verifiable credential), and `none` (no authorization required).
17
+ */
18
+ const oauthRequirement = z.object({
19
+ type: z.literal('oauth'),
20
+ /** The provider id an adapter registry resolves to a concrete adapter. */
21
+ provider: z.string().min(1),
22
+ /** Scopes the flow must obtain; omitted means the adapter's default set. */
23
+ requiredScopes: z.array(z.string()).optional(),
24
+ });
25
+ const mdlRequirement = z.object({ type: z.literal('mdl') });
26
+ const idvRequirement = z.object({ type: z.literal('idv') });
27
+ const credentialRequirement = z.object({ type: z.literal('credential') });
28
+ const noneRequirement = z.object({ type: z.literal('none') });
29
+ export const AuthorizationRequirementSchema = z.discriminatedUnion('type', [
30
+ oauthRequirement,
31
+ mdlRequirement,
32
+ idvRequirement,
33
+ credentialRequirement,
34
+ noneRequirement,
35
+ ]);
36
+ /**
37
+ * Binds a tool to the authorization it requires. The PEP consults the
38
+ * requirement before dispatching a tool, and an adapter turns an unmet
39
+ * requirement into a `needs_authorization` challenge.
40
+ */
41
+ export const ToolProtectionSchema = z.object({
42
+ toolName: z.string().min(1),
43
+ requirement: AuthorizationRequirementSchema,
44
+ });
45
+ //# sourceMappingURL=requirement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirement.js","sourceRoot":"","sources":["../../src/authz/requirement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;GAeG;AACH,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,4EAA4E;IAC5E,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CAC/C,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC5D,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC5D,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AAC1E,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAE9D,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IACzE,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,qBAAqB;IACrB,eAAe;CAChB,CAAC,CAAC;AAIH;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,WAAW,EAAE,8BAA8B;CAC5C,CAAC,CAAC"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Delegation chain enforcement — framework-agnostic core (E3 · #2888).
3
+ *
4
+ * The leaf→root chain walk, scope-attenuation, audience binding, confused-deputy
5
+ * guard (KYA-OS §11.6), and ancestor-revocation rules, lifted out of the
6
+ * `with-kya-os` middleware closure so the SAME logic runs in every host (MCP
7
+ * middleware, an HTTP PEP, the conformance harness) against one implementation
8
+ * rather than a per-transport fork.
9
+ *
10
+ * Dependencies are injected as ports (interface-first): a per-credential
11
+ * verifier, an optional ancestor resolver, and an optional graph-backed
12
+ * `RevocationChecker`. Nothing here imports a transport or framework.
13
+ */
14
+ import { type DelegationCredential } from "../types/protocol.js";
15
+ /** Union of a credential's delegation scopes and its constraint scopes. */
16
+ export declare function getDelegationScopes(credential: DelegationCredential): string[];
17
+ /**
18
+ * A child re-delegation may only narrow (attenuate) its parent's authority.
19
+ * Enforces flat-scope subset AND crisp-matcher subset (by matcher+resource),
20
+ * failing closed on any widening. Pure; never throws.
21
+ */
22
+ export declare function validateScopeAttenuation(parentCredential: DelegationCredential, childCredential: DelegationCredential): {
23
+ valid: boolean;
24
+ reason?: string;
25
+ };
26
+ /** Per-credential verifier port (signature / schema / expiry / own status). */
27
+ export interface DelegationCredentialVerifierPort {
28
+ verifyDelegationCredential(credential: DelegationCredential, options?: {
29
+ skipSignature?: boolean;
30
+ }): Promise<{
31
+ valid: boolean;
32
+ reason?: string;
33
+ }>;
34
+ }
35
+ /**
36
+ * Graph-backed ancestor-revocation port. The reference adapter is
37
+ * `CascadingRevocationManager` (./cascading-revocation), whose `isRevoked()`
38
+ * walks root→target over the delegation graph + StatusList, detecting a
39
+ * cascade-revoked ANCESTOR independently of how the chain was resolved.
40
+ *
41
+ * Wiring this is the E3.1 correctness fix: the prior closure checked only each
42
+ * credential's OWN `credentialStatus` bit via the resolver, so an ancestor
43
+ * cascade-revocation that hadn't flipped the leaf's own bit could be missed.
44
+ */
45
+ export interface RevocationChecker {
46
+ isRevoked(delegationId: string): Promise<{
47
+ revoked: boolean;
48
+ reason?: string;
49
+ revokedAncestor?: string;
50
+ }>;
51
+ }
52
+ export interface ChainEnforcementDeps {
53
+ /** The verifying server's DID — every chain credential's audience must include it. */
54
+ serverDid: string;
55
+ /** Per-credential verifier (signature / schema / expiry / own status). */
56
+ verifier: DelegationCredentialVerifierPort;
57
+ /**
58
+ * Resolve ancestor credentials for a re-delegated leaf. May return ancestors
59
+ * only (root→parent) or the full chain (root→leaf). Required when the leaf has
60
+ * a `parentId`.
61
+ */
62
+ resolveDelegationChain?: (leafCredential: DelegationCredential) => Promise<DelegationCredential[]>;
63
+ /**
64
+ * Whether a StatusList resolver is configured downstream. A credential bearing
65
+ * `credentialStatus` is rejected when false (fail-closed).
66
+ */
67
+ statusListConfigured: boolean;
68
+ /** Optional graph-backed ancestor-revocation check (see {@link RevocationChecker}). */
69
+ revocationChecker?: RevocationChecker;
70
+ }
71
+ export interface ChainValidationResult {
72
+ valid: boolean;
73
+ reason?: string;
74
+ }
75
+ /**
76
+ * Validate a delegation credential and (if re-delegated) its full chain:
77
+ * structural shape, per-credential verification, audience binding to the server,
78
+ * the §11.6 re-delegation audience-constraint requirement, parent↔child linkage
79
+ * (parentId + issuerDid==parent.subjectDid), cycle detection, scope attenuation,
80
+ * and — when a {@link RevocationChecker} is supplied — graph-backed ancestor
81
+ * revocation. Never throws on a malformed input; returns `{ valid, reason }`.
82
+ */
83
+ export declare function validateDelegationChain(leafCredential: DelegationCredential, deps: ChainEnforcementDeps, options?: {
84
+ skipSignature?: boolean;
85
+ }): Promise<ChainValidationResult>;
86
+ //# sourceMappingURL=chain-enforcement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain-enforcement.d.ts","sourceRoot":"","sources":["../../src/delegation/chain-enforcement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAEL,KAAK,oBAAoB,EAE1B,MAAM,sBAAsB,CAAC;AAG9B,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,oBAAoB,GAAG,MAAM,EAAE,CAS9E;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,gBAAgB,EAAE,oBAAoB,EACtC,eAAe,EAAE,oBAAoB,GACpC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CA8CrC;AAED,+EAA+E;AAC/E,MAAM,WAAW,gCAAgC;IAC/C,0BAA0B,CACxB,UAAU,EAAE,oBAAoB,EAChC,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GACpC,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;QACvC,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,oBAAoB;IACnC,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,EAAE,gCAAgC,CAAC;IAC3C;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,CACvB,cAAc,EAAE,oBAAoB,KACjC,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACrC;;;OAGG;IACH,oBAAoB,EAAE,OAAO,CAAC;IAC9B,uFAAuF;IACvF,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,cAAc,EAAE,oBAAoB,EACpC,IAAI,EAAE,oBAAoB,EAC1B,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GACpC,OAAO,CAAC,qBAAqB,CAAC,CAkLhC"}