Skip to content

feat: migrate Newsletter Service#5292

Open
princerajpoot20 wants to merge 10 commits intoasyncapi:masterfrom
princerajpoot20:phase1_migration
Open

feat: migrate Newsletter Service#5292
princerajpoot20 wants to merge 10 commits intoasyncapi:masterfrom
princerajpoot20:phase1_migration

Conversation

@princerajpoot20
Copy link
Copy Markdown
Member

@princerajpoot20 princerajpoot20 commented Mar 28, 2026

Resloves #5127 asyncapi/community#2223 Related: asyncapi/community#2223
Related PRs: asyncapi/community#3505 asyncapi/.github#396

Things need to be done later

  • Create an official account on Kit.com
  • Create these 3 tags: Newsletter, Meetings, TSC Voting and update the value in the config file. (As of now, the tag value are of my personal account)
  • Add the env secret. Key: KIT_API_KEY
  • Migrate data from Mailchimp to Kit.com

Testing Evidence

https://asyncapi.princerajpoot.com/en/newsletter

  • Filled form
image
  • Successfully subscribed
image
  • Verified entry via Kit.com
image
  • Verifed tag entry
image
  • Newsletter mail looks good.
Image
  • We also have an option to update preferences, which allows users to change the topics they receive, as well as update their name or email address.
Image

Summary by CodeRabbit

Release Notes

  • Refactor

    • Updated newsletter subscription handling with stricter input validation and comprehensive error response codes.
    • Added 15-second request timeout protection for newsletter subscription operations to prevent hanging requests.
  • Style

    • Updated email template footer styling for improved visual presentation.
  • Chores

    • Removed unused project dependencies.

@netlify
Copy link
Copy Markdown

netlify bot commented Mar 28, 2026

Deploy Preview for asyncapi-website ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 1cd8aeb
🔍 Latest deploy log https://app.netlify.com/projects/asyncapi-website/deploys/69e2493cff9eeb00083294cc
😎 Deploy Preview https://deploy-preview-5292--asyncapi-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 28, 2026

📝 Walkthrough

Walkthrough

The changes migrate newsletter subscription handling from Mailchimp to a Kit API-based approach. The Mailchimp configuration file and dependencies are removed, the subscription handler is refactored with new validation and timeout logic, and email footer styling is updated.

Changes

