diff --git a/package-lock.json b/package-lock.json index bc29a01..0871975 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,10 +12,8 @@ "@commandlayer/runtime-core": "github:commandlayer/runtime-core#main", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", - "dotenv": "^17.3.1", "ethers": "^6.16.0", - "express": "^4.22.1", - "node-fetch": "^3.3.2" + "express": "^4.22.1" }, "engines": { "node": ">=20.0.0" @@ -225,15 +223,6 @@ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT" }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -262,18 +251,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/dotenv": { - "version": "17.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", - "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -444,29 +421,6 @@ ], "license": "BSD-3-Clause" }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, "node_modules/finalhandler": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", @@ -485,18 +439,6 @@ "node": ">= 0.8" } }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "license": "MIT", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -734,44 +676,6 @@ "node": ">= 0.6" } }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "deprecated": "Use your platform's native DOMException instead", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "license": "MIT", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -1091,15 +995,6 @@ "node": ">= 0.8" } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, "node_modules/ws": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", diff --git a/package.json b/package.json index 2216935..bbe7515 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,7 @@ "@commandlayer/runtime-core": "github:commandlayer/runtime-core#main", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", - "dotenv": "^17.3.1", "ethers": "^6.16.0", - "express": "^4.22.1", - "node-fetch": "^3.3.2" + "express": "^4.22.1" } } diff --git a/server.mjs b/server.mjs index 9c0496c..1a2c746 100644 --- a/server.mjs +++ b/server.mjs @@ -1576,9 +1576,6 @@ app.post("/debug/prewarm", requireDebug, (req, res) => { startWarmWorker(); }); -// ----------------------- -// verify endpoint (signature/hash + optional schema + optional ENS binding) -// ----------------------- // ----------------------- // verify endpoint (signature/hash + optional schema + optional ENS binding) // ----------------------- diff --git a/tools/patch-catch.mjs b/tools/patch-catch.mjs deleted file mode 100644 index 1b30b01..0000000 --- a/tools/patch-catch.mjs +++ /dev/null @@ -1,55 +0,0 @@ -import fs from "node:fs"; - -const p = "server.mjs"; -let s = fs.readFileSync(p, "utf8"); - -// Find the bad line -const target = "return res.status(500).json(receipt);"; -if (!s.includes(target)) { - console.error("Target line not found:", target); - process.exit(1); -} - -// Ensure we are inside handleVerb catch by checking nearby anchor -const anchor = "const err = {"; -const iTarget = s.indexOf(target); -const iAnchor = s.lastIndexOf(anchor, iTarget); -if (iAnchor < 0) { - console.error("Could not find catch anchor near target"); - process.exit(1); -} - -// Insert a proper receipt definition right before the return. -// We DO NOT try to sign if signing fails; we fall back to unsigned. -const insert = ` - let receipt; - try { - receipt = makeReceipt({ x402, trace, status: "error", error: err, actor }); - } catch (e2) { - receipt = { - status: "error", - x402, - trace, - error: err, - metadata: { - proof: { - alg: "ed25519-sha256", - canonical: CANONICAL_ID_SORTED_KEYS_V1, - signer_id: SIGNER_ID, - kid: SIGNER_KID, - hash_sha256: null, - signature_b64: null, - note: "unsigned_error_receipt", - }, - receipt_id: "", - ...(actor ? { actor } : {}), - }, - }; - } - -`; - -s = s.replace(target, insert + " " + target); - -fs.writeFileSync(p, s, "utf8"); -console.log("patched: handleVerb catch now defines receipt + unsigned fallback"); diff --git a/tools/patch-sign-order.mjs b/tools/patch-sign-order.mjs deleted file mode 100644 index 6166344..0000000 --- a/tools/patch-sign-order.mjs +++ /dev/null @@ -1,40 +0,0 @@ -import fs from "node:fs"; - -const p = "server.mjs"; -let s = fs.readFileSync(p, "utf8"); - -const start = s.indexOf("async function handleVerb"); -if (start < 0) throw new Error("Could not find: async function handleVerb"); - -const end = s.indexOf("\n}\n", start); -if (end < 0) throw new Error("Could not find end of handleVerb block"); - -const before = s.slice(0, start); -let body = s.slice(start, end); -const after = s.slice(end); - -// Grab BOTH makeReceipt calls inside handleVerb (success + error) -const re = /\n\s*const\s+receipt\s*=\s*makeReceipt\([\s\S]*?\);\s*/gm; -const matches = [...body.matchAll(re)]; -if (matches.length < 1) throw new Error("No 'const receipt = makeReceipt(...)' found inside handleVerb"); - -// Remove them from current positions -const blocks = matches.map(m => m[0]); -body = body.replace(re, "\n"); - -// Insert them right before sending the response in each path. -// We anchor on 'res.json(receipt)' lines. -let inserted = 0; -body = body.replace(/\n(\s*)(return\s+)?res\.json\(\s*receipt\s*\)\s*;\s*\n/g, (m, indent) => { - const block = blocks[inserted] || blocks[blocks.length - 1]; - inserted++; - return `\n${block}\n${m}`; -}); - -if (inserted === 0) { - // fallback: put all blocks at end of function body - body += "\n" + blocks.join("\n") + "\n"; -} - -fs.writeFileSync(p, before + body + after, "utf8"); -console.log(`patched: moved ${blocks.length} makeReceipt() call(s) to just before res.json(receipt)`); diff --git a/tools/patch-smoke.mjs b/tools/patch-smoke.mjs deleted file mode 100644 index f6e116d..0000000 --- a/tools/patch-smoke.mjs +++ /dev/null @@ -1,76 +0,0 @@ -import fs from "fs"; - -const path = "tests/smoke.mjs"; -let s = fs.readFileSync(path, "utf8"); - -// 1) Add stricter asserts helper (insert after httpJson or near top) -if (!s.includes("function assertReceiptInvariants(")) { - s = s.replace( - /async function httpJson[\s\S]*?\n}\n/m, - (m) => m + ` -function assertReceiptInvariants(receipt) { - if (!receipt || typeof receipt !== "object") throw new Error("receipt must be object"); - const proof = receipt?.metadata?.proof || {}; - if (proof.alg !== "ed25519-sha256") throw new Error("proof.alg must be ed25519-sha256"); - const canonical = String(proof.canonical_id || proof.canonical || ""); - if (canonical !== "json.sorted_keys.v1") throw new Error("canonical must be json.sorted_keys.v1"); - if (String(proof.kid || "") !== "v1") throw new Error("kid must be v1"); - - const h = String(proof.hash_sha256 || ""); - if (!/^[a-f0-9]{64}$/i.test(h)) throw new Error("hash_sha256 must be 64 hex chars"); - - const sigB64 = String(proof.signature_b64 || ""); - let sig; - try { sig = Buffer.from(sigB64, "base64"); } catch { sig = null; } - if (!sig || sig.length !== 64) throw new Error("signature_b64 must decode to 64 bytes"); -} -` - ); -} - -// 2) Ensure SMOKE_ENS logic exists (we’ll modify verify call to optionally use ?ens=1) -if (!s.includes("const SMOKE_ENS")) { - s = s.replace( - /const baseUrl = `http:\/\/127\.0\.0\.1:\$\{port\}`;\n/, - `const baseUrl = \`http://127.0.0.1:\${port}\`;\n const SMOKE_ENS = String(process.env.SMOKE_ENS || "0") === "1";\n` - ); -} - -// 3) Ensure env includes ETH_RPC_URL when SMOKE_ENS=1 (don’t require it otherwise) -if (!s.includes("ETH_RPC_URL:")) { - s = s.replace( - /const env = \{\n([\s\S]*?)\n\s*\};/m, - (m, inner) => { - // inject ETH_RPC_URL near top - const injected = - inner.replace( - /ENABLE_DEBUG: "1",\n\s*DEBUG_TOKEN: "smoke",\n/, - `ENABLE_DEBUG: "1",\n DEBUG_TOKEN: "smoke",\n ...(SMOKE_ENS && process.env.ETH_RPC_URL ? { ETH_RPC_URL: String(process.env.ETH_RPC_URL) } : {}),\n` - ); - return `const env = {\n${injected}\n };`; - } - ); -} - -// 4) Change verify call to use ENS mode when enabled -s = s.replace( - /const verify = await httpJson\(`\$\{baseUrl\}\/verify`, \{ method: "POST", body: receipt \}\);/g, - `const verifyUrl = SMOKE_ENS ? \`\${baseUrl}/verify?ens=1&refresh=1\` : \`\${baseUrl}/verify\`;\n const verify = await httpJson(verifyUrl, { method: "POST", body: receipt });` -); - -// 5) After receipt returned from describe call, assert invariants before verify -if (!s.includes("assertReceiptInvariants(receipt)")) { - s = s.replace( - /const receipt = describe\.json;\n/, - `const receipt = describe.json;\n assertReceiptInvariants(receipt);\n` - ); -} - -// 6) Improve verify assertion error to include values -s = s.replace( - /assert\.equal\(verify\.status,\s*200,\s*`verify failed: \$\{JSON\.stringify\(verify\.json\)\}`\);\n/g, - `assert.equal(verify.status, 200, \`verify failed: \${JSON.stringify(verify.json)}\`);\n` -); - -fs.writeFileSync(path, s); -console.log("patched tests/smoke.mjs");