_blogs
// blogs / 20260807.md
// blogs / 20260807.md
Dev Log: August 07 Wrap-up
Overview
Today was mostly about fortifying our AI chat widget against abuse. It's one of those days where you don't build many 'features' but spend a lot of time making sure the existing ones don't get hammered by bots or weirdly long inputs.
What I Worked On
Making reCAPTCHA Less Annoying
We’ve been using the standard reCAPTCHA v2 (the checkbox one), but it’s a bit of a friction point for a chat interface. I spent a good chunk of the day switching us over to reCAPTCHA v3. The beauty of v3 is that it's silent—it gives us a score based on user behavior rather than making them click on pictures of traffic lights.
I had to update the environment configs to support the new v3SiteKey and then wire it through the chat components. The tricky part was ensuring that the token is freshly minted for each action (like starting a session or sending a message) and then passed correctly from our UI to the decorator service and finally to the backend.
I also had to make sure we didn't break the existing login-based flows. If the site key is missing, the widget just gracefully falls back or stays disabled instead of crashing the whole page.
Hardening the Backend
On the Python side, I added the actual verification logic. It’s simple enough: we grab the token from the request, ping Google’s API, and check the score. To keep things clean, I wrapped this in a helper function used across our chat endpoints.
def verify_token(request, action_name, user_token):
# Simplified check to ensure we aren't dealing with bots
if not user_token:
raise SecurityException("Missing captcha token")
score = get_recaptcha_score(user_token, action_name)
if score < 0.5:
raise SecurityException("Bot activity detected")
While I was in there, I also enabled token expiry for our embedded sessions. Security is a lot tighter now. Before, we were being a bit too relaxed with how long these tokens lived, but now they’ll time out properly after an hour.
Character Limits and Debugging
I noticed some users (or maybe just me testing) were sending massive blocks of text to the AI. To keep things performant and prevent our LLM costs from spiking unexpectedly, I implemented a 1000-character limit on the decorator side.
I had to be careful here to only apply this to user messages. If I accidentally limited the bot’s response, we’d be cutting off the AI mid-sentence. It’s a small check, but it prevents the backend from processing junk data.
I also flipped the logging to debug mode for a while to trace exactly how the tokens were flowing through the middleware. It's always satisfying when you see the logs finally line up and the tokens matching across services.
Wrapping Up
Everything is looking much more robust. The silent reCAPTCHA makes the chat feel more premium, and the character limits give me some peace of mind. Tomorrow, I’ll probably double-check the logs to see if any real users are hitting that character cap and adjust if needed. Catch you then.