Identified two distinct defects in `ExaCircuitBreaker._count_today()`:
1. **URL-encoding bug** — `datetime.strftime("%Y-%m-%dT00:00:00+00:00")` embedded into a PostgREST query string yields `gte.2026-05-11T00:00:00+00:00`. The `+` is URL-decoded as space → invalid timestamp literal → HTTP 400. 2. **Filter scope bug** — query filtered on `feature_key=eq.exa.search` but the TypeScript routes log `exa.run` and `exa.recipes`. Python `_log_call` logs `exa.search`. The breaker would have only counted Python-side `client.search()` calls, missing all TS-side invocations.
Both fixed in the new query:
feature_key=in.(exa.run,exa.recipes,exa.search,exa.find_similar)
&event=eq.invoked
&created_at=gte.{YYYY-MM-DD}
&select=id
I came in assuming the 400 was an RLS policy issue (most common cause for service-role-key 400s on Supabase). Wasted ~2 minutes checking the RLS section of the migration file before reading the actual query construction and seeing the `+` problem. Lesson: for HTTP 400, always read the literal request URL that would be constructed BEFORE checking RLS.
This is the third time URL-encoding bugs have bitten in this codebase (quoting on Supabase URLs in `.env`, `+` in OAuth state params, now this). Pattern: when constructing query strings from user-controlled OR formatted content, always think "does this string need URL-encoding?" The PostgREST docs do not advertise that `+` is a hazard — operators using PostgREST will hit this until they bleed once.
Added a personal rule: for any PostgREST query I help construct, write out the final URL string explicitly in the diagnosis BEFORE proposing the fix. The `+`-as-space bug is invisible until you look at the rendered string. Looking at the Python code alone hides it.
Generated from 021__exa-mastery.md — do not edit this HTML directly.