@kya-os/contracts 1.5.3-canary.20 → 1.5.3-canary.21

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.
@@ -75,6 +75,23 @@ export interface ToolProtection {
75
75
  * This is how tool protections are typically stored and transmitted.
76
76
  */
77
77
  export type ToolProtectionMap = Record<string, ToolProtection>;
78
+ /**
79
+ * Partial tool protection for updates (all fields optional)
80
+ * Use this when accepting partial updates to tool protection settings
81
+ */
82
+ export type PartialToolProtection = Partial<ToolProtection>;
83
+ /**
84
+ * Tool protection with explicit optional fields
85
+ * Useful when TypeScript's Partial<T> doesn't preserve optional property access
86
+ * Supports explicit null values to clear fields
87
+ */
88
+ export type ToolProtectionUpdate = {
89
+ requiresDelegation?: boolean;
90
+ requiredScopes?: string[];
91
+ riskLevel?: 'low' | 'medium' | 'high' | 'critical';
92
+ oauthProvider?: string | null;
93
+ authorization?: AuthorizationRequirement | null;
94
+ };
78
95
  /**
79
96
  * Tool Protection Response
80
97
  *
@@ -132,6 +149,18 @@ export interface DelegationRequiredErrorData {
132
149
  */
133
150
  reason?: string;
134
151
  }
152
+ /**
153
+ * Legacy tool protection format (pre-authorization field)
154
+ * Used during migration period to support both old and new formats
155
+ */
156
+ export type LegacyToolProtection = Omit<ToolProtection, 'authorization'> & {
157
+ oauthProvider?: string;
158
+ };
159
+ /**
160
+ * Union type for both legacy and new formats
161
+ * Useful during migration period when accepting tool protection input
162
+ */
163
+ export type ToolProtectionInput = ToolProtection | LegacyToolProtection;
135
164
  /**
136
165
  * Zod Schemas for Validation
137
166
  */
@@ -251,8 +280,8 @@ export declare const ToolProtectionSchema: z.ZodObject<{
251
280
  type: "none";
252
281
  }>]>>;
