Repository navigation
fix(gov): enforce daily index call limits - #5144
Conversation
The gov index is free and reachable as an Alexandria provider that the Exchange calls in-cluster, past the per-minute limiters, with up to 10 calls per request. One team ran about 223k gov searches in a day and saturated the search-index reranker. Every path into a free index now spends from one per-team budget per UTC day, one unit per call, so a 10-call batch spends 10: the Alexandria provider, /v2/search/gov and the gov category on /v2/search. A request that does not fit is refused whole with 429 and Retry-After, before any quote or execution, and spends nothing. Redis failures fail open. Gov is limited at GOV_INDEX_CALLS_PER_DAY (default 500). The research index is wired the same way but stays unlimited until RESEARCH_INDEX_CALLS_PER_DAY is set. Also drops the unused isPale export flagged by knip.
There was a problem hiding this comment.
All reported issues were addressed across 7 files
This PR changes payment, billing, or quota logic. Ultrareviews find 2.4x more serious bugs than standard reviews. Comment @cubic-dev-ai ultrareview to run one.
View guided diff | Turn on auto-fix | Re-trigger cubic
…alues - Alexandria: index calls reserved before the quote and credit hold are given back on every refusal before execution (and on an exception), so transient quote or billing failures no longer burn a team's daily budget. Refusals after the Exchange executed still count. - Alexandria: send the Retry-After header when a refusal carries retryAfterSeconds, as the other gov paths do. - /v2/search: reserve the gov call immediately before executeSearch, after every rejecting validation, so a 403 spends nothing. - Config: blank GOV_INDEX_CALLS_PER_DAY falls back to 500 and a blank RESEARCH_INDEX_CALLS_PER_DAY stays unset, instead of coercing to 0. - Bound the Redis wait at 500 ms: an unreachable Redis queues commands rather than failing, which broke the fail-open promise. - Tests: release and rollback, Retry-After on the Alexandria route, the /v2/search/gov 429, gov-only counting in retrieve, and gov-search tests no longer depend on a live Redis.
- /v2/search/gov reserves after the request is logged, like /v2/search, so a failed log spends nothing, and gives the call back when the index is not configured. - The gov daily-limit 429 on /v2/search and /v2/search/gov carries code INDEX_DAILY_LIMIT, so clients can tell it from the per-minute limiter and stop retrying until the reset (Alexandria already returns index_daily_limit). - Correct the config comment: gov defaults to 500; only research is unlimited while unset.
There was a problem hiding this comment.
All reported issues were addressed across 9 files (changes from recent commits).
Tip: Get a Slack DM when cubic finishes reviewing your PRs. Connect Slack
View guided diff | Turn on auto-fix | Re-trigger cubic
- Alexandria: set Retry-After only for the index_daily_limit refusal. The Exchange already returns retryAfterSeconds for other providers' refusals, which keep their existing responses. - After a Redis timeout the reservation command can still land once Redis reconnects. Its release now waits for that command in the background and gives back what it took, so a request refused before it ran spends nothing. A synchronous eval throw is also caught.
There was a problem hiding this comment.
All reported issues were addressed across 11 files (changes from recent commits).
Requires human review: Auto-approval blocked because this review re-detected 1 unresolved P0–P2 issue already reported by Cubic.
Tip: Review your code locally with the cubic CLI to iterate faster.
View guided diff | Turn on auto-fix | Re-trigger cubic
There was a problem hiding this comment.
0 issues found across 9 files (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Requires human review: Auto-approval blocked by 1 unresolved P0–P2 issue from previous reviews.
View guided diff | Turn on auto-fix | Re-trigger cubic
Restrict daily quotas to government index requests and leave other indexes unchanged. Make reservation refunds idempotent and register the API-level quota error.
Limit government-index calls per team per UTC day across
/v2/search/gov, gov-category search, and the government Alexandria provider. Non-gov requests retain their existing behavior.GOV_INDEX_CALLS_PER_DAY(default: 500).Retry-After.Validation: API build, formatting, and targeted local unit/regression checks. Additional validation tests remain local; the PR contains production changes only.