@kya-os/mcp-i 1.5.5 → 1.5.6-canary.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.
@@ -20,8 +20,8 @@
20
20
  * Related: PHASE_1_XMCP_I_SERVER.md Ticket 1.3
21
21
  * Related: AGENTSHIELD_DASHBOARD_PLAN.md Epic 2 (Public API)
22
22
  */
23
- import { DelegationRecord } from '@kya-os/contracts/delegation';
24
- import { DelegationVerifier, DelegationVerifierConfig, VerifyDelegationResult, VerifyDelegationOptions } from './delegation-verifier';
23
+ import { DelegationRecord } from "@kya-os/contracts/delegation";
24
+ import { DelegationVerifier, DelegationVerifierConfig, VerifyDelegationResult, VerifyDelegationOptions } from "./delegation-verifier";
25
25
  /**
26
26
  * AgentShield API Delegation Verifier
27
27
  *
@@ -24,6 +24,7 @@
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.AgentShieldAPIDelegationVerifier = void 0;
26
26
  const delegation_1 = require("@kya-os/contracts/delegation");
27
+ const agentshield_api_1 = require("@kya-os/contracts/agentshield-api");
27
28
  const delegation_verifier_1 = require("./delegation-verifier");
28
29
  /**
29
30
  * Simple in-memory cache (same as KV verifier)
@@ -62,6 +63,7 @@ class DelegationCache {
62
63
  this.cache.clear();
63
64
  }
64
65
  }
66
+ // Use standard AgentShield API response types from contracts
65
67
  /**
66
68
  * AgentShield API Delegation Verifier
67
69
  *
@@ -75,9 +77,9 @@ class AgentShieldAPIDelegationVerifier {
75
77
  debug;
76
78
  constructor(config) {
77
79
  if (!config.agentshield?.apiUrl || !config.agentshield?.apiKey) {
78
- throw new Error('AgentShieldAPIDelegationVerifier requires agentshield.apiUrl and agentshield.apiKey in config');
80
+ throw new Error("AgentShieldAPIDelegationVerifier requires agentshield.apiUrl and agentshield.apiKey in config");
79
81
  }
80
- this.apiUrl = config.agentshield.apiUrl.replace(/\/$/, ''); // Remove trailing slash
82
+ this.apiUrl = config.agentshield.apiUrl.replace(/\/$/, ""); // Remove trailing slash
81
83
  this.apiKey = config.agentshield.apiKey;
82
84
  this.cache = new DelegationCache();
83
85
  this.cacheTtl = config.cacheTtl || 60_000; // Default 1 minute
@@ -87,6 +89,18 @@ class AgentShieldAPIDelegationVerifier {
87
89
  * Verify agent delegation via API
88
90
  */
