@kya-os/checkpoint-wasm-runtime 1.0.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 (71) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/dist/adapters.d.mts +257 -0
  3. package/dist/adapters.d.ts +257 -0
  4. package/dist/adapters.js +603 -0
  5. package/dist/adapters.js.map +1 -0
  6. package/dist/adapters.mjs +586 -0
  7. package/dist/adapters.mjs.map +1 -0
  8. package/dist/dynamic-loader-cS-pUisw.d.ts +65 -0
  9. package/dist/dynamic-loader-qGJacfEC.d.mts +65 -0
  10. package/dist/edge.d.mts +22 -0
  11. package/dist/edge.d.ts +22 -0
  12. package/dist/edge.js +1403 -0
  13. package/dist/edge.js.map +1 -0
  14. package/dist/edge.mjs +1391 -0
  15. package/dist/edge.mjs.map +1 -0
  16. package/dist/engine-edge.d.mts +58 -0
  17. package/dist/engine-edge.d.ts +58 -0
  18. package/dist/engine-edge.js +537 -0
  19. package/dist/engine-edge.js.map +1 -0
  20. package/dist/engine-edge.mjs +533 -0
  21. package/dist/engine-edge.mjs.map +1 -0
  22. package/dist/engine.d.mts +34 -0
  23. package/dist/engine.d.ts +34 -0
  24. package/dist/engine.js +11 -0
  25. package/dist/engine.js.map +1 -0
  26. package/dist/engine.mjs +9 -0
  27. package/dist/engine.mjs.map +1 -0
  28. package/dist/index.d.mts +58 -0
  29. package/dist/index.d.ts +58 -0
  30. package/dist/index.js +1652 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/index.mjs +1637 -0
  33. package/dist/index.mjs.map +1 -0
  34. package/dist/node.d.mts +26 -0
  35. package/dist/node.d.ts +26 -0
  36. package/dist/node.js +972 -0
  37. package/dist/node.js.map +1 -0
  38. package/dist/node.mjs +960 -0
  39. package/dist/node.mjs.map +1 -0
  40. package/dist/orchestrator-edge.d.mts +243 -0
  41. package/dist/orchestrator-edge.d.ts +243 -0
  42. package/dist/orchestrator-edge.js +1076 -0
  43. package/dist/orchestrator-edge.js.map +1 -0
  44. package/dist/orchestrator-edge.mjs +1065 -0
  45. package/dist/orchestrator-edge.mjs.map +1 -0
  46. package/dist/orchestrator.d.mts +50 -0
  47. package/dist/orchestrator.d.ts +50 -0
  48. package/dist/orchestrator.js +1185 -0
  49. package/dist/orchestrator.js.map +1 -0
  50. package/dist/orchestrator.mjs +1172 -0
  51. package/dist/orchestrator.mjs.map +1 -0
  52. package/dist/rules-detector-DjbTJ1-Q.d.mts +470 -0
  53. package/dist/rules-detector-DjbTJ1-Q.d.ts +470 -0
  54. package/dist/static-loader-C1hUlksK.d.ts +72 -0
  55. package/dist/static-loader-Ds4iNw7c.d.mts +72 -0
  56. package/dist/types-D0j85fF0.d.mts +163 -0
  57. package/dist/types-D0j85fF0.d.ts +163 -0
  58. package/package.json +141 -0
  59. package/wasm/agentshield_wasm.d.ts +485 -0
  60. package/wasm/agentshield_wasm.js +1551 -0
  61. package/wasm/agentshield_wasm_bg.wasm +0 -0
  62. package/wasm/agentshield_wasm_bg.wasm.d.ts +97 -0
  63. package/wasm/kya-os-engine/kya_os_engine.d.ts +24 -0
  64. package/wasm/kya-os-engine/kya_os_engine.js +517 -0
  65. package/wasm/kya-os-engine/kya_os_engine_bg.wasm +0 -0
  66. package/wasm/kya-os-engine/kya_os_engine_bg.wasm.d.ts +8 -0
  67. package/wasm/kya-os-engine-web/kya_os_engine.d.ts +56 -0
  68. package/wasm/kya-os-engine-web/kya_os_engine.js +574 -0
  69. package/wasm/kya-os-engine-web/kya_os_engine_bg.wasm +0 -0
  70. package/wasm/kya-os-engine-web/kya_os_engine_bg.wasm.d.ts +8 -0
  71. package/wasm/package.json +30 -0
