Skip to content

Protect and validate newsletter submissions - #206

Merged
truthixify merged 14 commits into
wraith-protocol:developfrom
Nacho1499:bug/Rate-limit
Oct 21, 2026
Merged

truthixify merged 14 commits into
wraith-protocol:developfrom
Nacho1499:bug/Rate-limit

Conversation

@Nacho1499

Copy link
Copy Markdown
Contributor

Closes #186

Summary

  • Rate limit submissions to five per client IP every 15 minutes using Vercel’s trusted x-vercel-forwarded-for header; return stable 429 responses with Retry-After.
  • Collapse concurrent submissions for the same normalized email and return the same success response for new and existing addresses.
  • Require JSON, limit request bodies to 2,048 bytes, and allow only the newsletter and careers tags.
  • Document the safeguards and update newsletter UI behavior.

Verification

  • Build passed.
  • Unit tests: 368 passed.
  • Smoke tests: 17 passed.
  • Accessibility tests: 15 passed.

Note: The in-memory rate limit and deduplication are scoped to each warm serverless instance.

@Nacho1499
Nacho1499 requested a review from truthixify as a code owner October 19, 2026 08:54
@vercel

vercel Bot commented Oct 19, 2026

Copy link
Copy Markdown

@Nacho1499 is attempting to deploy a commit to the truthixify's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Oct 19, 2026

Copy link
Copy Markdown

@Nacho1499 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@truthixify truthixify left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This head is not syntactically valid: tests/subscribe.test.ts reaches EOF with a missing closing brace, so the unit suite cannot collect it and the build and formatting job fails. It also defines scripts.build twice in package.json; JSON keeps only the second value, so the new SDK-size check is silently discarded. Please fix the test structure, keep one build script with the intended gates, format the changed files, and rerun the required checks.

@truthixify truthixify left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prior syntax and build-script blockers are fixed, and the focused tests and production build pass. The 2,048-byte body limit is still bypassable, though: the handler measures JSON.stringify(req.body) after the raw request has already been buffered and parsed. A chunked request containing 4,096 bytes of whitespace plus a small valid JSON object has no Content-Length and returns 201 in the submitted preview server. Enforce the limit while reading raw bytes before JSON parsing, or configure an equivalent platform-level raw-body limit, then add a chunked/whitespace regression that proves the provider is not called after the limit is crossed.

Read the request stream directly and stop once 2,048 bytes are crossed,
so whitespace padding and chunked uploads without Content-Length can no
longer bypass the limit. The preview server now passes the request
through unread. Adds unit and smoke regressions proving the provider is
not called after the limit is crossed.
@Nacho1499

Copy link
Copy Markdown
Contributor Author

done

@truthixify truthixify left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The raw-stream byte limit fixes the prior chunked whitespace bypass, and the local build plus 53 focused tests pass. One correctness blocker remains: inFlightSubmissions is keyed only by normalized email, while the endpoint accepts both newsletter and careers tags. Concurrent requests for the same address with different tags collapse into one provider call, silently dropping the second tag while returning success. Key deduplication by email plus tag, or explicitly merge tag intents, and add a concurrent cross-tag regression test.

@Nacho1499

Copy link
Copy Markdown
Contributor Author

done

@truthixify truthixify left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous blocker resolved. In-flight deduplication is now keyed by normalized email plus validated tag, so newsletter and careers submissions for the same address no longer collapse into one upstream request. Local production build, format check, and 33 focused tests passed.

@truthixify
truthixify merged commit b7420ae into wraith-protocol:develop Oct 21, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Wave 10][Carryover] Rate limit, deduplicate, and validate newsletter submissions

2 participants