@private.me/xbind 3.0.2 → 3.0.3

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 (221) hide show
  1. package/README.md +2366 -204
  2. package/README.md.backup +2121 -0
  3. package/dist-standalone/_deps/mldsa-wasm/dist/mldsa.js +1 -1920
  4. package/dist-standalone/_deps/shared/cjs/errors.js +1 -729
  5. package/dist-standalone/_deps/shared/cjs/index.js +1 -463
  6. package/dist-standalone/_deps/shared/cjs/types.js +1 -315
  7. package/dist-standalone/_deps/shared/errors.js +1 -244
  8. package/dist-standalone/_deps/shared/index.js +1 -72
  9. package/dist-standalone/_deps/shared/types.js +1 -86
  10. package/dist-standalone/_deps/ux-helpers/cjs/errors.js +1 -1
  11. package/dist-standalone/_deps/ux-helpers/cjs/index.js +1 -1
  12. package/dist-standalone/_deps/ux-helpers/cjs/pagination.js +1 -1
  13. package/dist-standalone/_deps/ux-helpers/cjs/progress.js +1 -1
  14. package/dist-standalone/_deps/ux-helpers/cjs/search.js +1 -1
  15. package/dist-standalone/_deps/ux-helpers/cjs/types.js +1 -1
  16. package/dist-standalone/_deps/ux-helpers/errors.js +1 -1
  17. package/dist-standalone/_deps/ux-helpers/index.js +1 -1
  18. package/dist-standalone/_deps/ux-helpers/pagination.js +1 -1
  19. package/dist-standalone/_deps/ux-helpers/progress.js +1 -1
  20. package/dist-standalone/_deps/ux-helpers/search.js +1 -1
  21. package/dist-standalone/_deps/xchange/auto-accept.js +1 -1
  22. package/dist-standalone/_deps/xchange/cjs/auto-accept.js +1 -1
  23. package/dist-standalone/_deps/xchange/cjs/errors.js +1 -1
  24. package/dist-standalone/_deps/xchange/cjs/index.js +1 -1
  25. package/dist-standalone/_deps/xchange/cjs/invite-client.js +1 -1
  26. package/dist-standalone/_deps/xchange/cjs/lazy-init.js +1 -1
  27. package/dist-standalone/_deps/xchange/cjs/trust-integration.js +1 -1
  28. package/dist-standalone/_deps/xchange/cjs/xchange.js +1 -1
  29. package/dist-standalone/_deps/xchange/errors.js +1 -1
  30. package/dist-standalone/_deps/xchange/index.js +1 -1
  31. package/dist-standalone/_deps/xchange/invite-client.js +1 -1
  32. package/dist-standalone/_deps/xchange/lazy-init.js +1 -1
  33. package/dist-standalone/_deps/xchange/trust-integration.js +1 -1
  34. package/dist-standalone/_deps/xchange/xchange.js +1 -1
  35. package/dist-standalone/_deps/xregistry/cjs/discovery.js +1 -1
  36. package/dist-standalone/_deps/xregistry/cjs/errors.js +1 -1
  37. package/dist-standalone/_deps/xregistry/cjs/index.js +1 -1
  38. package/dist-standalone/_deps/xregistry/cjs/registry.js +1 -1
  39. package/dist-standalone/_deps/xregistry/cjs/schema.js +1 -1
  40. package/dist-standalone/_deps/xregistry/cjs/types.js +1 -1
  41. package/dist-standalone/_deps/xregistry/discovery.js +1 -1
  42. package/dist-standalone/_deps/xregistry/errors.js +1 -1
  43. package/dist-standalone/_deps/xregistry/index.js +1 -1
  44. package/dist-standalone/_deps/xregistry/registry.js +1 -1
  45. package/dist-standalone/_deps/xregistry/schema.js +1 -1
  46. package/dist-standalone/_deps/xregistry/types.js +1 -1
  47. package/dist-standalone/agent-call.d.ts +2 -2
  48. package/dist-standalone/agent-call.js +1 -659
  49. package/dist-standalone/agent-sdk.js +1 -328
  50. package/dist-standalone/agent.d.ts +2 -0
  51. package/dist-standalone/agent.js +1 -1800
  52. package/dist-standalone/approval.js +1 -193
  53. package/dist-standalone/async-iterators.d.ts +3 -3
  54. package/dist-standalone/async-iterators.js +1 -382
  55. package/dist-standalone/auth.js +1 -219
  56. package/dist-standalone/auto-accept.js +1 -229
  57. package/dist-standalone/backup-config.js +1 -201
  58. package/dist-standalone/backup.js +1 -326
  59. package/dist-standalone/batch-operations.js +1 -388
  60. package/dist-standalone/cancellation.js +1 -477
  61. package/dist-standalone/checkpoint.js +1 -186
  62. package/dist-standalone/circuit-breaker.js +1 -468
  63. package/dist-standalone/cjs/agent-call.js +1 -701
  64. package/dist-standalone/cjs/agent-sdk.js +1 -332
  65. package/dist-standalone/cjs/agent.js +1 -1837
  66. package/dist-standalone/cjs/approval.js +1 -199
  67. package/dist-standalone/cjs/async-iterators.js +1 -392
  68. package/dist-standalone/cjs/auth.js +1 -225
  69. package/dist-standalone/cjs/auto-accept.js +1 -233
  70. package/dist-standalone/cjs/backup-config.js +1 -207
  71. package/dist-standalone/cjs/backup.js +1 -330
  72. package/dist-standalone/cjs/batch-operations.js +1 -397
  73. package/dist-standalone/cjs/cancellation.js +1 -490
  74. package/dist-standalone/cjs/checkpoint.js +1 -193
  75. package/dist-standalone/cjs/circuit-breaker.js +1 -476
  76. package/dist-standalone/cjs/cli/init.js +1 -492
  77. package/dist-standalone/cjs/config-validation.js +1 -522
  78. package/dist-standalone/cjs/connect.js +1 -312
  79. package/dist-standalone/cjs/connection-pool.js +1 -506
  80. package/dist-standalone/cjs/correlation-id.js +1 -339
  81. package/dist-standalone/cjs/crypto-utils.js +1 -176
  82. package/dist-standalone/cjs/debug-mode.js +1 -534
  83. package/dist-standalone/cjs/did-document.js +1 -101
  84. package/dist-standalone/cjs/did-privateme.js +1 -130
  85. package/dist-standalone/cjs/did-web.js +1 -201
  86. package/dist-standalone/cjs/discovery.js +1 -462
  87. package/dist-standalone/cjs/dual-mode.js +1 -251
  88. package/dist-standalone/cjs/email-templates.js +1 -313
  89. package/dist-standalone/cjs/email-transport.js +1 -239
  90. package/dist-standalone/cjs/envelope.js +1 -538
  91. package/dist-standalone/cjs/errors.js +1 -913
  92. package/dist-standalone/cjs/event-emitter.js +1 -461
  93. package/dist-standalone/cjs/gateway-state.js +1 -55
  94. package/dist-standalone/cjs/gateway-transport.js +1 -120
  95. package/dist-standalone/cjs/graceful-degradation.js +1 -403
  96. package/dist-standalone/cjs/guardrails.js +1 -223
  97. package/dist-standalone/cjs/health-check.js +1 -336
  98. package/dist-standalone/cjs/http-compat.js +1 -272
  99. package/dist-standalone/cjs/http-status-map.js +1 -571
  100. package/dist-standalone/cjs/identity.js +1 -645
  101. package/dist-standalone/cjs/index.js +1 -406
  102. package/dist-standalone/cjs/invitation.js +1 -421
  103. package/dist-standalone/cjs/invite.js +1 -328
  104. package/dist-standalone/cjs/key-agreement.js +1 -335
  105. package/dist-standalone/cjs/lazy-init.js +1 -300
  106. package/dist-standalone/cjs/logger.js +1 -291
  107. package/dist-standalone/cjs/loopback-transport.js +1 -0
  108. package/dist-standalone/cjs/mdns-discovery.js +1 -202
  109. package/dist-standalone/cjs/nonce-store.js +1 -80
  110. package/dist-standalone/cjs/pairing-manager.js +1 -223
  111. package/dist-standalone/cjs/plugin-system.js +1 -264
  112. package/dist-standalone/cjs/plugins/logging.js +1 -168
  113. package/dist-standalone/cjs/plugins/metrics.js +1 -181
  114. package/dist-standalone/cjs/plugins/validation.js +1 -302
  115. package/dist-standalone/cjs/policy.js +1 -320
  116. package/dist-standalone/cjs/progress-callbacks.js +1 -583
  117. package/dist-standalone/cjs/redis-nonce-store.js +1 -76
  118. package/dist-standalone/cjs/registry-middleware.js +1 -50
  119. package/dist-standalone/cjs/retry-strategies.js +1 -544
  120. package/dist-standalone/cjs/retry-transport.js +1 -102
  121. package/dist-standalone/cjs/runtime/browser.js +1 -533
  122. package/dist-standalone/cjs/runtime/edge.js +1 -526
  123. package/dist-standalone/cjs/runtime/react-native.js +1 -394
  124. package/dist-standalone/cjs/security-policy.js +1 -245
  125. package/dist-standalone/cjs/serialization.js +1 -1040
  126. package/dist-standalone/cjs/split-channel.js +1 -225
  127. package/dist-standalone/cjs/subscription-proof.js +1 -230
  128. package/dist-standalone/cjs/succession.js +1 -148
  129. package/dist-standalone/cjs/timeouts.js +1 -412
  130. package/dist-standalone/cjs/trace-context.js +1 -424
  131. package/dist-standalone/cjs/trace-spans.js +1 -495
  132. package/dist-standalone/cjs/transport.js +1 -63
  133. package/dist-standalone/cjs/trust-registry.js +1 -991
  134. package/dist-standalone/cjs/types/error-response.js +1 -56
  135. package/dist-standalone/cjs/vault-auth.js +1 -178
  136. package/dist-standalone/cjs/vault-store-loader.js +1 -194
  137. package/dist-standalone/cjs/verify.js +1 -25
  138. package/dist-standalone/cjs/version-info.js +1 -543
  139. package/dist-standalone/cjs/xfetch.js +1 -340
  140. package/dist-standalone/cli/init.js +1 -455
  141. package/dist-standalone/cli/setup.js +1 -514
  142. package/dist-standalone/cli/types.js +1 -27
  143. package/dist-standalone/cli/xbind.js +1 -148
  144. package/dist-standalone/config-validation.js +1 -513
  145. package/dist-standalone/connect.js +1 -274
  146. package/dist-standalone/connection-pool.js +1 -500
  147. package/dist-standalone/correlation-id.js +1 -326
  148. package/dist-standalone/crypto-utils.d.ts +2 -7
  149. package/dist-standalone/crypto-utils.js +1 -157
  150. package/dist-standalone/debug-mode.js +1 -510
  151. package/dist-standalone/did-document.js +1 -96
  152. package/dist-standalone/did-privateme.js +1 -121
  153. package/dist-standalone/did-web.js +1 -196
  154. package/dist-standalone/discovery.js +1 -458
  155. package/dist-standalone/dual-mode.js +1 -247
  156. package/dist-standalone/email-templates.js +1 -309
  157. package/dist-standalone/email-transport.d.ts +2 -2
  158. package/dist-standalone/email-transport.js +1 -232
  159. package/dist-standalone/envelope.js +1 -525
  160. package/dist-standalone/errors.d.ts +13 -3
  161. package/dist-standalone/errors.js +1 -896
  162. package/dist-standalone/event-emitter.js +1 -456
  163. package/dist-standalone/gateway-state.d.ts +1 -1
  164. package/dist-standalone/gateway-state.js +1 -51
  165. package/dist-standalone/gateway-transport.js +1 -116
  166. package/dist-standalone/graceful-degradation.js +1 -396
  167. package/dist-standalone/guardrails.js +1 -216
  168. package/dist-standalone/health-check.d.ts +5 -1
  169. package/dist-standalone/health-check.js +1 -332
  170. package/dist-standalone/http-compat.d.ts +1 -1
  171. package/dist-standalone/http-compat.js +1 -267
  172. package/dist-standalone/http-status-map.js +1 -561
  173. package/dist-standalone/identity.js +1 -619
  174. package/dist-standalone/index.d.ts +15 -4
  175. package/dist-standalone/index.js +1 -78
  176. package/dist-standalone/invitation.js +1 -415
  177. package/dist-standalone/invite.js +1 -324
  178. package/dist-standalone/key-agreement.js +1 -325
  179. package/dist-standalone/lazy-init.d.ts +11 -6
  180. package/dist-standalone/lazy-init.js +1 -295
  181. package/dist-standalone/logger.js +1 -285
  182. package/dist-standalone/loopback-transport.d.ts +87 -0
  183. package/dist-standalone/loopback-transport.js +1 -0
  184. package/dist-standalone/mdns-discovery.js +1 -195
  185. package/dist-standalone/nonce-store.js +1 -76
  186. package/dist-standalone/pairing-manager.js +1 -219
  187. package/dist-standalone/plugin-system.js +1 -257
  188. package/dist-standalone/plugins/logging.js +1 -163
  189. package/dist-standalone/plugins/metrics.d.ts +4 -4
  190. package/dist-standalone/plugins/metrics.js +1 -176
  191. package/dist-standalone/plugins/validation.js +1 -297
  192. package/dist-standalone/policy.js +1 -315
  193. package/dist-standalone/progress-callbacks.js +1 -576
  194. package/dist-standalone/redis-nonce-store.js +1 -72
  195. package/dist-standalone/registry-middleware.js +1 -47
  196. package/dist-standalone/retry-strategies.js +1 -534
  197. package/dist-standalone/retry-transport.js +1 -98
  198. package/dist-standalone/runtime/browser.js +1 -516
  199. package/dist-standalone/runtime/edge.js +1 -511
  200. package/dist-standalone/runtime/react-native.d.ts +1 -1
  201. package/dist-standalone/runtime/react-native.js +1 -383
  202. package/dist-standalone/security-policy.js +1 -239
  203. package/dist-standalone/serialization.js +1 -1031
  204. package/dist-standalone/split-channel.js +1 -219
  205. package/dist-standalone/subscription-proof.js +1 -224
  206. package/dist-standalone/succession.js +1 -142
  207. package/dist-standalone/timeouts.js +1 -398
  208. package/dist-standalone/trace-context.js +1 -414
  209. package/dist-standalone/trace-spans.js +1 -488
  210. package/dist-standalone/transport.js +1 -59
  211. package/dist-standalone/trust-registry.d.ts +3 -3
  212. package/dist-standalone/trust-registry.js +1 -950
  213. package/dist-standalone/types/error-response.js +1 -52
  214. package/dist-standalone/vault-auth.js +1 -174
  215. package/dist-standalone/vault-store-loader.d.ts +9 -0
  216. package/dist-standalone/vault-store-loader.js +1 -187
  217. package/dist-standalone/verify.js +1 -16
  218. package/dist-standalone/version-info.js +1 -530
  219. package/dist-standalone/xfetch.js +1 -335
  220. package/package.json +1 -1
  221. package/share1.dat +0 -0