89
91
  async verify(agentDid, scopes, options) {
92
+ // Validate inputs
93
+ const validation = delegation_verifier_1.VerifyDelegationInputSchema.safeParse({
94
+ agentDid,
95
+ scopes,
96
+ options,
97
+ });
98
+ if (!validation.success) {
99
+ return {
100
+ valid: false,
101
+ reason: `Invalid request: ${validation.error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ")}`,
102
+ };
103
+ }
90
104
  const startTime = Date.now();
91
105
  // Build cache key
92
106
  const scopesKey = this.buildScopesKey(scopes);
@@ -106,79 +120,104 @@ class AgentShieldAPIDelegationVerifier {
106
120
  console.log(`[AgentShield] Cache MISS for ${agentDid}, calling API...`);
107
121
  }
108
122
  try {
123
+ // Validate request input using contracts schema
124
+ const requestBody = agentshield_api_1.verifyDelegationRequestSchema.parse({
125
+ agent_did: agentDid,
126
+ scopes,
127
+ });
109
128
  // Use the correct AgentShield bouncer API endpoint
110
129
  const response = await fetch(`${this.apiUrl}/api/v1/bouncer/delegations/verify`, {
111
- method: 'POST',
130
+ method: "POST",
112
131
  headers: {
113
- 'Content-Type': 'application/json',
114
- 'Authorization': `Bearer ${this.apiKey}`,
132
+ "Content-Type": "application/json",
133
+ Authorization: `Bearer ${this.apiKey}`,
115
134
  },
116
- body: JSON.stringify({
117
- agent_did: agentDid, // AgentShield uses snake_case
118
- scopes,
119
- }),
135
+ body: JSON.stringify(requestBody),
120
136
  });
121
137
  if (!response.ok) {
122
- // Handle API errors
138
+ // Handle API errors using standard error format
123
139
  if (response.status === 404) {
124
140
  const result = {
125
141
  valid: false,
126
- reason: 'No delegation found',
142
+ reason: "No delegation found",
127
143
  cached: false,
128
144
  };
129
145
  this.cache.set(cacheKey, result, this.cacheTtl / 2);
130
146
  return result;
131
147
  }
132
148
  if (response.status === 401 || response.status === 403) {
133
- throw new Error(`AgentShield API authentication failed: ${response.status}`);
149
+ const error = {
150
+ error: "authentication_failed",
151
+ message: `AgentShield API authentication failed: ${response.status}`,
152
+ httpStatus: response.status,
153
+ };
154
+ throw new agentshield_api_1.AgentShieldAPIError(error.error, error.message, error.details);
134
155
  }
135
- throw new Error(`AgentShield API error: ${response.status} ${response.statusText}`);
136
- }
137
- // AgentShield wraps response in success/data structure
138
- const response_body = await response.json();
139
- const data = response_body.data || response_body;
140
- // AgentShield returns either valid with credential or error
141
- let result;
142
- if (data.valid && data.credential) {
143
- // For valid delegations, we only need to return that it's valid
144
- // The delegation details are not needed for the verification flow
145
- result = {
146
- valid: true,
147
- // Only return delegation if it's in the correct format
148
- delegation: data.delegation, // This will be undefined if not provided
149
- reason: undefined,
150
- cached: false,
151
- };
152
- }
153
- else if (data.error) {
154
- result = {
155
- valid: false,
156
- reason: data.error.message || data.error.code || 'Delegation not valid',
157
- cached: false,
156
+ const error = {
157
+ error: "api_error",
158
+ message: `AgentShield API error: ${response.status} ${response.statusText}`,
159
+ httpStatus: response.status,
158
160
  };
161
+ throw new agentshield_api_1.AgentShieldAPIError(error.error, error.message, error.details);
159
162
  }
160
- else {
161
- result = {
162
- valid: data.valid || false,
163
+ // Validate response using standard AgentShield API response schema
164
+ const responseBody = await response.json();
165
+ const parsedResponse = agentshield_api_1.verifyDelegationAPIResponseSchema.safeParse(responseBody);
166
+ if (!parsedResponse.success) {
167
+ // If response doesn't match standard wrapper, try direct data format
168
+ const directData = agentshield_api_1.verifyDelegationResponseSchema.safeParse(responseBody);
169
+ if (!directData.success) {
170
+ throw new agentshield_api_1.AgentShieldAPIError("invalid_response", "AgentShield API returned invalid response format", { validationErrors: parsedResponse.error.errors });
171
+ }
172
+ // Use direct data format (backward compatibility)
173
+ const data = directData.data;
174
+ const result = {
175
+ valid: data.valid,
163
176
  delegation: data.delegation,
164
- reason: data.reason || 'Unknown error',
177
+ reason: data.reason,
165
178
  cached: false,
166
179
  };
180
+ const ttl = data.valid ? this.cacheTtl : this.cacheTtl / 2;
181
+ this.cache.set(cacheKey, result, ttl);
182
+ return result;
167
183
  }
184
+ // Standard wrapped response format
185
+ const wrappedResponse = parsedResponse.data;
186
+ const data = wrappedResponse.data;
187
+ // Build result from validated response
188
+ const result = {
189
+ valid: data.valid,
190
+ delegation: data.delegation,
191
+ reason: data.error ? data.error.message : data.reason,
192
+ cached: false,
193
+ };
168
194
  // Cache result
169
195
  const ttl = data.valid ? this.cacheTtl : this.cacheTtl / 2;
170
196
  this.cache.set(cacheKey, result, ttl);
171
197
  if (this.debug) {
172
- console.log(`[AgentShield] Delegation ${data.valid ? 'verified' : 'rejected'} (${Date.now() - startTime}ms)`);
198
+ console.log(`[AgentShield] Delegation ${data.valid ? "verified" : "rejected"} (${Date.now() - startTime}ms)`);
173
199
  }
174
200
  return result;
175
201
  }
176
202
  catch (error) {
177
- console.error('[AgentShield] API call failed:', error);
203
+ console.error("[AgentShield] API call failed:", error);
178
204
  // Return negative result on error (don't cache failures)
205
+ // Use standard error format
206
+ if (error instanceof agentshield_api_1.AgentShieldAPIError) {
207
+ return {
208
+ valid: false,
209
+ reason: error.message,
210
+ cached: false,
211
+ };
212
+ }
213
+ const runtimeError = {
214
+ error: "api_error",
215
+ message: error instanceof Error ? error.message : "Unknown error",
216
+ httpStatus: 500,
217
+ };
179
218
  return {
180
219
  valid: false,
181
- reason: `API error: ${error instanceof Error ? error.message : 'Unknown error'}`,
220
+ reason: runtimeError.message,
182
221
  cached: false,
183
222
  };
184
223
  }
@@ -187,16 +226,12 @@ class AgentShieldAPIDelegationVerifier {
187
226
  * Get delegation by ID via API
188
227
  */
189
228
  async get(delegationId) {
190
- const cacheKey = `delegation:${delegationId}`;
191
- // Check cache
192
- const cached = this.cache.get(cacheKey);
193
- if (cached)
194
- return cached;
229
+ // Fetch from API (no caching - cache is for verification results only)
195
230
  try {
196
231
  const response = await fetch(`${this.apiUrl}/api/v1/bouncer/delegations/${delegationId}`, {
197
- method: 'GET',
232
+ method: "GET",
198
233
  headers: {
199
- 'Authorization': `Bearer ${this.apiKey}`,
234
+ Authorization: `Bearer ${this.apiKey}`,
200
235
  },
201
236
  });
202
237
  if (!response.ok) {
@@ -207,16 +242,13 @@ class AgentShieldAPIDelegationVerifier {
207
242
  const data = await response.json();
208
243
  const parsed = delegation_1.DelegationRecordSchema.safeParse(data);
209
244
  if (!parsed.success) {
210
- console.error('[AgentShield] Invalid delegation in API response:', parsed.error);
245
+ console.error("[AgentShield] Invalid delegation in API response:", parsed.error);
211
246
  return null;
212
247
  }
213
- const delegation = parsed.data;
214
- // Cache it
215
- this.cache.set(cacheKey, delegation, this.cacheTtl);
216
- return delegation;
248
+ return parsed.data;
217
249
  }
218
250
  catch (error) {
219
- console.error('[AgentShield] Failed to get delegation:', error);
251
+ console.error("[AgentShield] Failed to get delegation:", error);
220
252
  return null;
221
253
  }
222
254
  }
@@ -234,10 +266,10 @@ class AgentShieldAPIDelegationVerifier {
234
266
  }
235
267
  try {
236
268
  const response = await fetch(`${this.apiUrl}/api/v1/bouncer/delegations`, {
237
- method: 'POST',
269
+ method: "POST",
238
270
  headers: {
239
- 'Content-Type': 'application/json',
240
- 'Authorization': `Bearer ${this.apiKey}`,
271
+ "Content-Type": "application/json",
272
+ Authorization: `Bearer ${this.apiKey}`,
241
273
  },
242
274
  body: JSON.stringify(delegation),
243
275
  });
@@ -254,7 +286,7 @@ class AgentShieldAPIDelegationVerifier {
254
286
  }
255
287
  }
256
288
  catch (error) {
257
- console.error('[AgentShield] Failed to store delegation:', error);
289
+ console.error("[AgentShield] Failed to store delegation:", error);
258
290
  throw error;
259
291
  }
260
292
  }
@@ -264,10 +296,10 @@ class AgentShieldAPIDelegationVerifier {
264
296
  async revoke(delegationId, reason) {
265
297
  try {
266
298
  const response = await fetch(`${this.apiUrl}/api/v1/bouncer/delegations/${delegationId}/revoke`, {
267
- method: 'POST',
299
+ method: "POST",
268
300
  headers: {
269
- 'Content-Type': 'application/json',
270
- 'Authorization': `Bearer ${this.apiKey}`,
301
+ "Content-Type": "application/json",
302
+ Authorization: `Bearer ${this.apiKey}`,
271
303
  },
272
304
  body: JSON.stringify({ reason }),
273
305
  });
@@ -281,7 +313,7 @@ class AgentShieldAPIDelegationVerifier {
281
313
  }
282
314
  }
283
315
  catch (error) {
284
- console.error('[AgentShield] Failed to revoke delegation:', error);
316
+ console.error("[AgentShield] Failed to revoke delegation:", error);
285
317
  throw error;
286
318
  }
287
319
  }
@@ -296,7 +328,7 @@ class AgentShieldAPIDelegationVerifier {
296
328
  */
297
329
  buildScopesKey(scopes) {
298
330
  const sorted = [...scopes].sort();
299
- const str = sorted.join(',');
331
+ const str = sorted.join(",");
300
332
  let hash = 0;
301
333
  for (let i = 0; i < str.length; i++) {
302
334
  const char = str.charCodeAt(i);
@@ -20,6 +20,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
20
20
  exports.CloudflareKVDelegationVerifier = void 0;
21
21
  const delegation_1 = require("@kya-os/contracts/delegation");
22
22
  const delegation_verifier_1 = require("./delegation-verifier");
23
+ const delegation_verifier_2 = require("./delegation-verifier");
23
24
  /**
24
25
  * Simple in-memory LRU cache for delegation lookups
25
26
  */
@@ -65,7 +66,7 @@ class DelegationCache {
65
66
  * Self-hosted mode: Stores delegations in local Cloudflare KV namespace
66
67
  */
67
68
  class CloudflareKVDelegationVerifier {
68
- kv; // KVNamespace from @cloudflare/workers-types
69
+ kv;
69
70
  cache;
70
71
  cacheTtl;
71
72
  debug;
@@ -82,6 +83,14 @@ class CloudflareKVDelegationVerifier {
82
83
  * Verify agent delegation
83
84
  */
84
85
  async verify(agentDid, scopes, options) {
86
+ // Validate inputs
87
+ const validation = delegation_verifier_2.VerifyDelegationInputSchema.safeParse({ agentDid, scopes, options });
88
+ if (!validation.success) {
89
+ return {
90
+ valid: false,
91
+ reason: `Invalid request: ${validation.error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ')}`,
92
+ };
93
+ }
85
94
  const startTime = Date.now();
86
95
  // Build cache key from agent DID + sorted scopes
87
96
  const scopesKey = this.buildScopesKey(scopes);
@@ -118,7 +127,7 @@ class CloudflareKVDelegationVerifier {
118
127
  // Try each delegation to find one that matches the requested scopes
119
128
  let matchingDelegation = null;
120
129
  for (const key of listResult.keys) {
121
- const delegationId = await this.kv.get(key.name, 'text');
130
+ const delegationId = await this.kv.get(key.name);
122
131
  if (!delegationId)
123
132
  continue;
124
133
  const delegation = await this.get(delegationId);
@@ -147,12 +156,12 @@ class CloudflareKVDelegationVerifier {
147
156
  }
148
157
  const delegation = matchingDelegation;
149
158
  // Validate delegation
150
- const validation = (0, delegation_verifier_1.validateDelegation)(delegation);
151
- if (!validation.valid) {
159
+ const delegationValidation = (0, delegation_verifier_1.validateDelegation)(delegation);
160
+ if (!delegationValidation.valid) {
152
161
  const result = {
153
162
  valid: false,
154
163
  delegation,
155
- reason: validation.reason,
164
+ reason: delegationValidation.reason,
156
165
  cached: false,
157
166
  };
158
167
  this.cache.set(cacheKey, result, this.cacheTtl / 2);
@@ -188,14 +197,9 @@ class CloudflareKVDelegationVerifier {
188
197
  * Get delegation by ID
189
198
  */
190
199
  async get(delegationId) {
191
- const cacheKey = `delegation:${delegationId}`;
192
- // Check cache
193
- const cached = this.cache.get(cacheKey);
194
- if (cached)
195
- return cached;
196
- // Fetch from KV
200
+ // Fetch from KV (no caching - cache is for verification results only)
197
201
  const kvKey = `delegation:${delegationId}`;
198
- const raw = await this.kv.get(kvKey, 'text');
202
+ const raw = await this.kv.get(kvKey);
199
203
  if (!raw)
200
204
  return null;
201
205
  try {
@@ -205,10 +209,7 @@ class CloudflareKVDelegationVerifier {
205
209
  console.error('[KV] Invalid delegation record:', parsed.error);
206
210
  return null;
207
211
  }
208
- const delegation = parsed.data;
209
- // Cache it
210
- this.cache.set(cacheKey, delegation, this.cacheTtl);
211
- return delegation;
212
+ return parsed.data;
212
213
  }
213
214
  catch (error) {
214
215
  console.error('[KV] Failed to parse delegation:', error);
@@ -32,6 +32,14 @@ class MemoryDelegationVerifier {
32
32
  * Verify agent delegation
33
33
  */
34
34
  async verify(agentDid, scopes, _options) {
35
+ // Validate inputs
36
+ const validation = delegation_verifier_1.VerifyDelegationInputSchema.safeParse({ agentDid, scopes, options: _options });
37
+ if (!validation.success) {
38
+ return {
39
+ valid: false,
40
+ reason: `Invalid request: ${validation.error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ')}`,
41
+ };
42
+ }
35
43
  // Find all delegations for this agent
36
44
  const delegationIds = this.agentIndex.get(agentDid);
37
45
  if (!delegationIds || delegationIds.size === 0) {
@@ -12,6 +12,7 @@
12
12
  * Related: PHASE_1_XMCP_I_SERVER.md Epic 1 (Delegation Storage Layer)
13
13
  */
14
14
  import { DelegationRecord } from '@kya-os/contracts/delegation';
15
+ import { z } from 'zod';
15
16
  /**
16
17
  * Result of delegation verification
17
18
  */
@@ -103,6 +104,37 @@ export declare function validateDelegation(delegation: DelegationRecord): {
103
104
  valid: boolean;
104
105
  reason?: string;
105
106
  };
107
+ /**
108
+ * Validation schema for verify method inputs
109
+ */
110
+ export declare const VerifyDelegationInputSchema: z.ZodObject<{
111
+ agentDid: z.ZodString;
112
+ scopes: z.ZodArray<z.ZodString, "many">;
113
+ options: z.ZodOptional<z.ZodObject<{
114
+ skipCache: z.ZodOptional<z.ZodBoolean>;
115
+ maxCacheAge: z.ZodOptional<z.ZodNumber>;
116
+ }, "strip", z.ZodTypeAny, {
117
+ skipCache?: boolean | undefined;
118
+ maxCacheAge?: number | undefined;
119
+ }, {
120
+ skipCache?: boolean | undefined;
121
+ maxCacheAge?: number | undefined;
122
+ }>>;
123
+ }, "strip", z.ZodTypeAny, {
124
+ scopes: string[];
125
+ agentDid: string;
126
+ options?: {
127
+ skipCache?: boolean | undefined;
128
+ maxCacheAge?: number | undefined;
129
+ } | undefined;
130
+ }, {
131
+ scopes: string[];
132
+ agentDid: string;
133
+ options?: {
134
+ skipCache?: boolean | undefined;
135
+ maxCacheAge?: number | undefined;
136
+ } | undefined;
137
+ }>;
106
138
  /**
107
139
  * Configuration for delegation verifiers
108
140
  */
@@ -110,7 +142,18 @@ export interface DelegationVerifierConfig {
110
142
  /** Verifier type */
111
143
  type: 'cloudflare-kv' | 'agentshield-api' | 'memory';
112
144
  /** Cloudflare KV namespace (for cloudflare-kv type) */
113
- kvNamespace?: any;
145
+ kvNamespace?: {
146
+ get(key: string): Promise<string | null>;
147
+ put(key: string, value: string): Promise<void>;
148
+ delete(key: string): Promise<void>;
149
+ list(options?: {
150
+ prefix?: string;
151
+ }): Promise<{
152
+ keys: Array<{
153
+ name: string;
154
+ }>;
155
+ }>;
156
+ };
114
157
  /** AgentShield API configuration (for agentshield-api type) */
115
158
  agentshield?: {
116
159
  apiUrl: string;
@@ -127,6 +170,11 @@ export interface DelegationVerifierConfig {
127
170
  * Note: We import all adapters statically for better compatibility.
128
171
  * Tree-shaking will remove unused adapters in production builds.
129
172
  *
173
+ * Note: AgentShield API responses use standard wrapper format
174
+ * { success: boolean, data: {...}, metadata?: {...} } as defined in
175
+ * @kya-os/contracts/agentshield-api. This is handled in the
176
+ * AgentShieldAPIDelegationVerifier implementation.
177
+ *
130
178
  * @param config - Verifier configuration
131
179
  * @returns DelegationVerifier instance
132
180
  */
@@ -13,11 +13,13 @@
13
13
  * Related: PHASE_1_XMCP_I_SERVER.md Epic 1 (Delegation Storage Layer)
14
14
  */
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.VerifyDelegationInputSchema = void 0;
16
17
  exports.extractScopes = extractScopes;
17
18
  exports.checkScopes = checkScopes;
18
19
  exports.validateDelegation = validateDelegation;
19
20
  exports.createDelegationVerifier = createDelegationVerifier;
20
21
  const delegation_1 = require("@kya-os/contracts/delegation");
22
+ const zod_1 = require("zod");
21
23
  /**
22
24
  * Helper: Extract scopes from delegation (handles both simple and CRISP formats)
23
25
  *
@@ -76,32 +78,56 @@ function validateDelegation(delegation) {
76
78
  }
77
79
  return { valid: true };
78
80
  }
81
+ /**
82
+ * Validation schema for verify method inputs
83
+ */
84
+ exports.VerifyDelegationInputSchema = zod_1.z.object({
85
+ agentDid: zod_1.z.string().min(1),
86
+ scopes: zod_1.z.array(zod_1.z.string()).min(1),
87
+ options: zod_1.z.object({
88
+ skipCache: zod_1.z.boolean().optional(),
89
+ maxCacheAge: zod_1.z.number().int().positive().optional(),
90
+ }).optional(),
91
+ });
79
92
  /**
80
93
  * Factory: Create delegation verifier based on config
81
94
  *
82
95
  * Note: We import all adapters statically for better compatibility.
83
96
  * Tree-shaking will remove unused adapters in production builds.
84
97
  *
98
+ * Note: AgentShield API responses use standard wrapper format
99
+ * { success: boolean, data: {...}, metadata?: {...} } as defined in
100
+ * @kya-os/contracts/agentshield-api. This is handled in the
101
+ * AgentShieldAPIDelegationVerifier implementation.
102
+ *
85
103
  * @param config - Verifier configuration
86
104
  * @returns DelegationVerifier instance
87
105
  */
88
106
  function createDelegationVerifier(config) {
89
- // Import adapters dynamically to avoid circular dependencies
90
- // but keep them in the same file scope
91
- let CloudflareKVDelegationVerifier;
92
- let AgentShieldAPIDelegationVerifier;
93
- let MemoryDelegationVerifier;
94
107
  switch (config.type) {
95
- case 'cloudflare-kv':
96
- CloudflareKVDelegationVerifier = require('./delegation-verifier-kv').CloudflareKVDelegationVerifier;
108
+ case 'cloudflare-kv': {
109
+ const CloudflareKVDelegationVerifier = require('./delegation-verifier-kv').CloudflareKVDelegationVerifier;
97
110
  return new CloudflareKVDelegationVerifier(config);
98
- case 'agentshield-api':
99
- AgentShieldAPIDelegationVerifier = require('./delegation-verifier-agentshield').AgentShieldAPIDelegationVerifier;
111
+ }
112
+ case 'agentshield-api': {
113
+ const AgentShieldAPIDelegationVerifier = require('./delegation-verifier-agentshield').AgentShieldAPIDelegationVerifier;
100
114
  return new AgentShieldAPIDelegationVerifier(config);
101
- case 'memory':
102
- MemoryDelegationVerifier = require('./delegation-verifier-memory').MemoryDelegationVerifier;
115
+ }
116
+ case 'memory': {
117
+ const MemoryDelegationVerifier = require('./delegation-verifier-memory').MemoryDelegationVerifier;
103
118
  return new MemoryDelegationVerifier(config);
119
+ }
104
120
  default:
105
- throw new Error(`Unknown delegation verifier type: ${config.type}`);
121
+ const configType = 'type' in config ? config.type : 'unknown';
122
+ // Use RuntimeError format from @kya-os/contracts/runtime/errors
123
+ const runtimeError = {
124
+ error: 'invalid_config',
125
+ message: `Unknown delegation verifier type: ${configType}`,
126
+ httpStatus: 500,
127
+ };
128
+ // Create Error object that can be checked with RuntimeErrorSchema
129
+ const error = new Error(runtimeError.message);
130
+ Object.assign(error, runtimeError);
131
+ throw error;
106
132
  }
107
133
  }