@@ -0,0 +1,586 @@
1
+ import { base58btc } from 'multiformats/bases/base58';
2
+ import { gunzipSync } from 'zlib';
3
+
4
+ // src/engine/adapters/did-resolver.ts
5
+
6
+ // src/engine/adapters/outbound-url-policy.ts
7
+ var BLOCKED_HOSTNAMES = /* @__PURE__ */ new Set(["localhost", "metadata", "metadata.google.internal"]);
8
+ var UnsafeOutboundUrl = class extends Error {
9
+ kind = "UnsafeOutboundUrl";
10
+ };
11
+ function assertSafeHttpsUrl(rawUrl, label = "outbound URL") {
12
+ let parsed;
13
+ try {
14
+ parsed = new URL(rawUrl);
15
+ } catch {
16
+ throw new UnsafeOutboundUrl(`${label} must be a valid URL: ${rawUrl}`);
17
+ }
18
+ if (parsed.protocol !== "https:") {
19
+ throw new UnsafeOutboundUrl(`${label} must use https: ${rawUrl}`);
20
+ }
21
+ if (parsed.username || parsed.password) {
22
+ throw new UnsafeOutboundUrl(`${label} must not contain credentials: ${rawUrl}`);
23
+ }
24
+ const hostname = normalizeHostname(parsed.hostname);
25
+ if (!hostname || isBlockedHostname(hostname)) {
26
+ throw new UnsafeOutboundUrl(`${label} targets a local or private host: ${rawUrl}`);
27
+ }
28
+ return rawUrl;
29
+ }
30
+ function normalizeHostname(hostname) {
31
+ let normalized = hostname.trim().toLowerCase();
32
+ if (normalized.startsWith("[") && normalized.endsWith("]")) {
33
+ normalized = normalized.slice(1, -1);
34
+ }
35
+ while (normalized.endsWith(".")) {
36
+ normalized = normalized.slice(0, -1);
37
+ }
38
+ return normalized;
39
+ }
40
+ function isBlockedHostname(hostname) {
41
+ if (BLOCKED_HOSTNAMES.has(hostname) || hostname.endsWith(".localhost")) {
42
+ return true;
43
+ }
44
+ const ipv4 = parseIpv4(hostname);
45
+ if (ipv4) {
46
+ return isBlockedIpv4(ipv4);
47
+ }
48
+ return isBlockedIpv6(hostname);
49
+ }
50
+ function parseIpv4(hostname) {
51
+ const parts = hostname.split(".");
52
+ if (parts.length !== 4) return null;
53
+ const octets = parts.map((part) => {
54
+ if (!/^\d{1,3}$/.test(part)) return Number.NaN;
55
+ const value = Number(part);
56
+ return value >= 0 && value <= 255 ? value : Number.NaN;
57
+ });
58
+ if (octets.some(Number.isNaN)) return null;
59
+ return octets;
60
+ }
61
+ function isBlockedIpv4([a, b]) {
62
+ return a === 0 || a === 10 || a === 127 || a === 100 && b >= 64 && b <= 127 || a === 169 && b === 254 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a === 198 && (b === 18 || b === 19) || a >= 224;
63
+ }
64
+ function isBlockedIpv6(hostname) {
65
+ if (!hostname.includes(":")) return false;
66
+ const ipv4Mapped = hostname.match(/(?:^|:)ffff:(\d{1,3}(?:\.\d{1,3}){3})$/);
67
+ if (ipv4Mapped) {
68
+ const ipv4 = parseIpv4(ipv4Mapped[1]);
69
+ return ipv4 ? isBlockedIpv4(ipv4) : true;
70
+ }
71
+ if (hostname === "::" || hostname === "::1" || hostname === "0:0:0:0:0:0:0:1") {
72
+ return true;
73
+ }
74
+ const firstSegment = Number.parseInt(hostname.split(":")[0] || "0", 16);
75
+ if (Number.isNaN(firstSegment)) return true;
76
+ return (firstSegment & 65024) === 64512 || // unique local fc00::/7
77
+ (firstSegment & 65472) === 65152 || // link-local fe80::/10
78
+ (firstSegment & 65280) === 65280;
79
+ }
80
+
81
+ // src/engine/adapters/util.ts
82
+ function base64UrlDecode(input) {
83
+ const padded = input.replace(/-/g, "+").replace(/_/g, "/");
84
+ const padding = padded.length % 4 === 0 ? "" : "=".repeat(4 - padded.length % 4);
85
+ return new Uint8Array(Buffer.from(padded + padding, "base64"));
86
+ }
87
+
88
+ // src/engine/adapters/did-resolver.ts
89
+ var ED25519_PUBLIC_KEY_LENGTH = 32;
90
+ var MalformedDid = class extends Error {
91
+ kind = "MalformedDid";
92
+ };
93
+ var UnsupportedKeyType = class extends Error {
94
+ kind = "UnsupportedKeyType";
95
+ };
96
+ var DidNotFound = class extends Error {
97
+ kind = "DidNotFound";
98
+ };
99
+ var DidResolverTimeout = class extends Error {
100
+ kind = "DidResolverTimeout";
101
+ };
102
+ var DidResolverError = class extends Error {
103
+ kind = "DidResolverError";
104
+ };
105
+ var UnsupportedDidMethod = class extends Error {
106
+ kind = "UnsupportedDidMethod";
107
+ };
108
+ var ED25519_MULTICODEC_PREFIX = [237, 1];
109
+ var DEFAULT_FETCH_TIMEOUT_MS = 3e3;
110
+ var DEFAULT_TTL_MS = 5 * 6e4;
111
+ function makeDidResolver(opts = {}) {
112
+ const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;
113
+ const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;
114
+ const fetchImpl = opts.fetch ?? fetch;
115
+ const cache = opts.cache ?? /* @__PURE__ */ new Map();
116
+ const now = opts.now ?? (() => Date.now());
117
+ return {
118
+ async resolve(did) {
119
+ const cached = cache.get(did);
120
+ if (cached && now() - cached.fetchedAt < ttlMs) {
121
+ return cached.value;
122
+ }
123
+ if (did.startsWith("did:key:")) {
124
+ const doc = decodeDidKey(did);
125
+ cache.set(did, { value: doc, fetchedAt: now() });
126
+ return doc;
127
+ }
128
+ if (did.startsWith("did:web:")) {
129
+ const doc = await resolveDidWeb(did, fetchImpl, timeoutMs);
130
+ cache.set(did, { value: doc, fetchedAt: now() });
131
+ return doc;
132
+ }
133
+ throw new UnsupportedDidMethod(`Phase 1 supports did:key and did:web only; got: ${did}`);
134
+ }
135
+ };
136
+ }
137
+ function decodeDidKey(did) {
138
+ if (!did.startsWith("did:key:")) {
139
+ throw new MalformedDid(`expected did:key prefix, got: ${did}`);
140
+ }
141
+ const multibaseValue = did.slice("did:key:".length);
142
+ if (!multibaseValue.startsWith("z")) {
143
+ throw new MalformedDid(
144
+ `did:key expects base58btc (multibase 'z' prefix); got: ${multibaseValue[0] ?? "<empty>"}`
145
+ );
146
+ }
147
+ let decoded;
148
+ try {
149
+ decoded = base58btc.decode(multibaseValue);
150
+ } catch (cause) {
151
+ throw new MalformedDid(`did:key multibase decode failed: ${String(cause)}`);
152
+ }
153
+ if (decoded.length < 2 || decoded[0] !== ED25519_MULTICODEC_PREFIX[0] || decoded[1] !== ED25519_MULTICODEC_PREFIX[1]) {
154
+ const prefixHex = decoded.length >= 2 ? `0x${decoded[0].toString(16).padStart(2, "0")}${decoded[1].toString(16).padStart(2, "0")}` : "<too short>";
155
+ throw new UnsupportedKeyType(
156
+ `did:key expects Ed25519 multicodec 0xed01; got ${prefixHex} (only Ed25519 supported in Phase 1)`
157
+ );
158
+ }
159
+ const publicKey = decoded.slice(2);
160
+ if (publicKey.length !== 32) {
161
+ throw new MalformedDid(`did:key Ed25519 public key must be 32 bytes; got ${publicKey.length}`);
162
+ }
163
+ const vm = {
164
+ id: `${did}#${multibaseValue}`,
165
+ // multibase as fragment — mcp-i-core PR #16
166
+ keyType: "Ed25519",
167
+ publicKeyBytes: Array.from(publicKey)
168
+ };
169
+ return {
170
+ id: did,
171
+ verificationMethods: [vm]
172
+ };
173
+ }
174
+ async function resolveDidWeb(did, fetchImpl, timeoutMs) {
175
+ const transformedUrl = didWebToUrl(did);
176
+ let url;
177
+ try {
178
+ url = assertSafeHttpsUrl(transformedUrl, "did:web resolution URL");
179
+ } catch (cause) {
180
+ if (cause instanceof UnsafeOutboundUrl) {
181
+ throw new DidResolverError(cause.message);
182
+ }
183
+ throw cause;
184
+ }
185
+ const controller = new AbortController();
186
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
187
+ let response;
188
+ try {
189
+ response = await fetchImpl(url, { signal: controller.signal });
190
+ } catch (cause) {
191
+ if (cause instanceof Error && cause.name === "AbortError") {
192
+ throw new DidResolverTimeout(`did:web fetch timed out after ${timeoutMs}ms: ${url}`);
193
+ }
194
+ throw new DidResolverError(`did:web fetch failed: ${url}: ${String(cause)}`);
195
+ } finally {
196
+ clearTimeout(timer);
197
+ }
198
+ if (response.status === 404) {
199
+ throw new DidNotFound(`no DID document at ${url}`);
200
+ }
201
+ if (!response.ok) {
202
+ throw new DidResolverError(`did:web HTTP ${response.status} at ${url}`);
203
+ }
204
+ let raw;
205
+ try {
206
+ raw = await response.json();
207
+ } catch (cause) {
208
+ throw new DidResolverError(`did:web response not valid JSON at ${url}: ${String(cause)}`);
209
+ }
210
+ return mapW3CDocToEngineShape(raw, did);
211
+ }
212
+ function didWebToUrl(did) {
213
+ const path = did.slice("did:web:".length);
214
+ if (!path) {
215
+ throw new MalformedDid(`did:web with empty path: ${did}`);
216
+ }
217
+ const parts = path.split(":").map((segment) => {
218
+ try {
219
+ return decodeURIComponent(segment);
220
+ } catch {
221
+ throw new MalformedDid(`did:web segment contains invalid percent-encoding: ${segment}`);
222
+ }
223
+ });
224
+ if (parts.length === 1) {
225
+ return `https://${parts[0]}/.well-known/did.json`;
226
+ }
227
+ return `https://${parts[0]}/${parts.slice(1).join("/")}/did.json`;
228
+ }
229
+ function mapW3CDocToEngineShape(raw, requestedDid) {
230
+ if (raw === null || typeof raw !== "object") {
231
+ throw new DidResolverError(`did:web response must be a JSON object`);
232
+ }
233
+ const doc = raw;
234
+ const id = typeof doc.id === "string" ? doc.id : requestedDid;
235
+ const w3cMethods = Array.isArray(doc.verificationMethod) ? doc.verificationMethod : [];
236
+ const verificationMethods = [];
237
+ for (const entry of w3cMethods) {
238
+ if (entry === null || typeof entry !== "object") continue;
239
+ const vm = entry;
240
+ if (!isEd25519Type(vm.type)) continue;
241
+ const vmId = typeof vm.id === "string" ? vm.id : void 0;
242
+ if (!vmId) continue;
243
+ const pubKey = extractEd25519PublicKey(vm);
244
+ if (!pubKey) continue;
245
+ verificationMethods.push({
246
+ id: vmId,
247
+ keyType: "Ed25519",
248
+ publicKeyBytes: Array.from(pubKey)
249
+ });
250
+ }
251
+ return { id, verificationMethods };
252
+ }
253
+ function isEd25519Type(type) {
254
+ return type === "Ed25519VerificationKey2020" || type === "Ed25519VerificationKey2018";
255
+ }
256
+ function extractEd25519PublicKey(vm) {
257
+ if (typeof vm.publicKeyMultibase === "string") {
258
+ const mb = vm.publicKeyMultibase;
259
+ if (!mb.startsWith("z")) return null;
260
+ try {
261
+ const decoded = base58btc.decode(mb);
262
+ if (decoded.length === 34 && decoded[0] === ED25519_MULTICODEC_PREFIX[0] && decoded[1] === ED25519_MULTICODEC_PREFIX[1]) {
263
+ return decoded.slice(2);
264
+ }
265
+ if (decoded.length === 32) return decoded;
266
+ } catch {
267
+ return null;
268
+ }
269
+ return null;
270
+ }
271
+ if (vm.publicKeyJwk && typeof vm.publicKeyJwk === "object") {
272
+ const jwk = vm.publicKeyJwk;
273
+ if (jwk.kty !== "OKP" || jwk.crv !== "Ed25519") return null;
274
+ if (typeof jwk.x !== "string") return null;
275
+ let decoded;
276
+ try {
277
+ decoded = base64UrlDecode(jwk.x);
278
+ } catch {
279
+ return null;
280
+ }
281
+ if (decoded.length !== ED25519_PUBLIC_KEY_LENGTH) {
282
+ return null;
283
+ }
284
+ return decoded;
285
+ }
286
+ return null;
287
+ }
288
+ var StatusListUnavailable = class extends Error {
289
+ kind = "StatusListUnavailable";
290
+ };
291
+ var MalformedStatusList = class extends Error {
292
+ kind = "MalformedStatusList";
293
+ };
294
+ var StatusListTimeout = class extends Error {
295
+ kind = "StatusListTimeout";
296
+ };
297
+ var DEFAULT_FETCH_TIMEOUT_MS2 = 3e3;
298
+ var DEFAULT_TTL_MS2 = 3e4;
299
+ function makeStatusListCache(opts = {}) {
300
+ const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS2;
301
+ const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS2;
302
+ const fetchImpl = opts.fetch ?? fetch;
303
+ const cache = opts.cache ?? /* @__PURE__ */ new Map();
304
+ const now = opts.now ?? (() => Date.now());
305
+ return {
306
+ async fetch(url) {
307
+ const cached = cache.get(url);
308
+ if (cached && now() - cached.fetchedAt < ttlMs) {
309
+ return cached.indices;
310
+ }
311
+ const indices = await fetchAndDecode(url, fetchImpl, timeoutMs);
312
+ cache.set(url, { indices, fetchedAt: now() });
313
+ return indices;
314
+ }
315
+ };
316
+ }
317
+ async function fetchAndDecode(url, fetchImpl, timeoutMs) {
318
+ let safeUrl;
319
+ try {
320
+ safeUrl = assertSafeHttpsUrl(url, "status list URL");
321
+ } catch (cause) {
322
+ if (cause instanceof UnsafeOutboundUrl) {
323
+ throw new StatusListUnavailable(cause.message);
324
+ }
325
+ throw cause;
326
+ }
327
+ const controller = new AbortController();
328
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
329
+ let response;
330
+ try {
331
+ response = await fetchImpl(safeUrl, { signal: controller.signal });
332
+ } catch (cause) {
333
+ if (cause instanceof Error && cause.name === "AbortError") {
334
+ throw new StatusListTimeout(`status list fetch timed out after ${timeoutMs}ms: ${url}`);
335
+ }
336
+ throw new StatusListUnavailable(`status list fetch failed: ${url}: ${String(cause)}`);
337
+ } finally {
338
+ clearTimeout(timer);
339
+ }
340
+ if (!response.ok) {
341
+ throw new StatusListUnavailable(`status list HTTP ${response.status} at ${url}`);
342
+ }
343
+ let vc;
344
+ try {
345
+ vc = await response.json();
346
+ } catch (cause) {
347
+ throw new MalformedStatusList(
348
+ `status list response not valid JSON at ${url}: ${String(cause)}`
349
+ );
350
+ }
351
+ const encoded = extractEncodedList(vc);
352
+ return enumerateRevokedIndices(encoded);
353
+ }
354
+ function extractEncodedList(vc) {
355
+ if (vc === null || typeof vc !== "object") {
356
+ throw new MalformedStatusList("status list VC must be a JSON object");
357
+ }
358
+ const obj = vc;
359
+ const subject = obj.credentialSubject;
360
+ if (subject === null || typeof subject !== "object") {
361
+ throw new MalformedStatusList("status list VC missing credentialSubject");
362
+ }
363
+ const encoded = subject.encodedList;
364
+ if (typeof encoded !== "string") {
365
+ throw new MalformedStatusList("status list VC missing credentialSubject.encodedList string");
366
+ }
367
+ return encoded;
368
+ }
369
+ function enumerateRevokedIndices(encodedList) {
370
+ let bytes;
371
+ try {
372
+ const compressed = base64UrlDecode(encodedList);
373
+ bytes = new Uint8Array(gunzipSync(compressed));
374
+ } catch (cause) {
375
+ throw new MalformedStatusList(`status list bitstring decode failed: ${String(cause)}`);
376
+ }
377
+ const indices = [];
378
+ for (let byteIndex = 0; byteIndex < bytes.length; byteIndex += 1) {
379
+ const byte = bytes[byteIndex];
380
+ if (byte === 0) continue;
381
+ for (let bit = 0; bit < 8; bit += 1) {
382
+ const mask = 1 << 7 - bit;
383
+ if ((byte & mask) !== 0) {
384
+ indices.push(byteIndex * 8 + bit);
385
+ }
386
+ }
387
+ }
388
+ return indices;
389
+ }
390
+
391
+ // src/engine/adapters/reputation-oracle.ts
392
+ var DEFAULT_FETCH_TIMEOUT_MS3 = 1500;
393
+ var DEFAULT_TTL_MS3 = 1e4;
394
+ var DEFAULT_BASELINE = 1;
395
+ function makeReputationOracle(opts = {}) {
396
+ const argusUrl = opts.argusUrl;
397
+ const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS3;
398
+ const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS3;
399
+ const fetchImpl = opts.fetch ?? fetch;
400
+ const baseline = opts.baselineWhenUnreachable ?? DEFAULT_BASELINE;
401
+ const cache = opts.cache ?? /* @__PURE__ */ new Map();
402
+ const now = opts.now ?? (() => Date.now());
403
+ const log = opts.logger ?? (() => {
404
+ });
405
+ return {
406
+ async score(agentDid) {
407
+ const cached = cache.get(agentDid);
408
+ if (cached && now() - cached.fetchedAt < ttlMs) {
409
+ return cached.value;
410
+ }
411
+ if (!argusUrl) {
412
+ return baseline;
413
+ }
414
+ const value = await fetchAndValidate(argusUrl, agentDid, fetchImpl, timeoutMs, baseline, log);
415
+ cache.set(agentDid, { value, fetchedAt: now() });
416
+ return value;
417
+ }
418
+ };
419
+ }
420
+ async function fetchAndValidate(argusUrl, agentDid, fetchImpl, timeoutMs, baseline, log) {
421
+ const url = `${argusUrl.replace(/\/$/, "")}/v1/reputation?agent=${encodeURIComponent(agentDid)}`;
422
+ const controller = new AbortController();
423
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
424
+ let response;
425
+ try {
426
+ response = await fetchImpl(url, { signal: controller.signal });
427
+ } catch (cause) {
428
+ if (cause instanceof Error && cause.name === "AbortError") {
429
+ log(
430
+ `[reputation-oracle] Argus timed out after ${timeoutMs}ms (${agentDid}); using baseline ${baseline}`
431
+ );
432
+ } else {
433
+ log(
434
+ `[reputation-oracle] Argus fetch failed (${agentDid}): ${String(cause)}; using baseline ${baseline}`
435
+ );
436
+ }
437
+ return baseline;
438
+ } finally {
439
+ clearTimeout(timer);
440
+ }
441
+ if (!response.ok) {
442
+ log(
443
+ `[reputation-oracle] Argus HTTP ${response.status} (${agentDid}); using baseline ${baseline}`
444
+ );
445
+ return baseline;
446
+ }
447
+ let body;
448
+ try {
449
+ body = await response.json();
450
+ } catch (cause) {
451
+ log(
452
+ `[reputation-oracle] Argus response not JSON (${agentDid}): ${String(cause)}; using baseline ${baseline}`
453
+ );
454
+ return baseline;
455
+ }
456
+ if (body === null || typeof body !== "object") {
457
+ log(
458
+ `[reputation-oracle] Argus response not an object (${agentDid}); using baseline ${baseline}`
459
+ );
460
+ return baseline;
461
+ }
462
+ const score = body.score;
463
+ if (typeof score !== "number" || !Number.isFinite(score)) {
464
+ log(
465
+ `[reputation-oracle] Argus score not a finite number (${agentDid}): ${String(score)}; using baseline ${baseline}`
466
+ );
467
+ return baseline;
468
+ }
469
+ if (score < 0 || score > 1) {
470
+ log(
471
+ `[reputation-oracle] Argus score out of range (${agentDid}): ${score}; using baseline ${baseline}`
472
+ );
473
+ return baseline;
474
+ }
475
+ return score;
476
+ }
477
+
478
+ // src/engine/adapters/policy-evaluator.ts
479
+ var DEFAULT_FETCH_TIMEOUT_MS4 = 2e3;
480
+ var DEFAULT_TTL_MS4 = 6e4;
481
+ var PERMIT_BY_DEFAULT_POLICY = { reputationThreshold: 0 };
482
+ function makePolicyEvaluator(opts = {}) {
483
+ const dashboardUrl = opts.dashboardUrl;
484
+ const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS4;
485
+ const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS4;
486
+ const fetchImpl = opts.fetch ?? fetch;
487
+ const fallbackPolicy = opts.defaultPolicy ?? PERMIT_BY_DEFAULT_POLICY;
488
+ const cache = opts.cache ?? /* @__PURE__ */ new Map();
489
+ const now = opts.now ?? (() => Date.now());
490
+ const log = opts.logger ?? (() => {
491
+ });
492
+ return {
493
+ async evaluate(input) {
494
+ const policy = await getOrFetchPolicy(
495
+ input.tenantHost,
496
+ dashboardUrl,
497
+ fetchImpl,
498
+ timeoutMs,
499
+ fallbackPolicy,
500
+ cache,
501
+ ttlMs,
502
+ now,
503
+ log
504
+ );
505
+ return computeDecision(policy, input);
506
+ }
507
+ };
508
+ }
509
+ function computeDecision(policy, input) {
510
+ if (input.reputation < policy.reputationThreshold) {
511
+ return {
512
+ kind: "Block",
513
+ reason: {
514
+ kind: "LowReputation",
515
+ score: input.reputation,
516
+ threshold: policy.reputationThreshold
517
+ }
518
+ };
519
+ }
520
+ return { kind: "Permit" };
521
+ }
522
+ async function getOrFetchPolicy(tenantHost, dashboardUrl, fetchImpl, timeoutMs, fallbackPolicy, cache, ttlMs, now, log) {
523
+ const cached = cache.get(tenantHost);
524
+ if (cached && now() - cached.fetchedAt < ttlMs) {
525
+ return cached.policy;
526
+ }
527
+ const cacheFallback = () => {
528
+ cache.set(tenantHost, { policy: fallbackPolicy, fetchedAt: now() });
529
+ return fallbackPolicy;
530
+ };
531
+ if (!dashboardUrl) {
532
+ return cacheFallback();
533
+ }
534
+ const url = `${dashboardUrl.replace(/\/$/, "")}/api/policy?tenant=${encodeURIComponent(tenantHost)}`;
535
+ const controller = new AbortController();
536
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
537
+ let response;
538
+ try {
539
+ response = await fetchImpl(url, { signal: controller.signal });
540
+ } catch (cause) {
541
+ log(`[policy-evaluator] fetch failed (${tenantHost}): ${String(cause)}; using fallback`);
542
+ return cacheFallback();
543
+ } finally {
544
+ clearTimeout(timer);
545
+ }
546
+ if (!response.ok) {
547
+ log(`[policy-evaluator] dashboard HTTP ${response.status} (${tenantHost}); using fallback`);
548
+ return cacheFallback();
549
+ }
550
+ let body;
551
+ try {
552
+ body = await response.json();
553
+ } catch (cause) {
554
+ log(
555
+ `[policy-evaluator] dashboard response not JSON (${tenantHost}): ${String(cause)}; using fallback`
556
+ );
557
+ return cacheFallback();
558
+ }
559
+ const parsed = parseTenantPolicy(body);
560
+ if (!parsed) {
561
+ log(`[policy-evaluator] dashboard response malformed (${tenantHost}); using fallback`);
562
+ return cacheFallback();
563
+ }
564
+ cache.set(tenantHost, { policy: parsed, fetchedAt: now() });
565
+ return parsed;
566
+ }
567
+ function parseTenantPolicy(raw) {
568
+ if (raw === null || typeof raw !== "object") return null;
569
+ const threshold = raw.reputationThreshold;
570
+ if (typeof threshold !== "number" || !Number.isFinite(threshold) || threshold < 0 || threshold > 1) {
571
+ return null;
572
+ }
573
+ return { reputationThreshold: threshold };
574
+ }
575
+
576
+ // src/engine/adapters/clock.ts
577
+ function makeSystemClock() {
578
+ return { nowUnix: () => Math.floor(Date.now() / 1e3) };
579
+ }
580
+ function makeFixedClock(unixSeconds) {
581
+ return { nowUnix: () => unixSeconds };
582
+ }
583
+
584
+ export { DidNotFound, DidResolverError, DidResolverTimeout, MalformedDid, MalformedStatusList, StatusListTimeout, StatusListUnavailable, UnsupportedDidMethod, UnsupportedKeyType, decodeDidKey, makeDidResolver, makeFixedClock, makePolicyEvaluator, makeReputationOracle, makeStatusListCache, makeSystemClock };
585
+ //# sourceMappingURL=adapters.mjs.map
586
+ //# sourceMappingURL=adapters.mjs.map