From f081c41d7c9ff2608ce37310383ee691910799f7 Mon Sep 17 00:00:00 2001 From: "@chitcommit" <208086304+chitcommit@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:13:18 -0600 Subject: [PATCH 01/12] chore: add hono and wrangler dependencies for service layer Co-Authored-By: Claude Opus 4.6 --- package-lock.json | 1089 ++++++++++++++++++++++++++++++++++++++++++--- package.json | 11 +- 2 files changed, 1048 insertions(+), 52 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1957e83..b60488f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,153 @@ { "name": "@chitty/chittyproof", - "version": "0.0.0", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@chitty/chittyproof", - "version": "0.0.0", + "version": "1.0.0", + "dependencies": { + "hono": "^4.12.3" + }, "devDependencies": { - "vitest": "^4.0.16" + "vitest": "^4.0.16", + "wrangler": "^4.69.0" + } + }, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.2.tgz", + "integrity": "sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==", + "dev": true, + "license": "MIT OR Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@cloudflare/unenv-preset": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.14.0.tgz", + "integrity": "sha512-XKAkWhi1nBdNsSEoNG9nkcbyvfUrSjSf+VYVPfOto3gLTZVc3F4g6RASCMh6IixBKCG2yDgZKQIHGKtjcnLnKg==", + "dev": true, + "license": "MIT OR Apache-2.0", + "peerDependencies": { + "unenv": "2.0.0-rc.24", + "workerd": "^1.20260218.0" + }, + "peerDependenciesMeta": { + "workerd": { + "optional": true + } + } + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20260305.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260305.0.tgz", + "integrity": "sha512-chhKOpymo0Eh9J3nymrauMqKGboCc4uz/j0gA1G4gioMnKsN2ZDKJ+qjRZDnCoVGy8u2C4pxlmyIfsXCAfIzhQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20260305.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260305.0.tgz", + "integrity": "sha512-K9aG2OQk5bBfOP+fyGPqLcqZ9OR3ra6uwnxJ8f2mveq2A2LsCI7ZeGxQiAj75Ti80ytH/gJffZIx4Np2JtU3aQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20260305.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260305.0.tgz", + "integrity": "sha512-tt7XUoIw/cYFeGbkPkcZ6XX1aZm26Aju/4ih+DXxOosbBeGshFSrNJDBfAKKOvkjsAZymJ+WWVDBU+hmNaGfwA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20260305.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260305.0.tgz", + "integrity": "sha512-72QTkY5EzylmvCZ8ZTrnJ9DctmQsfSof1OKyOWqu/pv/B2yACfuPMikq8RpPxvVu7hhS0ztGP6ZvXz72Htq4Zg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20260305.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260305.0.tgz", + "integrity": "sha512-BA0uaQPOaI2F6mJtBDqplGnQQhpXCzwEMI33p/TnDxtSk9u8CGIfBFuI6uqo8mJ6ijIaPjeBLGOn2CiRMET4qg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" } }, "node_modules/@esbuild/aix-ppc64": { @@ -334,123 +473,623 @@ "node": ">=18" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", "cpu": [ - "arm64" + "s390x" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "openbsd" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "openbsd" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "openharmony" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "sunos" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", "cpu": [ "ia32" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { @@ -460,6 +1099,46 @@ "dev": true, "license": "MIT" }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@poppinss/colors": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz", + "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^4.1.5" + } + }, + "node_modules/@poppinss/dumper": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz", + "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@sindresorhus/is": "^7.0.2", + "supports-color": "^10.0.0" + } + }, + "node_modules/@poppinss/exception": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", + "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", + "dev": true, + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.59.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", @@ -810,6 +1489,26 @@ "win32" ] }, + "node_modules/@sindresorhus/is": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@speed-highlight/core": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.14.tgz", + "integrity": "sha512-G4ewlBNhUtlLvrJTb88d2mdy2KRijzs4UhnlrOSRT4bmjh/IqNElZa3zkrZ+TC47TwtlDWzVLFADljF1Ijp5hA==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", @@ -963,6 +1662,13 @@ "node": ">=12" } }, + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true, + "license": "MIT" + }, "node_modules/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", @@ -973,6 +1679,40 @@ "node": ">=18" } }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/es-module-lexer": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", @@ -1075,6 +1815,25 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/hono": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.3.tgz", + "integrity": "sha512-SFsVSjp8sj5UumXOOFlkZOG6XS9SJDKw0TbwFeV+AJ8xlST8kxK5Z/5EYa111UY8732lK2S/xB653ceuaoGwpg==", + "license": "MIT", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -1085,6 +1844,27 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/miniflare": { + "version": "4.20260305.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260305.0.tgz", + "integrity": "sha512-jVhtKJtiwaZa3rI+WgoLvSJmEazDsoUmAPYRUmEe2VO6VSbvkhbnDRm+dsPbYRatgNIExwrpqG1rv96jHiSb0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "sharp": "^0.34.5", + "undici": "7.18.2", + "workerd": "1.20260305.0", + "ws": "8.18.0", + "youch": "4.1.0-beta.10" + }, + "bin": { + "miniflare": "bootstrap.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -1115,6 +1895,13 @@ ], "license": "MIT" }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -1216,6 +2003,64 @@ "fsevents": "~2.3.2" } }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", @@ -1247,6 +2092,19 @@ "dev": true, "license": "MIT" }, + "node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -1291,6 +2149,34 @@ "node": ">=14.0.0" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/undici": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.18.2.tgz", + "integrity": "sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/unenv": { + "version": "2.0.0-rc.24", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", + "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3" + } + }, "node_modules/vite": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", @@ -1460,6 +2346,109 @@ "engines": { "node": ">=8" } + }, + "node_modules/workerd": { + "version": "1.20260305.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260305.0.tgz", + "integrity": "sha512-JkhfCLU+w+KbQmZ9k49IcDYc78GBo7eG8Mir8E2+KVjR7otQAmpcLlsous09YLh8WQ3Bt3Mi6/WMStvMAPukeA==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20260305.0", + "@cloudflare/workerd-darwin-arm64": "1.20260305.0", + "@cloudflare/workerd-linux-64": "1.20260305.0", + "@cloudflare/workerd-linux-arm64": "1.20260305.0", + "@cloudflare/workerd-windows-64": "1.20260305.0" + } + }, + "node_modules/wrangler": { + "version": "4.69.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.69.0.tgz", + "integrity": "sha512-EmVfIM65I5b4ITHe3Y9R7zQyf4NUBQ1leStakMlWiVR9n6VlDwuEltyQI2l3i0JciDnWyR3uqe+T6C08ivniTQ==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@cloudflare/kv-asset-handler": "0.4.2", + "@cloudflare/unenv-preset": "2.14.0", + "blake3-wasm": "2.1.5", + "esbuild": "0.27.3", + "miniflare": "4.20260305.0", + "path-to-regexp": "6.3.0", + "unenv": "2.0.0-rc.24", + "workerd": "1.20260305.0" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=20.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^4.20260305.0" + }, + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/youch": { + "version": "4.1.0-beta.10", + "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", + "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@poppinss/dumper": "^0.6.4", + "@speed-highlight/core": "^1.2.7", + "cookie": "^1.0.2", + "youch-core": "^0.3.3" + } + }, + "node_modules/youch-core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/exception": "^1.2.2", + "error-stack-parser-es": "^1.0.5" + } } } } diff --git a/package.json b/package.json index fdc9ba6..078cd06 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "private": true, "type": "module", + "main": "src/worker.js", "exports": { ".": { "import": "./src/lib/chittyproof-v2-canonical.js" @@ -16,9 +17,15 @@ } }, "scripts": { - "test": "vitest run" + "test": "vitest run", + "dev": "wrangler dev", + "deploy": "wrangler deploy" }, "devDependencies": { - "vitest": "^4.0.16" + "vitest": "^4.0.16", + "wrangler": "^4.69.0" + }, + "dependencies": { + "hono": "^4.12.3" } } From 5aab8496c8314b0cc8cb49afde9cea1a51b59c8c Mon Sep 17 00:00:00 2001 From: "@chitcommit" <208086304+chitcommit@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:13:22 -0600 Subject: [PATCH 02/12] chore: add wrangler.toml for Cloudflare Worker deployment Co-Authored-By: Claude Opus 4.6 --- wrangler.toml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 wrangler.toml diff --git a/wrangler.toml b/wrangler.toml new file mode 100644 index 0000000..2f970b1 --- /dev/null +++ b/wrangler.toml @@ -0,0 +1,22 @@ +name = "chittyproof" +main = "src/worker.js" +compatibility_date = "2025-09-01" +compatibility_flags = ["nodejs_compat"] + +[observability] +enabled = true + +[[tail_consumers]] +service = "chittytrack" + +[routes] +pattern = "proof.chitty.cc/*" +zone_name = "chitty.cc" + +[vars] +SERVICE_NAME = "chittyproof" +SERVICE_VERSION = "1.0.0" + +[[kv_namespaces]] +binding = "PROOF_KEY_CACHE" +id = "TBD" From ba746bc09ca5b55a146676ea9ca137e5258ace91 Mon Sep 17 00:00:00 2001 From: "@chitcommit" <208086304+chitcommit@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:13:26 -0600 Subject: [PATCH 03/12] feat: add SDK barrel export (src/index.js) Co-Authored-By: Claude Opus 4.6 --- src/index.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/index.js diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..071eb05 --- /dev/null +++ b/src/index.js @@ -0,0 +1,25 @@ +/** + * ChittyProof SDK — re-exports all public library functions. + * + * @module src/index + * @canon chittycanon://core/services/chittyproof + */ + +export { + roundN, + normalizeBundle, + canonicalize, + canonicalSignedPayload, + sha256Hex, + hashSignedPayload, + verifyBundle, +} from "./lib/chittyproof-v2-canonical.js"; + +export { + b64urlToBytes, + bytesToB64url, + hexToBytes, + importP256Jwk, + getPublicKeyByKid, + verifyECDSA, +} from "./lib/chittyproof-verify-ecdsa.js"; From e2f65d9e5ffb822bef8fbeed96cd79426ce79d62 Mon Sep 17 00:00:00 2001 From: "@chitcommit" <208086304+chitcommit@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:15:11 -0600 Subject: [PATCH 04/12] feat: add shared-secret Bearer token auth middleware Co-Authored-By: Claude Opus 4.6 --- src/middleware/auth.js | 24 ++++++++++++++++ tests/middleware/auth.test.js | 52 +++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/middleware/auth.js create mode 100644 tests/middleware/auth.test.js diff --git a/src/middleware/auth.js b/src/middleware/auth.js new file mode 100644 index 0000000..88be0b9 --- /dev/null +++ b/src/middleware/auth.js @@ -0,0 +1,24 @@ +/** + * Shared-secret Bearer token middleware. + * + * Matches the ecosystem pattern: compare incoming Bearer token + * against env.CHITTY_AUTH_SERVICE_TOKEN. + * + * @canon chittycanon://core/services/chittyproof + */ + +export async function bearerAuth(c, next) { + const expected = c.env.CHITTY_AUTH_SERVICE_TOKEN; + if (!expected) { + return c.json({ error: "unauthorized", message: "auth not configured" }, 401); + } + + const header = c.req.header("authorization"); + const token = header?.startsWith("Bearer ") ? header.slice(7) : null; + + if (!token || token !== expected) { + return c.json({ error: "unauthorized" }, 401); + } + + await next(); +} diff --git a/tests/middleware/auth.test.js b/tests/middleware/auth.test.js new file mode 100644 index 0000000..3f34094 --- /dev/null +++ b/tests/middleware/auth.test.js @@ -0,0 +1,52 @@ +import { describe, it, expect } from "vitest"; +import { Hono } from "hono"; +import { bearerAuth } from "../../src/middleware/auth.js"; + +function makeApp() { + const app = new Hono(); + app.use("/api/v1/*", bearerAuth); + app.get("/api/v1/test", (c) => c.json({ ok: true })); + return app; +} + +describe("bearerAuth middleware", () => { + it("returns 401 when no Authorization header is present", async () => { + const app = makeApp(); + const res = await app.request("/api/v1/test", {}, { CHITTY_AUTH_SERVICE_TOKEN: "secret-123" }); + expect(res.status).toBe(401); + const body = await res.json(); + expect(body.error).toBe("unauthorized"); + }); + + it("returns 401 when token does not match", async () => { + const app = makeApp(); + const res = await app.request( + "/api/v1/test", + { headers: { Authorization: "Bearer wrong-token" } }, + { CHITTY_AUTH_SERVICE_TOKEN: "secret-123" }, + ); + expect(res.status).toBe(401); + }); + + it("passes through when token matches", async () => { + const app = makeApp(); + const res = await app.request( + "/api/v1/test", + { headers: { Authorization: "Bearer secret-123" } }, + { CHITTY_AUTH_SERVICE_TOKEN: "secret-123" }, + ); + expect(res.status).toBe(200); + const body = await res.json(); + expect(body.ok).toBe(true); + }); + + it("returns 401 when CHITTY_AUTH_SERVICE_TOKEN is not configured", async () => { + const app = makeApp(); + const res = await app.request( + "/api/v1/test", + { headers: { Authorization: "Bearer anything" } }, + {}, + ); + expect(res.status).toBe(401); + }); +}); From f7e63e3ff374b4227b4198b115eb8d3724b0303f Mon Sep 17 00:00:00 2001 From: "@chitcommit" <208086304+chitcommit@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:17:41 -0600 Subject: [PATCH 05/12] feat: add /health and /api/v1/status endpoints Co-Authored-By: Claude Opus 4.6 --- src/routes/health.js | 25 +++++++++++++++++++++++++ tests/routes/health.test.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/routes/health.js create mode 100644 tests/routes/health.test.js diff --git a/src/routes/health.js b/src/routes/health.js new file mode 100644 index 0000000..4192124 --- /dev/null +++ b/src/routes/health.js @@ -0,0 +1,25 @@ +/** + * Health and status endpoints. + * + * GET /health — public health probe (ChittyRegister / ChittyBeacon) + * GET /api/v1/status — service metadata + * + * @canon chittycanon://core/services/chittyproof + */ + +const START_TIME = Date.now(); + +export function healthRoutes(app) { + app.get("/health", (c) => { + return c.json({ status: "ok", service: "chittyproof" }); + }); + + app.get("/api/v1/status", (c) => { + return c.json({ + service: c.env.SERVICE_NAME || "chittyproof", + version: c.env.SERVICE_VERSION || "unknown", + status: "ok", + uptime_ms: Date.now() - START_TIME, + }); + }); +} diff --git a/tests/routes/health.test.js b/tests/routes/health.test.js new file mode 100644 index 0000000..d5b970d --- /dev/null +++ b/tests/routes/health.test.js @@ -0,0 +1,34 @@ +import { describe, it, expect } from "vitest"; +import { Hono } from "hono"; +import { healthRoutes } from "../../src/routes/health.js"; + +function makeApp(env = {}) { + const app = new Hono(); + healthRoutes(app); + return { app, env }; +} + +describe("health routes", () => { + it("GET /health returns status ok", async () => { + const { app } = makeApp(); + const res = await app.request("/health"); + expect(res.status).toBe(200); + const body = await res.json(); + expect(body.status).toBe("ok"); + expect(body.service).toBe("chittyproof"); + }); + + it("GET /api/v1/status returns service metadata", async () => { + const { app } = makeApp(); + const res = await app.request("/api/v1/status", {}, { + SERVICE_NAME: "chittyproof", + SERVICE_VERSION: "1.0.0", + }); + expect(res.status).toBe(200); + const body = await res.json(); + expect(body.service).toBe("chittyproof"); + expect(body.version).toBe("1.0.0"); + expect(body.status).toBe("ok"); + expect(typeof body.uptime_ms).toBe("number"); + }); +}); From 964906ed02bad9cc8b04200d91d7249f908f4251 Mon Sep 17 00:00:00 2001 From: "@chitcommit" <208086304+chitcommit@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:19:28 -0600 Subject: [PATCH 06/12] feat: add POST /api/v1/verify endpoint (hash + ECDSA) Co-Authored-By: Claude Opus 4.6 --- src/routes/verify.js | 44 +++++++++++++++++++++++++++ tests/routes/verify.test.js | 59 +++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 src/routes/verify.js create mode 100644 tests/routes/verify.test.js diff --git a/src/routes/verify.js b/src/routes/verify.js new file mode 100644 index 0000000..8cda58b --- /dev/null +++ b/src/routes/verify.js @@ -0,0 +1,44 @@ +/** + * Bundle verification endpoint. + * + * POST /api/v1/verify — hash integrity + optional ECDSA verification. + * + * @canon chittycanon://core/services/chittyproof + */ + +import { verifyBundle } from "../lib/chittyproof-v2-canonical.js"; +import { verifyECDSA } from "../lib/chittyproof-verify-ecdsa.js"; + +export function verifyRoutes(app) { + app.post("/api/v1/verify", async (c) => { + let body; + try { + body = await c.req.json(); + } catch { + return c.json({ error: "bad_request", message: "invalid JSON" }, 400); + } + + const { bundle, ecdsa = true } = body; + if (!bundle || typeof bundle !== "object") { + return c.json({ error: "bad_request", message: "bundle is required" }, 400); + } + + const hashResult = await verifyBundle(bundle); + const result = { + hash_ok: hashResult.ok, + signed_fields_hash_expected: hashResult.signed_fields_hash_expected, + signed_fields_hash_got: hashResult.signed_fields_hash_got, + }; + + if (ecdsa && hashResult.ok) { + const ecdsaResult = await verifyECDSA(bundle, c.env); + result.ecdsa = { + ok: ecdsaResult.ok, + reason: ecdsaResult.reason, + kid: ecdsaResult.kid, + }; + } + + return c.json(result); + }); +} diff --git a/tests/routes/verify.test.js b/tests/routes/verify.test.js new file mode 100644 index 0000000..13e37ef --- /dev/null +++ b/tests/routes/verify.test.js @@ -0,0 +1,59 @@ +import { describe, it, expect } from "vitest"; +import { Hono } from "hono"; +import { verifyRoutes } from "../../src/routes/verify.js"; +import { hashSignedPayload } from "../../src/lib/chittyproof-v2-canonical.js"; +import { makeFactProofBundle } from "../helpers/fact-proof-bundle.js"; + +function makeApp() { + const app = new Hono(); + verifyRoutes(app); + return app; +} + +describe("POST /api/v1/verify", () => { + it("returns hash verification result for a valid bundle (ecdsa=false)", async () => { + const bundle = makeFactProofBundle(); + bundle.signature.signed_fields_hash = await hashSignedPayload(bundle); + + const app = makeApp(); + const res = await app.request("/api/v1/verify", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ bundle, ecdsa: false }), + }); + + expect(res.status).toBe(200); + const body = await res.json(); + expect(body.hash_ok).toBe(true); + expect(body.ecdsa).toBeUndefined(); + }); + + it("returns hash mismatch for a tampered bundle", async () => { + const bundle = makeFactProofBundle(); + // Don't set the hash to match — it will mismatch + + const app = makeApp(); + const res = await app.request("/api/v1/verify", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ bundle, ecdsa: false }), + }); + + expect(res.status).toBe(200); + const body = await res.json(); + expect(body.hash_ok).toBe(false); + }); + + it("returns 400 when bundle is missing", async () => { + const app = makeApp(); + const res = await app.request("/api/v1/verify", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({}), + }); + + expect(res.status).toBe(400); + const body = await res.json(); + expect(body.error).toBe("bad_request"); + }); +}); From 36ea9ee962e6042346f160ca5e1c1e658d682525 Mon Sep 17 00:00:00 2001 From: "@chitcommit" <208086304+chitcommit@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:21:52 -0600 Subject: [PATCH 07/12] feat: add POST /api/v1/canonicalize endpoint Co-Authored-By: Claude Opus 4.6 --- src/routes/canonicalize.js | 31 +++++++++++++++++++++++++++ tests/routes/canonicalize.test.js | 35 +++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/routes/canonicalize.js create mode 100644 tests/routes/canonicalize.test.js diff --git a/src/routes/canonicalize.js b/src/routes/canonicalize.js new file mode 100644 index 0000000..016e55d --- /dev/null +++ b/src/routes/canonicalize.js @@ -0,0 +1,31 @@ +/** + * Canonicalization endpoint. + * + * POST /api/v1/canonicalize — deterministic JSON output. + * + * @canon chittycanon://core/services/chittyproof + */ + +import { canonicalize } from "../lib/chittyproof-v2-canonical.js"; + +export function canonicalizeRoutes(app) { + app.post("/api/v1/canonicalize", async (c) => { + let body; + try { + body = await c.req.json(); + } catch { + return c.json({ error: "bad_request", message: "invalid JSON" }, 400); + } + + if (!("payload" in body)) { + return c.json({ error: "bad_request", message: "payload is required" }, 400); + } + + try { + const canonical = canonicalize(body.payload); + return c.json({ canonical }); + } catch (err) { + return c.json({ error: "bad_request", message: err.message }, 400); + } + }); +} diff --git a/tests/routes/canonicalize.test.js b/tests/routes/canonicalize.test.js new file mode 100644 index 0000000..d96c5d6 --- /dev/null +++ b/tests/routes/canonicalize.test.js @@ -0,0 +1,35 @@ +import { describe, it, expect } from "vitest"; +import { Hono } from "hono"; +import { canonicalizeRoutes } from "../../src/routes/canonicalize.js"; + +function makeApp() { + const app = new Hono(); + canonicalizeRoutes(app); + return app; +} + +describe("POST /api/v1/canonicalize", () => { + it("returns canonical JSON for an object", async () => { + const app = makeApp(); + const res = await app.request("/api/v1/canonicalize", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ payload: { z: 1, a: { y: true, x: false } } }), + }); + + expect(res.status).toBe(200); + const body = await res.json(); + expect(body.canonical).toBe('{"a":{"x":false,"y":true},"z":1}'); + }); + + it("returns 400 when payload is missing", async () => { + const app = makeApp(); + const res = await app.request("/api/v1/canonicalize", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({}), + }); + + expect(res.status).toBe(400); + }); +}); From 5f858dcbe16ed44957d22c644a370d2eed9653e7 Mon Sep 17 00:00:00 2001 From: "@chitcommit" <208086304+chitcommit@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:22:37 -0600 Subject: [PATCH 08/12] feat: add POST /api/v1/hash endpoint Co-Authored-By: Claude Opus 4.6 --- src/routes/hash.js | 32 ++++++++++++++++++++++++++++++ tests/routes/hash.test.js | 41 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 src/routes/hash.js create mode 100644 tests/routes/hash.test.js diff --git a/src/routes/hash.js b/src/routes/hash.js new file mode 100644 index 0000000..ef032ee --- /dev/null +++ b/src/routes/hash.js @@ -0,0 +1,32 @@ +/** + * Hash endpoint. + * + * POST /api/v1/hash — SHA-256 of canonical signed payload. + * + * @canon chittycanon://core/services/chittyproof + */ + +import { hashSignedPayload } from "../lib/chittyproof-v2-canonical.js"; + +export function hashRoutes(app) { + app.post("/api/v1/hash", async (c) => { + let body; + try { + body = await c.req.json(); + } catch { + return c.json({ error: "bad_request", message: "invalid JSON" }, 400); + } + + const { bundle } = body; + if (!bundle || typeof bundle !== "object") { + return c.json({ error: "bad_request", message: "bundle is required" }, 400); + } + + try { + const signed_fields_hash = await hashSignedPayload(bundle); + return c.json({ signed_fields_hash }); + } catch (err) { + return c.json({ error: "bad_request", message: err.message }, 400); + } + }); +} diff --git a/tests/routes/hash.test.js b/tests/routes/hash.test.js new file mode 100644 index 0000000..05bf2c9 --- /dev/null +++ b/tests/routes/hash.test.js @@ -0,0 +1,41 @@ +import { describe, it, expect } from "vitest"; +import { Hono } from "hono"; +import { hashRoutes } from "../../src/routes/hash.js"; +import { hashSignedPayload } from "../../src/lib/chittyproof-v2-canonical.js"; +import { makeFactProofBundle } from "../helpers/fact-proof-bundle.js"; + +function makeApp() { + const app = new Hono(); + hashRoutes(app); + return app; +} + +describe("POST /api/v1/hash", () => { + it("returns sha256 hash of canonical signed payload", async () => { + const bundle = makeFactProofBundle(); + const expectedHash = await hashSignedPayload(bundle); + + const app = makeApp(); + const res = await app.request("/api/v1/hash", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ bundle }), + }); + + expect(res.status).toBe(200); + const body = await res.json(); + expect(body.signed_fields_hash).toBe(expectedHash); + expect(body.signed_fields_hash).toMatch(/^sha256:[0-9a-f]{64}$/); + }); + + it("returns 400 when bundle is missing", async () => { + const app = makeApp(); + const res = await app.request("/api/v1/hash", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({}), + }); + + expect(res.status).toBe(400); + }); +}); From 4c31a1359199cc7f40c27890e339a53290e42280 Mon Sep 17 00:00:00 2001 From: "@chitcommit" <208086304+chitcommit@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:23:31 -0600 Subject: [PATCH 09/12] feat: add POST /api/v1/validate endpoint (schema validation) Co-Authored-By: Claude Opus 4.6 --- src/routes/validate.js | 85 +++++++++++++++++++++++++++++++++++ tests/routes/validate.test.js | 71 +++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 src/routes/validate.js create mode 100644 tests/routes/validate.test.js diff --git a/src/routes/validate.js b/src/routes/validate.js new file mode 100644 index 0000000..b2a7a0d --- /dev/null +++ b/src/routes/validate.js @@ -0,0 +1,85 @@ +/** + * Schema validation endpoint. + * + * POST /api/v1/validate — validate a bundle against FACT v2 schema. + * Checks required fields, const values, and top-level structure. + * + * @canon chittycanon://core/services/chittyproof + */ + +import { readFileSync } from "node:fs"; + +const schema = JSON.parse( + readFileSync( + new URL( + "../../etc/authority/schema/chittyproof-v2-fact-bundle.schema.json", + import.meta.url, + ), + "utf8", + ), +); + +function validateRequired(obj, requiredFields, path) { + const errors = []; + for (const field of requiredFields) { + if (obj[field] === undefined || obj[field] === null) { + errors.push({ field: path ? `${path}.${field}` : field, error: "required" }); + } + } + return errors; +} + +function validateConst(obj, field, expected, path) { + const fullPath = path ? `${path}.${field}` : field; + if (obj[field] !== undefined && obj[field] !== expected) { + return [{ field: fullPath, error: `must be "${expected}", got "${obj[field]}"` }]; + } + return []; +} + +export function validateRoutes(app) { + app.post("/api/v1/validate", async (c) => { + let body; + try { + body = await c.req.json(); + } catch { + return c.json({ error: "bad_request", message: "invalid JSON" }, 400); + } + + const { bundle } = body; + if (!bundle || typeof bundle !== "object") { + return c.json({ error: "bad_request", message: "bundle is required" }, 400); + } + + const errors = []; + + // Top-level required fields + errors.push(...validateRequired(bundle, schema.required, "")); + + // Const values + errors.push(...validateConst(bundle, "proof_version", "2.0.0", "")); + errors.push(...validateConst(bundle, "ruleset_id", "chittyproof-v2-fact-default", "")); + + // Nested required fields + if (bundle.fact && typeof bundle.fact === "object") { + errors.push(...validateRequired(bundle.fact, schema.properties.fact.required, "fact")); + errors.push(...validateConst(bundle.fact, "status", "sealed", "fact")); + } + if (bundle.ledger && typeof bundle.ledger === "object") { + errors.push(...validateRequired(bundle.ledger, schema.properties.ledger.required, "ledger")); + } + if (bundle.chain && typeof bundle.chain === "object") { + errors.push(...validateRequired(bundle.chain, schema.properties.chain.required, "chain")); + } + if (bundle.score && typeof bundle.score === "object") { + errors.push(...validateRequired(bundle.score, schema.properties.score.required, "score")); + } + if (bundle.pillars && typeof bundle.pillars === "object") { + errors.push( + ...validateRequired(bundle.pillars, schema.properties.pillars.required, "pillars"), + ); + } + + return c.json({ valid: errors.length === 0, errors }); + }); +} diff --git a/tests/routes/validate.test.js b/tests/routes/validate.test.js new file mode 100644 index 0000000..48a002c --- /dev/null +++ b/tests/routes/validate.test.js @@ -0,0 +1,71 @@ +import { describe, it, expect } from "vitest"; +import { Hono } from "hono"; +import { validateRoutes } from "../../src/routes/validate.js"; +import { makeFactProofBundle } from "../helpers/fact-proof-bundle.js"; + +function makeApp() { + const app = new Hono(); + validateRoutes(app); + return app; +} + +describe("POST /api/v1/validate", () => { + it("returns valid for a well-formed FACT v2 bundle", async () => { + const bundle = makeFactProofBundle(); + + const app = makeApp(); + const res = await app.request("/api/v1/validate", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ bundle }), + }); + + expect(res.status).toBe(200); + const body = await res.json(); + expect(body.valid).toBe(true); + expect(body.errors).toHaveLength(0); + }); + + it("returns invalid when required fields are missing", async () => { + const app = makeApp(); + const res = await app.request("/api/v1/validate", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ bundle: { proof_version: "2.0.0" } }), + }); + + expect(res.status).toBe(200); + const body = await res.json(); + expect(body.valid).toBe(false); + expect(body.errors.length).toBeGreaterThan(0); + }); + + it("returns invalid when proof_version is wrong", async () => { + const bundle = makeFactProofBundle({ proof_version: "1.0.0" }); + + const app = makeApp(); + const res = await app.request("/api/v1/validate", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ bundle }), + }); + + expect(res.status).toBe(200); + const body = await res.json(); + expect(body.valid).toBe(false); + expect(body.errors).toContainEqual( + expect.objectContaining({ field: "proof_version" }), + ); + }); + + it("returns 400 when bundle is missing", async () => { + const app = makeApp(); + const res = await app.request("/api/v1/validate", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({}), + }); + + expect(res.status).toBe(400); + }); +}); From 9f996d933598c09534f4d70b44270a5ff8f2b230 Mon Sep 17 00:00:00 2001 From: "@chitcommit" <208086304+chitcommit@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:25:59 -0600 Subject: [PATCH 10/12] feat: add Hono Worker entry point wiring all routes and auth Co-Authored-By: Claude Opus 4.6 --- src/worker.js | 44 ++++++++++++++++++++++++++++++++++++ tests/worker.test.js | 54 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 src/worker.js create mode 100644 tests/worker.test.js diff --git a/src/worker.js b/src/worker.js new file mode 100644 index 0000000..b9e3946 --- /dev/null +++ b/src/worker.js @@ -0,0 +1,44 @@ +/** + * ChittyProof Cloudflare Worker — Hono HTTP layer. + * + * Wraps the pure-function library core with authenticated HTTP endpoints + * at proof.chitty.cc. + * + * @module src/worker + * @canon chittycanon://core/services/chittyproof + */ + +import { Hono } from "hono"; +import { bearerAuth } from "./middleware/auth.js"; +import { healthRoutes } from "./routes/health.js"; +import { verifyRoutes } from "./routes/verify.js"; +import { canonicalizeRoutes } from "./routes/canonicalize.js"; +import { hashRoutes } from "./routes/hash.js"; +import { validateRoutes } from "./routes/validate.js"; + +const app = new Hono(); + +// Global error handler — surface library errors as 400 bad_request +app.onError((err, c) => { + return c.json({ error: "bad_request", message: err.message }, 400); +}); + +// Public routes (no auth) +healthRoutes(app); + +// Authenticated routes +app.use("/api/v1/verify", bearerAuth); +app.use("/api/v1/canonicalize", bearerAuth); +app.use("/api/v1/hash", bearerAuth); +app.use("/api/v1/validate", bearerAuth); +verifyRoutes(app); +canonicalizeRoutes(app); +hashRoutes(app); +validateRoutes(app); + +// 404 fallback +app.notFound((c) => { + return c.json({ error: "not_found", message: `${c.req.method} ${c.req.path} not found` }, 404); +}); + +export default app; diff --git a/tests/worker.test.js b/tests/worker.test.js new file mode 100644 index 0000000..cbda96c --- /dev/null +++ b/tests/worker.test.js @@ -0,0 +1,54 @@ +import { describe, it, expect } from "vitest"; +import app from "../src/worker.js"; + +const ENV = { + CHITTY_AUTH_SERVICE_TOKEN: "test-token-123", + SERVICE_NAME: "chittyproof", + SERVICE_VERSION: "1.0.0", +}; + +describe("worker (integration)", () => { + it("GET /health is public and returns ok", async () => { + const res = await app.request("/health", {}, ENV); + expect(res.status).toBe(200); + const body = await res.json(); + expect(body.status).toBe("ok"); + expect(body.service).toBe("chittyproof"); + }); + + it("GET /api/v1/status is public", async () => { + const res = await app.request("/api/v1/status", {}, ENV); + expect(res.status).toBe(200); + const body = await res.json(); + expect(body.service).toBe("chittyproof"); + }); + + it("POST /api/v1/verify requires auth", async () => { + const res = await app.request("/api/v1/verify", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ bundle: {}, ecdsa: false }), + }, ENV); + + expect(res.status).toBe(401); + }); + + it("POST /api/v1/verify works with valid auth", async () => { + const res = await app.request("/api/v1/verify", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer test-token-123", + }, + body: JSON.stringify({ bundle: {}, ecdsa: false }), + }, ENV); + + // 400 because empty bundle, but NOT 401 + expect(res.status).toBe(400); + }); + + it("returns 404 for unknown routes", async () => { + const res = await app.request("/nonexistent", {}, ENV); + expect(res.status).toBe(404); + }); +}); From 2c8e2e9da9e1f2228f5564b7bf54e27c29acdddd Mon Sep 17 00:00:00 2001 From: "@chitcommit" <208086304+chitcommit@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:28:16 -0600 Subject: [PATCH 11/12] docs: update compliance triad for dual-export service transformation CHARTER.md: artifact type, HTTP endpoints table, expanded dependencies CHITTY.md: architecture, stack, endpoints, expanded consumers CLAUDE.md: full project structure, dual-export architecture, new commands Co-Authored-By: Claude Opus 4.6 --- CHARTER.md | 21 ++++++++++++++++++--- CHITTY.md | 30 +++++++++++++++++++++++++----- CLAUDE.md | 38 ++++++++++++++++++++++++++++++++------ 3 files changed, 75 insertions(+), 14 deletions(-) diff --git a/CHARTER.md b/CHARTER.md index 78fcde5..53dce7d 100644 --- a/CHARTER.md +++ b/CHARTER.md @@ -22,7 +22,7 @@ category: infrastructure - **Tier**: 0 (Trust Anchors) - **Organization**: CHITTYOS - **Domain**: proof.chitty.cc -- **Artifact Type**: Library (consumed by services, not deployed standalone) +- **Artifact Type**: Library + Service (dual-export at proof.chitty.cc) ## Mission @@ -38,6 +38,7 @@ Provide deterministic, court-grade cryptographic integrity primitives for the Ch - JWKS key resolution with KV caching (kid-based lookup via ChittyCert) - Defining the authoritative FACT v2 bundle JSON Schema - Providing `normalizeBundle` / `canonicalSignedPayload` / `verifyBundle` / `verifyECDSA` exports +- Serving HTTP verification endpoints at `proof.chitty.cc` for ecosystem consumers ### IS NOT Responsible For - Signing bundles (signing authority lives in the minting service) @@ -52,12 +53,16 @@ Provide deterministic, court-grade cryptographic integrity primitives for the Ch | Type | Service | Purpose | |------|---------|---------| | Upstream | ChittyCert | JWKS endpoint for public key resolution | +| Upstream | ChittyAuth | Shared-secret Bearer token validation | | Runtime | Web Crypto API | SHA-256 digest, ECDSA verify, key import | +| Runtime | Hono | HTTP framework for Cloudflare Workers | | Optional | Cloudflare KV | JWKS key caching (`PROOF_KEY_CACHE` binding) | +| Downstream | ChittyTrack | Automatic log/trace aggregation (tail_consumers) | +| Downstream | ChittyBeacon | Health monitoring (probes /health) | ## API Contract -ChittyProof is a library — it exports functions, not HTTP endpoints. +ChittyProof is both a library (SDK exports) and a deployed service (HTTP endpoints at proof.chitty.cc). ### Exports (`lib/chittyproof-v2-canonical.js`) | Export | Signature | Purpose | @@ -80,6 +85,16 @@ ChittyProof is a library — it exports functions, not HTTP endpoints. | `getPublicKeyByKid` | `(kid, env, opts?) => Promise` | KV-cached JWKS key resolution | | `verifyECDSA` | `(bundle, env, opts?) => Promise<{ok, reason, ...}>` | Full ECDSA signature verification | +### HTTP Endpoints (proof.chitty.cc) +| Method | Path | Auth | Purpose | +|--------|------|------|---------| +| GET | `/health` | None | Health probe | +| GET | `/api/v1/status` | None | Service metadata | +| POST | `/api/v1/verify` | Bearer | Hash integrity + ECDSA verification | +| POST | `/api/v1/canonicalize` | Bearer | Deterministic JSON canonicalization | +| POST | `/api/v1/hash` | Bearer | SHA-256 of canonical signed payload | +| POST | `/api/v1/validate` | Bearer | FACT v2 bundle schema validation | + ### Schema - `etc/authority/schema/chittyproof-v2-fact-bundle.schema.json` - `$id`: `chittycanon://schemas/chittyproof/v2/fact-bundle` @@ -98,7 +113,7 @@ ChittyProof is a library — it exports functions, not HTTP endpoints. - [x] CHARTER.md present - [x] CHITTY.md present - [x] CLAUDE.md present -- [x] Tests passing (10/10 vitest) +- [x] Tests passing (32/32 vitest) - [x] JSON Schema with canonical $id - [x] Canonical frontmatter with tech domain - [x] Package exports map defined diff --git a/CHITTY.md b/CHITTY.md index 30ed142..6d25f7c 100644 --- a/CHITTY.md +++ b/CHITTY.md @@ -21,23 +21,38 @@ category: infrastructure ## What It Does -Cryptographic integrity library for FACT v2 bundles. Provides deterministic JSON canonicalization, SHA-256 hashing, and ECDSA P-256 signature verification — the foundation that makes every fact in the ChittyOS ecosystem provably tamper-evident. +Cryptographic integrity library and service for FACT v2 bundles. Provides deterministic JSON canonicalization, SHA-256 hashing, and ECDSA P-256 signature verification — the foundation that makes every fact in the ChittyOS ecosystem provably tamper-evident. Available both as a library (SDK import) and as HTTP endpoints at `proof.chitty.cc`. ## Architecture -Pure JavaScript ESM library consumed by ChittyOS services. Runs anywhere the Web Crypto API is available (Cloudflare Workers, Node 20+, Deno, browsers). +Dual-export: pure JavaScript ESM library (SDK consumers import directly) + Hono Worker deployed at `proof.chitty.cc` (HTTP consumers). Library core runs anywhere the Web Crypto API is available (Workers, Node 20+, Deno, browsers). ### Stack - **Language**: JavaScript (ESM) +- **HTTP**: Hono on Cloudflare Workers - **Crypto**: Web Crypto API (SHA-256, ECDSA P-256) +- **Auth**: Shared-secret Bearer token (`CHITTY_AUTH_SERVICE_TOKEN`) - **Testing**: Vitest - **Key Authority**: ChittyCert JWKS (`cert.chitty.cc/.well-known/jwks.json`) ### Key Components +- `src/index.js` — SDK barrel export (library consumers) +- `src/worker.js` — Hono Worker entry point (HTTP consumers) - `src/lib/chittyproof-v2-canonical.js` — Canonicalization, normalization, hashing - `src/lib/chittyproof-verify-ecdsa.js` — ECDSA P-256 verification, JWKS resolution +- `src/routes/` — HTTP route handlers (health, verify, canonicalize, hash, validate) +- `src/middleware/auth.js` — Shared-secret Bearer token middleware - `etc/authority/schema/chittyproof-v2-fact-bundle.schema.json` — FACT v2 bundle schema -- `tests/helpers/fact-proof-bundle.js` — Test fixture factory + +### Endpoints +| Method | Path | Auth | Purpose | +|--------|------|------|---------| +| GET | `/health` | None | Health probe | +| GET | `/api/v1/status` | None | Service metadata | +| POST | `/api/v1/verify` | Bearer | Hash + ECDSA verification | +| POST | `/api/v1/canonicalize` | Bearer | Deterministic JSON | +| POST | `/api/v1/hash` | Bearer | SHA-256 of canonical payload | +| POST | `/api/v1/validate` | Bearer | FACT v2 schema validation | ### Design Principles - **Deterministic**: Same input always produces the same canonical JSON and hash, across all runtimes @@ -53,13 +68,16 @@ Pure JavaScript ESM library consumed by ChittyOS services. Runs anywhere the Web - **Last Certified**: 2026-03-01 ### ChittyDNA -- **Lineage**: root (foundational library) -- **Role**: Integrity primitive — consumed by any service that mints, seals, or verifies FACT bundles +- **Lineage**: root (foundational library + service) +- **Role**: Integrity primitive — consumed by any service that mints, seals, or verifies FACT bundles (SDK import or HTTP call) ### Dependencies | Service | Purpose | |---------|---------| | ChittyCert | JWKS public key hosting for signature verification | +| ChittyAuth | Shared-secret Bearer token validation | +| ChittyTrack | Log/trace aggregation (tail_consumers) | +| ChittyBeacon | Health monitoring (probes /health) | ### Consumers | Service | Usage | @@ -68,6 +86,8 @@ Pure JavaScript ESM library consumed by ChittyOS services. Runs anywhere the Web | ChittyEvidence | Evidence integrity checks | | ChittyLedger | Seal verification at ledger write | | ChittyCases | Bundle verification for case presentation | +| ChittySign | Canonical hash for signing counterpart | +| DocuMint | Bundle verification (library or HTTP) | ### Exports | Module | Key Functions | diff --git a/CLAUDE.md b/CLAUDE.md index 0798262..9680359 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # CLAUDE.md — ChittyProof -Cryptographic integrity library for FACT v2 bundle canonicalization, hashing, and ECDSA P-256 signature verification. +Cryptographic integrity library and service for FACT v2 bundle canonicalization, hashing, and ECDSA P-256 signature verification. **Canonical URI**: `chittycanon://core/services/chittyproof` **Tier**: 0 (Trust Anchors) @@ -10,16 +10,29 @@ Cryptographic integrity library for FACT v2 bundle canonicalization, hashing, an ```bash npm test # Run vitest (all tests) -npx vitest run # Same, explicit +npm run dev # Start local dev server (wrangler dev) +npm run deploy # Deploy to Cloudflare Workers +npx vitest run # Same as npm test, explicit npx vitest watch # Watch mode ``` ## Project Structure ``` -src/lib/ - chittyproof-v2-canonical.js # Canonicalization, normalization, SHA-256 hashing - chittyproof-verify-ecdsa.js # ECDSA P-256 verification, JWKS key resolution +src/ + index.js # SDK barrel export (library consumers) + worker.js # Hono Worker entry point (HTTP consumers) + lib/ + chittyproof-v2-canonical.js # Canonicalization, normalization, SHA-256 hashing + chittyproof-verify-ecdsa.js # ECDSA P-256 verification, JWKS key resolution + routes/ + health.js # GET /health, GET /api/v1/status + verify.js # POST /api/v1/verify + canonicalize.js # POST /api/v1/canonicalize + hash.js # POST /api/v1/hash + validate.js # POST /api/v1/validate + middleware/ + auth.js # Shared-secret Bearer token etc/authority/schema/ chittyproof-v2-fact-bundle.schema.json # FACT v2 bundle JSON Schema @@ -28,11 +41,20 @@ tests/ helpers/fact-proof-bundle.js # Test fixture factory (makeFactProofBundle) lib/chittyproof-v2-canonical.test.js # Canonicalization + hash tests lib/chittyproof-verify-ecdsa.test.js # ECDSA verification tests + middleware/auth.test.js # Auth middleware tests + routes/ # Route handler tests + worker.test.js # Integration tests ``` ## Architecture -This is a **library**, not a deployable service. It exports pure functions that run on any Web Crypto API runtime (Workers, Node 20+, Deno, browsers). +This is a **dual-export** project: a library (for in-process consumers) and a deployed service at `proof.chitty.cc` (for HTTP consumers). + +- `src/index.js` — SDK barrel export (library consumers import from here) +- `src/worker.js` — Hono Worker entry point (Cloudflare Workers deployment) +- `src/lib/` — Pure function core (unchanged from library-only days) +- `src/routes/` — HTTP route handlers wrapping the library functions +- `src/middleware/` — Auth middleware (shared-secret Bearer token) ### Canonicalization Pipeline 1. `normalizeBundle` — round score/pillar fields to deterministic precision, compute `score_100` @@ -48,7 +70,9 @@ This is a **library**, not a deployable service. It exports pure functions that 4. `crypto.subtle.verify` ECDSA P-256 over the hash bytes ### Key Dependencies +- **Hono** — HTTP framework for Cloudflare Workers - **ChittyCert** (`cert.chitty.cc/.well-known/jwks.json`) — public key authority +- **ChittyAuth** — shared-secret Bearer token (`CHITTY_AUTH_SERVICE_TOKEN`) - **KV binding** (`PROOF_KEY_CACHE`) — optional JWKS cache for Workers consumers ## Patterns @@ -58,3 +82,5 @@ This is a **library**, not a deployable service. It exports pure functions that - Non-finite numbers throw — no `NaN` or `Infinity` in canonical payloads - Base64url encoding/decoding handles padding normalization internally - `structuredClone` is used for immutable normalization (no mutation of input bundles) +- Routes are thin wrappers around library functions — no business logic in route handlers +- Auth middleware uses simple string comparison against `env.CHITTY_AUTH_SERVICE_TOKEN` From ce6d9fd4626396a0ad960a01fb3d670d547a6e25 Mon Sep 17 00:00:00 2001 From: "@chitcommit" <208086304+chitcommit@users.noreply.github.com> Date: Tue, 3 Mar 2026 12:53:39 -0600 Subject: [PATCH 12/12] ci: add GitHub Actions workflow for test automation Runs npm test on push to main and on pull requests. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/ci.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..29b7c89 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,26 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run tests + run: npm test