Cohort / File(s) Summary
Mailchimp Removal
config/mailchimp-config.json, package.json
Deleted Mailchimp config (listId and interest group mappings) and removed @mailchimp/mailchimp_marketing and md5 dependencies.
Kit API Migration
netlify/functions/newsletter_subscription.ts
Replaced Mailchimp client logic with two sequential Kit API calls (POST /subscribers, POST /tags/{tagId}/subscribers). Added AbortController-based timeout (15s), stricter JSON validation with fixed interest set, and new error mapping (502 for failed requests, 504 for timeouts, 503 for missing API key or tag ID).
Email Styling
.github/workflows/scripts/mailchimp/htmlContent.js
Wrapped "AsyncAPI Initiative" footer text in <span> with dark gray (#696969) inline color styling.

Sequence Diagram

sequenceDiagram
    actor Client
    participant Handler as newsletter_subscription<br/>handler
    participant KitAPI as Kit API
    
    Client->>Handler: POST /subscribe<br/>{email, interest}
    activate Handler
    
    Handler->>Handler: Validate JSON,<br/>email, interest
    
    Handler->>Handler: Check KIT_API_KEY<br/>and resolve tagId
    
    Handler->>KitAPI: POST /subscribers<br/>(email)
    activate KitAPI
    KitAPI-->>Handler: 200 or error
    deactivate KitAPI
    
    Handler->>KitAPI: POST /tags/{tagId}/subscribers<br/>(email)
    activate KitAPI
    KitAPI-->>Handler: 200 or error
    deactivate KitAPI
    
    Handler->>Handler: Map response<br/>(timeout, error,<br/>or success)
    
    Handler-->>Client: 200/400/502/503/504/500<br/>+ message
    deactivate Handler
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 From Mailchimp's nest we hopped with care,
To Kit's swift API, light as air,
With timeouts set and tags aligned,
New validations gently bind,
A subscription dance, refined! ✨🌿

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: migrate Newsletter Service' clearly and directly summarizes the main change in the PR, which implements migration of the Newsletter Service from Mailchimp to Kit.com across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@asyncapi-bot
Copy link
Copy Markdown
Contributor

asyncapi-bot commented Apr 4, 2026

⚡️ Lighthouse report for the changes in this PR:

Category Score
🟠 Performance 50
🟢 Accessibility 98
🟢 Best practices 92
🟢 SEO 100
🔴 PWA 33

Lighthouse ran on https://deploy-preview-5292--asyncapi-website.netlify.app/

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 4, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (566236d) to head (1cd8aeb).
⚠️ Report is 6 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff            @@
##            master     #5292   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           22        22           
  Lines          830       830           
  Branches       159       159           
=========================================
  Hits           830       830           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@config/kit-config.json`:
- Around line 3-5: The hardcoded tag IDs ("Newsletter", "Meetings", "TSC
Voting") in config/kit-config.json should be moved out of source control and
loaded from deploy-specific secrets; replace their static values with lookups to
environment/config variables (e.g., process.env or your secret manager) and
update any code that reads kit-config.json to fall back to those env vars when
present; ensure the KIT_API_KEY remains separate and that deployment configs
(staging/production) provide the correct tag IDs so the code that references the
"Newsletter", "Meetings", and "TSC Voting" keys continues to receive IDs at
runtime without committing them to the repo.

In `@netlify/functions/newsletter_subscription.ts`:
- Around line 54-66: The tagging call (tagRes) can fail after the subscriber was
created upstream, leaving an orphaned active subscriber; update the handler to
perform compensation: after creating the subscriber (capture the subscriber
id/response from the POST /subscribers call), if tagRes.ok is false attempt a
retry of the tagging request a limited number of times and if still failing call
the Kit endpoint to deactivate or delete the newly created subscriber (use the
subscriber id from the create response), log both tagging and compensation
outcomes, and return a clear response to the client indicating partial success
(subscriber created but tag failed) rather than a generic 502; ensure you
reference and use the existing tagRes variable and the create-subscriber
response payload to implement the rollback.
- Around line 32-58: The two open-ended fetch calls that create subRes and
tagRes against KIT_BASE (posting subscribers and tagging via tagId) need request
timeouts: create an AbortController for each request, start a short timer (e.g.,
3–10s) that calls controller.abort(), pass controller.signal into fetch, and
clear the timer when the response arrives; catch the abort (or FetchError) and
return a suitable error response (e.g., 504/timeout message) instead of letting
the Netlify invocation hang. Ensure you still set headers and body as before and
reuse the same pattern for both the subscriber POST (subRes) and the tag POST
(tagRes).
- Around line 15-29: Parse and validate the incoming payload safely before
looking up interest: wrap JSON.parse(event.body) in a try/catch and return 400
for invalid JSON; validate that parsed.email, parsed.name, and parsed.interest
exist and are strings (and that email conforms to a simple email pattern) before
using interest; when mapping to tagId, use a safe property check like
Object.prototype.hasOwnProperty.call(config.tags, interest) (or typeof
config.tags[interest] !== 'undefined') to avoid inherited properties and then
coerce/validate the resulting tagId (reject NaN/0) and return 400 for invalid
client input instead of 503; update the logic around the variables email, name,
interest and tagId in newsletter_subscription.ts accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bbbea95a-15ea-4a30-8fec-b447e988c02f

📥 Commits

Reviewing files that changed from the base of the PR and between 106998f and d2879b4.

📒 Files selected for processing (4)
  • config/kit-config.json
  • config/mailchimp-config.json
  • netlify/functions/newsletter_subscription.ts
  • package.json
💤 Files with no reviewable changes (2)
  • package.json
  • config/mailchimp-config.json

Comment thread config/kit-config.json Outdated
Comment thread netlify/functions/newsletter_subscription.ts Outdated
Comment thread netlify/functions/newsletter_subscription.ts
Comment on lines +54 to +66
const tagRes = await fetch(`${KIT_BASE}/tags/${tagId}/subscribers`, {
method: 'POST',
headers,
body: JSON.stringify({ email_address: email })
});

if (!tagRes.ok) {
await tagRes.text().catch(() => undefined);
return {
statusCode: err.status,
body: JSON.stringify(err)
statusCode: 502,
body: JSON.stringify({
message: 'Subscription could not be completed. Please try again later.'
})
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Apr 4, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat netlify/functions/newsletter_subscription.ts

Repository: asyncapi/website

Length of output: 2256


Handle the partial-success path when tagging fails.

If POST /subscribers succeeds and POST /tags/{tagId}/subscribers fails, this returns 502 after the upstream state has already changed. The subscriber is now active in Kit but untagged, and the client receives the same error message as if the subscription entirely failed, making retries ambiguous and leaving orphaned subscribers behind. Add compensation logic (e.g., deactivate/delete the subscriber on tagging failure) or implement a retry/reconciliation mechanism to handle this scenario.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@netlify/functions/newsletter_subscription.ts` around lines 54 - 66, The
tagging call (tagRes) can fail after the subscriber was created upstream,
leaving an orphaned active subscriber; update the handler to perform
compensation: after creating the subscriber (capture the subscriber id/response
from the POST /subscribers call), if tagRes.ok is false attempt a retry of the
tagging request a limited number of times and if still failing call the Kit
endpoint to deactivate or delete the newly created subscriber (use the
subscriber id from the create response), log both tagging and compensation
outcomes, and return a clear response to the client indicating partial success
(subscriber created but tag failed) rather than a generic 502; ensure you
reference and use the existing tagRes variable and the create-subscriber
response payload to implement the rollback.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

how kit endpoints works is, even if you already have an account, we call that endpoint with that email. it's more like a put endpoint, where it will create entry if you are new. in case you are already there in our database, it then updates the name as provided by you currently.

so in this case, if the tag updation fails, if we simply go ahead and remove the user, it does not make sense as that user might already be subscribed to different newsletters, and removing that removes those newsletter subscriptions as well. hence, since in case tag updation fails, then we should simply show that request is not processed and not proceed with deletion of that account

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.

@princerajpoot20, that's a great clarification — thank you. Since Kit's POST /subscribers is effectively an upsert (creates if new, updates if existing), a subscriber who calls the endpoint may already have pre-existing tag subscriptions in Kit. Deleting or deactivating that subscriber as compensation would silently remove those other subscriptions, which is clearly worse than just surfacing an error.

Given this, the current behavior — returning 502 when the tagging step fails, without touching the subscriber record — is the correct and safe approach. The client receives a clear signal that the full subscription flow did not complete, and the subscriber's existing state in Kit is preserved. I'll withdraw the rollback suggestion.


✏️ Learnings added
Learnt from: princerajpoot20
Repo: asyncapi/website PR: 5292
File: netlify/functions/newsletter_subscription.ts:0-0
Timestamp: 2026-04-12T14:05:00.648Z
Learning: In the asyncapi/website repository (PR `#5292`), the Kit API's `POST /subscribers` endpoint is an upsert: it creates a new subscriber if the email doesn't exist, or updates the existing subscriber's details (e.g., first name) if it does. Therefore, rolling back (deleting/deactivating) a subscriber after a tag-assignment failure is incorrect and harmful, as the subscriber may already have pre-existing tag subscriptions that would be destroyed. The correct behavior on tag-assignment failure is to return an error (e.g., 502) without modifying the subscriber record.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: asyncapi-bot
Repo: asyncapi/website PR: 0
File: :0-0
Timestamp: 2025-02-18T12:07:42.211Z
Learning: The following PR commands are supported in the asyncapi/website repository:
- `/please-take-a-look` or `/ptal`: Requests attention from reviewers who haven't reviewed the PR
- `/ready-to-merge` or `/rtm`: Triggers automerge when all conditions are met
- `/do-not-merge` or `/dnm`: Blocks automerge even if all conditions are met
- `/autoupdate` or `/au`: Adds autoupdate label to keep PR in sync with target branch
- `/update` or `/u`: One-time update of PR with latest changes from target branch

@princerajpoot20 princerajpoot20 marked this pull request as draft April 4, 2026 20:14
@princerajpoot20 princerajpoot20 marked this pull request as ready for review April 12, 2026 13:31
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
netlify/functions/newsletter_subscription.ts (1)

100-114: ⚠️ Potential issue | 🟠 Major

Partial-success scenario still leaves orphaned subscribers.

If the subscriber POST succeeds (lines 84-88) but the tagging POST fails (lines 100-104), the subscriber remains active in Kit but untagged. The client receives a generic 502 error without knowing subscription partially succeeded.

Consider one of these mitigations:

  1. Retry tagging before giving up (simple improvement)
  2. Compensate on failure by deleting/deactivating the subscriber if tagging fails
  3. Return a distinct status (e.g., 207 Partial) so the client knows state diverged

Given the migration context, option 1 (retry) may be sufficient for now.

♻️ Suggested retry approach
-    const tagRes = await kitFetch(`${KIT_BASE}/tags/${tagId}/subscribers`, {
-      method: 'POST',
-      headers,
-      body: JSON.stringify({ email_address: email })
-    });
-
-    if (!tagRes.ok) {
-      await tagRes.text().catch(() => undefined);
-      return {
-        statusCode: 502,
-        body: JSON.stringify({
-          message: 'Subscription could not be completed. Please try again later.'
-        })
-      };
-    }
+    let tagRes = await kitFetch(`${KIT_BASE}/tags/${tagId}/subscribers`, {
+      method: 'POST',
+      headers,
+      body: JSON.stringify({ email_address: email })
+    });
+
+    // Retry tagging once on failure
+    if (!tagRes.ok) {
+      await tagRes.text().catch(() => undefined);
+      tagRes = await kitFetch(`${KIT_BASE}/tags/${tagId}/subscribers`, {
+        method: 'POST',
+        headers,
+        body: JSON.stringify({ email_address: email })
+      });
+    }
+
+    if (!tagRes.ok) {
+      await tagRes.text().catch(() => undefined);
+      // Subscriber exists but is untagged - still return success
+      // since the core subscription succeeded
+      return {
+        statusCode: 200,
+        body: JSON.stringify({ message: 'Subscribed successfully.' })
+      };
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@netlify/functions/newsletter_subscription.ts` around lines 100 - 114, The tag
POST (tagRes) can fail after the initial subscriber POST, leaving orphaned
subscribers; implement a retry loop when calling
kitFetch(`${KIT_BASE}/tags/${tagId}/subscribers`) — e.g., 3 attempts with small
exponential backoff — and only return an error after retries exhaust; if tagging
still fails, perform compensation by deleting/deactivating the newly created
subscriber (use the subscriber ID from the successful subscriber response, e.g.,
subscriberRes/subscriberJson.id) before returning an error, and ensure errors
and final status distinguish a partial failure (or return 207) so the client can
know the divergent state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@netlify/functions/newsletter_subscription.ts`:
- Around line 100-114: The tag POST (tagRes) can fail after the initial
subscriber POST, leaving orphaned subscribers; implement a retry loop when
calling kitFetch(`${KIT_BASE}/tags/${tagId}/subscribers`) — e.g., 3 attempts
with small exponential backoff — and only return an error after retries exhaust;
if tagging still fails, perform compensation by deleting/deactivating the newly
created subscriber (use the subscriber ID from the successful subscriber
response, e.g., subscriberRes/subscriberJson.id) before returning an error, and
ensure errors and final status distinguish a partial failure (or return 207) so
the client can know the divergent state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c9e50be1-ddd0-48ee-ad17-3897ae34118f

📥 Commits

Reviewing files that changed from the base of the PR and between e42257f and 5700d29.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • netlify/functions/newsletter_subscription.ts
  • package.json
💤 Files with no reviewable changes (1)
  • package.json

@asyncapi-bot asyncapi-bot added the bounty AsyncAPI Bounty program related label label Apr 14, 2026
@aeworxet aeworxet moved this to In Progress in Bounty Program Apr 14, 2026
@aeworxet
Copy link
Copy Markdown
Contributor

@asyncapi/bounty_team

fmvilas
fmvilas previously approved these changes Apr 16, 2026
Copy link
Copy Markdown
Member

@fmvilas fmvilas left a comment

Choose a reason for hiding this comment

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

LGTM 👍 Just left a comment as a suggestion, not a blocker.

Comment thread config/kit-config.json Outdated
Comment on lines +3 to +5
"Newsletter": 18208674,
"Meetings": 18208677,
"TSC Voting": 18208683
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Perhaps these values could be environment variables too so we can change them without the need of a PR.

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
netlify/functions/newsletter_subscription.ts (2)

68-75: Optional: validate email format, not just type.

typeof email !== 'string' passes values like "foo" or "" straight through to Kit, which then returns a non-OK response and the user sees a generic 502 "Subscription could not be completed" instead of a clear 400. A lightweight regex check (or reusing whatever validation NewsletterSubscribe.tsx applies client-side) would give better UX and shed obviously-bad traffic before hitting Kit.

-  if (typeof email !== 'string' || typeof interest !== 'string' || !isValidInterest(interest)) {
+  const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+  if (
+    typeof email !== 'string' ||
+    !emailPattern.test(email) ||
+    typeof interest !== 'string' ||
+    !isValidInterest(interest)
+  ) {
     return {
       statusCode: 400,
       body: JSON.stringify({ message: 'Invalid subscription request.' })
     };
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@netlify/functions/newsletter_subscription.ts` around lines 68 - 75, The
current validation only checks that email is a string; update the request
validation in the newsletter subscription handler to also validate email format
(e.g., add a lightweight regex or reuse the client-side validator from
NewsletterSubscribe.tsx) before proceeding; modify the block that inspects the
destructured email, name, interest (and the isValidInterest(interest) check) to
reject malformed emails by returning the same 400 JSON response (message:
'Invalid subscription request.') so obviously-bad inputs are rejected early.

108-153: Failures are silently swallowed — add minimal logging for observability.

Both Kit failure paths read the error body and discard it (await subRes.text().catch(() => undefined) / await tagRes.text().catch(() => undefined)), and the outer catch never logs err. In production this means operators cannot distinguish between a 4xx misconfiguration from Kit (e.g., bad KIT_API_KEY, wrong tag ID), a 5xx upstream outage, or a timeout — all are indistinguishable 502/500 responses to the client with no trace in Netlify function logs.

Since you are already consuming the body, capture it and emit a console.error (or console.warn) with status + a truncated body. Netlify aggregates function logs, so this is essentially free.

🪵 Proposed fix
     if (!subRes.ok) {
-      await subRes.text().catch(() => undefined);
+      const detail = await subRes.text().catch(() => '');
+      console.error('[newsletter] Kit subscribers POST failed', {
+        status: subRes.status,
+        body: detail.slice(0, 500)
+      });
       return {
         statusCode: 502,
         body: JSON.stringify({
           message: 'Subscription could not be completed. Please try again later.'
         })
       };
     }
@@
     if (!tagRes.ok) {
-      await tagRes.text().catch(() => undefined);
+      const detail = await tagRes.text().catch(() => '');
+      console.error('[newsletter] Kit tag assignment failed', {
+        status: tagRes.status,
+        tagId,
+        body: detail.slice(0, 500)
+      });
       return {
         statusCode: 502,
         body: JSON.stringify({
           message: 'Subscription could not be completed. Please try again later.'
         })
       };
     }
@@
   } catch (err) {
     if (isAbortError(err)) {
+      console.error('[newsletter] Kit request timed out after', REQUEST_TIMEOUT_MS, 'ms');
       return {
         statusCode: 504,
         body: JSON.stringify({
           message: 'Subscription service timed out. Please try again later.'
         })
       };
     }
+    console.error('[newsletter] Unexpected error', err);
     return {
       statusCode: 500,

Note: avoid logging email/name to stay clear of PII retention concerns — status code and truncated upstream body are sufficient for triage.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@netlify/functions/newsletter_subscription.ts` around lines 108 - 153, The Kit
error bodies are being consumed and discarded and the outer catch never logs the
thrown error; update the failure paths around subRes and tagRes so they capture
the response text (e.g., const subBody = await subRes.text().catch(() =>
undefined)) and emit a concise console.error including subRes.status and a
truncated subBody (avoid PII), and do the same for tagRes; also log the caught
err in the catch block (but redact sensitive fields) so isAbortError handling
remains unchanged but unexpected errors are recorded for observability.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@netlify/functions/newsletter_subscription.ts`:
- Around line 68-75: The current validation only checks that email is a string;
update the request validation in the newsletter subscription handler to also
validate email format (e.g., add a lightweight regex or reuse the client-side
validator from NewsletterSubscribe.tsx) before proceeding; modify the block that
inspects the destructured email, name, interest (and the
isValidInterest(interest) check) to reject malformed emails by returning the
same 400 JSON response (message: 'Invalid subscription request.') so
obviously-bad inputs are rejected early.
- Around line 108-153: The Kit error bodies are being consumed and discarded and
the outer catch never logs the thrown error; update the failure paths around
subRes and tagRes so they capture the response text (e.g., const subBody = await
subRes.text().catch(() => undefined)) and emit a concise console.error including
subRes.status and a truncated subBody (avoid PII), and do the same for tagRes;
also log the caught err in the catch block (but redact sensitive fields) so
isAbortError handling remains unchanged but unexpected errors are recorded for
observability.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2076f12f-2db8-4b54-bf18-9d778f8f358b

📥 Commits

Reviewing files that changed from the base of the PR and between 5700d29 and 1cd8aeb.

📒 Files selected for processing (1)
  • netlify/functions/newsletter_subscription.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bounty AsyncAPI Bounty program related label

Projects

Status: In Progress
Status: To Be Triaged

Development

Successfully merging this pull request may close these issues.

4 participants