{"_id":"@3maem/ash-node","_rev":"8-40be8e51ed64ac33610ad421836c920c","name":"@3maem/ash-node","dist-tags":{"latest":"2.3.3"},"versions":{"1.0.0":{"name":"@3maem/ash-node","version":"1.0.0","keywords":["ash","security","integrity","anti-tamper","replay-prevention","cryptography","middleware"],"author":{"name":"3meam Co. | شركة عمائم"},"license":"MIT","_id":"@3maem/ash-node@1.0.0","maintainers":[{"name":"3maem","email":"3maem2025@gmail.com"}],"homepage":"https://github.com/3meam/ash#readme","bugs":{"url":"https://github.com/3meam/ash/issues"},"dist":{"shasum":"2633b145c847e6ee7660b368898bebbada7bb922","tarball":"https://registry.npmjs.org/@3maem/ash-node/-/ash-node-1.0.0.tgz","fileCount":22,"integrity":"sha512-u6XJoI/HempxTt7tEn4+EuaAjEVvyU2xpSedoltNGjw7DlP6A2wqWBKkbAlbSS6m5aQv/UGAdVdpuKKH4gk1nA==","signatures":[{"sig":"MEUCICpjXr8Wl38vY4OU+gZbafhXTjEMoLhcSuKAVAnYAdwtAiEAlIGKxNn023mHnzhWUAGK0b83zV6pnMyVdWmW/oSDZeI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":114930},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.mjs","require":"./dist/middleware/index.js"}},"gitHead":"cc3bf2f963e6c23122748cfda5802cea2397b1e9","scripts":{"lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts src/middleware/index.ts --format cjs,esm --dts","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"3maem","email":"3maem2025@gmail.com"},"repository":{"url":"git+https://github.com/3meam/ash.git","type":"git","directory":"packages/ash-node"},"_npmVersion":"10.8.2","description":"ASH SDK for Node.js - Request integrity and anti-replay protection library","directories":{},"_nodeVersion":"20.19.6","dependencies":{"@3maem/ash-wasm":"file:../ash-wasm/pkg"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.1","eslint":"^8.55.0","vitest":"^1.0.0","express":"^4.18.2","fastify":"^4.24.3","typescript":"^5.3.0","@types/node":"^20.10.0","@types/express":"^4.17.21","@typescript-eslint/parser":"^6.13.0","@typescript-eslint/eslint-plugin":"^6.13.0"},"peerDependencies":{"express":"^4.0.0 || ^5.0.0","fastify":"^4.0.0"},"peerDependenciesMeta":{"express":{"optional":true},"fastify":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/ash-node_1.0.0_1767381602534_0.9717968098168899","host":"s3://npm-registry-packages-npm-production"},"deprecated":"DEPRECATED — Use @3maem/ash-node-sdk instead. This package is End of Life (EOL). See https://ashcore.ai"},"1.0.1":{"name":"@3maem/ash-node","version":"1.0.1","keywords":["ash","security","integrity","anti-tamper","replay-prevention","cryptography","middleware"],"author":{"name":"3meam Co. | شركة عمائم"},"license":"Proprietary","_id":"@3maem/ash-node@1.0.1","maintainers":[{"name":"3maem","email":"3maem2025@gmail.com"}],"homepage":"https://github.com/3meam/ash#readme","bugs":{"url":"https://github.com/3meam/ash/issues"},"dist":{"shasum":"08a47b62d37257c4c7d0429db897c6483999cb48","tarball":"https://registry.npmjs.org/@3maem/ash-node/-/ash-node-1.0.1.tgz","fileCount":22,"integrity":"sha512-FzsyZTxJkA7/UsT+2yLWrDNcDTqYneYBrpJIIfqBeWcVMZhz7T8idvErmvo1Tfr2wPtv8ACEViLKPMerzJkrNQ==","signatures":[{"sig":"MEUCIBpOHDFZILp33A4OU8tsKaV4m9PN8eErqDmqVtl4SS2xAiEA5KrNeEPssKQFQR71UFAoQGDuSf+2JXVxzj0XkEQ+z/0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":114960},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.mjs","require":"./dist/middleware/index.js"}},"gitHead":"4c6110a05830e8f66e59dff2b0747d267549d609","scripts":{"lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts src/middleware/index.ts --format cjs,esm --dts","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"3maem","email":"3maem2025@gmail.com"},"repository":{"url":"git+https://github.com/3meam/ash.git","type":"git","directory":"packages/ash-node"},"_npmVersion":"10.8.2","description":"ASH SDK for Node.js - Request integrity and anti-replay protection library","directories":{},"_nodeVersion":"20.19.6","dependencies":{"@3maem/ash-wasm":"file:../ash-wasm/pkg"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.1","eslint":"^8.55.0","vitest":"^1.0.0","express":"^4.18.2","fastify":"^4.24.3","typescript":"^5.3.0","@types/node":"^20.10.0","@types/express":"^4.17.21","@typescript-eslint/parser":"^6.13.0","@typescript-eslint/eslint-plugin":"^6.13.0"},"peerDependencies":{"express":"^4.0.0 || ^5.0.0","fastify":"^4.0.0"},"peerDependenciesMeta":{"express":{"optional":true},"fastify":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/ash-node_1.0.1_1767382138620_0.684752863298191","host":"s3://npm-registry-packages-npm-production"},"deprecated":"DEPRECATED — Use @3maem/ash-node-sdk instead. This package is End of Life (EOL). See https://ashcore.ai"},"1.0.2":{"name":"@3maem/ash-node","version":"1.0.2","keywords":["ash","security","integrity","anti-tamper","replay-prevention","cryptography","middleware"],"author":{"name":"3meam Co. | شركة عمائم"},"license":"Proprietary","_id":"@3maem/ash-node@1.0.2","maintainers":[{"name":"3maem","email":"3maem2025@gmail.com"}],"homepage":"https://github.com/3meam/ash#readme","bugs":{"url":"https://github.com/3meam/ash/issues"},"dist":{"shasum":"f2cde711f87225dba75ce8953365d4f4b513603a","tarball":"https://registry.npmjs.org/@3maem/ash-node/-/ash-node-1.0.2.tgz","fileCount":22,"integrity":"sha512-MMHrBy+o+LnQfSbhLdRm2O1CySDWH7YvHM10xpllEf/iSJZMJrpu4KVMRhH8BmzlsjIpmgR9cXWRNHXlUz991A==","signatures":[{"sig":"MEYCIQDHkxV0ImipAeZGwjlOBrhkwWz0kxssNCisgYmwJBlCAQIhAIZtbgDWvfq5HJBbiy7bWWHV5zH81WtXm4aky+k0U7uE","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":114881},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.mjs","require":"./dist/middleware/index.js"}},"gitHead":"cd0dbc733361f8b2522cb26f883d16888f6d2416","scripts":{"lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts src/middleware/index.ts --format cjs,esm --dts","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"3maem","email":"3maem2025@gmail.com"},"repository":{"url":"git+https://github.com/3meam/ash.git","type":"git","directory":"packages/ash-node"},"_npmVersion":"10.8.2","description":"ASH SDK for Node.js - Request integrity and anti-replay protection library","directories":{},"_nodeVersion":"20.19.6","dependencies":{"@3maem/ash-wasm":"file:../ash-wasm/pkg"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.1","eslint":"^8.55.0","vitest":"^1.0.0","express":"^4.18.2","fastify":"^4.24.3","typescript":"^5.3.0","@types/node":"^20.10.0","@types/express":"^4.17.21","@typescript-eslint/parser":"^6.13.0","@typescript-eslint/eslint-plugin":"^6.13.0"},"peerDependencies":{"express":"^4.0.0 || ^5.0.0","fastify":"^4.0.0"},"peerDependenciesMeta":{"express":{"optional":true},"fastify":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/ash-node_1.0.2_1767382708038_0.7475787092568336","host":"s3://npm-registry-packages-npm-production"},"deprecated":"DEPRECATED — Use @3maem/ash-node-sdk instead. This package is End of Life (EOL). See https://ashcore.ai"},"2.3.0":{"name":"@3maem/ash-node","version":"2.3.0","keywords":["ash","security","integrity","anti-tamper","replay-prevention","cryptography","middleware"],"author":{"name":"3meam Co. | شركة عمائم"},"license":"Proprietary","_id":"@3maem/ash-node@2.3.0","maintainers":[{"name":"3maem","email":"3maem2025@gmail.com"}],"homepage":"https://github.com/3meam/ash#readme","bugs":{"url":"https://github.com/3meam/ash/issues"},"dist":{"shasum":"df0376d583f387e61986a0ac9ca2048fe86f6b5f","tarball":"https://registry.npmjs.org/@3maem/ash-node/-/ash-node-2.3.0.tgz","fileCount":23,"integrity":"sha512-/VdtYHO/KiUePZ0QSepCbhh5lANrNRTkP3Xeuz8W039NWRdBb77DLMzjGvcMIdGDMHdNb49lyzEWqwometLocA==","signatures":[{"sig":"MEYCIQDbuKIN6wGIE9hjnaE/mv8dcQlY5doqo1Oc6nE3FVkFNwIhAKNjsENw3AYlSatIglD5IQmfL/dsF7Av9LS/V89Rbs7k","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":165893},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.mjs","require":"./dist/middleware/index.js"}},"gitHead":"3869f381334de906b07231d87fee13dbb4cc9671","scripts":{"lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts src/middleware/index.ts --format cjs,esm --dts","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"3maem","email":"3maem2025@gmail.com"},"repository":{"url":"git+https://github.com/3meam/ash.git","type":"git","directory":"packages/ash-node"},"_npmVersion":"11.4.2","description":"ASH SDK for Node.js - Request integrity and anti-replay protection library","directories":{},"_nodeVersion":"22.16.0","dependencies":{"@3maem/ash-wasm":"file:../ash-wasm/pkg"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.1","eslint":"^8.55.0","vitest":"^1.0.0","express":"^4.18.2","fastify":"^4.24.3","typescript":"^5.3.0","@types/node":"^20.10.0","@types/express":"^4.17.21","@typescript-eslint/parser":"^6.13.0","@typescript-eslint/eslint-plugin":"^6.13.0"},"peerDependencies":{"express":"^4.0.0 || ^5.0.0","fastify":"^4.0.0"},"peerDependenciesMeta":{"express":{"optional":true},"fastify":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/ash-node_2.3.0_1768421540293_0.05902037147305683","host":"s3://npm-registry-packages-npm-production"},"deprecated":"DEPRECATED — Use @3maem/ash-node-sdk instead. This package is End of Life (EOL). See https://ashcore.ai"},"2.3.1":{"name":"@3maem/ash-node","version":"2.3.1","keywords":["ash","security","integrity","anti-tamper","replay-prevention","cryptography","middleware"],"author":{"name":"3meam Co. | شركة عمائم"},"license":"Proprietary","_id":"@3maem/ash-node@2.3.1","maintainers":[{"name":"3maem","email":"3maem2025@gmail.com"}],"homepage":"https://github.com/3meam/ash#readme","bugs":{"url":"https://github.com/3meam/ash/issues"},"dist":{"shasum":"991a4a205b5c798458d9859b50ee084ea5bba765","tarball":"https://registry.npmjs.org/@3maem/ash-node/-/ash-node-2.3.1.tgz","fileCount":24,"integrity":"sha512-lzuSwsUpzl58XefImZ960sptkIJqB2oMBWbtI/mOKZ88BWaBcHZJmiH2cxL7dV+m232jvGtXGkG8f9QkK3DbDw==","signatures":[{"sig":"MEYCIQDFuCk0dQs3rvJXvQ6UyKCNFqIpO9DQsm96IkGGBpnItwIhALWZIjutkerG564Is4ct6nHLOzpvgtskRxKV0mOdoOnt","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":222664},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.mjs","require":"./dist/middleware/index.js"}},"gitHead":"1b604350049cc3522ad3a7898d4e8cbc8f57dc30","scripts":{"lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts src/middleware/index.ts --format cjs,esm --dts","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"3maem","email":"3maem2025@gmail.com"},"repository":{"url":"git+https://github.com/3meam/ash.git","type":"git","directory":"packages/ash-node"},"_npmVersion":"11.4.2","description":"ASH SDK for Node.js - Request integrity and anti-replay protection library","directories":{},"_nodeVersion":"22.16.0","dependencies":{"@3maem/ash-wasm":"^2.3.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.1","eslint":"^8.55.0","vitest":"^1.0.0","express":"^4.18.2","fastify":"^4.24.3","typescript":"^5.3.0","@types/node":"^20.10.0","@types/express":"^4.17.21","@typescript-eslint/parser":"^6.13.0","@typescript-eslint/eslint-plugin":"^6.13.0"},"peerDependencies":{"express":"^4.0.0 || ^5.0.0","fastify":"^4.0.0"},"peerDependenciesMeta":{"express":{"optional":true},"fastify":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/ash-node_2.3.1_1769356825649_0.18907580662776002","host":"s3://npm-registry-packages-npm-production"},"deprecated":"DEPRECATED — Use @3maem/ash-node-sdk instead. This package is End of Life (EOL). See https://ashcore.ai"},"2.3.2":{"name":"@3maem/ash-node","version":"2.3.2","keywords":["ash","security","integrity","anti-tamper","replay-prevention","cryptography","middleware"],"author":{"name":"3meam Co. | شركة عمائم"},"license":"Proprietary","_id":"@3maem/ash-node@2.3.2","maintainers":[{"name":"3maem","email":"3maem2025@gmail.com"}],"homepage":"https://github.com/3meam/ash#readme","bugs":{"url":"https://github.com/3meam/ash/issues"},"dist":{"shasum":"b178cf12636577e303a5eb1ab76ef7f6c283518a","tarball":"https://registry.npmjs.org/@3maem/ash-node/-/ash-node-2.3.2.tgz","fileCount":26,"integrity":"sha512-Ss+GRF7JmD9YbRZ8zPIF86nSPf24NzqS2tJlJ0RLTT6U7bddtVW5qw+36Hj3AbjN6GurXzq/+QbAvxJki8mDDQ==","signatures":[{"sig":"MEUCIQCVHX3y7WWwS5QWuMGsfi6j28lGvQuS4CDs0indQw/j1AIgFF2XDFhDPWffpS6r9LGsdfhbGIXwRfOModHjLcqswZI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":359319},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.mjs","require":"./dist/middleware/index.js"}},"gitHead":"340188c3fc46e82f6f9a26bcff4256b1c3ebed89","scripts":{"lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts src/middleware/index.ts --format cjs,esm --dts","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"3maem","email":"3maem2025@gmail.com"},"repository":{"url":"git+https://github.com/3meam/ash.git","type":"git","directory":"packages/ash-node"},"_npmVersion":"11.4.2","description":"ASH SDK for Node.js - Request integrity and anti-replay protection library","directories":{},"_nodeVersion":"22.16.0","dependencies":{"@3maem/ash-wasm":"^2.3.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.1","eslint":"^8.55.0","vitest":"^1.0.0","express":"^4.18.2","fastify":"^4.24.3","typescript":"^5.3.0","@types/node":"^20.10.0","@types/express":"^4.17.21","@typescript-eslint/parser":"^6.13.0","@typescript-eslint/eslint-plugin":"^6.13.0"},"peerDependencies":{"express":"^4.0.0 || ^5.0.0","fastify":"^4.0.0"},"peerDependenciesMeta":{"express":{"optional":true},"fastify":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/ash-node_2.3.2_1769369042793_0.3323410759679064","host":"s3://npm-registry-packages-npm-production"},"deprecated":"DEPRECATED — Use @3maem/ash-node-sdk instead. This package is End of Life (EOL). See https://ashcore.ai"},"2.3.3":{"name":"@3maem/ash-node","version":"2.3.3","keywords":["ash","security","integrity","anti-tamper","replay-prevention","cryptography","middleware"],"author":{"name":"3meam Co. | شركة عمائم"},"license":"Proprietary","_id":"@3maem/ash-node@2.3.3","maintainers":[{"name":"3maem","email":"3maem2025@gmail.com"}],"homepage":"https://github.com/3meam/ash#readme","bugs":{"url":"https://github.com/3meam/ash/issues"},"dist":{"shasum":"14d61cbf5336464f644144bb8f05c2d00cd998f7","tarball":"https://registry.npmjs.org/@3maem/ash-node/-/ash-node-2.3.3.tgz","fileCount":26,"integrity":"sha512-McP88I1ak3Vh9Fm7nvJckwiOsOvdGY8gEsVVa5c/ai1fBsDDhB+l5yPbSucbnIyXHl39RBQ3LDncPyvzu8DUFw==","signatures":[{"sig":"MEUCIGqW5R9+nz/xwONwGb4OyhxthGZ5Lv38WEHJ9xQ46W4zAiEAhrh2yoiFWSnRikDT5Tc5yIdaKdsAZwVjuRI6C+1EuA8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":360595},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.mjs","require":"./dist/middleware/index.js"}},"gitHead":"01961225a71cdfffa37ae7320257fdc37a6716f0","scripts":{"lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts src/middleware/index.ts --format cjs,esm --dts","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"3maem","email":"3maem2025@gmail.com"},"repository":{"url":"git+https://github.com/3meam/ash.git","type":"git","directory":"packages/ash-node"},"_npmVersion":"11.4.2","description":"ASH (Application Security Hash) - RFC 8785 compliant request integrity verification with server-signed seals, anti-replay protection, and zero client secrets","directories":{},"_nodeVersion":"22.16.0","dependencies":{"@3maem/ash-wasm":"^2.3.3"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.1","eslint":"^8.55.0","vitest":"^1.0.0","express":"^4.18.2","fastify":"^4.24.3","typescript":"^5.3.0","@types/node":"^20.10.0","@types/express":"^4.17.21","@typescript-eslint/parser":"^6.13.0","@typescript-eslint/eslint-plugin":"^6.13.0"},"peerDependencies":{"express":"^4.0.0 || ^5.0.0","fastify":"^4.0.0"},"peerDependenciesMeta":{"express":{"optional":true},"fastify":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/ash-node_2.3.3_1769373318069_0.07114928201472526","host":"s3://npm-registry-packages-npm-production"},"deprecated":"DEPRECATED — Use @3maem/ash-node-sdk instead. This package is End of Life (EOL). See https://ashcore.ai"}},"time":{"created":"2026-01-02T19:20:02.438Z","modified":"2026-02-21T23:50:43.218Z","1.0.0":"2026-01-02T19:20:02.706Z","1.0.1":"2026-01-02T19:28:58.801Z","1.0.2":"2026-01-02T19:38:28.186Z","2.3.0":"2026-01-14T20:12:20.446Z","2.3.1":"2026-01-25T16:00:25.810Z","2.3.2":"2026-01-25T19:24:02.948Z","2.3.3":"2026-01-25T20:35:18.237Z"},"bugs":{"url":"https://github.com/3meam/ash/issues"},"author":{"name":"3meam Co. | شركة عمائم"},"license":"Proprietary","homepage":"https://github.com/3meam/ash#readme","keywords":["ash","security","integrity","anti-tamper","replay-prevention","cryptography","middleware"],"repository":{"url":"git+https://github.com/3meam/ash.git","type":"git","directory":"packages/ash-node"},"description":"ASH (Application Security Hash) - RFC 8785 compliant request integrity verification with server-signed seals, anti-replay protection, and zero client secrets","maintainers":[{"name":"3maem","email":"3maem2025@gmail.com"}],"readme":"# ASH SDK for Node.js\r\n\r\n**Developed by 3maem Co. | شركة عمائم**\r\n\r\nASH SDK provides request integrity and anti-replay protection for web applications. This SDK provides request integrity protection, anti-replay mechanisms, and middleware for Express and Fastify.\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @3maem/ash-node\r\n```\r\n\r\n**Requirements:** Node.js 18.0.0 or later\r\n\r\n## Quick Start\r\n\r\n### Initialize the Library\r\n\r\n```typescript\r\nimport { ashInit } from '@3maem/ash-node';\r\n\r\n// Call once before using other functions\r\nashInit();\r\n```\r\n\r\n### Canonicalize JSON\r\n\r\n```typescript\r\nimport { ashCanonicalizeJson, ashInit } from '@3maem/ash-node';\r\n\r\nashInit();\r\n\r\n// Canonicalize JSON to deterministic form\r\nconst canonical = ashCanonicalizeJson('{\"z\":1,\"a\":2}');\r\nconsole.log(canonical); // {\"a\":2,\"z\":1}\r\n```\r\n\r\n### Build a Proof\r\n\r\n```typescript\r\nimport { ashInit, ashCanonicalizeJson, ashBuildProof } from '@3maem/ash-node';\r\n\r\nashInit();\r\n\r\n// Canonicalize payload\r\nconst payload = JSON.stringify({ username: 'test', action: 'login' });\r\nconst canonical = ashCanonicalizeJson(payload);\r\n\r\n// Build proof\r\nconst proof = ashBuildProof(\r\n  'balanced',           // mode\r\n  'POST /api/login',    // binding\r\n  'ctx_abc123',         // contextId\r\n  null,                 // nonce (optional)\r\n  canonical             // canonicalPayload\r\n);\r\n\r\nconsole.log(`Proof: ${proof}`);\r\n```\r\n\r\n### Verify a Proof\r\n\r\n```typescript\r\nimport { ashInit, ashVerifyProof } from '@3maem/ash-node';\r\n\r\nashInit();\r\n\r\nconst expectedProof = 'abc123...';\r\nconst receivedProof = 'abc123...';\r\n\r\n// Use timing-safe comparison to prevent timing attacks\r\nif (ashVerifyProof(expectedProof, receivedProof)) {\r\n  console.log('Proof verified successfully');\r\n} else {\r\n  console.log('Proof verification failed');\r\n}\r\n```\r\n\r\n## Express Integration\r\n\r\n```typescript\r\nimport express from 'express';\r\nimport {\r\n  ashInit,\r\n  ashExpressMiddleware,\r\n  AshMemoryStore,\r\n} from '@3maem/ash-node';\r\n\r\nashInit();\r\n\r\nconst app = express();\r\nconst store = new AshMemoryStore();\r\n\r\napp.use(express.json());\r\n\r\n// Issue context endpoint\r\napp.post('/ash/context', async (req, res) => {\r\n  const context = await store.create({\r\n    binding: 'POST /api/update',\r\n    ttlMs: 30000,\r\n    mode: 'balanced',\r\n  });\r\n\r\n  res.json({\r\n    contextId: context.id,\r\n    expiresAt: context.expiresAt,\r\n    mode: context.mode,\r\n  });\r\n});\r\n\r\n// Protected endpoint with middleware\r\napp.post(\r\n  '/api/update',\r\n  ashExpressMiddleware({\r\n    store,\r\n    expectedBinding: 'POST /api/update',\r\n  }),\r\n  (req, res) => {\r\n    // Request verified - safe to process\r\n    res.json({ status: 'success' });\r\n  }\r\n);\r\n\r\napp.listen(3000, () => {\r\n  console.log('Server running on port 3000');\r\n});\r\n```\r\n\r\n## Fastify Integration\r\n\r\n```typescript\r\nimport Fastify from 'fastify';\r\nimport {\r\n  ashInit,\r\n  ashFastifyPlugin,\r\n  AshMemoryStore,\r\n} from '@3maem/ash-node';\r\n\r\nashInit();\r\n\r\nconst fastify = Fastify();\r\nconst store = new AshMemoryStore();\r\n\r\n// Register ASH plugin\r\nfastify.register(ashFastifyPlugin, {\r\n  store,\r\n  protectedPaths: ['/api/*'],\r\n});\r\n\r\n// Issue context endpoint\r\nfastify.post('/ash/context', async (request, reply) => {\r\n  const context = await store.create({\r\n    binding: 'POST /api/update',\r\n    ttlMs: 30000,\r\n    mode: 'balanced',\r\n  });\r\n\r\n  return {\r\n    contextId: context.id,\r\n    expiresAt: context.expiresAt,\r\n    mode: context.mode,\r\n  };\r\n});\r\n\r\n// Protected endpoint\r\nfastify.post('/api/update', async (request, reply) => {\r\n  // Request verified by plugin\r\n  return { status: 'success' };\r\n});\r\n\r\nfastify.listen({ port: 3000 });\r\n```\r\n\r\n## API Reference\r\n\r\n### Initialization\r\n\r\n#### `ashInit(): void`\r\n\r\nInitialize the ASH library. Call once before using other functions.\r\n\r\n```typescript\r\nimport { ashInit } from '@3maem/ash-node';\r\n\r\nashInit();\r\n```\r\n\r\n### Canonicalization\r\n\r\n#### `ashCanonicalizeJson(input: string): string`\r\n\r\nCanonicalizes JSON to deterministic form.\r\n\r\n**Rules:**\r\n- Object keys sorted lexicographically\r\n- No whitespace\r\n- Unicode NFC normalized\r\n\r\n```typescript\r\nconst canonical = ashCanonicalizeJson('{\"z\":1,\"a\":2}');\r\n// Result: '{\"a\":2,\"z\":1}'\r\n```\r\n\r\n#### `ashCanonicalizeUrlencoded(input: string): string`\r\n\r\nCanonicalizes URL-encoded form data.\r\n\r\n```typescript\r\nconst canonical = ashCanonicalizeUrlencoded('z=1&a=2');\r\n// Result: 'a=2&z=1'\r\n```\r\n\r\n### Proof Generation\r\n\r\n#### `ashBuildProof(mode, binding, contextId, nonce, canonicalPayload): string`\r\n\r\nBuilds a cryptographic proof for request integrity.\r\n\r\n```typescript\r\nconst proof = ashBuildProof(\r\n  'balanced',           // mode: 'minimal' | 'balanced' | 'strict'\r\n  'POST /api/update',   // binding\r\n  'ctx_abc123',         // contextId\r\n  null,                 // nonce (optional)\r\n  '{\"name\":\"John\"}'     // canonicalPayload\r\n);\r\n```\r\n\r\n#### `ashVerifyProof(expected: string, actual: string): boolean`\r\n\r\nVerifies two proofs match using constant-time comparison.\r\n\r\n```typescript\r\nconst isValid = ashVerifyProof(expectedProof, receivedProof);\r\n```\r\n\r\n### Binding Normalization\r\n\r\n#### `ashNormalizeBinding(method: string, path: string): string`\r\n\r\nNormalizes a binding string to canonical form.\r\n\r\n**Rules:**\r\n- Method uppercased\r\n- Path starts with /\r\n- Query string excluded\r\n- Duplicate slashes collapsed\r\n- Trailing slash removed (except for root)\r\n\r\n```typescript\r\nconst binding = ashNormalizeBinding('post', '/api//test/');\r\n// Result: 'POST /api/test'\r\n```\r\n\r\n### Secure Comparison\r\n\r\n#### `ashTimingSafeEqual(a: string, b: string): boolean`\r\n\r\nConstant-time string comparison to prevent timing attacks.\r\n\r\n```typescript\r\nconst isEqual = ashTimingSafeEqual('secret1', 'secret2');\r\n```\r\n\r\n### Version Information\r\n\r\n#### `ashVersion(): string`\r\n\r\nReturns the ASH protocol version (e.g., \"ASHv1\").\r\n\r\n#### `ashLibraryVersion(): string`\r\n\r\nReturns the library semantic version.\r\n\r\n## Types\r\n\r\n### AshMode\r\n\r\n```typescript\r\ntype AshMode = 'minimal' | 'balanced' | 'strict';\r\n```\r\n\r\n| Mode | Description |\r\n|------|-------------|\r\n| `minimal` | Basic integrity checking |\r\n| `balanced` | Recommended for most applications |\r\n| `strict` | Maximum security with nonce requirement |\r\n\r\n### AshContext\r\n\r\n```typescript\r\ninterface AshContext {\r\n  id: string;                          // Unique context identifier\r\n  binding: string;                     // Endpoint binding\r\n  expiresAt: number;                   // Expiration timestamp (Unix ms)\r\n  mode: AshMode;                       // Security mode\r\n  used: boolean;                       // Whether context has been used\r\n  nonce?: string;                      // Optional server-generated nonce\r\n  metadata?: Record<string, unknown>;  // Optional metadata\r\n}\r\n```\r\n\r\n### AshVerifyResult\r\n\r\n```typescript\r\ninterface AshVerifyResult {\r\n  valid: boolean;                      // Whether verification succeeded\r\n  errorCode?: string;                  // Error code if failed\r\n  errorMessage?: string;               // Error message if failed\r\n  metadata?: Record<string, unknown>;  // Context metadata (on success)\r\n}\r\n```\r\n\r\n### AshContextStore\r\n\r\n```typescript\r\ninterface AshContextStore {\r\n  create(options: AshContextOptions): Promise<AshContext>;\r\n  get(id: string): Promise<AshContext | null>;\r\n  consume(id: string): Promise<boolean>;\r\n  cleanup(): Promise<number>;\r\n}\r\n```\r\n\r\n## Context Stores\r\n\r\n### AshMemoryStore\r\n\r\nIn-memory store for development and testing.\r\n\r\n```typescript\r\nimport { AshMemoryStore } from '@3maem/ash-node';\r\n\r\nconst store = new AshMemoryStore();\r\n```\r\n\r\n### AshRedisStore\r\n\r\nProduction-ready store with atomic operations.\r\n\r\n```typescript\r\nimport { AshRedisStore } from '@3maem/ash-node';\r\nimport Redis from 'ioredis';\r\n\r\nconst redis = new Redis('redis://localhost:6379');\r\nconst store = new AshRedisStore(redis);\r\n```\r\n\r\n### AshSqlStore\r\n\r\nSQL-based store for relational databases.\r\n\r\n```typescript\r\nimport { AshSqlStore } from '@3maem/ash-node';\r\n\r\nconst store = new AshSqlStore(databaseConnection);\r\n```\r\n\r\n## Express Middleware\r\n\r\n### `ashExpressMiddleware(options: AshExpressOptions): RequestHandler`\r\n\r\nCreates ASH verification middleware for Express.\r\n\r\n```typescript\r\ninterface AshExpressOptions {\r\n  store: AshContextStore;              // Context store instance\r\n  expectedBinding?: string;            // Expected endpoint binding\r\n  mode?: AshMode;                      // Security mode (default: balanced)\r\n  onError?: (error, req, res, next) => void;  // Custom error handler\r\n  skip?: (req) => boolean;             // Skip verification condition\r\n}\r\n```\r\n\r\n### Usage\r\n\r\n```typescript\r\nimport express from 'express';\r\nimport { ashExpressMiddleware, AshMemoryStore } from '@3maem/ash-node';\r\n\r\nconst app = express();\r\nconst store = new AshMemoryStore();\r\n\r\n// Apply to specific route\r\napp.post(\r\n  '/api/update',\r\n  ashExpressMiddleware({\r\n    store,\r\n    expectedBinding: 'POST /api/update',\r\n  }),\r\n  handler\r\n);\r\n\r\n// Custom error handling\r\napp.post(\r\n  '/api/sensitive',\r\n  ashExpressMiddleware({\r\n    store,\r\n    onError: (error, req, res, next) => {\r\n      console.error('ASH verification failed:', error);\r\n      res.status(403).json({ error: error.code });\r\n    },\r\n  }),\r\n  handler\r\n);\r\n\r\n// Skip verification conditionally\r\napp.post(\r\n  '/api/data',\r\n  ashExpressMiddleware({\r\n    store,\r\n    skip: (req) => req.headers['x-internal'] === 'true',\r\n  }),\r\n  handler\r\n);\r\n```\r\n\r\n## Client Usage\r\n\r\nFor Node.js clients making requests to ASH-protected endpoints:\r\n\r\n```typescript\r\nimport { ashInit, ashCanonicalizeJson, ashBuildProof } from '@3maem/ash-node';\r\nimport axios from 'axios';\r\n\r\nashInit();\r\n\r\nasync function makeProtectedRequest() {\r\n  // 1. Get context from server\r\n  const { data: context } = await axios.post('https://api.example.com/ash/context');\r\n\r\n  // 2. Prepare payload\r\n  const payload = { name: 'John', action: 'update' };\r\n  const canonical = ashCanonicalizeJson(JSON.stringify(payload));\r\n\r\n  // 3. Build proof\r\n  const proof = ashBuildProof(\r\n    context.mode,\r\n    'POST /api/update',\r\n    context.contextId,\r\n    context.nonce ?? null,\r\n    canonical\r\n  );\r\n\r\n  // 4. Make protected request\r\n  const response = await axios.post(\r\n    'https://api.example.com/api/update',\r\n    payload,\r\n    {\r\n      headers: {\r\n        'X-ASH-Context-ID': context.contextId,\r\n        'X-ASH-Proof': proof,\r\n        'Content-Type': 'application/json',\r\n      },\r\n    }\r\n  );\r\n\r\n  return response.data;\r\n}\r\n```\r\n\r\n## Complete Server Example\r\n\r\n```typescript\r\nimport express from 'express';\r\nimport {\r\n  ashInit,\r\n  ashExpressMiddleware,\r\n  ashNormalizeBinding,\r\n  AshMemoryStore,\r\n} from '@3maem/ash-node';\r\n\r\nashInit();\r\n\r\nconst app = express();\r\nconst store = new AshMemoryStore();\r\n\r\napp.use(express.json());\r\n\r\n// Issue context endpoint\r\napp.post('/ash/context', async (req, res) => {\r\n  const { binding = 'POST /api/update', ttlMs = 30000 } = req.body;\r\n\r\n  const context = await store.create({\r\n    binding,\r\n    ttlMs,\r\n    mode: 'balanced',\r\n    metadata: { userId: req.headers['x-user-id'] },\r\n  });\r\n\r\n  res.json({\r\n    contextId: context.id,\r\n    expiresAt: context.expiresAt,\r\n    mode: context.mode,\r\n  });\r\n});\r\n\r\n// Protected endpoints\r\napp.post(\r\n  '/api/update',\r\n  ashExpressMiddleware({\r\n    store,\r\n    expectedBinding: 'POST /api/update',\r\n  }),\r\n  (req, res) => {\r\n    // Access context metadata\r\n    const ashContext = (req as any).ashContext;\r\n    console.log('User ID:', ashContext.metadata?.userId);\r\n\r\n    res.json({ status: 'success' });\r\n  }\r\n);\r\n\r\n// Global protection for /api/* routes\r\napp.use(\r\n  '/api',\r\n  ashExpressMiddleware({\r\n    store,\r\n    // Derive binding from request\r\n    expectedBinding: undefined,\r\n  })\r\n);\r\n\r\n// Cleanup expired contexts periodically\r\nsetInterval(async () => {\r\n  const cleaned = await store.cleanup();\r\n  console.log(`Cleaned up ${cleaned} expired contexts`);\r\n}, 60000);\r\n\r\napp.listen(3000, () => {\r\n  console.log('ASH-protected server running on port 3000');\r\n});\r\n```\r\n\r\n## Error Codes\r\n\r\n| Code | Description |\r\n|------|-------------|\r\n| `MISSING_CONTEXT_ID` | Missing X-ASH-Context-ID header |\r\n| `MISSING_PROOF` | Missing X-ASH-Proof header |\r\n| `INVALID_CONTEXT` | Invalid or expired context |\r\n| `CONTEXT_EXPIRED` | Context has expired |\r\n| `CONTEXT_USED` | Context already used (replay detected) |\r\n| `BINDING_MISMATCH` | Endpoint binding mismatch |\r\n| `PROOF_MISMATCH` | Proof verification failed |\r\n| `CANONICALIZATION_FAILED` | Failed to canonicalize payload |\r\n\r\n## License\r\n\r\n**ASH Source-Available License (ASAL-1.0)**\r\n\r\nSee the [LICENSE](https://github.com/3maem/ash/blob/main/LICENSE) for full terms.\r\n\r\n## Links\r\n\r\n- [Main Repository](https://github.com/3maem/ash)\r\n- [npm Package](https://www.npmjs.com/package/@3maem/ash-node)\r\n","readmeFilename":"README.md"}