QrRapido/CLAUDE.md

287 lines
9.7 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
QR Rapido is an ultra-fast QR code generator built with ASP.NET Core 8.0, focusing on speed and multilingual support (PT-BR, ES, EN). It features tiered user access (anonymous, logged-in free, premium), OAuth authentication (Google/Microsoft), Stripe payment integration, and ad-free session management.
**Key Performance Targets:**
- QR generation: <1.2s (average), <0.4s (premium users)
- Cache hit rate: >80%
- First Contentful Paint: <2s
## Common Commands
### Development
```bash
# Run locally (hot reload)
dotnet watch run
# Run locally (standard)
dotnet run
# Build for release
dotnet build --configuration Release
# Restore dependencies
dotnet restore
```
### Testing
```bash
# Run all tests
dotnet test
# Run with coverage
dotnet test --collect:"XPlat Code Coverage"
# Run specific test class
dotnet test --filter "QRRapidoServiceTests"
```
### Frontend Build
```bash
# Development mode with Vite
npm run dev
# Production build (Vite)
npm run build
# Preview production build
npm run preview
```
### Docker
```bash
# Build and run all services (MongoDB, Redis, Nginx)
docker-compose up -d
# View logs
docker-compose logs -f qrrapido
# Build production image for ARM64 (OCI Ampere servers)
docker buildx build --platform linux/arm64 -t qrrapido:latest .
# Stop all services
docker-compose down
```
### Stripe Webhooks (Local Testing - WSL)
```bash
# Forward Stripe webhooks to local HTTPS endpoint
stripe listen --forward-to https://localhost:52428/pagamento/stripewebhook --skip-verify
```
## Architecture
### Core Technology Stack
- **Backend**: ASP.NET Core 8.0 (MVC + Razor Pages)
- **Database**: MongoDB (users, QR history, sessions)
- **Cache**: Redis (distributed cache) + MemoryCache (fallback)
- **QR Generation**: QRCoder library with ImageSharp for logo overlay
- **Authentication**: Cookie-based with OAuth (Google, Microsoft)
- **Payments**: Stripe (subscriptions)
- **Logging**: Serilog OpenSearch/Console
- **Frontend Build**: Vite for asset bundling
### Project Structure
```
Controllers/ # MVC controllers (Home, QR, Account, Premium, Pagamento, Health)
Services/ # Business logic (QRRapido, User, Plan, Stripe, AdDisplay)
├── Monitoring/ # Resource and MongoDB monitoring
└── HealthChecks/# Health check implementations
Models/ # Domain models and ViewModels
Data/ # MongoDbContext
Middleware/ # Custom middleware (Language redirection, LastLogin update)
Providers/ # Culture providers for localization
Resources/ # .resx files for PT-BR, ES, EN localization
Views/ # Razor views
wwwroot/ # Static assets (CSS, JS, images)
Tests/ # Unit tests (xUnit, Moq)
```
### Key Services
**QRRapidoService** (`Services/QRRapidoService.cs`):
- Core QR generation with distributed cache support
- SemaphoreSlim limits concurrent generations (default: 100)
- Cache key based on content hash + settings
- Optimized error correction levels for speed
- Logo overlay with readability analysis
**UserService** (`Services/UserService.cs`):
- MongoDB user CRUD operations
- QR history management (anonymous vs authenticated)
- Premium status checks
- Graceful fallback when MongoDB unavailable
**AdDisplayService** (`Services/AdDisplayService.cs`):
- Controls ad visibility based on user status
- 30-day ad-free period after login
- Premium users: permanent ad-free
- Anonymous users: always show ads
**StripeService** (`Services/StripeService.cs`):
- Subscription creation and management
- Webhook handling (checkout.session.completed, etc.)
- Customer portal session creation
### Middleware Pipeline (Program.cs)
1. **LanguageRedirectionMiddleware**: Redirects root `/` to `/pt-BR/` or user's language preference
2. **Request Localization**: Sets culture based on route (`/{culture}/...`) QueryString Cookie
3. **Authentication/Authorization**
4. **Session**
5. **LastLoginUpdateMiddleware**: Updates user's last login timestamp
### Localization Strategy
- Route-based culture: `/{culture:regex(^(pt-BR|es-PY)$)}/{controller}/{action}`
- Default culture: `pt-BR`
- Supported cultures: `pt-BR`, `es-PY`
- Culture providers priority: Route QueryString Cookie
- Resources in `Resources/SharedResource.{culture}.resx`
### MongoDB Collections
- **Users**: User profiles, premium status, OAuth data
- **QRCodeHistory**: Generated QR codes (linked to users or anonymous)
- **AdFreeSessions**: Ad-free session tracking (30-day grants)
- **DataProtectionKeys**: ASP.NET Core Data Protection keys (for Docker Swarm)
### Docker Swarm Deployment
**Production** uses Docker Swarm with:
- 2 replicas across 2 ARM64 servers (OCI Ampere)
- Shared MongoDB for Data Protection keys (cross-replica cookie decryption)
- Rolling updates: `start-first` strategy, 30s delay between updates
- Health checks at `/healthcheck` endpoint
- Exposed on port 5001 internally, proxied by Nginx
**Staging** uses standalone Docker containers on 2 servers.
### CI/CD Pipeline (.github/workflows/deploy.yml)
1. **Test Job**: Runs on `ubuntu-latest`
- Restore Build Test with coverage
- Uploads coverage to Codecov
2. **Build-and-Push Job**: Runs on self-hosted ARM64 runner
- Builds ARM64 Docker image
- Tags: `latest` (main), `develop` (develop branch)
- Pushes to private registry: `registry.redecarneir.us`
3. **Deploy-Staging**: SSH to 2 servers, pull image, run container
4. **Deploy-Production**: SSH to Swarm manager, update service with zero-downtime
### Configuration Management
**appsettings.json** key sections:
- `ConnectionStrings:MongoDB`: MongoDB connection string
- `Authentication:Google/Microsoft`: OAuth credentials
- `Stripe`: API keys and webhook secret
- `Performance:MaxConcurrentGenerations`: Semaphore limit (default: 100)
- `Premium:FreeQRLimit`: Daily limit for logged-in free users (10)
- `Serilog:OpenSearchUrl`: Centralized logging endpoint
- `ResourceMonitoring`: CPU/memory thresholds for alerts
- `HealthChecks`: Timeout and test configurations
**Environment-specific overrides**:
- `appsettings.Development.json`
- `appsettings.Production.json`
### Rate Limiting & Performance
- Fixed window rate limiter: 600 requests/minute per IP on `/api` endpoints
- Kestrel max connections: 2000
- QR generation timeout: 2000ms
- Redis cache expiration: 60 minutes
- MongoDB query timeouts: 5 seconds (health checks)
### Health Checks
Endpoint: `/healthcheck`
Checks:
- **MongoDbHealthCheck**: Database connectivity, size metrics, test query
- **ResourceHealthCheck**: CPU/memory usage, GC pressure
- **ExternalServicesHealthCheck**: Stripe API availability
### Testing Strategy
- **Unit tests**: Services layer (QRRapidoService, AdDisplayService, etc.)
- **Mocking**: MongoDB and IDistributedCache with Moq
- **Coverage**: Run `dotnet test --collect:"XPlat Code Coverage"`
- Test files in `Tests/Services/`
### Known Quirks & WSL Compatibility
- **StaticWebAssets disabled**: Set `ASPNETCORE_HOSTINGSTARTUP__STATICWEBASSETS__ENABLED=false` for WSL path issues (see Program.cs:38-39)
- **DataProtection**: Uses MongoDB for key persistence in production (Docker Swarm), filesystem in development
- **Frontend build**: Vite runs during Release build via MSBuild target (`BuildFrontend` in .csproj)
- **Stripe local testing**: Use `stripe listen` in WSL (see README.md:345-347)
### Monitoring & Logging
- **Serilog** Console (development) + OpenSearch (production)
- **ResourceMonitoringService**: Background service tracking CPU/memory every 30s
- **HistoryCleanupService**: Cleans old anonymous QR history (7-day grace period, runs every 6 hours)
- **MongoDbMonitoringService**: Tracks database growth and collection stats (disabled by default)
### Premium Feature Gates
Check user premium status via `IUserService.GetUserAsync(userId)` `user.IsPremium`
Premium benefits:
- Unlimited QR codes (vs 10/day anonymous, 50/day free)
- No ads permanently
- Priority generation (faster SemaphoreSlim release)
- Dynamic QR codes (editable)
- API access
### Ad-Free Logic
See `AdDisplayService.ShouldShowAdsAsync()`:
- Anonymous users: always show ads
- Premium users: never show ads
- Free logged-in users: 30-day ad-free period from login (configurable in appsettings)
- Ad-free sessions tracked in MongoDB `AdFreeSessions` collection
### Security Considerations
- OAuth secure flow with PKCE
- HTTPS redirect enforced (non-dev environments)
- Stripe webhook signature verification
- Input sanitization on QR generation
- Rate limiting on API endpoints
- HSTS enabled in production
- Forwarded headers support for reverse proxy (Nginx)
### Common Workflows
**Adding a new QR type:**
1. Update `Models/ViewModels/QRGenerationRequest.cs` with new type enum
2. Add generation logic in `Services/QRRapidoService.cs` `GenerateQRCodeOptimizedAsync()`
3. Update frontend form in `Views/Home/Index.cshtml`
4. Add localized strings in `Resources/SharedResource.{culture}.resx`
**Adding a new language:**
1. Create `Resources/SharedResource.{culture}.resx`
2. Update `Program.cs` supported cultures array (line 214-218)
3. Update route constraint regex (line 354)
4. Add culture provider mapping if needed
**Debugging slow QR generation:**
1. Check `_logger` output in `QRRapidoService.GenerateRapidAsync()` for timing
2. Verify cache hit rate in logs
3. Check semaphore wait time (max concurrent limit)
4. Review `Performance:QRGenerationTimeoutMs` in appsettings
5. Monitor resource usage via `/healthcheck`
**Updating Stripe configuration:**
1. Update `appsettings.json` `Stripe` section
2. Verify webhook secret matches Stripe dashboard
3. Test locally with `stripe listen --forward-to ...`
4. Update `StripeService.cs` webhook handlers if event types change