@kya-os/checkpoint-wasm-runtime 1.0.0 → 1.1.1

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 (47) hide show
  1. package/CHANGELOG.md +166 -0
  2. package/dist/adapters.js +0 -2
  3. package/dist/adapters.mjs +0 -2
  4. package/dist/edge.js +0 -2
  5. package/dist/edge.mjs +0 -2
  6. package/dist/engine-edge.js +0 -2
  7. package/dist/engine-edge.mjs +0 -2
  8. package/dist/engine.js +447 -4
  9. package/dist/engine.mjs +447 -4
  10. package/dist/index.js +0 -2
  11. package/dist/index.mjs +0 -2
  12. package/dist/kya_os_engine_bg.wasm +0 -0
  13. package/dist/node.js +0 -2
  14. package/dist/node.mjs +0 -2
  15. package/dist/orchestrator-edge.d.mts +5 -199
  16. package/dist/orchestrator-edge.d.ts +5 -199
  17. package/dist/orchestrator-edge.js +0 -2
  18. package/dist/orchestrator-edge.mjs +0 -2
  19. package/dist/orchestrator-node.d.mts +49 -0
  20. package/dist/orchestrator-node.d.ts +49 -0
  21. package/dist/orchestrator-node.js +992 -0
  22. package/dist/orchestrator-node.mjs +983 -0
  23. package/dist/orchestrator.d.mts +4 -47
  24. package/dist/orchestrator.d.ts +4 -47
  25. package/dist/orchestrator.js +448 -8
  26. package/dist/orchestrator.mjs +448 -8
  27. package/dist/render-decision-C1a-iuiW.d.mts +200 -0
  28. package/dist/render-decision-Dsjwt96g.d.ts +200 -0
  29. package/package.json +14 -2
  30. package/wasm/kya-os-engine/package.json +7 -0
  31. package/wasm/kya-os-engine-web/package.json +7 -0
  32. package/dist/adapters.js.map +0 -1
  33. package/dist/adapters.mjs.map +0 -1
  34. package/dist/edge.js.map +0 -1
  35. package/dist/edge.mjs.map +0 -1
  36. package/dist/engine-edge.js.map +0 -1
  37. package/dist/engine-edge.mjs.map +0 -1
  38. package/dist/engine.js.map +0 -1
  39. package/dist/engine.mjs.map +0 -1
  40. package/dist/index.js.map +0 -1
  41. package/dist/index.mjs.map +0 -1
  42. package/dist/node.js.map +0 -1
  43. package/dist/node.mjs.map +0 -1
  44. package/dist/orchestrator-edge.js.map +0 -1
  45. package/dist/orchestrator-edge.mjs.map +0 -1
  46. package/dist/orchestrator.js.map +0 -1
  47. package/dist/orchestrator.mjs.map +0 -1
@@ -0,0 +1,200 @@
1
+ import { E as EnforcementMode, A as AgentRequest, V as VerifyResult } from './types-D0j85fF0.js';
2
+ import { DidResolverAdapter, StatusListCacheAdapter, ReputationOracleAdapter, PolicyEvaluatorAdapter, ClockAdapter } from './adapters.js';
3
+
4
+ /**
5
+ * Orchestrator-layer types — Phase C, host-side only.
6
+ *
7
+ * Nothing here crosses the WASM boundary. The engine ABI types live
8
+ * in `../types.ts`; the adapter interfaces live in
9
+ * `../adapters/index.ts`. This file is the host-wrapper-facing
10
+ * surface — what Phase D (Next.js) and Phase E (Express) import.
11
+ */
12
+
13
+ /**
14
+ * Framework-agnostic HTTP request shape.
15
+ *
16
+ * Next.js / Express / Cloudflare Workers / Hono adapters marshal
17
+ * their native request type into this shape before calling
18
+ * `verifyRequest`. The shape is intentionally minimal — only what
19
+ * the engine needs to make a verdict.
20
+ */
21
+ interface IncomingHttpLike {
22
+ method: string;
23
+ /** Path + query string (no scheme + host). */
24
+ url: string;
25
+ headers: Record<string, string | string[] | undefined>;
26
+ /**
27
+ * Parsed body if the framework has already parsed it (Next.js
28
+ * with `await req.json()`, Express with `body-parser`). Falsy if
29
+ * the caller hasn't materialised the body — the orchestrator
30
+ * treats that as "no MCP-I envelope present" and routes to
31
+ * PlainHttp.
32
+ */
33
+ body?: Buffer | string | object | null;
34
+ /** Client IP if the framework surfaces one (Express `req.ip`). */
35
+ remoteAddress?: string;
36
+ }
37
+ /**
38
+ * Options the host wrapper passes per-`verifyRequest`-construction.
39
+ * The five adapters + clock + tenant identifier + enforcement mode.
40
+ */
41
+ interface VerifyRequestOpts {
42
+ didResolver: DidResolverAdapter;
43
+ statusListCache: StatusListCacheAdapter;
44
+ reputationOracle: ReputationOracleAdapter;
45
+ policyEvaluator: PolicyEvaluatorAdapter;
46
+ clock: ClockAdapter;
47
+ /** Tenant identifier — the host customer this request targets. */
48
+ tenantHost: string;
49
+ enforcementMode: EnforcementMode;
50
+ /** Returned to the PolicyEvaluator when the request has no agent DID. Default 1.0. */
51
+ reputationBaseline?: number;
52
+ /**
53
+ * **Envelope-1 (#2537) coordination flag.** Pre-Envelope-1 the TS
54
+ * bouncer ships MCP-I proofs as `{protected,payload,signature}` JSON
55
+ * in a `KYA-Delegation` header. Post-Envelope-1 they ship compact
56
+ * JWS in `_meta.proof.jws` of the body. When this flag is true the
57
+ * orchestrator also accepts the legacy header form. **Default off.**
58
+ * Delete this flag once Envelope-1 ships end-to-end.
59
+ */
60
+ legacyEnvelopeFallback?: boolean;
61
+ /**
62
+ * Argus URL — passed only so the orchestrator can detect "Argus
63
+ * not configured" at construction time and log the one-shot
64
+ * warning. The actual reputation fetch goes through `reputationOracle`.
65
+ */
66
+ argusUrl?: string;
67
+ /** Injectable for the once-only Argus configuration warning. */
68
+ logger?: (msg: string) => void;
69
+ }
70
+ /**
71
+ * Transport-agnostic response shape `renderDecisionAsResponse`
72
+ * produces. Host wrappers adapt this to their framework's response
73
+ * type (NextResponse / Express `res` / Cloudflare Response).
74
+ *
75
+ * `status === null` means "pass through" — the request continues to
76
+ * the next handler. Happens in two cases:
77
+ * 1. `Decision::Permit` (no block in Enforce mode).
78
+ * 2. **Any verdict in Observe mode** — Observe never blocks, but
79
+ * the response headers still carry the would-have-been verdict.
80
+ */
81
+ interface RenderedResponse {
82
+ status: number | null;
83
+ headers: Record<string, string>;
84
+ body?: string | object;
85
+ }
86
+
87
+ /**
88
+ * HTTP-to-`AgentRequest` translator — Phase C.1.
89
+ *
90
+ * Detects which engine protocol the request belongs to and builds
91
+ * the typed `AgentRequest` the WASM consumes. Conservative
92
+ * detection: never escalates an ambiguous request into a higher
93
+ * verification tier. Anonymous PlainHttp is the default.
94
+ *
95
+ * **What this layer parses and what it doesn't.** It parses *only
96
+ * what's needed to drive conditional pre-fetch* — header presence,
97
+ * the MCP-I envelope's payload segment (to extract `iss` + `sub` +
98
+ * optional credentialStatus URL). It does **not** verify
99
+ * signatures, decode VC chains for revocation bits, or evaluate
100
+ * scope. Those live in the engine (H-1's parser + Stages 2-5).
101
+ *
102
+ * **Buffer-portability note.** This module uses `Buffer.from(...)` and
103
+ * `Buffer.isBuffer(...)` at multiple call sites (the JWS preflight
104
+ * `hasMalformedJwsBody`, both `tryBuildMcpIFromBody` variants, the
105
+ * legacy-header reconstitution path, and `bodyAsBytes`). All of these
106
+ * assume the Node `Buffer` global is available — provided natively by
107
+ * the Node runtime, polyfilled on Vercel Edge, and gated behind
108
+ * `nodejs_compat` on Cloudflare Workers. Bare-Edge and pure-browser
109
+ * embedders would need a `Buffer` polyfill or a refactor to
110
+ * `TextEncoder` / `Uint8Array.from`. Tracked as a follow-up since
111
+ * Phase D's Vercel Node + Vercel Edge targets are both covered today.
112
+ */
113
+
114
+ interface BuildAgentRequestOpts {
115
+ /** See `VerifyRequestOpts.legacyEnvelopeFallback`. */
116
+ legacyEnvelopeFallback?: boolean;
117
+ }
118
+ /**
119
+ * Translate an HTTP-like request into the engine's `AgentRequest`.
120
+ *
121
+ * Detection order (conservative — never escalate ambiguous input):
122
+ * 1. MCP-I L2 detached proof in `_meta.proof.jws` (spec form).
123
+ * 2. (Legacy, opt-in) MCP-I in `KYA-Delegation` header
124
+ * (Envelope-1 #2537 transition window only).
125
+ * 3. RFC 9421 HTTP Message Signatures (`Signature-Input` header).
126
+ * 4. PlainHttp (default — anonymous traffic).
127
+ */
128
+ declare function buildAgentRequest(req: IncomingHttpLike, opts?: BuildAgentRequestOpts): AgentRequest;
129
+ /**
130
+ * Preflight check — does the request body carry a `_meta.proof.jws`
131
+ * string that `parseJwsPayloadStruct` cannot project into a typed
132
+ * `McpIPayload`?
133
+ *
134
+ * The caller declared intent (an MCP-I envelope) by including the
135
+ * JWS field; structural failure to extract the payload means the
136
+ * envelope is malformed, not absent. Without this preflight, the
137
+ * orchestrator would silently fall through to PlainHttp — pre-#2560
138
+ * that happened to also Block (engine returned `Block(ParseError)`
139
+ * for every PlainHttp), so the regression was invisible; post-#2560
140
+ * the engine's Stage 1 + stub policy returns `Permit` for anonymous
141
+ * PlainHttp and tampered envelopes would be silently accepted.
142
+ *
143
+ * Returns `true` when the orchestrator should synthesize
144
+ * `Block(ParseError)` BEFORE calling `buildAgentRequest`.
145
+ */
146
+ declare function hasMalformedJwsBody(req: IncomingHttpLike): boolean;
147
+ /**
148
+ * Issuer DID — Stage 1 (identity resolution) targets this. `null`
149
+ * for PlainHttp (anonymous → no DID to resolve).
150
+ */
151
+ declare function extractIssuer(request: AgentRequest): string | null;
152
+ /**
153
+ * Agent DID — used by ReputationOracle. Defaults to `payload.sub`
154
+ * for MCP-I (subject = the agent the proof is *about*).
155
+ */
156
+ declare function extractAgentDid(request: AgentRequest): string | null;
157
+ /**
158
+ * Status-list URL for revocation pre-fetch. Pulled from the JWS
159
+ * payload's `vc.credentialStatus.id` (W3C VC Data Model 1.1).
160
+ * `null` when the envelope is L1 (no VC chain) — Stage 3 will skip.
161
+ */
162
+ declare function extractCredentialStatusUrl(request: AgentRequest): string | null;
163
+
164
+ /**
165
+ * Transport-agnostic `Decision` → HTTP renderer — Phase C.3.
166
+ *
167
+ * Translates a `VerifyResult` into a framework-neutral
168
+ * `{ status, headers, body }` shape. Phase D (Next.js) adapts this
169
+ * to `NextResponse`; Phase E (Express) adapts it to `res.status().set().send()`.
170
+ * One source of truth for the verdict→HTTP mapping.
171
+ *
172
+ * Mapping table (§ 4.5 of Phase C kickoff):
173
+ *
174
+ * | Decision | HTTP | Notes |
175
+ * |-----------------------------------|------|-----------------------------------------|
176
+ * | Permit | null | Pass through to next handler |
177
+ * | Block(Unauthenticated) | 401 | WWW-Authenticate header |
178
+ * | Block(InvalidSignature) | 403 | |
179
+ * | Block(Revoked) | 403 | |
180
+ * | Block(Expired) | 401 | Refresh-the-credential semantics |
181
+ * | Block(OutOfScope) | 403 | Body carries requested + granted |
182
+ * | Block(LowReputation) | 403 | Body carries score + threshold |
183
+ * | Block(PolicyDenied) | 403 | Body carries detail |
184
+ * | Block(ParseError) | 400 | Body carries detail |
185
+ * | Challenge | 401 | Body carries ChallengeParams |
186
+ * | Redirect | 302 | Location header |
187
+ * | Instruct | 422 | application/problem+json body |
188
+ *
189
+ * Observe mode overrides: every verdict renders as `status: null`
190
+ * (pass through) with an `X-Checkpoint-Would-Have-Been` header
191
+ * carrying the verdict kind, plus the standard attribution headers.
192
+ *
193
+ * Every response carries the Phase 0.1 attribution headers:
194
+ * `X-Checkpoint-Engine`, `X-Checkpoint-Engine-Version`, and
195
+ * (when present) `X-Checkpoint-Ruleset-Hash`.
196
+ */
197
+
198
+ declare function renderDecisionAsResponse(result: VerifyResult): RenderedResponse;
199
+
200
+ export { type BuildAgentRequestOpts as B, type IncomingHttpLike as I, type RenderedResponse as R, type VerifyRequestOpts as V, extractCredentialStatusUrl as a, buildAgentRequest as b, extractIssuer as c, extractAgentDid as e, hasMalformedJwsBody as h, renderDecisionAsResponse as r };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kya-os/checkpoint-wasm-runtime",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Checkpoint WASM runtime for AI agent detection across all environments (formerly @kya-os/agentshield-wasm-runtime)",
5
5
  "keywords": [
6
6
  "ai",
@@ -75,10 +75,20 @@
75
75
  "types": "./dist/orchestrator-edge.d.ts",
76
76
  "import": "./dist/orchestrator-edge.mjs"
77
77
  },
