Skip to content

rate-limit portrait/generate, fix admin N+1 + UUID type + remove shelved metrics - #33

Open
brooksRoley wants to merge 2 commits into
mainfrom
claude/staff-rate-limit-admin-correctness
Open

rate-limit portrait/generate, fix admin N+1 + UUID type + remove shelved metrics#33
brooksRoley wants to merge 2 commits into
mainfrom
claude/staff-rate-limit-admin-correctness

Conversation

@brooksRoley

Copy link
Copy Markdown
Owner

Staff Engineer session — 2026-08-11

Four verified findings from today's security/performance audit, all shipped in this PR.


1. POST /api/portrait/generate — missing rate limit (security)

Every call to this endpoint fired an LLM request on the server key. An authenticated user could spam it at arbitrary rate, burning quota and inflating cost.

Fix: @limiter.limit("5/hour") added, matching the auth endpoint pattern. Request injected as first param (slowapi requirement).

Tests: server/tests/test_portrait_ratelimit.py — 3 new tests (first call passes, 6th returns 429, Retry-After header present). Verified locally: 3/3 passing.


2. admin_connector_depth — correlated subquery N+1 (performance)

The previous query ran one SELECT COUNT(*) FROM oauth_tokens WHERE user_id = u.id subquery per user row in the outer scan. With N users that's N+1 DB round-trips inside a single query execution.

Fix: Replaced with a LEFT JOIN on a pre-aggregated subquery (GROUP BY user_id). One pass over oauth_tokens, joined once.


3. admin_user_connectorsuser_id: str instead of UUID (correctness)

An invalid UUID string passed to vv.user_id = $1 caused asyncpg to raise an exception → unhandled 500. FastAPI's path-parameter coercion with UUID type returns a clean 422 instead.

Fix: user_id: struser_id: UUID.


4. Shelved metric columns removed from admin_users + admin_funnel (correctness)

Five columns in admin_users queried karma_ledger, match_interactions, and messages — tables that exist in the DB but have been empty since the matching engine was shelved. They always returned 0, adding correlated subquery overhead and misleading the admin UI.

Same issue in admin_funnel: three funnel steps (played_game, got_mutual_match, sent_message) and their three LEFT JOINs always produced 0s.

Fix: Removed all six shelved columns / three shelved steps. The real funnel steps (opened_self_expression_view, completed_session, returned_next_day) remain untouched.


Test results (full relevant suite)

tests/test_portrait_ratelimit.py     3 passed
tests/test_auth_ratelimit.py         5 passed
tests/test_analytics.py              9 passed
                                    ─────────
                                    17 passed, 0 failed

Generated by Claude Code

@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
channelzero Ready Ready Preview Aug 11, 2026 4:25pm

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.

2 participants