Cleanup: drop Vercel path, wire rate-limit env vars, add tests, harden CI, refresh docs - #29
Merged
Merged
Conversation
…n CI, refresh docs - Remove the unused Vercel deployment (api/, vercel.json, .vercelignore, root tsconfig.json) plus dead start-dev.js, server/package.json.backup and server/tsconfig.node.json; Cloudflare Pages is the only target - Read WORKSHEET_/GENERAL_RATE_LIMIT_* from the environment (validated positive integers) instead of documenting knobs that were never read; drop the never-implemented MAX_REQUEST_SIZE from docs - Fix dev-port drift: .env.example/README/vite proxy now say 3001 and the vite proxy no longer strips the /api prefix - Add tests: request schema + rate-limit config (node:test via tsx) and the Cloudflare function (stubbed fetch, in-memory KV); npm test runs both and CI runs it - CI: permissions: contents: read, SHA-pinned actions, persist-credentials off, typecheck includes tests; Dependabot covers github-actions - Add favicon.svg (index.html pointed at a missing /vite.svg) - Rewrite README/server README to match the actual stack and Cloudflare deployment Co-Authored-By: Jason Maycock <jason@southbaycreations.com>
Contributor
Author
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
southbayjay
added a commit
that referenced
this pull request
Sep 23, 2026
cors/dotenv/express and their @types were only imported by api/*, removed in #29. The server workspace declares its own copies, so the lockfile still hoists them for server/. Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Jason Maycock <jason@southbaycreations.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Cleanup/docs/CI third of the security review. No runtime behaviour change for anyone using the defaults; the one deployment-relevant change is that the repo is now explicitly Cloudflare Pages only.
Removed dead Vercel deployment path —
api/(4 files, incl. the un-rate-limitedgenerate-worksheet.jscopy and two duplicate health handlers),vercel.json,.vercelignore, roottsconfig.json(only includedapi/**/*.ts), clientvercel-buildscript. Also droppedstart-dev.js(superseded by rootnpm run dev),server/package.json.backup,server/tsconfig.node.json(Vite leftover, server has no vite config). Rootpackage.jsonstill listscors/dotenv/express(onlyapi/used them) — left alone to avoid a lockfile conflict with #28; trivial follow-up once that lands.Rate-limit env vars are now real —
.env.example/README documentedWORKSHEET_RATE_LIMIT_*/GENERAL_RATE_LIMIT_*but nothing read them.worksheetSlowDownshares the worksheet window; 429 messages are derived from the configured values.MAX_REQUEST_SIZEwas never implemented on either runtime (both hard-code 1 KB) so it's removed from the docs rather than wired.Dev-port drift fixed —
.env.example, both READMEs and the Vite proxy said3000; the server and client constants use3001. The Vite proxy also hadrewrite: path.replace(/^\/api/, ''), which would have hit/generate-worksheet(404) had anything used it — removed..env.examplenow says up front that it belongs atserver/.env(whereconfig/index.tsactually loads it).Tests (new, run in CI via
npm test)test/cloudflare-function.test.mjs— importsonRequestPost/onRequestOptionsdirectly with an in-memory KV and a stubbedglobalThis.fetchfor OpenAI: invalid bodies → 400 without an upstream call; happy path returns the worksheet +RateLimit-*; upstream error is masked; 11th request in a window → 429; foreign origin 403 / allow-listed origin 204.server/src/middleware/validation.test.ts—worksheetRequestSchemaagainst every UI grade label, bare grades/bands, length bounds, filter words, complexity enum,.strict().server/src/middleware/rateLimiting.test.ts— defaults, overrides, and startup failure on0/-5/1.5/ten(each case in a child process since limits are read at import).node:test(node --import tsx --teston the server). Newserver/tsconfig.eslint.jsonincludes test files so ESLint's typed parsing and atsc --noEmit -p tsconfig.eslint.jsoncover them without emitting them intodist/.CI / supply chain —
permissions: contents: read,actions/checkout+actions/setup-nodepinned to v4.4.0 commit SHAs,persist-credentials: false, Dependabotgithub-actionsecosystem added, removed the step that loaded the deleted Vercel handler, smoke test also asserts/favicon.svg(index.html pointed at a non-existent/vite.svg; a smallfavicon.svgis added underserver/client/public/).Docs — root README rewritten around the actual stack (React 19 / Vite 8 / Tailwind 4 / Express 5 / Node 22, Cloudflare Pages + Functions + KV, 3001) with a step-by-step Pages deployment section (encrypted
OPENAI_API_KEY,RATE_LIMIT_KVbinding, WAF rate rule, OpenAI spend cap).server/README.mdreplaced (it described Docker/PM2/models/app.tsthat don't exist) with an accurate layout + API reference. Note: the README's security section describes the state after #27 and #28 land (Helmet,_headers,TRUST_PROXY, output validation).Verified locally on Node 24:
npm test(15 tests pass), servertscincl. tests,eslint .(0 errors), clienttsc+vite build(favicon indist/), production server withWORKSHEET_RATE_LIMIT_MAX_REQUESTS=2→ third request 429 with the derived message.Link to Devin session: https://app.devin.ai/sessions/9385fb134d5f4dacb30bc28bd6bede11
Open in Devin Desktop: https://app.devin.ai/desktop/session/9385fb134d5f4dacb30bc28bd6bede11?variant=devin
Requested by: @southbayjay