Skip to content

feat(botid): add Vercel BotID to the four public forms (observe mode) - #441

Draft
ignmandagaran wants to merge 2 commits into
mainfrom
ignmandagaran/botid-detect
Draft

feat(botid): add Vercel BotID to the four public forms (observe mode)#441
ignmandagaran wants to merge 2 commits into
mainfrom
ignmandagaran/botid-detect

Conversation

@ignmandagaran

@ignmandagaran ignmandagaran commented Aug 14, 2026

Copy link
Copy Markdown
Member

Summary

Adds Vercel BotID — an invisible CAPTCHA — to the four public forms. The contact form has no validation today and emails sales@basement.studio on every submit.

Nothing is blocked here. The actions call checkBotId(), report the verdict, then proceed as before. Suspected bots still reach Resend and Notion; their contact emails arrive prefixed [SUSPECTED BOT] so sales@ can judge accuracy first. Enforcement is a follow-up PR, once there's data.

Observe-first because BotID fails closed: a route missing from the client protect list gets no challenge headers, so a real visitor reads as a bot — on a lead form, a silently lost lead.

Changes

  • botid@^1.5.11; withSentryConfig(withBotId(nextConfig), …)
  • initBotId() lists all 13 (site) routes, not just /contact — the contact overlay is mounted in (site)/layout.tsx and a server action POSTs to whatever page invoked it
  • checkBotId() in the three actions, after the honeypot/rate-limit so free checks short-circuit first
  • src/lib/botid.ts reports via console.error + track("botid_detected"), not Sentry — attacker-triggerable and no sampleRate is set, so captureMessage would be unbounded under the very flood it reports on
  • Deep Analysis off; no checkLevel set, so it stays a dashboard toggle

Checklist

  • pnpm lint passes
  • Tested locally in dev mode
  • No breaking changes — no action returns anything different than today

@vercel

vercel Bot commented Aug 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
website-2k25 Ready Ready Preview Aug 14, 2026 2:04pm

Base automatically changed from ignmandagaran/newsletter-api-key-disabled to main August 14, 2026 13:46
@ignmandagaran
ignmandagaran marked this pull request as ready for review August 14, 2026 13:47
@ignmandagaran
ignmandagaran force-pushed the ignmandagaran/botid-detect branch 2 times, most recently from f2561d5 to 34ad596 Compare August 14, 2026 13:50
@greptile-apps

greptile-apps Bot commented Aug 14, 2026

Copy link
Copy Markdown

Greptile Summary

Adds Vercel BotID in observation mode to the newsletter, contact, and careers server actions without rejecting suspected bots.

  • Configures BotID’s Next.js integration and protected POST routes.
  • Reports suspected submissions through logs and Vercel Analytics.
  • Prefixes suspected contact emails while preserving provider submissions.
  • Wraps error-catching server actions with Sentry instrumentation.

Confidence Score: 5/5

The PR appears safe to merge, with no unacknowledged blocking or independently actionable non-blocking issues identified.

The protected route patterns cover the normal form surfaces, suspected bots continue to the existing providers, and telemetry failures are contained on the reachable server-action paths.

Reviews (1): Last reviewed commit: 4c1c76f | Re-trigger Greptile

Adds the invisible challenge and its proxy rewrites. No action calls
checkBotId() yet, so nothing is classified or blocked.

The protect list covers every route under (site): the contact overlay is
mounted in that layout and a server action POSTs to the page that invoked
it, so /contact alone would leave real submissions unchallenged everywhere
else. checkLevel is left unset so Deep Analysis stays a dashboard toggle.
checkBotId() runs on all three form actions, after the honeypot and rate
limit so the free checks short-circuit first. Nothing is dropped yet:
suspected bots still reach Mailchimp and Notion, and their contact emails
are delivered with a [SUSPECTED BOT] subject so sales@ can judge precision
before enforcement.

The verdict is reported as telemetry rather than a Sentry event: it is
attacker-triggerable and no sampleRate is configured, so captureMessage
would be unbounded under exactly the flood it reports on.
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.

1 participant