287 lines
9.7 KiB
Markdown
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
|