Skip to content

feat: User tier & limits system (#96)#98

Merged
DevanshuNEU merged 6 commits into
OpenCodeIntel:mainfrom
DevanshuNEU:feat/issue-96-user-tier-system
Dec 13, 2025
Merged

feat: User tier & limits system (#96)#98
DevanshuNEU merged 6 commits into
OpenCodeIntel:mainfrom
DevanshuNEU:feat/issue-96-user-tier-system

Conversation

@DevanshuNEU

Copy link
Copy Markdown
Collaborator

Summary

Implements centralized user tier and limits management system as foundation for #94, #95, and #93.

Tier System

Tier Repos Files/Repo Functions/Repo Playground/Day
Free 3 500 2,000 50
Pro 20 5,000 20,000
Enterprise 50,000 200,000

New API Endpoints

GET /api/v1/users/usage        - Get tier, limits, current usage
GET /api/v1/users/limits/check-repo-add  - Pre-check before adding repo

Files Changed

New Files

File Purpose
backend/services/user_limits.py Core tier/limits service (454 lines)
backend/routes/users.py User usage API endpoints
supabase/migrations/001_user_profiles.sql Database migration
supabase/README.md Migration documentation
docs/TIER_SYSTEM_DESIGN.md Full design document

Modified Files

File Change
backend/dependencies.py Initialize UserLimitsService
backend/main.py Register users router

Production-Ready Features

Security

  • ✅ RLS policies - users can only read own profile
  • ✅ No UPDATE policy for users (prevents self-upgrade)
  • ✅ Tier updates only via service role key
  • ✅ Input validation on user_id

Error Handling

  • ✅ Sentry integration for exception capture
  • ✅ Fail-CLOSED on DB errors during limit checks
  • ✅ Graceful Redis degradation (continue without cache)
  • ✅ Proper error codes: REPO_LIMIT_REACHED, REPO_TOO_LARGE, INVALID_USER, SYSTEM_ERROR

Observability

  • ✅ Structured logging with user_id, tier, limits
  • ✅ Metrics: user_limit_exceeded with tags
  • ✅ Cache hit/miss tracking

Usage Example

from dependencies import user_limits

# Check if user can add repo (fails CLOSED if DB down)
result = user_limits.check_repo_count(user_id)
if not result.allowed:
    raise HTTPException(403, detail=result.to_dict())

# Response includes tier for upgrade prompts
# {"allowed": false, "tier": "free", "error_code": "REPO_LIMIT_REACHED", ...}

Database Migration

Run supabase/migrations/001_user_profiles.sql in Supabase SQL Editor:

  • Creates user_profiles table
  • Auto-creates profile on signup (trigger)
  • RLS enabled (SELECT/INSERT only for users)

Testing Checklist

  • Run migration in Supabase
  • Test GET /users/usage endpoint
  • Test GET /users/limits/check-repo-add endpoint
  • Verify tier caching works (check Redis)
  • Test fail-closed behavior (stop DB, try to add repo)

Related Issues

Closes #96

- Create UserLimitsService for centralized tier management
- Define tier limits (free/pro/enterprise)
- Add methods: check_repo_count, check_repo_size, get_usage_summary
- Add Supabase migration for user_profiles table
- Initialize service in dependencies.py

Tiers:
- Free: 3 repos, 500 files, 2000 functions
- Pro: 20 repos, 5000 files, 20000 functions
- Enterprise: Unlimited

Used by OpenCodeIntel#93, OpenCodeIntel#94, OpenCodeIntel#95 for enforcing limits.
- Create routes/users.py with usage and limit check endpoints
- GET /users/usage - returns tier, repo count, limits
- GET /users/limits/check-repo-add - pre-check before adding repo
- Register users_router in main.py
Comprehensive design covering:
- All API endpoints and which need limit checks
- Error response format
- Redis key patterns
- Frontend integration points
- Implementation order
- Files to create/modify checklist
- Changed all async def to def in user_limits.py
- Removed await calls in routes/users.py
- Matches codebase pattern (supabase_service.py uses sync)
Security Fixes:
- Remove broken RLS UPDATE policy (was allowing any user to update any profile)
- Tier updates now ONLY via service role key (payment webhooks)

Code Quality:
- Add input validation for user_id (empty/null check)
- Add Sentry error capture for exceptions
- Fail-CLOSED on DB errors during check_repo_count (prevent bypass)
- Add LimitCheckError exception class
- Add invalidate_tier_cache() method for tier upgrades
- Add error_code field to LimitCheckResult
- Add tier field to all responses for frontend upgrade prompts
- Better Redis error handling (continue on failure)

Documentation:
- Fix date: 2024 → 2025
- Remove async references (code is sync)
- Add fail-safe behavior table
- Update error response format to match actual code
- Add new error codes: INVALID_USER, SYSTEM_ERROR
- routes/users.py: Use TIER_LIMITS[UserTier.FREE] instead of hardcoded values
- routes/users.py: Return tier and limit in check-repo-add for API key users
- user_limits.py: Remove unused 'field' import from dataclasses
@vercel

vercel Bot commented Dec 13, 2025

Copy link
Copy Markdown

@DevanshuNEU is attempting to deploy a commit to the Dev's projects Team on Vercel.

A member of the Team first needs to authorize it.

@vercel

vercel Bot commented Dec 13, 2025

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Review Updated (UTC)
opencodeintel Ignored Ignored Preview Dec 13, 2025 1:27am

@DevanshuNEU DevanshuNEU merged commit 999e21c into OpenCodeIntel:main Dec 13, 2025
6 checks passed
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.

feat(backend): Create user tier/limits system

1 participant