# 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