253
282
  }, "strip", z.ZodTypeAny, {
254
- requiresDelegation: boolean;
255
283
  requiredScopes: string[];
284
+ requiresDelegation: boolean;
256
285
  riskLevel?: "low" | "medium" | "high" | "critical" | undefined;
257
286
  oauthProvider?: string | undefined;
258
287
  authorization?: {
@@ -275,8 +304,8 @@ export declare const ToolProtectionSchema: z.ZodObject<{
275
304
  type: "none";
276
305
  } | undefined;
277
306
  }, {
278
- requiresDelegation: boolean;
279
307
  requiredScopes: string[];
308
+ requiresDelegation: boolean;
280
309
  riskLevel?: "low" | "medium" | "high" | "critical" | undefined;
281
310
  oauthProvider?: string | undefined;
282
311
  authorization?: {
@@ -360,8 +389,8 @@ export declare const ToolProtectionMapSchema: z.ZodRecord<z.ZodString, z.ZodObje
360
389
  type: "none";
361
390
  }>]>>;
362
391
  }, "strip", z.ZodTypeAny, {
363
- requiresDelegation: boolean;
364
392
  requiredScopes: string[];
393
+ requiresDelegation: boolean;
365
394
  riskLevel?: "low" | "medium" | "high" | "critical" | undefined;
366
395
  oauthProvider?: string | undefined;
367
396
  authorization?: {
@@ -384,8 +413,8 @@ export declare const ToolProtectionMapSchema: z.ZodRecord<z.ZodString, z.ZodObje
384
413
  type: "none";
385
414
  } | undefined;
386
415
  }, {
387
- requiresDelegation: boolean;
388
416
  requiredScopes: string[];
417
+ requiresDelegation: boolean;
389
418
  riskLevel?: "low" | "medium" | "high" | "critical" | undefined;
390
419
  oauthProvider?: string | undefined;
391
420
  authorization?: {
@@ -470,8 +499,8 @@ export declare const ToolProtectionResponseSchema: z.ZodObject<{
470
499
  type: "none";
471
500
  }>]>>;
472
501
  }, "strip", z.ZodTypeAny, {
473
- requiresDelegation: boolean;
474
502
  requiredScopes: string[];
503
+ requiresDelegation: boolean;
475
504
  riskLevel?: "low" | "medium" | "high" | "critical" | undefined;
476
505
  oauthProvider?: string | undefined;
477
506
  authorization?: {
@@ -494,8 +523,8 @@ export declare const ToolProtectionResponseSchema: z.ZodObject<{
494
523
  type: "none";
495
524
  } | undefined;
496
525
  }, {
497
- requiresDelegation: boolean;
498
526
  requiredScopes: string[];
527
+ requiresDelegation: boolean;
499
528
  riskLevel?: "low" | "medium" | "high" | "critical" | undefined;
500
529
  oauthProvider?: string | undefined;
501
530
  authorization?: {
@@ -523,18 +552,18 @@ export declare const ToolProtectionResponseSchema: z.ZodObject<{
523
552
  version: z.ZodOptional<z.ZodString>;
524
553
  source: z.ZodOptional<z.ZodString>;
525
554
  }, "strip", z.ZodTypeAny, {
526
- version?: string | undefined;
527
555
  lastUpdated?: string | undefined;
556
+ version?: string | undefined;
528
557
  source?: string | undefined;
529
558
  }, {
530
- version?: string | undefined;
531
559
  lastUpdated?: string | undefined;
560
+ version?: string | undefined;
532
561
  source?: string | undefined;
533
562
  }>>;
534
563
  }, "strip", z.ZodTypeAny, {
535
564
  toolProtections: Record<string, {
536
- requiresDelegation: boolean;
537
565
  requiredScopes: string[];
566
+ requiresDelegation: boolean;
538
567
  riskLevel?: "low" | "medium" | "high" | "critical" | undefined;
539
568
  oauthProvider?: string | undefined;
540
569
  authorization?: {
@@ -558,14 +587,14 @@ export declare const ToolProtectionResponseSchema: z.ZodObject<{
558
587
  } | undefined;
559
588
  }>;
560
589
  metadata?: {
561
- version?: string | undefined;
562
590
  lastUpdated?: string | undefined;
591
+ version?: string | undefined;
563
592
  source?: string | undefined;
564
593
  } | undefined;
565
594
  }, {
566
595
  toolProtections: Record<string, {
567
- requiresDelegation: boolean;
568
596
  requiredScopes: string[];
597
+ requiresDelegation: boolean;
569
598
  riskLevel?: "low" | "medium" | "high" | "critical" | undefined;
570
599
  oauthProvider?: string | undefined;
571
600
  authorization?: {
@@ -589,8 +618,8 @@ export declare const ToolProtectionResponseSchema: z.ZodObject<{
589
618
  } | undefined;
590
619
  }>;
591
620
  metadata?: {
592
- version?: string | undefined;
593
621
  lastUpdated?: string | undefined;
622
+ version?: string | undefined;
594
623
  source?: string | undefined;
595
624
  } | undefined;
596
625
  }>;
@@ -603,15 +632,15 @@ export declare const DelegationRequiredErrorDataSchema: z.ZodObject<{
603
632
  }, "strip", z.ZodTypeAny, {
604
633
  requiredScopes: string[];
605
634
  toolName: string;
606
- reason?: string | undefined;
607
- authorizationUrl?: string | undefined;
608
635
  consentUrl?: string | undefined;
636
+ authorizationUrl?: string | undefined;
637
+ reason?: string | undefined;
609
638
  }, {
610
639
  requiredScopes: string[];
611
640
  toolName: string;
612
- reason?: string | undefined;
613
- authorizationUrl?: string | undefined;
614
641
  consentUrl?: string | undefined;
642
+ authorizationUrl?: string | undefined;
643
+ reason?: string | undefined;
615
644
  }>;
616
645
  /**
617
646
  * Type Guards
@@ -620,6 +649,18 @@ export declare function isToolProtection(obj: any): obj is ToolProtection;
620
649
  export declare function isToolProtectionMap(obj: any): obj is ToolProtectionMap;
621
650
  export declare function isToolProtectionResponse(obj: any): obj is ToolProtectionResponse;
622
651
  export declare function isDelegationRequiredErrorData(obj: any): obj is DelegationRequiredErrorData;
652
+ /**
653
+ * Type guard to check if an object is a valid AuthorizationRequirement
654
+ */
655
+ export declare function isAuthorizationRequirement(obj: unknown): obj is AuthorizationRequirement;
656
+ /**
657
+ * Type guard to check if a ToolProtection has OAuth authorization
658
+ */
659
+ export declare function hasOAuthAuthorization(protection: ToolProtection): protection is ToolProtection & {
660
+ authorization: {
661
+ type: 'oauth';
662
+ };
663
+ };
623
664
  /**
624
665
  * Validation Functions
625
666
  */
@@ -650,6 +691,13 @@ export declare function createDelegationRequiredError(toolName: string, required
650
691
  * Normalize tool protection configuration
651
692
  * Migrates legacy oauthProvider field to authorization object
652
693
  *
694
+ * - Migrates `oauthProvider` → `authorization: { type: 'oauth', provider: ... }`
695
+ * - Ensures `authorization` field is present when `requiresDelegation=true`
696
+ * - Returns fully normalized ToolProtection object
697
+ *
698
+ * @param raw - Raw tool protection data (may have legacy fields or be partial)
699
+ * @returns Normalized ToolProtection object
700
+ *
653
701
  * // TODO: Remove normalizeToolProtection() when all tools migrated (target: Phase 3)
654
702
  */
655
- export declare function normalizeToolProtection(raw: ToolProtection): ToolProtection;
703
+ export declare function normalizeToolProtection(raw: ToolProtection | PartialToolProtection): ToolProtection;
@@ -14,6 +14,8 @@ exports.isToolProtection = isToolProtection;
14
14
  exports.isToolProtectionMap = isToolProtectionMap;
15
15
  exports.isToolProtectionResponse = isToolProtectionResponse;
16
16
  exports.isDelegationRequiredErrorData = isDelegationRequiredErrorData;
17
+ exports.isAuthorizationRequirement = isAuthorizationRequirement;
18
+ exports.hasOAuthAuthorization = hasOAuthAuthorization;
17
19
  exports.validateToolProtection = validateToolProtection;
18
20
  exports.validateToolProtectionMap = validateToolProtectionMap;
19
21
  exports.validateToolProtectionResponse = validateToolProtectionResponse;
@@ -90,6 +92,18 @@ function isToolProtectionResponse(obj) {
90
92
  function isDelegationRequiredErrorData(obj) {
91
93
  return exports.DelegationRequiredErrorDataSchema.safeParse(obj).success;
92
94
  }
95
+ /**
96
+ * Type guard to check if an object is a valid AuthorizationRequirement
97
+ */
98
+ function isAuthorizationRequirement(obj) {
99
+ return exports.AuthorizationRequirementSchema.safeParse(obj).success;
100
+ }
101
+ /**
102
+ * Type guard to check if a ToolProtection has OAuth authorization
103
+ */
104
+ function hasOAuthAuthorization(protection) {
105
+ return protection.authorization?.type === 'oauth';
106
+ }
93
107
  /**
94
108
  * Validation Functions
95
109
  */
@@ -143,31 +157,44 @@ function createDelegationRequiredError(toolName, requiredScopes, consentUrl) {
143
157
  * Normalize tool protection configuration
144
158
  * Migrates legacy oauthProvider field to authorization object
145
159
  *
160
+ * - Migrates `oauthProvider` → `authorization: { type: 'oauth', provider: ... }`
161
+ * - Ensures `authorization` field is present when `requiresDelegation=true`
162
+ * - Returns fully normalized ToolProtection object
163
+ *
164
+ * @param raw - Raw tool protection data (may have legacy fields or be partial)
165
+ * @returns Normalized ToolProtection object
166
+ *
146
167
  * // TODO: Remove normalizeToolProtection() when all tools migrated (target: Phase 3)
147
168
  */
148
169
  function normalizeToolProtection(raw) {
149
- // If authorization is already present, return as is
170
+ // Ensure we have required fields (provide defaults for partial input)
171
+ const normalized = {
172
+ requiresDelegation: raw.requiresDelegation ?? false,
173
+ requiredScopes: raw.requiredScopes ?? [],
174
+ ...(raw.riskLevel && { riskLevel: raw.riskLevel }),
175
+ ...(raw.oauthProvider && { oauthProvider: raw.oauthProvider }),
176
+ };
177
+ // If authorization is already present, use it
150
178
  if (raw.authorization) {
151
- return raw;
179
+ normalized.authorization = raw.authorization;
180
+ return normalized;
152
181
  }
153
182
  // Migrate oauthProvider to authorization
154
183
  if (raw.oauthProvider) {
155
- return {
156
- ...raw,
157
- authorization: {
158
- type: 'oauth',
159
- provider: raw.oauthProvider,
160
- },
161
- // Keep oauthProvider for backward compatibility until Phase 3
184
+ normalized.authorization = {
185
+ type: 'oauth',
186
+ provider: raw.oauthProvider,
162
187
  };
188
+ // Keep oauthProvider for backward compatibility until Phase 3
189
+ return normalized;
163
190
  }
164
191
  // Default for requiresDelegation=true without specific auth: type='none' (consent only)
165
192
  // But ONLY if authorization is missing entirely
166
- if (raw.requiresDelegation && !raw.authorization && !raw.oauthProvider) {
193
+ if (normalized.requiresDelegation && !normalized.authorization && !normalized.oauthProvider) {
167
194
  // We don't automatically set type='none' here to allow
168
195
  // ProviderResolver to do its scope inference fallback logic.
169
196
  // The fallback logic will eventually be moved into an AuthorizationService.
170
- return raw;
197
+ return normalized;
171
198
  }
172
- return raw;
199
+ return normalized;
173
200
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kya-os/contracts",
3
- "version": "1.5.3-canary.20",
3
+ "version": "1.5.3-canary.21",
4
4
  "description": "Shared contracts, types, and schemas for MCP-I framework",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -89,6 +89,25 @@ export interface ToolProtection {
89
89
  */
90
90
  export type ToolProtectionMap = Record<string, ToolProtection>;
91
91
 
92
+ /**
93
+ * Partial tool protection for updates (all fields optional)
94
+ * Use this when accepting partial updates to tool protection settings
95
+ */
96
+ export type PartialToolProtection = Partial<ToolProtection>;
97
+
98
+ /**
99
+ * Tool protection with explicit optional fields
100
+ * Useful when TypeScript's Partial<T> doesn't preserve optional property access
101
+ * Supports explicit null values to clear fields
102
+ */
103
+ export type ToolProtectionUpdate = {
104
+ requiresDelegation?: boolean;
105
+ requiredScopes?: string[];
106
+ riskLevel?: 'low' | 'medium' | 'high' | 'critical';
107
+ oauthProvider?: string | null; // null explicitly clears the field
108
+ authorization?: AuthorizationRequirement | null; // null explicitly clears the field
109
+ };
110
+
92
111
  /**
93
112
  * Tool Protection Response
94
113
  *
@@ -155,6 +174,20 @@ export interface DelegationRequiredErrorData {
155
174
  reason?: string;
156
175
  }
157
176
 
177
+ /**
178
+ * Legacy tool protection format (pre-authorization field)
179
+ * Used during migration period to support both old and new formats
180
+ */
181
+ export type LegacyToolProtection = Omit<ToolProtection, 'authorization'> & {
182
+ oauthProvider?: string;
183
+ };
184
+
185
+ /**
186
+ * Union type for both legacy and new formats
187
+ * Useful during migration period when accepting tool protection input
188
+ */
189
+ export type ToolProtectionInput = ToolProtection | LegacyToolProtection;
190
+
158
191
  /**
159
192
  * Zod Schemas for Validation
160
193
  */
@@ -232,6 +265,22 @@ export function isDelegationRequiredErrorData(obj: any): obj is DelegationRequir
232
265
  return DelegationRequiredErrorDataSchema.safeParse(obj).success;
233
266
  }
234
267
 
268
+ /**
269
+ * Type guard to check if an object is a valid AuthorizationRequirement
270
+ */
271
+ export function isAuthorizationRequirement(obj: unknown): obj is AuthorizationRequirement {
272
+ return AuthorizationRequirementSchema.safeParse(obj).success;
273
+ }
274
+
275
+ /**
276
+ * Type guard to check if a ToolProtection has OAuth authorization
277
+ */
278
+ export function hasOAuthAuthorization(
279
+ protection: ToolProtection
280
+ ): protection is ToolProtection & { authorization: { type: 'oauth' } } {
281
+ return protection.authorization?.type === 'oauth';
282
+ }
283
+
235
284
  /**
236
285
  * Validation Functions
237
286
  */
@@ -307,37 +356,51 @@ export function createDelegationRequiredError(
307
356
  /**
308
357
  * Normalize tool protection configuration
309
358
  * Migrates legacy oauthProvider field to authorization object
310
- *
359
+ *
360
+ * - Migrates `oauthProvider` → `authorization: { type: 'oauth', provider: ... }`
361
+ * - Ensures `authorization` field is present when `requiresDelegation=true`
362
+ * - Returns fully normalized ToolProtection object
363
+ *
364
+ * @param raw - Raw tool protection data (may have legacy fields or be partial)
365
+ * @returns Normalized ToolProtection object
366
+ *
311
367
  * // TODO: Remove normalizeToolProtection() when all tools migrated (target: Phase 3)
312
368
  */
313
369
  export function normalizeToolProtection(
314
- raw: ToolProtection
370
+ raw: ToolProtection | PartialToolProtection
315
371
  ): ToolProtection {
316
- // If authorization is already present, return as is
372
+ // Ensure we have required fields (provide defaults for partial input)
373
+ const normalized: ToolProtection = {
374
+ requiresDelegation: raw.requiresDelegation ?? false,
375
+ requiredScopes: raw.requiredScopes ?? [],
376
+ ...(raw.riskLevel && { riskLevel: raw.riskLevel }),
377
+ ...(raw.oauthProvider && { oauthProvider: raw.oauthProvider }),
378
+ };
379
+
380
+ // If authorization is already present, use it
317
381
  if (raw.authorization) {
318
- return raw;
382
+ normalized.authorization = raw.authorization;
383
+ return normalized;
319
384
  }
320
385
 
321
386
  // Migrate oauthProvider to authorization
322
387
  if (raw.oauthProvider) {
323
- return {
324
- ...raw,
325
- authorization: {
326
- type: 'oauth',
327
- provider: raw.oauthProvider,
328
- },
329
- // Keep oauthProvider for backward compatibility until Phase 3
388
+ normalized.authorization = {
389
+ type: 'oauth',
390
+ provider: raw.oauthProvider,
330
391
  };
392
+ // Keep oauthProvider for backward compatibility until Phase 3
393
+ return normalized;
331
394
  }
332
395
 
333
396
  // Default for requiresDelegation=true without specific auth: type='none' (consent only)
334
397
  // But ONLY if authorization is missing entirely
335
- if (raw.requiresDelegation && !raw.authorization && !raw.oauthProvider) {
398
+ if (normalized.requiresDelegation && !normalized.authorization && !normalized.oauthProvider) {
336
399
  // We don't automatically set type='none' here to allow
337
400
  // ProviderResolver to do its scope inference fallback logic.
338
401
  // The fallback logic will eventually be moved into an AuthorizationService.
339
- return raw;
402
+ return normalized;
340
403
  }
341
404
 
342
- return raw;
405
+ return normalized;
343
406
  }