@@ -1,403 +1 @@
1
- "use strict";
2
- /**
3
- * @module graceful-degradation
4
- * Enhanced Reliability Capabilities for xBind
5
- *
6
- * Provides graceful degradation mechanisms to maintain service continuity
7
- * when external services (registry, gateway, transport) experience issues.
8
- *
9
- * Features:
10
- * - Quality-of-Service (QoS) tiers for operation prioritization
11
- * - Fallback mechanisms with exponential backoff
12
- * - Intelligent caching with TTL
13
- * - User-friendly error messages with actionable recovery hints
14
- */
15
- Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.GracefulDegradationManager = void 0;
17
- exports.registryLookupWithFallback = registryLookupWithFallback;
18
- exports.sendWithTransportFallback = sendWithTransportFallback;
19
- exports.enhanceError = enhanceError;
20
- const shared_1 = require("../_deps/shared/index.js");
21
- const ux_helpers_1 = require("../_deps/ux-helpers/index.js");
22
- const DEFAULT_CACHE_CONFIG = {
23
- defaultTTL: 300_000, // 5 minutes
24
- maxSize: 1000,
25
- allowStale: true,
26
- maxStaleMs: 3600_000, // 1 hour
27
- };
28
- const DEFAULT_RETRY_CONFIG = {
29
- maxAttempts: 3,
30
- initialDelayMs: 1000,
31
- backoffMultiplier: 2,
32
- maxDelayMs: 30_000,
33
- jitter: true,
34
- };
35
- /**
36
- * Graceful Degradation Manager
37
- *
38
- * Coordinates fallback mechanisms, caching, and retry logic across
39
- * registry, gateway, and transport layers.
40
- */
41
- class GracefulDegradationManager {
42
- cacheConfig;
43
- retryConfig;
44
- cache = new Map();
45
- serviceStatus = new Map();
46
- constructor(cacheConfig, retryConfig) {
47
- this.cacheConfig = { ...DEFAULT_CACHE_CONFIG, ...cacheConfig };
48
- this.retryConfig = { ...DEFAULT_RETRY_CONFIG, ...retryConfig };
49
- }
50
- /* ── Cache Operations ── */
51
- /**
52
- * Get cached value if available and valid for the given QoS level.
53
- *
54
- * @param key Cache key
55
- * @param qos Quality of service level
56
- * @returns Cached value or undefined
57
- */
58
- getCached(key, qos) {
59
- const entry = this.cache.get(key);
60
- if (!entry)
61
- return undefined;
62
- const now = Date.now();
63
- const age = now - entry.cachedAt;
64
- const isFresh = age <= entry.ttl;
65
- const isStale = age > entry.ttl && age <= this.cacheConfig.maxStaleMs;
66
- // CRITICAL/HIGH: Only use fresh cache
67
- if (qos === 'CRITICAL' || qos === 'HIGH') {
68
- return isFresh ? entry.value : undefined;
69
- }
70
- // NORMAL/LOW: Use stale cache if allowed
71
- if (this.cacheConfig.allowStale && (isFresh || isStale)) {
72
- entry.usageCount++;
73
- return entry.value;
74
- }
75
- return isFresh ? entry.value : undefined;
76
- }
77
- /**
78
- * Store value in cache with TTL.
79
- *
80
- * @param key Cache key
81
- * @param value Value to cache
82
- * @param ttl Time-to-live in milliseconds (uses default if omitted)
83
- */
84
- setCached(key, value, ttl) {
85
- // Evict oldest entry if cache is full
86
- if (this.cache.size >= this.cacheConfig.maxSize) {
87
- const oldestKey = this.cache.keys().next().value;
88
- if (oldestKey)
89
- this.cache.delete(oldestKey);
90
- }
91
- this.cache.set(key, {
92
- value,
93
- cachedAt: Date.now(),
94
- ttl: ttl ?? this.cacheConfig.defaultTTL,
95
- usageCount: 0,
96
- });
97
- }
98
- /**
99
- * Invalidate cached entry.
100
- *
101
- * @param key Cache key
102
- */
103
- invalidate(key) {
104
- this.cache.delete(key);
105
- }
106
- /**
107
- * Clear all cached entries.
108
- */
109
- clearCache() {
110
- this.cache.clear();
111
- }
112
- /**
113
- * Get cache statistics.
114
- */
115
- getCacheStats() {
116
- const now = Date.now();
117
- const entries = Array.from(this.cache.entries()).map(([key, entry]) => ({
118
- key,
119
- age: now - entry.cachedAt,
120
- usageCount: entry.usageCount,
121
- }));
122
- return {
123
- size: this.cache.size,
124
- maxSize: this.cacheConfig.maxSize,
125
- entries,
126
- };
127
- }
128
- /* ── Service Health Tracking ── */
129
- /**
130
- * Record successful operation for a service.
131
- *
132
- * @param serviceName Service identifier (e.g., 'registry', 'gateway', 'transport')
133
- */
134
- recordSuccess(serviceName) {
135
- const existing = this.serviceStatus.get(serviceName);
136
- const status = existing || {
137
- health: 'HEALTHY',
138
- lastSuccess: 0,
139
- failureCount: 0,
140
- };
141
- status.health = 'HEALTHY';
142
- status.lastSuccess = Date.now();
143
- status.failureCount = 0;
144
- status.lastError = undefined;
145
- this.serviceStatus.set(serviceName, status);
146
- }
147
- /**
148
- * Record failed operation for a service.
149
- *
150
- * @param serviceName Service identifier
151
- * @param error Error message
152
- */
153
- recordFailure(serviceName, error) {
154
- const existing = this.serviceStatus.get(serviceName);
155
- const status = existing || {
156
- health: 'HEALTHY',
157
- lastSuccess: 0,
158
- failureCount: 0,
159
- };
160
- status.failureCount++;
161
- status.lastError = error;
162
- // Update health based on consecutive failures
163
- if (status.failureCount >= 5) {
164
- status.health = 'UNAVAILABLE';
165
- }
166
- else if (status.failureCount >= 2) {
167
- status.health = 'DEGRADED';
168
- }
169
- this.serviceStatus.set(serviceName, status);
170
- }
171
- /**
172
- * Get service health status.
173
- *
174
- * @param serviceName Service identifier
175
- * @returns Service health status
176
- */
177
- getServiceHealth(serviceName) {
178
- return this.serviceStatus.get(serviceName)?.health ?? 'HEALTHY';
179
- }
180
- /**
181
- * Get detailed service status.
182
- *
183
- * @param serviceName Service identifier
184
- * @returns Service status or undefined if not tracked
185
- */
186
- getServiceStatus(serviceName) {
187
- return this.serviceStatus.get(serviceName);
188
- }
189
- /**
190
- * Reset service health tracking.
191
- *
192
- * @param serviceName Service identifier (all services if omitted)
193
- */
194
- resetServiceHealth(serviceName) {
195
- if (serviceName) {
196
- this.serviceStatus.delete(serviceName);
197
- }
198
- else {
199
- this.serviceStatus.clear();
200
- }
201
- }
202
- /* ── Retry Logic ── */
203
- /**
204
- * Execute operation with retry logic based on QoS level.
205
- *
206
- * @param operation Async operation to execute
207
- * @param context Operation context with QoS level
208
- * @returns Result of operation
209
- */
210
- async withRetry(operation, context) {
211
- const maxAttempts = this.getMaxAttempts(context.qos);
212
- let lastError;
213
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
214
- const result = await operation();
215
- if (result.ok) {
216
- return result;
217
- }
218
- lastError = result.error;
219
- // Don't retry on last attempt
220
- if (attempt < maxAttempts) {
221
- const delay = this.calculateBackoff(attempt);
222
- await this.sleep(delay);
223
- }
224
- }
225
- // All retries exhausted
226
- return (0, shared_1.err)(lastError);
227
- }
228
- /**
229
- * Get maximum retry attempts for QoS level.
230
- */
231
- getMaxAttempts(qos) {
232
- switch (qos) {
233
- case 'CRITICAL':
234
- return 1; // Fail fast
235
- case 'HIGH':
236
- return this.retryConfig.maxAttempts;
237
- case 'NORMAL':
238
- return Math.max(1, this.retryConfig.maxAttempts - 1);
239
- case 'LOW':
240
- return 1; // No retries
241
- }
242
- }
243
- /**
244
- * Calculate exponential backoff delay with optional jitter.
245
- */
246
- calculateBackoff(attempt) {
247
- const base = this.retryConfig.initialDelayMs * Math.pow(this.retryConfig.backoffMultiplier, attempt - 1);
248
- const capped = Math.min(base, this.retryConfig.maxDelayMs);
249
- if (!this.retryConfig.jitter) {
250
- return capped;
251
- }
252
- // Add ±25% jitter using cryptographically secure random
253
- const randomBytes = new Uint8Array(4);
254
- crypto.getRandomValues(randomBytes);
255
- const randomValue = new DataView(randomBytes.buffer).getUint32(0) / 0xffffffff;
256
- const jitterFactor = 0.75 + randomValue * 0.5;
257
- return Math.floor(capped * jitterFactor);
258
- }
259
- /**
260
- * Sleep for specified milliseconds.
261
- */
262
- sleep(ms) {
263
- return new Promise((resolve) => setTimeout(resolve, ms));
264
- }
265
- }
266
- exports.GracefulDegradationManager = GracefulDegradationManager;
267
- /* ── Registry Fallback ── */
268
- /**
269
- * Registry lookup with graceful degradation.
270
- *
271
- * Provides intelligent fallback for DID resolution:
272
- * 1. Try primary registry lookup
273
- * 2. On failure, check cache based on QoS level
274
- * 3. Return user-friendly error if all fallbacks exhausted
275
- *
276
- * @param registry Trust registry instance
277
- * @param did DID to resolve
278
- * @param context Operation context
279
- * @param manager Degradation manager
280
- * @returns Registry lookup result
281
- */
282
- async function registryLookupWithFallback(registry, did, context, manager) {
283
- const cacheKey = `registry:${did}`;
284
- // Check cache first for LOW QoS
285
- if (context.qos === 'LOW') {
286
- const cached = manager.getCached(cacheKey, context.qos);
287
- if (cached) {
288
- return (0, shared_1.ok)(cached);
289
- }
290
- }
291
- // Attempt registry lookup with retry
292
- const lookupResult = await manager.withRetry(() => registry.getEntry(did), context);
293
- if (lookupResult.ok) {
294
- manager.recordSuccess('registry');
295
- // Convert Uint8Array publicKey to base64 string for caching
296
- const publicKeyStr = Buffer.from(lookupResult.value.publicKey).toString('base64');
297
- const entryValue = { publicKey: publicKeyStr };
298
- manager.setCached(cacheKey, entryValue);
299
- return (0, shared_1.ok)(entryValue);
300
- }
301
- // Lookup failed - record failure
302
- manager.recordFailure('registry', String(lookupResult.error));
303
- // Try cache fallback for HIGH/NORMAL QoS
304
- if (context.qos === 'HIGH' || context.qos === 'NORMAL') {
305
- const cached = manager.getCached(cacheKey, context.qos);
306
- if (cached) {
307
- return (0, shared_1.ok)(cached);
308
- }
309
- }
310
- // All fallbacks exhausted - return detailed error
311
- return (0, shared_1.err)((0, ux_helpers_1.createDetailedError)('REGISTRY_UNAVAILABLE', `Failed to resolve DID: ${did}`, {
312
- hint: manager.getServiceHealth('registry') === 'UNAVAILABLE'
313
- ? 'Registry service is currently unavailable. Using cached data may help.'
314
- : 'Registry lookup failed after retries. Check network connectivity.',
315
- suggested_action: context.qos === 'CRITICAL'
316
- ? 'Wait for registry service to recover before retrying critical operations.'
317
- : 'Lower QoS level to NORMAL or LOW to use cached data.',
318
- docs: 'https://private.me/docs/xbind/registry-fallback',
319
- severity: context.qos === 'CRITICAL' ? 'critical' : 'error',
320
- }));
321
- }
322
- /* ── Transport Fallback ── */
323
- /**
324
- * Send envelope with transport fallback.
325
- *
326
- * Tries multiple transports in order until one succeeds:
327
- * 1. Primary transport with retry
328
- * 2. Fallback transports (if configured)
329
- * 3. Return detailed error if all transports fail
330
- *
331
- * @param transports Array of transport adapters
332
- * @param envelope Envelope to send
333
- * @param recipientDid Recipient DID
334
- * @param context Operation context
335
- * @param manager Degradation manager
336
- * @returns Send result
337
- */
338
- async function sendWithTransportFallback(transports, envelope, recipientDid, context, manager) {
339
- if (transports.length === 0) {
340
- return (0, shared_1.err)((0, ux_helpers_1.createDetailedError)('NO_TRANSPORT', 'No transport adapters configured', {
341
- hint: 'Configure at least one transport adapter for envelope delivery.',
342
- suggested_action: 'Add HttpsTransportAdapter or custom transport to agent configuration.',
343
- docs: 'https://private.me/docs/xbind/transport',
344
- severity: 'critical',
345
- }));
346
- }
347
- const errors = [];
348
- for (let i = 0; i < transports.length; i++) {
349
- const transport = transports[i];
350
- if (!transport)
351
- continue;
352
- const sendResult = await manager.withRetry(() => transport.send(envelope, recipientDid), context);
353
- if (sendResult.ok) {
354
- manager.recordSuccess(`transport:${i}`);
355
- return (0, shared_1.ok)(undefined);
356
- }
357
- // Record failure and try next transport
358
- errors.push({ transport: i, error: sendResult.error });
359
- manager.recordFailure(`transport:${i}`, sendResult.error);
360
- }
361
- // All transports failed
362
- const primaryError = errors[0]?.error ?? 'SEND_FAILED';
363
- return (0, shared_1.err)((0, ux_helpers_1.createDetailedError)('TRANSPORT_EXHAUSTED', `All transport adapters failed: ${errors.map(e => e.error).join(', ')}`, {
364
- hint: primaryError === 'NETWORK_ERROR'
365
- ? 'Network connectivity issue detected. Check internet connection.'
366
- : primaryError === 'TIMEOUT'
367
- ? 'Transport timeout occurred. Recipient may be unreachable or overloaded.'
368
- : primaryError === 'RECIPIENT_UNREACHABLE'
369
- ? 'Recipient DID not found or offline.'
370
- : 'Transport layer failure. Check transport configuration.',
371
- suggested_action: 'Verify recipient endpoint and network connectivity. Consider increasing timeout or adding fallback transports.',
372
- docs: 'https://private.me/docs/xbind/transport-fallback',
373
- severity: context.qos === 'CRITICAL' ? 'critical' : 'error',
374
- }));
375
- }
376
- /* ── User-Friendly Error Messages ── */
377
- /**
378
- * Enhance error with QoS-appropriate messaging.
379
- *
380
- * @param error Original error
381
- * @param context Operation context
382
- * @param manager Degradation manager
383
- * @returns Enhanced error with actionable hints
384
- */
385
- function enhanceError(error, context, manager) {
386
- const serviceHealth = manager.getServiceHealth(context.type.split(':')[0] ?? 'unknown');
387
- // Add service health context to hint
388
- const healthHint = serviceHealth === 'DEGRADED'
389
- ? ' Service is experiencing degraded performance.'
390
- : serviceHealth === 'UNAVAILABLE'
391
- ? ' Service is currently unavailable.'
392
- : '';
393
- // Add QoS-specific suggestions
394
- const qosHint = context.qos === 'CRITICAL'
395
- ? ' Consider retrying when service recovers.'
396
- : context.qos === 'HIGH'
397
- ? ' Cached data may be used if available.'
398
- : ' Using cached data regardless of staleness.';
399
- return {
400
- ...error,
401
- hint: (error.hint ?? '') + healthHint + qosHint,
402
- };
403
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.GracefulDegradationManager=void 0,exports.registryLookupWithFallback=registryLookupWithFallback,exports.sendWithTransportFallback=sendWithTransportFallback,exports.enhanceError=enhanceError;const shared_1=require("../_deps/shared/index.js"),ux_helpers_1=require("../_deps/ux-helpers/index.js"),DEFAULT_CACHE_CONFIG={defaultTTL:3e5,maxSize:1e3,allowStale:!0,maxStaleMs:36e5},DEFAULT_RETRY_CONFIG={maxAttempts:3,initialDelayMs:1e3,backoffMultiplier:2,maxDelayMs:3e4,jitter:!0};class GracefulDegradationManager{cacheConfig;retryConfig;cache=new Map;serviceStatus=new Map;constructor(e,t){this.cacheConfig={...DEFAULT_CACHE_CONFIG,...e},this.retryConfig={...DEFAULT_RETRY_CONFIG,...t}}getCached(e,t){const r=this.cache.get(e);if(!r)return;const a=Date.now()-r.cachedAt,s=a<=r.ttl,i=a>r.ttl&&a<=this.cacheConfig.maxStaleMs;return"CRITICAL"===t||"HIGH"===t?s?r.value:void 0:this.cacheConfig.allowStale&&(s||i)?(r.usageCount++,r.value):s?r.value:void 0}setCached(e,t,r){if(this.cache.size>=this.cacheConfig.maxSize){const e=this.cache.keys().next().value;e&&this.cache.delete(e)}this.cache.set(e,{value:t,cachedAt:Date.now(),ttl:r??this.cacheConfig.defaultTTL,usageCount:0})}invalidate(e){this.cache.delete(e)}clearCache(){this.cache.clear()}getCacheStats(){const e=Date.now(),t=Array.from(this.cache.entries()).map(([t,r])=>({key:t,age:e-r.cachedAt,usageCount:r.usageCount}));return{size:this.cache.size,maxSize:this.cacheConfig.maxSize,entries:t}}recordSuccess(e){const t=this.serviceStatus.get(e)||{health:"HEALTHY",lastSuccess:0,failureCount:0};t.health="HEALTHY",t.lastSuccess=Date.now(),t.failureCount=0,t.lastError=void 0,this.serviceStatus.set(e,t)}recordFailure(e,t){const r=this.serviceStatus.get(e)||{health:"HEALTHY",lastSuccess:0,failureCount:0};r.failureCount++,r.lastError=t,r.failureCount>=5?r.health="UNAVAILABLE":r.failureCount>=2&&(r.health="DEGRADED"),this.serviceStatus.set(e,r)}getServiceHealth(e){return this.serviceStatus.get(e)?.health??"HEALTHY"}getServiceStatus(e){return this.serviceStatus.get(e)}resetServiceHealth(e){e?this.serviceStatus.delete(e):this.serviceStatus.clear()}async withRetry(e,t){const r=this.getMaxAttempts(t.qos);let a;for(let t=1;t<=r;t++){const s=await e();if(s.ok)return s;if(a=s.error,t<r){const e=this.calculateBackoff(t);await this.sleep(e)}}return(0,shared_1.err)(a)}getMaxAttempts(e){switch(e){case"CRITICAL":case"LOW":return 1;case"HIGH":return this.retryConfig.maxAttempts;case"NORMAL":return Math.max(1,this.retryConfig.maxAttempts-1)}}calculateBackoff(e){const t=this.retryConfig.initialDelayMs*Math.pow(this.retryConfig.backoffMultiplier,e-1),r=Math.min(t,this.retryConfig.maxDelayMs);if(!this.retryConfig.jitter)return r;const a=new Uint8Array(4);crypto.getRandomValues(a);const s=.75+.5*(new DataView(a.buffer).getUint32(0)/4294967295);return Math.floor(r*s)}sleep(e){return new Promise(t=>setTimeout(t,e))}}async function registryLookupWithFallback(e,t,r,a){const s=`registry:${t}`;if("LOW"===r.qos){const e=a.getCached(s,r.qos);if(e)return(0,shared_1.ok)(e)}const i=await a.withRetry(()=>e.getEntry(t),r);if(i.ok){a.recordSuccess("registry");const e={publicKey:Buffer.from(i.value.publicKey).toString("base64")};return a.setCached(s,e),(0,shared_1.ok)(e)}if(a.recordFailure("registry",String(i.error)),"HIGH"===r.qos||"NORMAL"===r.qos){const e=a.getCached(s,r.qos);if(e)return(0,shared_1.ok)(e)}return(0,shared_1.err)((0,ux_helpers_1.createDetailedError)("REGISTRY_UNAVAILABLE",`Failed to resolve DID: ${t}`,{hint:"UNAVAILABLE"===a.getServiceHealth("registry")?"Registry service is currently unavailable. Using cached data may help.":"Registry lookup failed after retries. Check network connectivity.",suggested_action:"CRITICAL"===r.qos?"Wait for registry service to recover before retrying critical operations.":"Lower QoS level to NORMAL or LOW to use cached data.",docs:"https://private.me/docs/xbind/registry-fallback",severity:"CRITICAL"===r.qos?"critical":"error"}))}async function sendWithTransportFallback(e,t,r,a,s){if(0===e.length)return(0,shared_1.err)((0,ux_helpers_1.createDetailedError)("NO_TRANSPORT","No transport adapters configured",{hint:"Configure at least one transport adapter for envelope delivery.",suggested_action:"Add HttpsTransportAdapter or custom transport to agent configuration.",docs:"https://private.me/docs/xbind/transport",severity:"critical"}));const i=[];for(let o=0;o<e.length;o++){const c=e[o];if(!c)continue;const n=await s.withRetry(()=>c.send(t,r),a);if(n.ok)return s.recordSuccess(`transport:${o}`),(0,shared_1.ok)(void 0);i.push({transport:o,error:n.error}),s.recordFailure(`transport:${o}`,n.error)}const o=i[0]?.error??"SEND_FAILED";return(0,shared_1.err)((0,ux_helpers_1.createDetailedError)("TRANSPORT_EXHAUSTED",`All transport adapters failed: ${i.map(e=>e.error).join(", ")}`,{hint:"NETWORK_ERROR"===o?"Network connectivity issue detected. Check internet connection.":"TIMEOUT"===o?"Transport timeout occurred. Recipient may be unreachable or overloaded.":"RECIPIENT_UNREACHABLE"===o?"Recipient DID not found or offline.":"Transport layer failure. Check transport configuration.",suggested_action:"Verify recipient endpoint and network connectivity. Consider increasing timeout or adding fallback transports.",docs:"https://private.me/docs/xbind/transport-fallback",severity:"CRITICAL"===a.qos?"critical":"error"}))}function enhanceError(e,t,r){const a=r.getServiceHealth(t.type.split(":")[0]??"unknown"),s="DEGRADED"===a?" Service is experiencing degraded performance.":"UNAVAILABLE"===a?" Service is currently unavailable.":"",i="CRITICAL"===t.qos?" Consider retrying when service recovers.":"HIGH"===t.qos?" Cached data may be used if available.":" Using cached data regardless of staleness.";return{...e,hint:(e.hint??"")+s+i}}exports.GracefulDegradationManager=GracefulDegradationManager;
@@ -1,223 +1 @@
1
- "use strict";
2
- /**
3
- * @module guardrails
4
- * Enhanced error messages with actionable suggestions for policy violations
5
- *
6
- * When policies deny requests, guardrails provide specific, actionable
7
- * guidance on how to fix the issue or what to request from admins.
8
- */
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.Guardrails = exports.PolicyDenied = void 0;
11
- exports.extractSuggestion = extractSuggestion;
12
- exports.toPolicyDenied = toPolicyDenied;
13
- /**
14
- * Policy violation error with actionable suggestions
15
- */
16
- class PolicyDenied extends Error {
17
- rule;
18
- allowed;
19
- requested;
20
- suggestion;
21
- details;
22
- constructor(
23
- /** Which policy rule was violated */
24
- rule,
25
- /** What the policy allows */
26
- allowed,
27
- /** What was requested */
28
- requested,
29
- /** Actionable suggestion for how to fix */
30
- suggestion,
31
- /** Full policy violation details */
32
- details) {
33
- super(`Policy violation: ${rule}`);
34
- this.rule = rule;
35
- this.allowed = allowed;
36
- this.requested = requested;
37
- this.suggestion = suggestion;
38
- this.details = details;
39
- this.name = 'PolicyDenied';
40
- }
41
- /**
42
- * Format error for AI agent consumption
43
- *
44
- * Structured format optimized for LLM parsing
45
- */
46
- toAgentFormat() {
47
- return [
48
- `POLICY_VIOLATION: ${this.rule}`,
49
- `REQUESTED: ${JSON.stringify(this.requested)}`,
50
- `ALLOWED: ${JSON.stringify(this.allowed)}`,
51
- `SUGGESTION: ${this.suggestion}`,
52
- ].join('\n');
53
- }
54
- /**
55
- * Format error for human consumption
56
- *
57
- * User-friendly format with clear next steps
58
- */
59
- toUserFormat() {
60
- return [
61
- `❌ Policy Violation: ${this.rule}`,
62
- '',
63
- `You requested: ${this.formatValue(this.requested)}`,
64
- `Policy allows: ${this.formatValue(this.allowed)}`,
65
- '',
66
- `💡 Suggestion: ${this.suggestion}`,
67
- ].join('\n');
68
- }
69
- /**
70
- * Format error for logs (structured JSON)
71
- */
72
- toLogFormat() {
73
- return {
74
- error: 'PolicyDenied',
75
- rule: this.rule,
76
- allowed: this.allowed,
77
- requested: this.requested,
78
- suggestion: this.suggestion,
79
- details: this.details,
80
- timestamp: new Date().toISOString(),
81
- };
82
- }
83
- formatValue(value) {
84
- if (typeof value === 'number') {
85
- // Format currency if it looks like money
86
- if (this.rule.includes('amount') || this.rule.includes('Amount')) {
87
- return `$${value.toLocaleString()}`;
88
- }
89
- return value.toLocaleString();
90
- }
91
- if (Array.isArray(value)) {
92
- return value.map((v) => `"${String(v)}"`).join(', ');
93
- }
94
- return JSON.stringify(value);
95
- }
96
- }
97
- exports.PolicyDenied = PolicyDenied;
98
- /**
99
- * Guardrail builder - fluent API for creating policy errors with suggestions
100
- *
101
- * @example
102
- * ```typescript
103
- * const error = Guardrails.amountExceeded({
104
- * requested: 5000,
105
- * limit: 1000,
106
- * type: 'per-transaction'
107
- * });
108
- *
109
- * throw error;
110
- * // ❌ Policy Violation: maxAmount
111
- * // You requested: $5,000
112
- * // Policy allows: $1,000
113
- * // 💡 Suggestion: Reduce amount to $1,000 or request policy update from admin
114
- * ```
115
- */
116
- class Guardrails {
117
- /**
118
- * Amount exceeded (per-transaction limit)
119
- */
120
- static amountExceeded(options) {
121
- let rule;
122
- let suggestion;
123
- switch (options.type) {
124
- case 'per-transaction':
125
- rule = 'maxAmount';
126
- suggestion = `Reduce amount to $${options.limit.toLocaleString()} or request policy update from admin`;
127
- break;
128
- case 'daily':
129
- rule = 'dailyAmount';
130
- suggestion = `Reduce amount to stay within daily limit of $${options.limit.toLocaleString()}, or wait until tomorrow`;
131
- break;
132
- case 'monthly':
133
- rule = 'monthlyAmount';
134
- suggestion = `Reduce amount to stay within monthly limit of $${options.limit.toLocaleString()}, or wait until next month`;
135
- break;
136
- }
137
- return new PolicyDenied(rule, options.limit, options.requested, suggestion);
138
- }
139
- /**
140
- * Rate limit exceeded
141
- */
142
- static rateLimitExceeded(options) {
143
- const windowSec = options.windowMs / 1000;
144
- const suggestion = windowSec >= 60
145
- ? `Wait ${Math.ceil(windowSec / 60)} minutes before making additional calls`
146
- : `Wait ${windowSec} seconds before making additional calls`;
147
- return new PolicyDenied('callsPerMinute', options.limit, options.current + 1, suggestion);
148
- }
149
- /**
150
- * Tool not allowed
151
- */
152
- static toolDenied(options) {
153
- const [service] = options.tool.split(':');
154
- const suggestion = options.allowed.length === 0
155
- ? `No tools are currently allowed. Request approval from admin to enable "${options.tool}"`
156
- : `Request approval from admin to add "${options.tool}" or "${service}:*" to allowed tools`;
157
- return new PolicyDenied('allowedTools', options.allowed, options.tool, suggestion);
158
- }
159
- /**
160
- * Scope not allowed
161
- */
162
- static scopeDenied(options) {
163
- const suggestion = options.allowed.length === 0
164
- ? `No scopes are currently allowed. Request approval from admin to enable "${options.scope}"`
165
- : `Request approval from admin to add "${options.scope}" to allowed scopes`;
166
- return new PolicyDenied('allowedScopes', options.allowed, options.scope, suggestion);
167
- }
168
- /**
169
- * Field filter denied (data access restriction)
170
- */
171
- static fieldDenied(options) {
172
- const suggestion = `Field "${options.field}" is restricted. Contact admin to update policy.fieldFilters for "${options.tool}"`;
173
- return new PolicyDenied('fieldFilters', options.allowed, options.field, suggestion);
174
- }
175
- /**
176
- * Time window restriction
177
- */
178
- static timeWindowDenied(options) {
179
- const suggestion = `Actions are only allowed between ${options.allowedStart} and ${options.allowedEnd}. Current time is ${options.current.toTimeString()}`;
180
- return new PolicyDenied('timeWindow', `${options.allowedStart} - ${options.allowedEnd}`, options.current.toTimeString(), suggestion);
181
- }
182
- /**
183
- * Generic policy violation
184
- */
185
- static custom(options) {
186
- return new PolicyDenied(options.rule, options.allowed, options.requested, options.suggestion);
187
- }
188
- }
189
- exports.Guardrails = Guardrails;
190
- /**
191
- * Helper: Extract actionable suggestion from AgentError details
192
- *
193
- * Used by agent.call() to convert PolicyViolationDetails into PolicyDenied
194
- */
195
- function extractSuggestion(details) {
196
- return details.fix ?? 'Contact administrator to update policy';
197
- }
198
- /**
199
- * Helper: Convert PolicyViolationDetails to PolicyDenied
200
- */
201
- function toPolicyDenied(details) {
202
- let rule;
203
- switch (details.constraint) {
204
- case 'amountPerTxn':
205
- rule = 'maxAmount';
206
- break;
207
- case 'dailyAmount':
208
- rule = 'dailyAmount';
209
- break;
210
- case 'callsPerMinute':
211
- rule = 'callsPerMinute';
212
- break;
213
- case 'scope':
214
- rule = 'allowedScopes';
215
- break;
216
- case 'tool':
217
- rule = 'allowedTools';
218
- break;
219
- default:
220
- rule = String(details.constraint);
221
- }
222
- return new PolicyDenied(rule, details.allowed, details.requested, details.fix, details);
223
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Guardrails=exports.PolicyDenied=void 0,exports.extractSuggestion=extractSuggestion,exports.toPolicyDenied=toPolicyDenied;class PolicyDenied extends Error{rule;allowed;requested;suggestion;details;constructor(e,t,o,i,l){super(`Policy violation: ${e}`),this.rule=e,this.allowed=t,this.requested=o,this.suggestion=i,this.details=l,this.name="PolicyDenied"}toAgentFormat(){return[`POLICY_VIOLATION: ${this.rule}`,`REQUESTED: ${JSON.stringify(this.requested)}`,`ALLOWED: ${JSON.stringify(this.allowed)}`,`SUGGESTION: ${this.suggestion}`].join("\n")}toUserFormat(){return[`❌ Policy Violation: ${this.rule}`,"",`You requested: ${this.formatValue(this.requested)}`,`Policy allows: ${this.formatValue(this.allowed)}`,"",`💡 Suggestion: ${this.suggestion}`].join("\n")}toLogFormat(){return{error:"PolicyDenied",rule:this.rule,allowed:this.allowed,requested:this.requested,suggestion:this.suggestion,details:this.details,timestamp:(new Date).toISOString()}}formatValue(e){return"number"==typeof e?this.rule.includes("amount")||this.rule.includes("Amount")?`$${e.toLocaleString()}`:e.toLocaleString():Array.isArray(e)?e.map(e=>`"${String(e)}"`).join(", "):JSON.stringify(e)}}exports.PolicyDenied=PolicyDenied;class Guardrails{static amountExceeded(e){let t,o;switch(e.type){case"per-transaction":t="maxAmount",o=`Reduce amount to $${e.limit.toLocaleString()} or request policy update from admin`;break;case"daily":t="dailyAmount",o=`Reduce amount to stay within daily limit of $${e.limit.toLocaleString()}, or wait until tomorrow`;break;case"monthly":t="monthlyAmount",o=`Reduce amount to stay within monthly limit of $${e.limit.toLocaleString()}, or wait until next month`}return new PolicyDenied(t,e.limit,e.requested,o)}static rateLimitExceeded(e){const t=e.windowMs/1e3,o=t>=60?`Wait ${Math.ceil(t/60)} minutes before making additional calls`:`Wait ${t} seconds before making additional calls`;return new PolicyDenied("callsPerMinute",e.limit,e.current+1,o)}static toolDenied(e){const[t]=e.tool.split(":"),o=0===e.allowed.length?`No tools are currently allowed. Request approval from admin to enable "${e.tool}"`:`Request approval from admin to add "${e.tool}" or "${t}:*" to allowed tools`;return new PolicyDenied("allowedTools",e.allowed,e.tool,o)}static scopeDenied(e){const t=0===e.allowed.length?`No scopes are currently allowed. Request approval from admin to enable "${e.scope}"`:`Request approval from admin to add "${e.scope}" to allowed scopes`;return new PolicyDenied("allowedScopes",e.allowed,e.scope,t)}static fieldDenied(e){const t=`Field "${e.field}" is restricted. Contact admin to update policy.fieldFilters for "${e.tool}"`;return new PolicyDenied("fieldFilters",e.allowed,e.field,t)}static timeWindowDenied(e){const t=`Actions are only allowed between ${e.allowedStart} and ${e.allowedEnd}. Current time is ${e.current.toTimeString()}`;return new PolicyDenied("timeWindow",`${e.allowedStart} - ${e.allowedEnd}`,e.current.toTimeString(),t)}static custom(e){return new PolicyDenied(e.rule,e.allowed,e.requested,e.suggestion)}}function extractSuggestion(e){return e.fix??"Contact administrator to update policy"}function toPolicyDenied(e){let t;switch(e.constraint){case"amountPerTxn":t="maxAmount";break;case"dailyAmount":t="dailyAmount";break;case"callsPerMinute":t="callsPerMinute";break;case"scope":t="allowedScopes";break;case"tool":t="allowedTools";break;default:t=String(e.constraint)}return new PolicyDenied(t,e.allowed,e.requested,e.fix,e)}exports.Guardrails=Guardrails;