78
+ "node": {
79
+ "types": "./dist/orchestrator-node.d.ts",
80
+ "import": "./dist/orchestrator-node.mjs",
81
+ "require": "./dist/orchestrator-node.js"
82
+ },
78
83
  "types": "./dist/orchestrator.d.ts",
79
84
  "import": "./dist/orchestrator.mjs",
80
85
  "require": "./dist/orchestrator.js"
81
86
  },
87
+ "./orchestrator/node": {
88
+ "types": "./dist/orchestrator-node.d.ts",
89
+ "import": "./dist/orchestrator-node.mjs",
90
+ "require": "./dist/orchestrator-node.js"
91
+ },
82
92
  "./orchestrator/edge": {
83
93
  "types": "./dist/orchestrator-edge.d.ts",
84
94
  "edge-runtime": "./dist/orchestrator-edge.mjs",
@@ -120,7 +130,9 @@
120
130
  "publishConfig": {
121
131
  "access": "public"
122
132
  },
123
- "sideEffects": false,
133
+ "sideEffects": [
134
+ "./wasm/**/*.js"
135
+ ],
124
136
  "scripts": {
125
137
  "build": "tsup",
126
138
  "build:watch": "tsup --watch",
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "kya-os-engine-nodejs-wasm-glue",
3
+ "type": "commonjs",
4
+ "main": "kya_os_engine.js",
5
+ "types": "kya_os_engine.d.ts",
6
+ "_note": "wasm-bindgen --target nodejs output: uses `module.exports` + `require('fs')` at module load. The parent wasm/package.json says type:module (for the OLDER agentshield_wasm.js ESM file), which would make Node mis-classify this CJS file and throw ERR_REQUIRE_ESM. This nested package.json overrides per Node's nearest-package.json resolution algorithm. See SDK-WASM-Bundler-Loader-1 follow-up in @kya-os/checkpoint-wasm-runtime@1.1.1 CHANGELOG."
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "kya-os-engine-web-wasm-glue",
3
+ "type": "module",
4
+ "main": "kya_os_engine.js",
5
+ "types": "kya_os_engine.d.ts",
6
+ "_note": "wasm-bindgen --target web output: pure ESM with `import.meta.url` URL-based WASM loading. Matches the parent wasm/package.json's type:module, but pinned explicitly here so the per-engine subdirectory's module type stays unambiguous if the parent ever changes. Pairs with kya-os-engine/package.json (CJS sibling)."
7
+ }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/engine/adapters/outbound-url-policy.ts","../src/engine/adapters/util.ts","../src/engine/adapters/did-resolver.ts","../src/engine/adapters/status-list-cache.ts","../src/engine/adapters/reputation-oracle.ts","../src/engine/adapters/policy-evaluator.ts","../src/engine/adapters/clock.ts"],"names":["base58btc","DEFAULT_FETCH_TIMEOUT_MS","DEFAULT_TTL_MS","gunzipSync"],"mappings":"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","file":"adapters.js","sourcesContent":["/**\n * Shared egress guard for verifier-owned outbound fetches.\n *\n * MCP-I payloads are attacker controlled until the signature verifies. Any\n * host-side fetch derived from that payload must reject obvious local/private\n * targets before invoking `fetch`.\n */\n\nconst BLOCKED_HOSTNAMES = new Set(['localhost', 'metadata', 'metadata.google.internal']);\n\nexport class UnsafeOutboundUrl extends Error {\n readonly kind = 'UnsafeOutboundUrl';\n}\n\nexport function assertSafeHttpsUrl(rawUrl: string, label = 'outbound URL'): string {\n let parsed: URL;\n try {\n parsed = new URL(rawUrl);\n } catch {\n throw new UnsafeOutboundUrl(`${label} must be a valid URL: ${rawUrl}`);\n }\n\n if (parsed.protocol !== 'https:') {\n throw new UnsafeOutboundUrl(`${label} must use https: ${rawUrl}`);\n }\n if (parsed.username || parsed.password) {\n throw new UnsafeOutboundUrl(`${label} must not contain credentials: ${rawUrl}`);\n }\n\n const hostname = normalizeHostname(parsed.hostname);\n if (!hostname || isBlockedHostname(hostname)) {\n throw new UnsafeOutboundUrl(`${label} targets a local or private host: ${rawUrl}`);\n }\n\n return rawUrl;\n}\n\nfunction normalizeHostname(hostname: string): string {\n let normalized = hostname.trim().toLowerCase();\n if (normalized.startsWith('[') && normalized.endsWith(']')) {\n normalized = normalized.slice(1, -1);\n }\n while (normalized.endsWith('.')) {\n normalized = normalized.slice(0, -1);\n }\n return normalized;\n}\n\nfunction isBlockedHostname(hostname: string): boolean {\n if (BLOCKED_HOSTNAMES.has(hostname) || hostname.endsWith('.localhost')) {\n return true;\n }\n\n const ipv4 = parseIpv4(hostname);\n if (ipv4) {\n return isBlockedIpv4(ipv4);\n }\n\n return isBlockedIpv6(hostname);\n}\n\nfunction parseIpv4(hostname: string): [number, number, number, number] | null {\n const parts = hostname.split('.');\n if (parts.length !== 4) return null;\n\n const octets = parts.map((part) => {\n if (!/^\\d{1,3}$/.test(part)) return Number.NaN;\n const value = Number(part);\n return value >= 0 && value <= 255 ? value : Number.NaN;\n });\n\n if (octets.some(Number.isNaN)) return null;\n return octets as [number, number, number, number];\n}\n\nfunction isBlockedIpv4([a, b]: [number, number, number, number]): boolean {\n return (\n a === 0 ||\n a === 10 ||\n a === 127 ||\n (a === 100 && b >= 64 && b <= 127) ||\n (a === 169 && b === 254) ||\n (a === 172 && b >= 16 && b <= 31) ||\n (a === 192 && b === 168) ||\n (a === 198 && (b === 18 || b === 19)) ||\n a >= 224\n );\n}\n\nfunction isBlockedIpv6(hostname: string): boolean {\n if (!hostname.includes(':')) return false;\n\n const ipv4Mapped = hostname.match(/(?:^|:)ffff:(\\d{1,3}(?:\\.\\d{1,3}){3})$/);\n if (ipv4Mapped) {\n const ipv4 = parseIpv4(ipv4Mapped[1]);\n return ipv4 ? isBlockedIpv4(ipv4) : true;\n }\n\n if (hostname === '::' || hostname === '::1' || hostname === '0:0:0:0:0:0:0:1') {\n return true;\n }\n\n const firstSegment = Number.parseInt(hostname.split(':')[0] || '0', 16);\n if (Number.isNaN(firstSegment)) return true;\n\n return (\n (firstSegment & 0xfe00) === 0xfc00 || // unique local fc00::/7\n (firstSegment & 0xffc0) === 0xfe80 || // link-local fe80::/10\n (firstSegment & 0xff00) === 0xff00 // multicast ff00::/8\n );\n}\n","/**\n * Shared utilities for the Phase B adapters.\n *\n * Anything used by more than one adapter belongs here so a future\n * bug fix touches one site, not N.\n */\n\n/**\n * base64url decode without external deps. Pads if necessary,\n * substitutes URL-safe chars, returns the raw bytes as `Uint8Array`.\n * RFC 4648 § 5 — characters `-` and `_` substitute for `+` and `/`;\n * padding `=` is optional and stripped in URL contexts.\n */\nexport function base64UrlDecode(input: string): Uint8Array {\n const padded = input.replace(/-/g, '+').replace(/_/g, '/');\n const padding = padded.length % 4 === 0 ? '' : '='.repeat(4 - (padded.length % 4));\n return new Uint8Array(Buffer.from(padded + padding, 'base64'));\n}\n","/**\n * DidResolver adapter — sub-phase B.1.\n *\n * Resolves `did:key:*` (in-memory multibase decode) and `did:web:*`\n * (HTTPS fetch of `.well-known/did.json`) into the engine's\n * `DidDocument` shape. The async half does any required I/O; the\n * adapter's output is plain data that the host wrapper bundles into\n * `ContextSpec.didDocs` before calling `engineVerify`.\n *\n * Phase 1 supports only Ed25519 verification methods (the engine's\n * `KeyType` is `#[non_exhaustive]` with `Ed25519` as its single\n * variant). Non-Ed25519 methods on a resolved doc are silently\n * filtered out — the engine wouldn't accept them as a valid Stage 2\n * key match anyway.\n *\n * **`kid` for `did:key`**: the verification-method id is\n * `<did>#<multibase>` per mcp-i-core PR #16. **NOT** `<did>#keys-1`.\n * H-1's `stage2_did_key_fragment_resolution` test pins this.\n */\n\nimport { base58btc } from 'multiformats/bases/base58';\n\nimport type { DidDocument, KeyType, VerificationMethod } from '../types';\nimport { assertSafeHttpsUrl, UnsafeOutboundUrl } from './outbound-url-policy';\nimport { base64UrlDecode } from './util';\n\nconst ED25519_PUBLIC_KEY_LENGTH = 32;\n\n// -----------------------------------------------------------------------------\n// Errors — the adapter throws these; the host wrapper translates to verdicts.\n// -----------------------------------------------------------------------------\n\nexport class MalformedDid extends Error {\n readonly kind = 'MalformedDid';\n}\n\nexport class UnsupportedKeyType extends Error {\n readonly kind = 'UnsupportedKeyType';\n}\n\nexport class DidNotFound extends Error {\n readonly kind = 'DidNotFound';\n}\n\nexport class DidResolverTimeout extends Error {\n readonly kind = 'DidResolverTimeout';\n}\n\nexport class DidResolverError extends Error {\n readonly kind = 'DidResolverError';\n}\n\nexport class UnsupportedDidMethod extends Error {\n readonly kind = 'UnsupportedDidMethod';\n}\n\n// -----------------------------------------------------------------------------\n// Public surface — `DidResolverAdapter` is the seam Phase C composes.\n// -----------------------------------------------------------------------------\n\nexport interface DidResolverAdapter {\n resolve(did: string): Promise<DidDocument>;\n}\n\ninterface CacheEntry<T> {\n value: T;\n fetchedAt: number;\n}\n\nexport interface DidResolverOpts {\n /** AbortController timeout for did:web fetches. Default 3000ms. */\n fetchTimeoutMs?: number;\n /** TTL for the in-memory cache. Default 5 minutes. */\n ttlMs?: number;\n /** Injectable fetch — defaults to global `fetch` (Node 18+). */\n fetch?: typeof fetch;\n /**\n * Injectable cache — defaults to a fresh `Map` per adapter instance.\n * Tests pass a shared cache to assert miss/hit behaviour.\n */\n cache?: Map<string, CacheEntry<DidDocument>>;\n /** Injectable wall-clock — defaults to `Date.now()`. Tests use a stub. */\n now?: () => number;\n}\n\nconst ED25519_MULTICODEC_PREFIX = [0xed, 0x01] as const;\nconst DEFAULT_FETCH_TIMEOUT_MS = 3_000;\nconst DEFAULT_TTL_MS = 5 * 60_000;\n\nexport function makeDidResolver(opts: DidResolverOpts = {}): DidResolverAdapter {\n const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;\n const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;\n const fetchImpl = opts.fetch ?? fetch;\n const cache = opts.cache ?? new Map<string, CacheEntry<DidDocument>>();\n const now = opts.now ?? (() => Date.now());\n\n return {\n async resolve(did: string): Promise<DidDocument> {\n const cached = cache.get(did);\n if (cached && now() - cached.fetchedAt < ttlMs) {\n return cached.value;\n }\n // SSRF defense — Phase 1 supports `did:key` + `did:web` only.\n // The pre-fix code routed every non-`did:key:` input into\n // `resolveDidWeb`, which blindly stripped the first 8 chars\n // and used the remainder as a URL host. `did:ion:abc123` →\n // `https://n:abc123/.well-known/did.json` (probe). An\n // attacker submitting arbitrary DID strings could construct\n // arbitrary HTTPS URLs against the host's network namespace\n // — an SSRF probe surface against internal services.\n // Explicit prefix matching closes the surface.\n if (did.startsWith('did:key:')) {\n const doc = decodeDidKey(did);\n cache.set(did, { value: doc, fetchedAt: now() });\n return doc;\n }\n if (did.startsWith('did:web:')) {\n const doc = await resolveDidWeb(did, fetchImpl, timeoutMs);\n cache.set(did, { value: doc, fetchedAt: now() });\n return doc;\n }\n throw new UnsupportedDidMethod(`Phase 1 supports did:key and did:web only; got: ${did}`);\n },\n };\n}\n\n// -----------------------------------------------------------------------------\n// did:key — in-memory multibase decode.\n// -----------------------------------------------------------------------------\n\nexport function decodeDidKey(did: string): DidDocument {\n if (!did.startsWith('did:key:')) {\n throw new MalformedDid(`expected did:key prefix, got: ${did}`);\n }\n const multibaseValue = did.slice('did:key:'.length);\n if (!multibaseValue.startsWith('z')) {\n throw new MalformedDid(\n `did:key expects base58btc (multibase 'z' prefix); got: ${multibaseValue[0] ?? '<empty>'}`\n );\n }\n\n let decoded: Uint8Array;\n try {\n decoded = base58btc.decode(multibaseValue);\n } catch (cause) {\n throw new MalformedDid(`did:key multibase decode failed: ${String(cause)}`);\n }\n\n if (\n decoded.length < 2 ||\n decoded[0] !== ED25519_MULTICODEC_PREFIX[0] ||\n decoded[1] !== ED25519_MULTICODEC_PREFIX[1]\n ) {\n const prefixHex =\n decoded.length >= 2\n ? `0x${decoded[0].toString(16).padStart(2, '0')}${decoded[1].toString(16).padStart(2, '0')}`\n : '<too short>';\n throw new UnsupportedKeyType(\n `did:key expects Ed25519 multicodec 0xed01; got ${prefixHex} (only Ed25519 supported in Phase 1)`\n );\n }\n\n const publicKey = decoded.slice(2);\n if (publicKey.length !== 32) {\n throw new MalformedDid(`did:key Ed25519 public key must be 32 bytes; got ${publicKey.length}`);\n }\n\n const vm: VerificationMethod = {\n id: `${did}#${multibaseValue}`, // multibase as fragment — mcp-i-core PR #16\n keyType: 'Ed25519' satisfies KeyType,\n publicKeyBytes: Array.from(publicKey),\n };\n return {\n id: did,\n verificationMethods: [vm],\n };\n}\n\n// -----------------------------------------------------------------------------\n// did:web — HTTPS fetch + W3C → engine shape mapping.\n// -----------------------------------------------------------------------------\n\nasync function resolveDidWeb(\n did: string,\n fetchImpl: typeof fetch,\n timeoutMs: number\n): Promise<DidDocument> {\n const transformedUrl = didWebToUrl(did);\n let url: string;\n try {\n url = assertSafeHttpsUrl(transformedUrl, 'did:web resolution URL');\n } catch (cause) {\n if (cause instanceof UnsafeOutboundUrl) {\n throw new DidResolverError(cause.message);\n }\n throw cause;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetchImpl(url, { signal: controller.signal });\n } catch (cause) {\n if (cause instanceof Error && cause.name === 'AbortError') {\n throw new DidResolverTimeout(`did:web fetch timed out after ${timeoutMs}ms: ${url}`);\n }\n throw new DidResolverError(`did:web fetch failed: ${url}: ${String(cause)}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (response.status === 404) {\n throw new DidNotFound(`no DID document at ${url}`);\n }\n if (!response.ok) {\n throw new DidResolverError(`did:web HTTP ${response.status} at ${url}`);\n }\n\n let raw: unknown;\n try {\n raw = await response.json();\n } catch (cause) {\n throw new DidResolverError(`did:web response not valid JSON at ${url}: ${String(cause)}`);\n }\n return mapW3CDocToEngineShape(raw, did);\n}\n\n/**\n * `did:web:example.com` → `https://example.com/.well-known/did.json`.\n * `did:web:example.com:user:alice` → `https://example.com/user/alice/did.json`.\n * `did:web:localhost%3A8080` transforms to\n * `https://localhost:8080/.well-known/did.json`, then the egress guard rejects\n * it before fetch because localhost/private targets are never safe verifier I/O.\n *\n * Per W3C did-method-web § 3.2 \"DID-to-HTTPS Transformation\": split on\n * `:`, then `decodeURIComponent` each segment so percent-encoded\n * characters (ports, paths-with-colons, etc.) are unescaped before\n * URL construction. Bugbot caught the missing decode pass on the\n * initial B.1 drop — without it, `did:web:host%3Aport` resolved to\n * `https://host%3Aport/...` which never reaches the right server.\n */\nfunction didWebToUrl(did: string): string {\n const path = did.slice('did:web:'.length);\n if (!path) {\n throw new MalformedDid(`did:web with empty path: ${did}`);\n }\n const parts = path.split(':').map((segment) => {\n try {\n return decodeURIComponent(segment);\n } catch {\n throw new MalformedDid(`did:web segment contains invalid percent-encoding: ${segment}`);\n }\n });\n if (parts.length === 1) {\n return `https://${parts[0]}/.well-known/did.json`;\n }\n return `https://${parts[0]}/${parts.slice(1).join('/')}/did.json`;\n}\n\n/**\n * Convert a W3C DID Core JSON document into the engine's shape.\n *\n * Phase 1 only accepts Ed25519 verification methods — the engine's\n * `KeyType::Ed25519` is the only currently-supported variant. Non-\n * Ed25519 methods are silently filtered (the engine wouldn't accept\n * them as a valid Stage 2 `kid` match).\n *\n * W3C uses `verificationMethod` (singular array name); the engine\n * uses `verificationMethods` (plural) — the rename happens here.\n */\nfunction mapW3CDocToEngineShape(raw: unknown, requestedDid: string): DidDocument {\n if (raw === null || typeof raw !== 'object') {\n throw new DidResolverError(`did:web response must be a JSON object`);\n }\n const doc = raw as Record<string, unknown>;\n const id = typeof doc.id === 'string' ? doc.id : requestedDid;\n\n const w3cMethods = Array.isArray(doc.verificationMethod) ? doc.verificationMethod : [];\n const verificationMethods: VerificationMethod[] = [];\n for (const entry of w3cMethods) {\n if (entry === null || typeof entry !== 'object') continue;\n const vm = entry as Record<string, unknown>;\n if (!isEd25519Type(vm.type)) continue;\n const vmId = typeof vm.id === 'string' ? vm.id : undefined;\n if (!vmId) continue;\n const pubKey = extractEd25519PublicKey(vm);\n if (!pubKey) continue;\n verificationMethods.push({\n id: vmId,\n keyType: 'Ed25519',\n publicKeyBytes: Array.from(pubKey),\n });\n }\n\n return { id, verificationMethods };\n}\n\nfunction isEd25519Type(type: unknown): boolean {\n return type === 'Ed25519VerificationKey2020' || type === 'Ed25519VerificationKey2018';\n}\n\n/**\n * Extract the 32-byte Ed25519 public key from a W3C verificationMethod\n * entry. Accepts either `publicKeyMultibase` (Ed25519VerificationKey2020)\n * or `publicKeyJwk` with `kty: OKP, crv: Ed25519, x: <base64url>`.\n *\n * Returns `null` if extraction fails; the caller drops the method.\n */\nfunction extractEd25519PublicKey(vm: Record<string, unknown>): Uint8Array | null {\n if (typeof vm.publicKeyMultibase === 'string') {\n const mb = vm.publicKeyMultibase;\n if (!mb.startsWith('z')) return null;\n try {\n const decoded = base58btc.decode(mb);\n // `publicKeyMultibase` on Ed25519VerificationKey2020 is prefixed\n // with the same `0xed01` multicodec as `did:key`. Strip it.\n if (\n decoded.length === 34 &&\n decoded[0] === ED25519_MULTICODEC_PREFIX[0] &&\n decoded[1] === ED25519_MULTICODEC_PREFIX[1]\n ) {\n return decoded.slice(2);\n }\n // Some legacy docs emit the raw 32 bytes without the multicodec.\n if (decoded.length === 32) return decoded;\n } catch {\n return null;\n }\n return null;\n }\n if (vm.publicKeyJwk && typeof vm.publicKeyJwk === 'object') {\n const jwk = vm.publicKeyJwk as Record<string, unknown>;\n if (jwk.kty !== 'OKP' || jwk.crv !== 'Ed25519') return null;\n if (typeof jwk.x !== 'string') return null;\n let decoded: Uint8Array;\n try {\n decoded = base64UrlDecode(jwk.x);\n } catch {\n return null;\n }\n // Ed25519 public keys are exactly 32 bytes. A JWK with a\n // shorter or longer `x` is malformed; dropping the method is\n // safer than smuggling an invalid key into the WASM engine.\n if (decoded.length !== ED25519_PUBLIC_KEY_LENGTH) {\n return null;\n }\n return decoded;\n }\n return null;\n}\n","/**\n * StatusListCache adapter — sub-phase B.2.\n *\n * Fetches a W3C StatusList2021 Verifiable Credential, base64url-decodes\n * + gunzips the encoded bitstring, and enumerates set bits as a sorted\n * list of revoked indices. Phase C bundles the output as\n * `ContextSpec.revoked: Record<url, number[]>`; the engine's\n * `MapStatusListCache::is_revoked(url, index)` (in `wasm.rs`) checks\n * `indices.contains(&index)` to make a Stage 3 contribution.\n *\n * Architectural choice (deviation from kickoff § 5 B.2): the kickoff\n * sketched a contract where the WASM side does the bit-level lookup\n * on raw bytes. Phase A's `wasm.rs` already shipped with the simpler\n * `Vec<u64>`-of-indices shape, and § 4.1 of Phase B's mandate is\n * \"TS-only.\" The adapter does the bitstring decode + bit enumeration\n * on the TS side; the engine stays unchanged.\n *\n * Bit convention: W3C VC Status List § \"Bitstring expansion algorithm\"\n * — index N is bit `7 - (N % 8)` of byte `floor(N / 8)`, MSB-first.\n */\n\nimport { gunzipSync } from 'node:zlib';\n\nimport { assertSafeHttpsUrl, UnsafeOutboundUrl } from './outbound-url-policy';\nimport { base64UrlDecode } from './util';\n\n// -----------------------------------------------------------------------------\n// Errors.\n// -----------------------------------------------------------------------------\n\nexport class StatusListUnavailable extends Error {\n readonly kind = 'StatusListUnavailable';\n}\n\nexport class MalformedStatusList extends Error {\n readonly kind = 'MalformedStatusList';\n}\n\nexport class StatusListTimeout extends Error {\n readonly kind = 'StatusListTimeout';\n}\n\n// -----------------------------------------------------------------------------\n// Public surface.\n// -----------------------------------------------------------------------------\n\nexport interface StatusListCacheAdapter {\n /**\n * Fetch the status list at `url`, decode it, and return the sorted\n * set of revoked credential indices.\n *\n * @throws {StatusListUnavailable} on transport / non-2xx response.\n * @throws {StatusListTimeout} when the fetch budget is exceeded.\n * @throws {MalformedStatusList} when the VC is unparseable.\n */\n fetch(url: string): Promise<number[]>;\n}\n\ninterface CacheEntry {\n indices: number[];\n fetchedAt: number;\n}\n\nexport interface StatusListCacheOpts {\n fetchTimeoutMs?: number;\n ttlMs?: number;\n fetch?: typeof fetch;\n cache?: Map<string, CacheEntry>;\n now?: () => number;\n}\n\nconst DEFAULT_FETCH_TIMEOUT_MS = 3_000;\nconst DEFAULT_TTL_MS = 30_000;\n\nexport function makeStatusListCache(opts: StatusListCacheOpts = {}): StatusListCacheAdapter {\n const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;\n const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;\n const fetchImpl = opts.fetch ?? fetch;\n const cache = opts.cache ?? new Map<string, CacheEntry>();\n const now = opts.now ?? (() => Date.now());\n\n return {\n async fetch(url: string): Promise<number[]> {\n const cached = cache.get(url);\n if (cached && now() - cached.fetchedAt < ttlMs) {\n return cached.indices;\n }\n const indices = await fetchAndDecode(url, fetchImpl, timeoutMs);\n cache.set(url, { indices, fetchedAt: now() });\n return indices;\n },\n };\n}\n\n// -----------------------------------------------------------------------------\n// Decode pipeline — fetch → JSON → base64url → gunzip → enumerate.\n// -----------------------------------------------------------------------------\n\nasync function fetchAndDecode(\n url: string,\n fetchImpl: typeof fetch,\n timeoutMs: number\n): Promise<number[]> {\n let safeUrl: string;\n try {\n safeUrl = assertSafeHttpsUrl(url, 'status list URL');\n } catch (cause) {\n if (cause instanceof UnsafeOutboundUrl) {\n throw new StatusListUnavailable(cause.message);\n }\n throw cause;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetchImpl(safeUrl, { signal: controller.signal });\n } catch (cause) {\n if (cause instanceof Error && cause.name === 'AbortError') {\n throw new StatusListTimeout(`status list fetch timed out after ${timeoutMs}ms: ${url}`);\n }\n throw new StatusListUnavailable(`status list fetch failed: ${url}: ${String(cause)}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n throw new StatusListUnavailable(`status list HTTP ${response.status} at ${url}`);\n }\n\n let vc: unknown;\n try {\n vc = await response.json();\n } catch (cause) {\n throw new MalformedStatusList(\n `status list response not valid JSON at ${url}: ${String(cause)}`\n );\n }\n\n const encoded = extractEncodedList(vc);\n return enumerateRevokedIndices(encoded);\n}\n\nfunction extractEncodedList(vc: unknown): string {\n if (vc === null || typeof vc !== 'object') {\n throw new MalformedStatusList('status list VC must be a JSON object');\n }\n const obj = vc as Record<string, unknown>;\n const subject = obj.credentialSubject;\n if (subject === null || typeof subject !== 'object') {\n throw new MalformedStatusList('status list VC missing credentialSubject');\n }\n const encoded = (subject as Record<string, unknown>).encodedList;\n if (typeof encoded !== 'string') {\n throw new MalformedStatusList('status list VC missing credentialSubject.encodedList string');\n }\n return encoded;\n}\n\n/**\n * Walk every byte of the decoded bitstring. For each set bit, push the\n * logical index into the result. W3C VC Status List spec: index N is\n * bit `7 - (N % 8)` of byte `floor(N / 8)`, MSB-first.\n */\nfunction enumerateRevokedIndices(encodedList: string): number[] {\n let bytes: Uint8Array;\n try {\n const compressed = base64UrlDecode(encodedList);\n bytes = new Uint8Array(gunzipSync(compressed));\n } catch (cause) {\n throw new MalformedStatusList(`status list bitstring decode failed: ${String(cause)}`);\n }\n\n const indices: number[] = [];\n for (let byteIndex = 0; byteIndex < bytes.length; byteIndex += 1) {\n const byte = bytes[byteIndex];\n if (byte === 0) continue; // fast path — typical bitstring is mostly zeros\n for (let bit = 0; bit < 8; bit += 1) {\n const mask = 1 << (7 - bit); // MSB-first per W3C\n if ((byte & mask) !== 0) {\n indices.push(byteIndex * 8 + bit);\n }\n }\n }\n return indices;\n}\n","/**\n * ReputationOracle adapter — sub-phase B.3.\n *\n * Resolves a per-DID reputation score in `[0.0, 1.0]`. Phase 1 wires\n * an optional HTTP endpoint (Argus). Unavailable / misconfigured /\n * out-of-range responses degrade to a baseline score so infrastructure\n * blips can't silently DOS Adobe-class traffic. The engine's Stage 6\n * compares the returned score against the tenant-configured threshold\n * (Phase B.4 builds the threshold via `PolicyEvaluator`).\n *\n * **Degrade-to-trust** (Phase B § 4.5). Reputation is best-effort;\n * Argus outages do not block traffic. The adapter returns the\n * configured baseline (default 1.0 = \"no signal, treat as trusted\")\n * and logs loudly. The engine's `LowReputation` block fires only\n * when score < threshold from tenant policy; baseline-1.0 ensures\n * no traffic is silently rejected just because Argus went down.\n */\n\n// -----------------------------------------------------------------------------\n// Public surface.\n// -----------------------------------------------------------------------------\n\nexport interface ReputationOracleAdapter {\n /**\n * Return the agent's reputation in `[0.0, 1.0]`. Higher is better.\n *\n * **Does not throw.** Network / parse / range failures degrade to\n * the baseline + log; the engine should never see a thrown error\n * from this adapter.\n */\n score(agentDid: string): Promise<number>;\n}\n\ninterface CacheEntry {\n value: number;\n fetchedAt: number;\n}\n\nexport interface ReputationOracleOpts {\n /**\n * Base URL for the reputation service (Argus). When unset, the\n * adapter returns the baseline without fetching. Phase 1 only —\n * Argus's HTTP surface is post-Adobe; until it lands, every host\n * runs in degrade-to-trust mode.\n */\n argusUrl?: string;\n /** Fetch budget. Default 1500ms — reputation is best-effort, tighter than DID resolution. */\n fetchTimeoutMs?: number;\n /** Cache TTL. Default 10s — reputation churns faster than DIDs. */\n ttlMs?: number;\n /** Injectable fetch. Defaults to global `fetch`. */\n fetch?: typeof fetch;\n /** Returned when Argus is unset / unreachable / malformed. Default 1.0. */\n baselineWhenUnreachable?: number;\n /** Injectable cache for tests. */\n cache?: Map<string, CacheEntry>;\n /** Injectable wall-clock. */\n now?: () => number;\n /** Hook for diagnostics. Phase 1 keeps log volume manageable by sampling. */\n logger?: (msg: string) => void;\n}\n\nconst DEFAULT_FETCH_TIMEOUT_MS = 1_500;\nconst DEFAULT_TTL_MS = 10_000;\nconst DEFAULT_BASELINE = 1.0;\n\nexport function makeReputationOracle(opts: ReputationOracleOpts = {}): ReputationOracleAdapter {\n const argusUrl = opts.argusUrl;\n const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;\n const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;\n const fetchImpl = opts.fetch ?? fetch;\n const baseline = opts.baselineWhenUnreachable ?? DEFAULT_BASELINE;\n const cache = opts.cache ?? new Map<string, CacheEntry>();\n const now = opts.now ?? (() => Date.now());\n const log = opts.logger ?? (() => {});\n\n return {\n async score(agentDid: string): Promise<number> {\n const cached = cache.get(agentDid);\n if (cached && now() - cached.fetchedAt < ttlMs) {\n return cached.value;\n }\n\n if (!argusUrl) {\n // No Argus configured — degrade-to-trust silently (the host\n // logs the config gap once at startup, not per-request).\n return baseline;\n }\n\n const value = await fetchAndValidate(argusUrl, agentDid, fetchImpl, timeoutMs, baseline, log);\n cache.set(agentDid, { value, fetchedAt: now() });\n return value;\n },\n };\n}\n\nasync function fetchAndValidate(\n argusUrl: string,\n agentDid: string,\n fetchImpl: typeof fetch,\n timeoutMs: number,\n baseline: number,\n log: (msg: string) => void\n): Promise<number> {\n const url = `${argusUrl.replace(/\\/$/, '')}/v1/reputation?agent=${encodeURIComponent(agentDid)}`;\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetchImpl(url, { signal: controller.signal });\n } catch (cause) {\n if (cause instanceof Error && cause.name === 'AbortError') {\n log(\n `[reputation-oracle] Argus timed out after ${timeoutMs}ms (${agentDid}); using baseline ${baseline}`\n );\n } else {\n log(\n `[reputation-oracle] Argus fetch failed (${agentDid}): ${String(cause)}; using baseline ${baseline}`\n );\n }\n return baseline;\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n log(\n `[reputation-oracle] Argus HTTP ${response.status} (${agentDid}); using baseline ${baseline}`\n );\n return baseline;\n }\n\n let body: unknown;\n try {\n body = await response.json();\n } catch (cause) {\n log(\n `[reputation-oracle] Argus response not JSON (${agentDid}): ${String(cause)}; using baseline ${baseline}`\n );\n return baseline;\n }\n\n if (body === null || typeof body !== 'object') {\n log(\n `[reputation-oracle] Argus response not an object (${agentDid}); using baseline ${baseline}`\n );\n return baseline;\n }\n const score = (body as Record<string, unknown>).score;\n if (typeof score !== 'number' || !Number.isFinite(score)) {\n log(\n `[reputation-oracle] Argus score not a finite number (${agentDid}): ${String(score)}; using baseline ${baseline}`\n );\n return baseline;\n }\n if (score < 0 || score > 1) {\n log(\n `[reputation-oracle] Argus score out of range (${agentDid}): ${score}; using baseline ${baseline}`\n );\n return baseline;\n }\n return score;\n}\n","/**\n * PolicyEvaluator adapter — sub-phase B.4.\n *\n * Computes the **tenant verdict** on the JS side and hands the engine\n * a constant `Decision` for the WASM `WasmConstantPolicy` to echo as\n * Stage 7's contribution. The engine's cross-stage priority order\n * (locked in D-design § 6 row 4) handles how Stage 7 interacts with\n * Stages 2 / 3 / 4 / 5.\n *\n * **Sync-engine / async-host invariant.** The JS adapter is async (it\n * fetches tenant policy from the Checkpoint dashboard); the engine\n * sees only the resolved `Decision`. Cedar-1 will replace this\n * adapter's implementation without touching the surrounding orchestrator.\n *\n * **Cedar-1 forward-compat.** [`PolicyEvaluatorAdapter`] is the\n * Cedar-swappable interface: `(input) → Decision`. The Phase 1 stub\n * is a reputation-threshold check; Cedar-1 will replace the\n * implementation, not the surface. Don't bake Cedar internals into\n * this seam.\n *\n * **Degrade-to-permit.** Per Phase B § 4.5: when the dashboard policy\n * endpoint is unreachable, fall back to `defaultPolicy` (caller-supplied)\n * or `permit-by-default`. Loud log; no silent block.\n */\n\nimport type { Decision } from '../types';\n\n// -----------------------------------------------------------------------------\n// Public surface — the Cedar-swappable seam.\n// -----------------------------------------------------------------------------\n\n/**\n * Pre-fetched inputs the JS host knows before calling the engine.\n * Phase 1's evaluator only consumes `reputation` + `tenantHost`; later\n * implementations (Cedar-1) may extend.\n */\nexport interface PolicyEvalInput {\n tenantHost: string;\n reputation: number;\n // Layer 2 may add: classification, requestShape, agentDid, etc.\n}\n\nexport interface PolicyEvaluatorAdapter {\n evaluate(input: PolicyEvalInput): Promise<Decision>;\n}\n\n/**\n * Phase 1 tenant-policy shape — just a reputation threshold.\n * Cedar-1 replaces this with a full policy bundle; for now the\n * dashboard exposes one field.\n */\nexport interface TenantPolicy {\n reputationThreshold: number;\n}\n\nexport interface PolicyEvaluatorOpts {\n /**\n * Dashboard policy endpoint. When unset, every tenant resolves to\n * `defaultPolicy` (or permit-by-default if that's also unset).\n */\n dashboardUrl?: string;\n fetchTimeoutMs?: number;\n ttlMs?: number;\n fetch?: typeof fetch;\n /** Used when the dashboard endpoint is unreachable or unconfigured. */\n defaultPolicy?: TenantPolicy;\n cache?: Map<string, CacheEntry>;\n now?: () => number;\n logger?: (msg: string) => void;\n}\n\ninterface CacheEntry {\n policy: TenantPolicy;\n fetchedAt: number;\n}\n\nconst DEFAULT_FETCH_TIMEOUT_MS = 2_000;\nconst DEFAULT_TTL_MS = 60_000;\n/** Permit-by-default — threshold 0 means no reputation gate fires. */\nconst PERMIT_BY_DEFAULT_POLICY: TenantPolicy = { reputationThreshold: 0 };\n\nexport function makePolicyEvaluator(opts: PolicyEvaluatorOpts = {}): PolicyEvaluatorAdapter {\n const dashboardUrl = opts.dashboardUrl;\n const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;\n const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;\n const fetchImpl = opts.fetch ?? fetch;\n const fallbackPolicy = opts.defaultPolicy ?? PERMIT_BY_DEFAULT_POLICY;\n const cache = opts.cache ?? new Map<string, CacheEntry>();\n const now = opts.now ?? (() => Date.now());\n const log = opts.logger ?? (() => {});\n\n return {\n async evaluate(input: PolicyEvalInput): Promise<Decision> {\n const policy = await getOrFetchPolicy(\n input.tenantHost,\n dashboardUrl,\n fetchImpl,\n timeoutMs,\n fallbackPolicy,\n cache,\n ttlMs,\n now,\n log\n );\n return computeDecision(policy, input);\n },\n };\n}\n\n// -----------------------------------------------------------------------------\n// JS-side Decision computation — the Cedar-1 replaceable body.\n// -----------------------------------------------------------------------------\n\nfunction computeDecision(policy: TenantPolicy, input: PolicyEvalInput): Decision {\n if (input.reputation < policy.reputationThreshold) {\n return {\n kind: 'Block',\n reason: {\n kind: 'LowReputation',\n score: input.reputation,\n threshold: policy.reputationThreshold,\n },\n };\n }\n return { kind: 'Permit' };\n}\n\n// -----------------------------------------------------------------------------\n// Policy fetch + cache.\n// -----------------------------------------------------------------------------\n\nasync function getOrFetchPolicy(\n tenantHost: string,\n dashboardUrl: string | undefined,\n fetchImpl: typeof fetch,\n timeoutMs: number,\n fallbackPolicy: TenantPolicy,\n cache: Map<string, CacheEntry>,\n ttlMs: number,\n now: () => number,\n log: (msg: string) => void\n): Promise<TenantPolicy> {\n const cached = cache.get(tenantHost);\n if (cached && now() - cached.fetchedAt < ttlMs) {\n return cached.policy;\n }\n\n // Thundering-herd defense — every degraded path writes the fallback\n // back to the cache. Pre-fix, a dashboard outage meant every\n // request re-attempted the failing fetch and ate up to\n // `fetchTimeoutMs` (2s default). Architect flagged the symmetry\n // gap against ReputationOracle (which caches degraded baselines).\n //\n // When the dashboard recovers, the cached fallback stays in\n // effect until `ttlMs` expires — bounded staleness, acceptable\n // for Phase 1. Negative-TTL knobs (retry sooner on degrade)\n // land as a follow-up if production telemetry justifies them.\n const cacheFallback = (): TenantPolicy => {\n cache.set(tenantHost, { policy: fallbackPolicy, fetchedAt: now() });\n return fallbackPolicy;\n };\n\n if (!dashboardUrl) {\n return cacheFallback();\n }\n\n const url = `${dashboardUrl.replace(/\\/$/, '')}/api/policy?tenant=${encodeURIComponent(tenantHost)}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetchImpl(url, { signal: controller.signal });\n } catch (cause) {\n log(`[policy-evaluator] fetch failed (${tenantHost}): ${String(cause)}; using fallback`);\n return cacheFallback();\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n log(`[policy-evaluator] dashboard HTTP ${response.status} (${tenantHost}); using fallback`);\n return cacheFallback();\n }\n\n let body: unknown;\n try {\n body = await response.json();\n } catch (cause) {\n log(\n `[policy-evaluator] dashboard response not JSON (${tenantHost}): ${String(cause)}; using fallback`\n );\n return cacheFallback();\n }\n\n const parsed = parseTenantPolicy(body);\n if (!parsed) {\n log(`[policy-evaluator] dashboard response malformed (${tenantHost}); using fallback`);\n return cacheFallback();\n }\n\n cache.set(tenantHost, { policy: parsed, fetchedAt: now() });\n return parsed;\n}\n\nfunction parseTenantPolicy(raw: unknown): TenantPolicy | null {\n if (raw === null || typeof raw !== 'object') return null;\n const threshold = (raw as Record<string, unknown>).reputationThreshold;\n if (\n typeof threshold !== 'number' ||\n !Number.isFinite(threshold) ||\n threshold < 0 ||\n threshold > 1\n ) {\n return null;\n }\n return { reputationThreshold: threshold };\n}\n","/**\n * Clock adapter — sub-phase B.5.\n *\n * Provides the Unix-seconds timestamp the engine's `Clock` trait needs\n * for Stage 4 expiration checks. Trivial; the trait shape exists so\n * tests can inject a frozen clock (and so the engine's sync-trait\n * surface is satisfied without a JS callback crossing the WASM\n * boundary — `ContextSpec.nowUnix` carries the value).\n */\n\nexport interface ClockAdapter {\n nowUnix(): number;\n}\n\nexport function makeSystemClock(): ClockAdapter {\n return { nowUnix: () => Math.floor(Date.now() / 1000) };\n}\n\nexport function makeFixedClock(unixSeconds: number): ClockAdapter {\n return { nowUnix: () => unixSeconds };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/engine/adapters/outbound-url-policy.ts","../src/engine/adapters/util.ts","../src/engine/adapters/did-resolver.ts","../src/engine/adapters/status-list-cache.ts","../src/engine/adapters/reputation-oracle.ts","../src/engine/adapters/policy-evaluator.ts","../src/engine/adapters/clock.ts"],"names":["DEFAULT_FETCH_TIMEOUT_MS","DEFAULT_TTL_MS"],"mappings":"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","file":"adapters.mjs","sourcesContent":["/**\n * Shared egress guard for verifier-owned outbound fetches.\n *\n * MCP-I payloads are attacker controlled until the signature verifies. Any\n * host-side fetch derived from that payload must reject obvious local/private\n * targets before invoking `fetch`.\n */\n\nconst BLOCKED_HOSTNAMES = new Set(['localhost', 'metadata', 'metadata.google.internal']);\n\nexport class UnsafeOutboundUrl extends Error {\n readonly kind = 'UnsafeOutboundUrl';\n}\n\nexport function assertSafeHttpsUrl(rawUrl: string, label = 'outbound URL'): string {\n let parsed: URL;\n try {\n parsed = new URL(rawUrl);\n } catch {\n throw new UnsafeOutboundUrl(`${label} must be a valid URL: ${rawUrl}`);\n }\n\n if (parsed.protocol !== 'https:') {\n throw new UnsafeOutboundUrl(`${label} must use https: ${rawUrl}`);\n }\n if (parsed.username || parsed.password) {\n throw new UnsafeOutboundUrl(`${label} must not contain credentials: ${rawUrl}`);\n }\n\n const hostname = normalizeHostname(parsed.hostname);\n if (!hostname || isBlockedHostname(hostname)) {\n throw new UnsafeOutboundUrl(`${label} targets a local or private host: ${rawUrl}`);\n }\n\n return rawUrl;\n}\n\nfunction normalizeHostname(hostname: string): string {\n let normalized = hostname.trim().toLowerCase();\n if (normalized.startsWith('[') && normalized.endsWith(']')) {\n normalized = normalized.slice(1, -1);\n }\n while (normalized.endsWith('.')) {\n normalized = normalized.slice(0, -1);\n }\n return normalized;\n}\n\nfunction isBlockedHostname(hostname: string): boolean {\n if (BLOCKED_HOSTNAMES.has(hostname) || hostname.endsWith('.localhost')) {\n return true;\n }\n\n const ipv4 = parseIpv4(hostname);\n if (ipv4) {\n return isBlockedIpv4(ipv4);\n }\n\n return isBlockedIpv6(hostname);\n}\n\nfunction parseIpv4(hostname: string): [number, number, number, number] | null {\n const parts = hostname.split('.');\n if (parts.length !== 4) return null;\n\n const octets = parts.map((part) => {\n if (!/^\\d{1,3}$/.test(part)) return Number.NaN;\n const value = Number(part);\n return value >= 0 && value <= 255 ? value : Number.NaN;\n });\n\n if (octets.some(Number.isNaN)) return null;\n return octets as [number, number, number, number];\n}\n\nfunction isBlockedIpv4([a, b]: [number, number, number, number]): boolean {\n return (\n a === 0 ||\n a === 10 ||\n a === 127 ||\n (a === 100 && b >= 64 && b <= 127) ||\n (a === 169 && b === 254) ||\n (a === 172 && b >= 16 && b <= 31) ||\n (a === 192 && b === 168) ||\n (a === 198 && (b === 18 || b === 19)) ||\n a >= 224\n );\n}\n\nfunction isBlockedIpv6(hostname: string): boolean {\n if (!hostname.includes(':')) return false;\n\n const ipv4Mapped = hostname.match(/(?:^|:)ffff:(\\d{1,3}(?:\\.\\d{1,3}){3})$/);\n if (ipv4Mapped) {\n const ipv4 = parseIpv4(ipv4Mapped[1]);\n return ipv4 ? isBlockedIpv4(ipv4) : true;\n }\n\n if (hostname === '::' || hostname === '::1' || hostname === '0:0:0:0:0:0:0:1') {\n return true;\n }\n\n const firstSegment = Number.parseInt(hostname.split(':')[0] || '0', 16);\n if (Number.isNaN(firstSegment)) return true;\n\n return (\n (firstSegment & 0xfe00) === 0xfc00 || // unique local fc00::/7\n (firstSegment & 0xffc0) === 0xfe80 || // link-local fe80::/10\n (firstSegment & 0xff00) === 0xff00 // multicast ff00::/8\n );\n}\n","/**\n * Shared utilities for the Phase B adapters.\n *\n * Anything used by more than one adapter belongs here so a future\n * bug fix touches one site, not N.\n */\n\n/**\n * base64url decode without external deps. Pads if necessary,\n * substitutes URL-safe chars, returns the raw bytes as `Uint8Array`.\n * RFC 4648 § 5 — characters `-` and `_` substitute for `+` and `/`;\n * padding `=` is optional and stripped in URL contexts.\n */\nexport function base64UrlDecode(input: string): Uint8Array {\n const padded = input.replace(/-/g, '+').replace(/_/g, '/');\n const padding = padded.length % 4 === 0 ? '' : '='.repeat(4 - (padded.length % 4));\n return new Uint8Array(Buffer.from(padded + padding, 'base64'));\n}\n","/**\n * DidResolver adapter — sub-phase B.1.\n *\n * Resolves `did:key:*` (in-memory multibase decode) and `did:web:*`\n * (HTTPS fetch of `.well-known/did.json`) into the engine's\n * `DidDocument` shape. The async half does any required I/O; the\n * adapter's output is plain data that the host wrapper bundles into\n * `ContextSpec.didDocs` before calling `engineVerify`.\n *\n * Phase 1 supports only Ed25519 verification methods (the engine's\n * `KeyType` is `#[non_exhaustive]` with `Ed25519` as its single\n * variant). Non-Ed25519 methods on a resolved doc are silently\n * filtered out — the engine wouldn't accept them as a valid Stage 2\n * key match anyway.\n *\n * **`kid` for `did:key`**: the verification-method id is\n * `<did>#<multibase>` per mcp-i-core PR #16. **NOT** `<did>#keys-1`.\n * H-1's `stage2_did_key_fragment_resolution` test pins this.\n */\n\nimport { base58btc } from 'multiformats/bases/base58';\n\nimport type { DidDocument, KeyType, VerificationMethod } from '../types';\nimport { assertSafeHttpsUrl, UnsafeOutboundUrl } from './outbound-url-policy';\nimport { base64UrlDecode } from './util';\n\nconst ED25519_PUBLIC_KEY_LENGTH = 32;\n\n// -----------------------------------------------------------------------------\n// Errors — the adapter throws these; the host wrapper translates to verdicts.\n// -----------------------------------------------------------------------------\n\nexport class MalformedDid extends Error {\n readonly kind = 'MalformedDid';\n}\n\nexport class UnsupportedKeyType extends Error {\n readonly kind = 'UnsupportedKeyType';\n}\n\nexport class DidNotFound extends Error {\n readonly kind = 'DidNotFound';\n}\n\nexport class DidResolverTimeout extends Error {\n readonly kind = 'DidResolverTimeout';\n}\n\nexport class DidResolverError extends Error {\n readonly kind = 'DidResolverError';\n}\n\nexport class UnsupportedDidMethod extends Error {\n readonly kind = 'UnsupportedDidMethod';\n}\n\n// -----------------------------------------------------------------------------\n// Public surface — `DidResolverAdapter` is the seam Phase C composes.\n// -----------------------------------------------------------------------------\n\nexport interface DidResolverAdapter {\n resolve(did: string): Promise<DidDocument>;\n}\n\ninterface CacheEntry<T> {\n value: T;\n fetchedAt: number;\n}\n\nexport interface DidResolverOpts {\n /** AbortController timeout for did:web fetches. Default 3000ms. */\n fetchTimeoutMs?: number;\n /** TTL for the in-memory cache. Default 5 minutes. */\n ttlMs?: number;\n /** Injectable fetch — defaults to global `fetch` (Node 18+). */\n fetch?: typeof fetch;\n /**\n * Injectable cache — defaults to a fresh `Map` per adapter instance.\n * Tests pass a shared cache to assert miss/hit behaviour.\n */\n cache?: Map<string, CacheEntry<DidDocument>>;\n /** Injectable wall-clock — defaults to `Date.now()`. Tests use a stub. */\n now?: () => number;\n}\n\nconst ED25519_MULTICODEC_PREFIX = [0xed, 0x01] as const;\nconst DEFAULT_FETCH_TIMEOUT_MS = 3_000;\nconst DEFAULT_TTL_MS = 5 * 60_000;\n\nexport function makeDidResolver(opts: DidResolverOpts = {}): DidResolverAdapter {\n const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;\n const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;\n const fetchImpl = opts.fetch ?? fetch;\n const cache = opts.cache ?? new Map<string, CacheEntry<DidDocument>>();\n const now = opts.now ?? (() => Date.now());\n\n return {\n async resolve(did: string): Promise<DidDocument> {\n const cached = cache.get(did);\n if (cached && now() - cached.fetchedAt < ttlMs) {\n return cached.value;\n }\n // SSRF defense — Phase 1 supports `did:key` + `did:web` only.\n // The pre-fix code routed every non-`did:key:` input into\n // `resolveDidWeb`, which blindly stripped the first 8 chars\n // and used the remainder as a URL host. `did:ion:abc123` →\n // `https://n:abc123/.well-known/did.json` (probe). An\n // attacker submitting arbitrary DID strings could construct\n // arbitrary HTTPS URLs against the host's network namespace\n // — an SSRF probe surface against internal services.\n // Explicit prefix matching closes the surface.\n if (did.startsWith('did:key:')) {\n const doc = decodeDidKey(did);\n cache.set(did, { value: doc, fetchedAt: now() });\n return doc;\n }\n if (did.startsWith('did:web:')) {\n const doc = await resolveDidWeb(did, fetchImpl, timeoutMs);\n cache.set(did, { value: doc, fetchedAt: now() });\n return doc;\n }\n throw new UnsupportedDidMethod(`Phase 1 supports did:key and did:web only; got: ${did}`);\n },\n };\n}\n\n// -----------------------------------------------------------------------------\n// did:key — in-memory multibase decode.\n// -----------------------------------------------------------------------------\n\nexport function decodeDidKey(did: string): DidDocument {\n if (!did.startsWith('did:key:')) {\n throw new MalformedDid(`expected did:key prefix, got: ${did}`);\n }\n const multibaseValue = did.slice('did:key:'.length);\n if (!multibaseValue.startsWith('z')) {\n throw new MalformedDid(\n `did:key expects base58btc (multibase 'z' prefix); got: ${multibaseValue[0] ?? '<empty>'}`\n );\n }\n\n let decoded: Uint8Array;\n try {\n decoded = base58btc.decode(multibaseValue);\n } catch (cause) {\n throw new MalformedDid(`did:key multibase decode failed: ${String(cause)}`);\n }\n\n if (\n decoded.length < 2 ||\n decoded[0] !== ED25519_MULTICODEC_PREFIX[0] ||\n decoded[1] !== ED25519_MULTICODEC_PREFIX[1]\n ) {\n const prefixHex =\n decoded.length >= 2\n ? `0x${decoded[0].toString(16).padStart(2, '0')}${decoded[1].toString(16).padStart(2, '0')}`\n : '<too short>';\n throw new UnsupportedKeyType(\n `did:key expects Ed25519 multicodec 0xed01; got ${prefixHex} (only Ed25519 supported in Phase 1)`\n );\n }\n\n const publicKey = decoded.slice(2);\n if (publicKey.length !== 32) {\n throw new MalformedDid(`did:key Ed25519 public key must be 32 bytes; got ${publicKey.length}`);\n }\n\n const vm: VerificationMethod = {\n id: `${did}#${multibaseValue}`, // multibase as fragment — mcp-i-core PR #16\n keyType: 'Ed25519' satisfies KeyType,\n publicKeyBytes: Array.from(publicKey),\n };\n return {\n id: did,\n verificationMethods: [vm],\n };\n}\n\n// -----------------------------------------------------------------------------\n// did:web — HTTPS fetch + W3C → engine shape mapping.\n// -----------------------------------------------------------------------------\n\nasync function resolveDidWeb(\n did: string,\n fetchImpl: typeof fetch,\n timeoutMs: number\n): Promise<DidDocument> {\n const transformedUrl = didWebToUrl(did);\n let url: string;\n try {\n url = assertSafeHttpsUrl(transformedUrl, 'did:web resolution URL');\n } catch (cause) {\n if (cause instanceof UnsafeOutboundUrl) {\n throw new DidResolverError(cause.message);\n }\n throw cause;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetchImpl(url, { signal: controller.signal });\n } catch (cause) {\n if (cause instanceof Error && cause.name === 'AbortError') {\n throw new DidResolverTimeout(`did:web fetch timed out after ${timeoutMs}ms: ${url}`);\n }\n throw new DidResolverError(`did:web fetch failed: ${url}: ${String(cause)}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (response.status === 404) {\n throw new DidNotFound(`no DID document at ${url}`);\n }\n if (!response.ok) {\n throw new DidResolverError(`did:web HTTP ${response.status} at ${url}`);\n }\n\n let raw: unknown;\n try {\n raw = await response.json();\n } catch (cause) {\n throw new DidResolverError(`did:web response not valid JSON at ${url}: ${String(cause)}`);\n }\n return mapW3CDocToEngineShape(raw, did);\n}\n\n/**\n * `did:web:example.com` → `https://example.com/.well-known/did.json`.\n * `did:web:example.com:user:alice` → `https://example.com/user/alice/did.json`.\n * `did:web:localhost%3A8080` transforms to\n * `https://localhost:8080/.well-known/did.json`, then the egress guard rejects\n * it before fetch because localhost/private targets are never safe verifier I/O.\n *\n * Per W3C did-method-web § 3.2 \"DID-to-HTTPS Transformation\": split on\n * `:`, then `decodeURIComponent` each segment so percent-encoded\n * characters (ports, paths-with-colons, etc.) are unescaped before\n * URL construction. Bugbot caught the missing decode pass on the\n * initial B.1 drop — without it, `did:web:host%3Aport` resolved to\n * `https://host%3Aport/...` which never reaches the right server.\n */\nfunction didWebToUrl(did: string): string {\n const path = did.slice('did:web:'.length);\n if (!path) {\n throw new MalformedDid(`did:web with empty path: ${did}`);\n }\n const parts = path.split(':').map((segment) => {\n try {\n return decodeURIComponent(segment);\n } catch {\n throw new MalformedDid(`did:web segment contains invalid percent-encoding: ${segment}`);\n }\n });\n if (parts.length === 1) {\n return `https://${parts[0]}/.well-known/did.json`;\n }\n return `https://${parts[0]}/${parts.slice(1).join('/')}/did.json`;\n}\n\n/**\n * Convert a W3C DID Core JSON document into the engine's shape.\n *\n * Phase 1 only accepts Ed25519 verification methods — the engine's\n * `KeyType::Ed25519` is the only currently-supported variant. Non-\n * Ed25519 methods are silently filtered (the engine wouldn't accept\n * them as a valid Stage 2 `kid` match).\n *\n * W3C uses `verificationMethod` (singular array name); the engine\n * uses `verificationMethods` (plural) — the rename happens here.\n */\nfunction mapW3CDocToEngineShape(raw: unknown, requestedDid: string): DidDocument {\n if (raw === null || typeof raw !== 'object') {\n throw new DidResolverError(`did:web response must be a JSON object`);\n }\n const doc = raw as Record<string, unknown>;\n const id = typeof doc.id === 'string' ? doc.id : requestedDid;\n\n const w3cMethods = Array.isArray(doc.verificationMethod) ? doc.verificationMethod : [];\n const verificationMethods: VerificationMethod[] = [];\n for (const entry of w3cMethods) {\n if (entry === null || typeof entry !== 'object') continue;\n const vm = entry as Record<string, unknown>;\n if (!isEd25519Type(vm.type)) continue;\n const vmId = typeof vm.id === 'string' ? vm.id : undefined;\n if (!vmId) continue;\n const pubKey = extractEd25519PublicKey(vm);\n if (!pubKey) continue;\n verificationMethods.push({\n id: vmId,\n keyType: 'Ed25519',\n publicKeyBytes: Array.from(pubKey),\n });\n }\n\n return { id, verificationMethods };\n}\n\nfunction isEd25519Type(type: unknown): boolean {\n return type === 'Ed25519VerificationKey2020' || type === 'Ed25519VerificationKey2018';\n}\n\n/**\n * Extract the 32-byte Ed25519 public key from a W3C verificationMethod\n * entry. Accepts either `publicKeyMultibase` (Ed25519VerificationKey2020)\n * or `publicKeyJwk` with `kty: OKP, crv: Ed25519, x: <base64url>`.\n *\n * Returns `null` if extraction fails; the caller drops the method.\n */\nfunction extractEd25519PublicKey(vm: Record<string, unknown>): Uint8Array | null {\n if (typeof vm.publicKeyMultibase === 'string') {\n const mb = vm.publicKeyMultibase;\n if (!mb.startsWith('z')) return null;\n try {\n const decoded = base58btc.decode(mb);\n // `publicKeyMultibase` on Ed25519VerificationKey2020 is prefixed\n // with the same `0xed01` multicodec as `did:key`. Strip it.\n if (\n decoded.length === 34 &&\n decoded[0] === ED25519_MULTICODEC_PREFIX[0] &&\n decoded[1] === ED25519_MULTICODEC_PREFIX[1]\n ) {\n return decoded.slice(2);\n }\n // Some legacy docs emit the raw 32 bytes without the multicodec.\n if (decoded.length === 32) return decoded;\n } catch {\n return null;\n }\n return null;\n }\n if (vm.publicKeyJwk && typeof vm.publicKeyJwk === 'object') {\n const jwk = vm.publicKeyJwk as Record<string, unknown>;\n if (jwk.kty !== 'OKP' || jwk.crv !== 'Ed25519') return null;\n if (typeof jwk.x !== 'string') return null;\n let decoded: Uint8Array;\n try {\n decoded = base64UrlDecode(jwk.x);\n } catch {\n return null;\n }\n // Ed25519 public keys are exactly 32 bytes. A JWK with a\n // shorter or longer `x` is malformed; dropping the method is\n // safer than smuggling an invalid key into the WASM engine.\n if (decoded.length !== ED25519_PUBLIC_KEY_LENGTH) {\n return null;\n }\n return decoded;\n }\n return null;\n}\n","/**\n * StatusListCache adapter — sub-phase B.2.\n *\n * Fetches a W3C StatusList2021 Verifiable Credential, base64url-decodes\n * + gunzips the encoded bitstring, and enumerates set bits as a sorted\n * list of revoked indices. Phase C bundles the output as\n * `ContextSpec.revoked: Record<url, number[]>`; the engine's\n * `MapStatusListCache::is_revoked(url, index)` (in `wasm.rs`) checks\n * `indices.contains(&index)` to make a Stage 3 contribution.\n *\n * Architectural choice (deviation from kickoff § 5 B.2): the kickoff\n * sketched a contract where the WASM side does the bit-level lookup\n * on raw bytes. Phase A's `wasm.rs` already shipped with the simpler\n * `Vec<u64>`-of-indices shape, and § 4.1 of Phase B's mandate is\n * \"TS-only.\" The adapter does the bitstring decode + bit enumeration\n * on the TS side; the engine stays unchanged.\n *\n * Bit convention: W3C VC Status List § \"Bitstring expansion algorithm\"\n * — index N is bit `7 - (N % 8)` of byte `floor(N / 8)`, MSB-first.\n */\n\nimport { gunzipSync } from 'node:zlib';\n\nimport { assertSafeHttpsUrl, UnsafeOutboundUrl } from './outbound-url-policy';\nimport { base64UrlDecode } from './util';\n\n// -----------------------------------------------------------------------------\n// Errors.\n// -----------------------------------------------------------------------------\n\nexport class StatusListUnavailable extends Error {\n readonly kind = 'StatusListUnavailable';\n}\n\nexport class MalformedStatusList extends Error {\n readonly kind = 'MalformedStatusList';\n}\n\nexport class StatusListTimeout extends Error {\n readonly kind = 'StatusListTimeout';\n}\n\n// -----------------------------------------------------------------------------\n// Public surface.\n// -----------------------------------------------------------------------------\n\nexport interface StatusListCacheAdapter {\n /**\n * Fetch the status list at `url`, decode it, and return the sorted\n * set of revoked credential indices.\n *\n * @throws {StatusListUnavailable} on transport / non-2xx response.\n * @throws {StatusListTimeout} when the fetch budget is exceeded.\n * @throws {MalformedStatusList} when the VC is unparseable.\n */\n fetch(url: string): Promise<number[]>;\n}\n\ninterface CacheEntry {\n indices: number[];\n fetchedAt: number;\n}\n\nexport interface StatusListCacheOpts {\n fetchTimeoutMs?: number;\n ttlMs?: number;\n fetch?: typeof fetch;\n cache?: Map<string, CacheEntry>;\n now?: () => number;\n}\n\nconst DEFAULT_FETCH_TIMEOUT_MS = 3_000;\nconst DEFAULT_TTL_MS = 30_000;\n\nexport function makeStatusListCache(opts: StatusListCacheOpts = {}): StatusListCacheAdapter {\n const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;\n const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;\n const fetchImpl = opts.fetch ?? fetch;\n const cache = opts.cache ?? new Map<string, CacheEntry>();\n const now = opts.now ?? (() => Date.now());\n\n return {\n async fetch(url: string): Promise<number[]> {\n const cached = cache.get(url);\n if (cached && now() - cached.fetchedAt < ttlMs) {\n return cached.indices;\n }\n const indices = await fetchAndDecode(url, fetchImpl, timeoutMs);\n cache.set(url, { indices, fetchedAt: now() });\n return indices;\n },\n };\n}\n\n// -----------------------------------------------------------------------------\n// Decode pipeline — fetch → JSON → base64url → gunzip → enumerate.\n// -----------------------------------------------------------------------------\n\nasync function fetchAndDecode(\n url: string,\n fetchImpl: typeof fetch,\n timeoutMs: number\n): Promise<number[]> {\n let safeUrl: string;\n try {\n safeUrl = assertSafeHttpsUrl(url, 'status list URL');\n } catch (cause) {\n if (cause instanceof UnsafeOutboundUrl) {\n throw new StatusListUnavailable(cause.message);\n }\n throw cause;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetchImpl(safeUrl, { signal: controller.signal });\n } catch (cause) {\n if (cause instanceof Error && cause.name === 'AbortError') {\n throw new StatusListTimeout(`status list fetch timed out after ${timeoutMs}ms: ${url}`);\n }\n throw new StatusListUnavailable(`status list fetch failed: ${url}: ${String(cause)}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n throw new StatusListUnavailable(`status list HTTP ${response.status} at ${url}`);\n }\n\n let vc: unknown;\n try {\n vc = await response.json();\n } catch (cause) {\n throw new MalformedStatusList(\n `status list response not valid JSON at ${url}: ${String(cause)}`\n );\n }\n\n const encoded = extractEncodedList(vc);\n return enumerateRevokedIndices(encoded);\n}\n\nfunction extractEncodedList(vc: unknown): string {\n if (vc === null || typeof vc !== 'object') {\n throw new MalformedStatusList('status list VC must be a JSON object');\n }\n const obj = vc as Record<string, unknown>;\n const subject = obj.credentialSubject;\n if (subject === null || typeof subject !== 'object') {\n throw new MalformedStatusList('status list VC missing credentialSubject');\n }\n const encoded = (subject as Record<string, unknown>).encodedList;\n if (typeof encoded !== 'string') {\n throw new MalformedStatusList('status list VC missing credentialSubject.encodedList string');\n }\n return encoded;\n}\n\n/**\n * Walk every byte of the decoded bitstring. For each set bit, push the\n * logical index into the result. W3C VC Status List spec: index N is\n * bit `7 - (N % 8)` of byte `floor(N / 8)`, MSB-first.\n */\nfunction enumerateRevokedIndices(encodedList: string): number[] {\n let bytes: Uint8Array;\n try {\n const compressed = base64UrlDecode(encodedList);\n bytes = new Uint8Array(gunzipSync(compressed));\n } catch (cause) {\n throw new MalformedStatusList(`status list bitstring decode failed: ${String(cause)}`);\n }\n\n const indices: number[] = [];\n for (let byteIndex = 0; byteIndex < bytes.length; byteIndex += 1) {\n const byte = bytes[byteIndex];\n if (byte === 0) continue; // fast path — typical bitstring is mostly zeros\n for (let bit = 0; bit < 8; bit += 1) {\n const mask = 1 << (7 - bit); // MSB-first per W3C\n if ((byte & mask) !== 0) {\n indices.push(byteIndex * 8 + bit);\n }\n }\n }\n return indices;\n}\n","/**\n * ReputationOracle adapter — sub-phase B.3.\n *\n * Resolves a per-DID reputation score in `[0.0, 1.0]`. Phase 1 wires\n * an optional HTTP endpoint (Argus). Unavailable / misconfigured /\n * out-of-range responses degrade to a baseline score so infrastructure\n * blips can't silently DOS Adobe-class traffic. The engine's Stage 6\n * compares the returned score against the tenant-configured threshold\n * (Phase B.4 builds the threshold via `PolicyEvaluator`).\n *\n * **Degrade-to-trust** (Phase B § 4.5). Reputation is best-effort;\n * Argus outages do not block traffic. The adapter returns the\n * configured baseline (default 1.0 = \"no signal, treat as trusted\")\n * and logs loudly. The engine's `LowReputation` block fires only\n * when score < threshold from tenant policy; baseline-1.0 ensures\n * no traffic is silently rejected just because Argus went down.\n */\n\n// -----------------------------------------------------------------------------\n// Public surface.\n// -----------------------------------------------------------------------------\n\nexport interface ReputationOracleAdapter {\n /**\n * Return the agent's reputation in `[0.0, 1.0]`. Higher is better.\n *\n * **Does not throw.** Network / parse / range failures degrade to\n * the baseline + log; the engine should never see a thrown error\n * from this adapter.\n */\n score(agentDid: string): Promise<number>;\n}\n\ninterface CacheEntry {\n value: number;\n fetchedAt: number;\n}\n\nexport interface ReputationOracleOpts {\n /**\n * Base URL for the reputation service (Argus). When unset, the\n * adapter returns the baseline without fetching. Phase 1 only —\n * Argus's HTTP surface is post-Adobe; until it lands, every host\n * runs in degrade-to-trust mode.\n */\n argusUrl?: string;\n /** Fetch budget. Default 1500ms — reputation is best-effort, tighter than DID resolution. */\n fetchTimeoutMs?: number;\n /** Cache TTL. Default 10s — reputation churns faster than DIDs. */\n ttlMs?: number;\n /** Injectable fetch. Defaults to global `fetch`. */\n fetch?: typeof fetch;\n /** Returned when Argus is unset / unreachable / malformed. Default 1.0. */\n baselineWhenUnreachable?: number;\n /** Injectable cache for tests. */\n cache?: Map<string, CacheEntry>;\n /** Injectable wall-clock. */\n now?: () => number;\n /** Hook for diagnostics. Phase 1 keeps log volume manageable by sampling. */\n logger?: (msg: string) => void;\n}\n\nconst DEFAULT_FETCH_TIMEOUT_MS = 1_500;\nconst DEFAULT_TTL_MS = 10_000;\nconst DEFAULT_BASELINE = 1.0;\n\nexport function makeReputationOracle(opts: ReputationOracleOpts = {}): ReputationOracleAdapter {\n const argusUrl = opts.argusUrl;\n const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;\n const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;\n const fetchImpl = opts.fetch ?? fetch;\n const baseline = opts.baselineWhenUnreachable ?? DEFAULT_BASELINE;\n const cache = opts.cache ?? new Map<string, CacheEntry>();\n const now = opts.now ?? (() => Date.now());\n const log = opts.logger ?? (() => {});\n\n return {\n async score(agentDid: string): Promise<number> {\n const cached = cache.get(agentDid);\n if (cached && now() - cached.fetchedAt < ttlMs) {\n return cached.value;\n }\n\n if (!argusUrl) {\n // No Argus configured — degrade-to-trust silently (the host\n // logs the config gap once at startup, not per-request).\n return baseline;\n }\n\n const value = await fetchAndValidate(argusUrl, agentDid, fetchImpl, timeoutMs, baseline, log);\n cache.set(agentDid, { value, fetchedAt: now() });\n return value;\n },\n };\n}\n\nasync function fetchAndValidate(\n argusUrl: string,\n agentDid: string,\n fetchImpl: typeof fetch,\n timeoutMs: number,\n baseline: number,\n log: (msg: string) => void\n): Promise<number> {\n const url = `${argusUrl.replace(/\\/$/, '')}/v1/reputation?agent=${encodeURIComponent(agentDid)}`;\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetchImpl(url, { signal: controller.signal });\n } catch (cause) {\n if (cause instanceof Error && cause.name === 'AbortError') {\n log(\n `[reputation-oracle] Argus timed out after ${timeoutMs}ms (${agentDid}); using baseline ${baseline}`\n );\n } else {\n log(\n `[reputation-oracle] Argus fetch failed (${agentDid}): ${String(cause)}; using baseline ${baseline}`\n );\n }\n return baseline;\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n log(\n `[reputation-oracle] Argus HTTP ${response.status} (${agentDid}); using baseline ${baseline}`\n );\n return baseline;\n }\n\n let body: unknown;\n try {\n body = await response.json();\n } catch (cause) {\n log(\n `[reputation-oracle] Argus response not JSON (${agentDid}): ${String(cause)}; using baseline ${baseline}`\n );\n return baseline;\n }\n\n if (body === null || typeof body !== 'object') {\n log(\n `[reputation-oracle] Argus response not an object (${agentDid}); using baseline ${baseline}`\n );\n return baseline;\n }\n const score = (body as Record<string, unknown>).score;\n if (typeof score !== 'number' || !Number.isFinite(score)) {\n log(\n `[reputation-oracle] Argus score not a finite number (${agentDid}): ${String(score)}; using baseline ${baseline}`\n );\n return baseline;\n }\n if (score < 0 || score > 1) {\n log(\n `[reputation-oracle] Argus score out of range (${agentDid}): ${score}; using baseline ${baseline}`\n );\n return baseline;\n }\n return score;\n}\n","/**\n * PolicyEvaluator adapter — sub-phase B.4.\n *\n * Computes the **tenant verdict** on the JS side and hands the engine\n * a constant `Decision` for the WASM `WasmConstantPolicy` to echo as\n * Stage 7's contribution. The engine's cross-stage priority order\n * (locked in D-design § 6 row 4) handles how Stage 7 interacts with\n * Stages 2 / 3 / 4 / 5.\n *\n * **Sync-engine / async-host invariant.** The JS adapter is async (it\n * fetches tenant policy from the Checkpoint dashboard); the engine\n * sees only the resolved `Decision`. Cedar-1 will replace this\n * adapter's implementation without touching the surrounding orchestrator.\n *\n * **Cedar-1 forward-compat.** [`PolicyEvaluatorAdapter`] is the\n * Cedar-swappable interface: `(input) → Decision`. The Phase 1 stub\n * is a reputation-threshold check; Cedar-1 will replace the\n * implementation, not the surface. Don't bake Cedar internals into\n * this seam.\n *\n * **Degrade-to-permit.** Per Phase B § 4.5: when the dashboard policy\n * endpoint is unreachable, fall back to `defaultPolicy` (caller-supplied)\n * or `permit-by-default`. Loud log; no silent block.\n */\n\nimport type { Decision } from '../types';\n\n// -----------------------------------------------------------------------------\n// Public surface — the Cedar-swappable seam.\n// -----------------------------------------------------------------------------\n\n/**\n * Pre-fetched inputs the JS host knows before calling the engine.\n * Phase 1's evaluator only consumes `reputation` + `tenantHost`; later\n * implementations (Cedar-1) may extend.\n */\nexport interface PolicyEvalInput {\n tenantHost: string;\n reputation: number;\n // Layer 2 may add: classification, requestShape, agentDid, etc.\n}\n\nexport interface PolicyEvaluatorAdapter {\n evaluate(input: PolicyEvalInput): Promise<Decision>;\n}\n\n/**\n * Phase 1 tenant-policy shape — just a reputation threshold.\n * Cedar-1 replaces this with a full policy bundle; for now the\n * dashboard exposes one field.\n */\nexport interface TenantPolicy {\n reputationThreshold: number;\n}\n\nexport interface PolicyEvaluatorOpts {\n /**\n * Dashboard policy endpoint. When unset, every tenant resolves to\n * `defaultPolicy` (or permit-by-default if that's also unset).\n */\n dashboardUrl?: string;\n fetchTimeoutMs?: number;\n ttlMs?: number;\n fetch?: typeof fetch;\n /** Used when the dashboard endpoint is unreachable or unconfigured. */\n defaultPolicy?: TenantPolicy;\n cache?: Map<string, CacheEntry>;\n now?: () => number;\n logger?: (msg: string) => void;\n}\n\ninterface CacheEntry {\n policy: TenantPolicy;\n fetchedAt: number;\n}\n\nconst DEFAULT_FETCH_TIMEOUT_MS = 2_000;\nconst DEFAULT_TTL_MS = 60_000;\n/** Permit-by-default — threshold 0 means no reputation gate fires. */\nconst PERMIT_BY_DEFAULT_POLICY: TenantPolicy = { reputationThreshold: 0 };\n\nexport function makePolicyEvaluator(opts: PolicyEvaluatorOpts = {}): PolicyEvaluatorAdapter {\n const dashboardUrl = opts.dashboardUrl;\n const timeoutMs = opts.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;\n const ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;\n const fetchImpl = opts.fetch ?? fetch;\n const fallbackPolicy = opts.defaultPolicy ?? PERMIT_BY_DEFAULT_POLICY;\n const cache = opts.cache ?? new Map<string, CacheEntry>();\n const now = opts.now ?? (() => Date.now());\n const log = opts.logger ?? (() => {});\n\n return {\n async evaluate(input: PolicyEvalInput): Promise<Decision> {\n const policy = await getOrFetchPolicy(\n input.tenantHost,\n dashboardUrl,\n fetchImpl,\n timeoutMs,\n fallbackPolicy,\n cache,\n ttlMs,\n now,\n log\n );\n return computeDecision(policy, input);\n },\n };\n}\n\n// -----------------------------------------------------------------------------\n// JS-side Decision computation — the Cedar-1 replaceable body.\n// -----------------------------------------------------------------------------\n\nfunction computeDecision(policy: TenantPolicy, input: PolicyEvalInput): Decision {\n if (input.reputation < policy.reputationThreshold) {\n return {\n kind: 'Block',\n reason: {\n kind: 'LowReputation',\n score: input.reputation,\n threshold: policy.reputationThreshold,\n },\n };\n }\n return { kind: 'Permit' };\n}\n\n// -----------------------------------------------------------------------------\n// Policy fetch + cache.\n// -----------------------------------------------------------------------------\n\nasync function getOrFetchPolicy(\n tenantHost: string,\n dashboardUrl: string | undefined,\n fetchImpl: typeof fetch,\n timeoutMs: number,\n fallbackPolicy: TenantPolicy,\n cache: Map<string, CacheEntry>,\n ttlMs: number,\n now: () => number,\n log: (msg: string) => void\n): Promise<TenantPolicy> {\n const cached = cache.get(tenantHost);\n if (cached && now() - cached.fetchedAt < ttlMs) {\n return cached.policy;\n }\n\n // Thundering-herd defense — every degraded path writes the fallback\n // back to the cache. Pre-fix, a dashboard outage meant every\n // request re-attempted the failing fetch and ate up to\n // `fetchTimeoutMs` (2s default). Architect flagged the symmetry\n // gap against ReputationOracle (which caches degraded baselines).\n //\n // When the dashboard recovers, the cached fallback stays in\n // effect until `ttlMs` expires — bounded staleness, acceptable\n // for Phase 1. Negative-TTL knobs (retry sooner on degrade)\n // land as a follow-up if production telemetry justifies them.\n const cacheFallback = (): TenantPolicy => {\n cache.set(tenantHost, { policy: fallbackPolicy, fetchedAt: now() });\n return fallbackPolicy;\n };\n\n if (!dashboardUrl) {\n return cacheFallback();\n }\n\n const url = `${dashboardUrl.replace(/\\/$/, '')}/api/policy?tenant=${encodeURIComponent(tenantHost)}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetchImpl(url, { signal: controller.signal });\n } catch (cause) {\n log(`[policy-evaluator] fetch failed (${tenantHost}): ${String(cause)}; using fallback`);\n return cacheFallback();\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n log(`[policy-evaluator] dashboard HTTP ${response.status} (${tenantHost}); using fallback`);\n return cacheFallback();\n }\n\n let body: unknown;\n try {\n body = await response.json();\n } catch (cause) {\n log(\n `[policy-evaluator] dashboard response not JSON (${tenantHost}): ${String(cause)}; using fallback`\n );\n return cacheFallback();\n }\n\n const parsed = parseTenantPolicy(body);\n if (!parsed) {\n log(`[policy-evaluator] dashboard response malformed (${tenantHost}); using fallback`);\n return cacheFallback();\n }\n\n cache.set(tenantHost, { policy: parsed, fetchedAt: now() });\n return parsed;\n}\n\nfunction parseTenantPolicy(raw: unknown): TenantPolicy | null {\n if (raw === null || typeof raw !== 'object') return null;\n const threshold = (raw as Record<string, unknown>).reputationThreshold;\n if (\n typeof threshold !== 'number' ||\n !Number.isFinite(threshold) ||\n threshold < 0 ||\n threshold > 1\n ) {\n return null;\n }\n return { reputationThreshold: threshold };\n}\n","/**\n * Clock adapter — sub-phase B.5.\n *\n * Provides the Unix-seconds timestamp the engine's `Clock` trait needs\n * for Stage 4 expiration checks. Trivial; the trait shape exists so\n * tests can inject a frozen clock (and so the engine's sync-trait\n * surface is satisfied without a JS callback crossing the WASM\n * boundary — `ContextSpec.nowUnix` carries the value).\n */\n\nexport interface ClockAdapter {\n nowUnix(): number;\n}\n\nexport function makeSystemClock(): ClockAdapter {\n return { nowUnix: () => Math.floor(Date.now() / 1000) };\n}\n\nexport function makeFixedClock(unixSeconds: number): ClockAdapter {\n return { nowUnix: () => unixSeconds };\n}\n"]}