import { HTTPFacilitatorClient, x402ResourceServer } from "npm:@x402/core@2.27.0/server"; import { ExactEvmScheme } from "npm:@x402/evm@2.27.0/exact/server"; import { ExactNanoScheme } from "npm:@x402nano/exact@0.2.3/server"; const NANO_PRICE = "0.001"; const NANO_FACILITATOR = "https://facilitator.pursekeeper.dev"; const NANO_PAY_TO = "nano_3mr761i87o7o33hmrd67a1emt81j6djgdqeyod95ip5qcidz77b71x4ukqea"; const NANO_NETWORK = "nano:mainnet"; const BASE_PRICE = "$0.01"; const BASE_FACILITATOR = "https://facilitator.payai.network"; const BASE_PAY_TO = "0xf200174de10c26ce7670aaf41d69a8979fe5629d"; const BASE_NETWORK = "eip155:8453"; const PUBLIC_BASE = "https://tkoqkknsezxavtxfywkm.supabase.co/functions/v1/nano-npm-risk"; const PAID = `${PUBLIC_BASE}/v1/npm-risk`; const nanoServer = new x402ResourceServer(new HTTPFacilitatorClient({ url: NANO_FACILITATOR })) .register(NANO_NETWORK, new ExactNanoScheme()); const baseServer = new x402ResourceServer(new HTTPFacilitatorClient({ url: BASE_FACILITATOR })) .register(BASE_NETWORK, new ExactEvmScheme()); const nanoInit = nanoServer.initialize(); const baseInit = baseServer.initialize(); function json(body: unknown, status = 200, headers: HeadersInit = {}) { return new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json; charset=utf-8", "cache-control": "no-store", ...headers }, }); } function encodeWire(value: unknown) { return btoa(JSON.stringify(value)); } function decodeWire(value: string) { try { return JSON.parse(atob(value)); } catch { return null; } } function validatePackageName(value: string | null) { if (typeof value !== "string") return null; const name = value.trim(); if (!name || name.length > 214 || /\s/.test(name)) return null; if (name.startsWith("@")) return /^@[a-z0-9][a-z0-9._~-]*\/[a-z0-9][a-z0-9._~-]*$/i.test(name) ? name : null; return /^[a-z0-9][a-z0-9._~-]*$/i.test(name) ? name : null; } function daysSince(iso: string | null, now: Date) { if (!iso) return null; const timestamp = Date.parse(iso); if (!Number.isFinite(timestamp)) return null; return Math.max(0, Math.floor((now.getTime() - timestamp) / 86_400_000)); } function repositoryUrl(repository: unknown): string | null { if (!repository) return null; if (typeof repository === "string") return repository; if (typeof repository === "object" && repository !== null && "url" in repository) { const value = (repository as { url?: unknown }).url; return typeof value === "string" ? value : null; } return null; } async function buildNpmRiskReport(packageName: string | null) { const normalized = validatePackageName(packageName); if (!normalized) throw Object.assign(new Error("Invalid npm package name"), { statusCode: 400 }); const encoded = encodeURIComponent(normalized); const [metadataResponse, downloadsResponse] = await Promise.all([ fetch(`https://registry.npmjs.org/${encoded}`, { headers: { accept: "application/json" } }), fetch(`https://api.npmjs.org/downloads/point/last-week/${encoded}`, { headers: { accept: "application/json" } }), ]); if (metadataResponse.status === 404) throw Object.assign(new Error("Package not found"), { statusCode: 404 }); if (!metadataResponse.ok) throw Object.assign(new Error(`npm registry returned ${metadataResponse.status}`), { statusCode: 502 }); const metadata = await metadataResponse.json(); const latestVersion = metadata["dist-tags"]?.latest ?? null; const latest = latestVersion ? metadata.versions?.[latestVersion] ?? {} : {}; const lastPublishedAt = latestVersion ? metadata.time?.[latestVersion] ?? null : null; const lastPublishedDaysAgo = daysSince(lastPublishedAt, new Date()); const maintainers = Array.isArray(metadata.maintainers) ? metadata.maintainers.length : 0; const weeklyDownloads = downloadsResponse.ok ? Number((await downloadsResponse.json()).downloads ?? 0) : null; const flags: Record[] = []; if (latest.deprecated) flags.push({ code: "deprecated", severity: "high", detail: String(latest.deprecated) }); if (lastPublishedDaysAgo === null) flags.push({ code: "publish_date_unknown", severity: "medium" }); else if (lastPublishedDaysAgo > 730) flags.push({ code: "stale_over_2y", severity: "high", days: lastPublishedDaysAgo }); else if (lastPublishedDaysAgo > 365) flags.push({ code: "stale_over_1y", severity: "medium", days: lastPublishedDaysAgo }); if (maintainers === 0) flags.push({ code: "no_listed_maintainers", severity: "high" }); else if (maintainers === 1) flags.push({ code: "single_maintainer", severity: "low" }); if (weeklyDownloads !== null && weeklyDownloads < 100) flags.push({ code: "low_weekly_downloads", severity: "medium", downloads: weeklyDownloads }); if (!latest.license && !metadata.license) flags.push({ code: "license_unknown", severity: "medium" }); if (!repositoryUrl(latest.repository ?? metadata.repository)) flags.push({ code: "repository_missing", severity: "low" }); const penalty = flags.reduce((total, flag) => total + ({ high: 25, medium: 12, low: 5 }[String(flag.severity)] ?? 0), 0); const score = Math.max(0, 100 - penalty); return { package: normalized, latestVersion, score, verdict: score >= 80 ? "low-obvious-risk" : score >= 55 ? "review" : "high-caution", flags, evidence: { lastPublishedAt, lastPublishedDaysAgo, weeklyDownloads, maintainers, license: latest.license ?? metadata.license ?? null, repository: repositoryUrl(latest.repository ?? metadata.repository), }, generatedAt: new Date().toISOString(), methodology: "Public npm registry metadata and npm weekly download counts; heuristic, not a security audit.", }; } function statusCode(error: unknown, fallback = 500) { if (error && typeof error === "object" && "statusCode" in error) { const value = Number((error as { statusCode?: unknown }).statusCode); if (Number.isInteger(value) && value >= 400 && value <= 599) return value; } return fallback; } async function paymentContext(resourceUrl: string) { await Promise.all([nanoInit, baseInit]); const nanoRequirements = (await nanoServer.buildPaymentRequirements({ scheme: "exact", network: NANO_NETWORK, price: NANO_PRICE, payTo: NANO_PAY_TO, description: "Evidence-backed npm package health and maintenance-risk report", mimeType: "application/json", }))[0]; const baseRequirements = (await baseServer.buildPaymentRequirements({ scheme: "exact", network: BASE_NETWORK, price: BASE_PRICE, payTo: BASE_PAY_TO, description: "Evidence-backed npm package health and maintenance-risk report", mimeType: "application/json", }))[0]; const required = { x402Version: 2, resource: { url: resourceUrl, description: "Evidence-backed npm package health and maintenance-risk report", mimeType: "application/json", serviceName: "Ops Control HQ npm Package Risk", tags: ["npm", "package-risk", "package-health", "maintenance-risk", "developer-tools"], }, accepts: [nanoRequirements, baseRequirements], }; return { nanoRequirements, baseRequirements, required }; } function selectedNetwork(payload: any): string | null { return payload?.accepted?.network ?? payload?.network ?? null; } const manifest = { x402: "1.0", name: "ops-control-hq-npm-package-risk", description: "Evidence-backed npm package health and maintenance-risk report with dual x402 payment rails: Nano/XNO or Base/USDC.", capabilities: ["npm", "package-risk", "package-health", "maintenance-risk", "developer-tools"], pricing: { options: [ { currency: "XNO", amount: NANO_PRICE, network: NANO_NETWORK }, { currency: "USDC", amount: "0.01", network: BASE_NETWORK }, ], unit: "request", }, payment: { options: [ { address: NANO_PAY_TO, network: NANO_NETWORK, facilitator: NANO_FACILITATOR }, { address: BASE_PAY_TO, network: BASE_NETWORK, facilitator: BASE_FACILITATOR }, ], }, endpoint: `${PAID}?package=react`, }; Deno.serve(async (req: Request) => { const internalUrl = new URL(req.url); const suffix = internalUrl.pathname.replace(/^\/nano-npm-risk/, ""); if (req.method === "GET" && (suffix === "/healthz" || suffix === "/" || suffix === "")) { return json({ ok: true, service: "Ops Control HQ npm Package Risk", paidRoute: PAID, paymentOptions: [ { network: NANO_NETWORK, price: `${NANO_PRICE} XNO`, facilitator: NANO_FACILITATOR }, { network: BASE_NETWORK, price: "$0.01 USDC", facilitator: BASE_FACILITATOR }, ], discovery: { x402: `${PUBLIC_BASE}/.well-known/x402` }, }, 200, { "cache-control": "public,max-age=60" }); } if (req.method === "GET" && suffix === "/.well-known/x402") { return json(manifest, 200, { "cache-control": "public,max-age=300" }); } if (req.method !== "GET" || suffix !== "/v1/npm-risk") return json({ error: "not_found" }, 404); const requestedPackage = validatePackageName(internalUrl.searchParams.get("package")); if (!requestedPackage) return json({ error: "invalid_package", message: "Provide ?package=" }, 400); const publicResourceUrl = `${PUBLIC_BASE}/v1/npm-risk${internalUrl.search}`; let ctx; try { ctx = await paymentContext(publicResourceUrl); } catch (error) { console.error("NPM_RISK_PAYMENT_CONTEXT_FAILED", error instanceof Error ? error.message : String(error)); return json({ error: "payment_configuration_unavailable" }, 503); } const paymentHeader = req.headers.get("PAYMENT-SIGNATURE") || req.headers.get("X-PAYMENT"); if (!paymentHeader) { return json({ error: "payment_required", accepts: [ { network: NANO_NETWORK, price: `${NANO_PRICE} XNO` }, { network: BASE_NETWORK, price: "$0.01 USDC" }, ], }, 402, { "PAYMENT-REQUIRED": encodeWire(ctx.required) }); } const payload = decodeWire(paymentHeader); if (!payload) return json({ error: "invalid_payment_payload" }, 400, { "PAYMENT-REQUIRED": encodeWire(ctx.required) }); const network = selectedNetwork(payload); const paymentServer = network === BASE_NETWORK ? baseServer : network === NANO_NETWORK ? nanoServer : null; const requirements = network === BASE_NETWORK ? ctx.baseRequirements : network === NANO_NETWORK ? ctx.nanoRequirements : null; if (!paymentServer || !requirements) { return json({ error: "unsupported_payment_network", supported: [NANO_NETWORK, BASE_NETWORK] }, 402, { "PAYMENT-REQUIRED": encodeWire(ctx.required), }); } try { const verified = await paymentServer.verifyPayment(payload, requirements); if (!verified.isValid) return json({ error: "invalid_payment", reason: verified.invalidReason }, 402, { "PAYMENT-REQUIRED": encodeWire(ctx.required), }); let report; try { report = await buildNpmRiskReport(requestedPackage); } catch (error) { const status = statusCode(error, 502); return json({ error: status === 404 ? "package_not_found" : status === 400 ? "invalid_package" : "upstream_error", message: error instanceof Error ? error.message : String(error), }, status); } const settled = await paymentServer.settlePayment(payload, requirements); if (!settled.success) return json({ error: "settlement_failed", reason: settled.errorReason }, 402, { "PAYMENT-REQUIRED": encodeWire(ctx.required), }); console.log("NPM_RISK_X402_SETTLED", JSON.stringify({ network, transaction: settled.transaction ?? null, package: requestedPackage, at: new Date().toISOString(), })); return json({ ...report, payment: settled.transaction ?? null, paymentNetwork: network }, 200, { "PAYMENT-RESPONSE": encodeWire(settled), }); } catch (error) { console.error("NPM_RISK_REQUEST_FAILED", error instanceof Error ? error.message : String(error)); return json({ error: "request_failed", message: error instanceof Error ? error.message : String(error) }, 400); } });