docs: consolidate and sanitize documentation for public release
**Changes Summary:** **Files Deleted (6 files):** - doc/HTMX-PRODUCTION-RECOMMENDATIONS.md (implementation notes) - doc/SEO-OPTIMIZATION-COMPLETE.md (implementation artifact) - doc/PROJECT-DOCUMENTATION-SUMMARY.md (meta-documentation) - doc/PROJECT_STATUS.md (internal roadmap) - doc/API-QUICK-REFERENCE.md (consolidated into API.md) - doc/API-PROTECTION.md (consolidated into API.md and SECURITY.md) **API Documentation Enhanced:** - Added Quick Reference section to API.md (from API-QUICK-REFERENCE.md) - Added Security & Protection section to API.md (from API-PROTECTION.md) - Updated Rate Limiting section to reflect actual implementation - Added Origin Checking documentation with examples **SECURITY.md Enhanced:** - Added comprehensive API Protection Features section - Updated Rate Limiting section (was marked "Not implemented", now shows it IS implemented) - Added Origin Checking configuration and examples - Added Combined Protection flow documentation - Added Testing Protection section with curl examples - Added Production Deployment Checklist - Added Troubleshooting section **Private Information Removed:** - README.md: Removed matomo.drolo.club and site ID references - PRIVACY.md: Replaced specific Matomo server with generic template - CUSTOMIZATION.md: Replaced Analytics Configuration with generic guide - All Matomo-specific details replaced with placeholders **Documentation Navigation:** - README.md: Enhanced Documentation section with organized categories - Getting Started (README, DEPLOYMENT, CUSTOMIZATION) - Technical Reference (ARCHITECTURE, API) - Policies & Standards (SECURITY, PRIVACY, CODE_OF_CONDUCT, CONTRIBUTING) - License **Broken Links Fixed:** - Removed reference to non-existent CHANGELOG.md in API.md - Fixed relative paths for cross-document references - Verified all internal documentation links **Result:** - Documentation reduced from 16 files to 10 core files (37.5% reduction) - No private information exposed (all Matomo details sanitized) - No implementation artifacts remaining - Clear, professional structure suitable for public instructive project - Comprehensive API and security documentation - All essential content preserved and enhanced This documentation now represents a professional, instructive open-source project suitable for public consumption and learning purposes.
This commit is contained in:
+231
-33
@@ -40,6 +40,114 @@ The server can be configured via environment variables:
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
**Quick access to common operations and endpoints.**
|
||||
|
||||
### Base URL
|
||||
```
|
||||
http://localhost:1999
|
||||
```
|
||||
|
||||
### All Endpoints
|
||||
|
||||
| Endpoint | Method | Description | Common Use |
|
||||
|----------|--------|-------------|------------|
|
||||
| `/?lang={en\|es}` | GET | Full HTML page with CV content | Initial page load |
|
||||
| `/cv?lang={en\|es}` | GET | HTML partial for HTMX swaps | Language switching |
|
||||
| `/export/pdf?lang={en\|es}` | GET | Download PDF resume | Export functionality |
|
||||
| `/health` | GET | Health check (JSON) | Monitoring |
|
||||
| `/static/{path}` | GET | Static files (CSS, JS, images) | Assets |
|
||||
|
||||
### Quick curl Examples
|
||||
|
||||
```bash
|
||||
# Health check
|
||||
curl http://localhost:1999/health | jq
|
||||
|
||||
# English CV (full page)
|
||||
curl "http://localhost:1999/?lang=en"
|
||||
|
||||
# Spanish CV (full page)
|
||||
curl "http://localhost:1999/?lang=es"
|
||||
|
||||
# CV content partial (for HTMX)
|
||||
curl "http://localhost:1999/cv?lang=en"
|
||||
|
||||
# Export PDF
|
||||
curl -O -J "http://localhost:1999/export/pdf?lang=en"
|
||||
|
||||
# Static file with headers
|
||||
curl -I http://localhost:1999/static/css/main.css
|
||||
```
|
||||
|
||||
### HTMX Integration Pattern
|
||||
|
||||
```html
|
||||
<!-- Language switcher button -->
|
||||
<button
|
||||
hx-get="/cv?lang=en"
|
||||
hx-target="#cv-content"
|
||||
hx-swap="innerHTML"
|
||||
hx-push-url="/?lang=en">
|
||||
🇬🇧 English
|
||||
</button>
|
||||
|
||||
<button
|
||||
hx-get="/cv?lang=es"
|
||||
hx-target="#cv-content"
|
||||
hx-swap="innerHTML"
|
||||
hx-push-url="/?lang=es">
|
||||
🇪🇸 Español
|
||||
</button>
|
||||
|
||||
<!-- Content container -->
|
||||
<main id="cv-content">
|
||||
<!-- CV content will be swapped here -->
|
||||
</main>
|
||||
```
|
||||
|
||||
### Common Error Codes
|
||||
|
||||
| Code | Meaning | Common Cause |
|
||||
|------|---------|--------------|
|
||||
| 200 | Success | Request processed correctly |
|
||||
| 400 | Bad Request | Invalid `lang` parameter (not `en` or `es`) |
|
||||
| 403 | Forbidden | Origin check failed (PDF endpoint) |
|
||||
| 404 | Not Found | Invalid route or static file not found |
|
||||
| 429 | Too Many Requests | Rate limit exceeded (PDF endpoint) |
|
||||
| 500 | Server Error | Template error, data loading error, PDF generation failed |
|
||||
|
||||
### Performance Targets
|
||||
|
||||
| Endpoint | Target Response Time |
|
||||
|----------|---------------------|
|
||||
| `/health` | <1ms |
|
||||
| `/` and `/cv` | 7-8ms |
|
||||
| `/static/*` | <5ms |
|
||||
| `/export/pdf` | ~3 seconds |
|
||||
|
||||
### Environment Configuration
|
||||
|
||||
```bash
|
||||
# Development
|
||||
PORT=1999
|
||||
HOST=localhost
|
||||
GO_ENV=development
|
||||
|
||||
# Production
|
||||
PORT=1999
|
||||
HOST=0.0.0.0
|
||||
GO_ENV=production
|
||||
ALLOWED_ORIGINS=yourdomain.com,www.yourdomain.com
|
||||
```
|
||||
|
||||
### Need More Details?
|
||||
|
||||
For comprehensive documentation of each endpoint, request/response formats, and advanced usage, see the [Detailed Endpoint Documentation](#detailed-endpoint-documentation) below.
|
||||
|
||||
---
|
||||
|
||||
## Endpoints Overview
|
||||
|
||||
| Method | Path | Description | HTMX Support |
|
||||
@@ -1001,39 +1109,125 @@ if lang != "en" && lang != "es" {
|
||||
**Protected Endpoints:**
|
||||
- `/export/pdf` - Full protection (origin checking + rate limiting)
|
||||
|
||||
**Configuration via Environment Variable:**
|
||||
```bash
|
||||
# Development (default)
|
||||
ALLOWED_ORIGINS=
|
||||
|
||||
# Production
|
||||
ALLOWED_ORIGINS=yourdomain.com,www.yourdomain.com
|
||||
```
|
||||
|
||||
**How It Works:**
|
||||
1. Checks `Origin` header (CORS requests)
|
||||
2. Falls back to `Referer` header (navigation requests)
|
||||
3. Allows localhost in development
|
||||
4. Blocks external domains in production
|
||||
5. Requires headers in production for PDF endpoint
|
||||
|
||||
**Example Requests:**
|
||||
|
||||
```bash
|
||||
# ✅ Allowed (localhost in development)
|
||||
curl http://localhost:1999/export/pdf?lang=en
|
||||
|
||||
# ✅ Allowed (valid referer)
|
||||
curl -H "Referer: http://localhost:1999/" \
|
||||
http://localhost:1999/export/pdf?lang=en
|
||||
|
||||
# ❌ Blocked (external referer)
|
||||
curl -H "Referer: https://evil.com/" \
|
||||
http://localhost:1999/export/pdf?lang=en
|
||||
# Response: 403 Forbidden
|
||||
```
|
||||
|
||||
For more details on origin checking, see [SECURITY.md](SECURITY.md#origin-checking).
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
**Status:** ✅ **Implemented**
|
||||
|
||||
**Current Configuration:**
|
||||
- **Endpoint:** `/export/pdf`
|
||||
- **Limit:** 3 requests per minute per IP
|
||||
- **Window:** 1 minute (rolling)
|
||||
- **Response:** 429 Too Many Requests when exceeded
|
||||
|
||||
**Implementation:**
|
||||
limit_req zone=api burst=5;
|
||||
```go
|
||||
// Applied in main.go
|
||||
```
|
||||
pdfRateLimiter := middleware.NewRateLimiter(3, 1*time.Minute)
|
||||
|
||||
protectedPDFHandler := middleware.OriginChecker(
|
||||
pdfRateLimiter.Middleware(
|
||||
http.HandlerFunc(cvHandler.ExportPDF),
|
||||
),
|
||||
**2. Go Middleware:**
|
||||
```go
|
||||
// Example rate limiter
|
||||
import "golang.org/x/time/rate"
|
||||
|
||||
func RateLimit(next http.Handler) http.Handler {
|
||||
limiter := rate.NewLimiter(10, 20) // 10 req/s, burst 20
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if !limiter.Allow() {
|
||||
)
|
||||
```
|
||||
return
|
||||
}
|
||||
|
||||
**Behavior:**
|
||||
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### Security Best Practices
|
||||
|
||||
✅ **Implemented:**
|
||||
- Security headers (CSP, X-Frame-Options, etc.)
|
||||
- HSTS in production
|
||||
- Input validation
|
||||
- Error message sanitization (internal errors hidden)
|
||||
| Requests | Status | Response |
|
||||
|----------|--------|----------|
|
||||
| 1st-3rd requests | ✅ 200 OK | PDF generated |
|
||||
| 4th+ request (within 1 min) | ❌ 429 Too Many Requests | Rate limit exceeded |
|
||||
| After 1 minute | ✅ 200 OK | Counter reset |
|
||||
|
||||
**Rate Limit Response:**
|
||||
```http
|
||||
HTTP/1.1 429 Too Many Requests
|
||||
Retry-After: 60
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
|
||||
```
|
||||
|
||||
**IP Detection:**
|
||||
- Checks `X-Forwarded-For` (proxy/CDN)
|
||||
- Falls back to `X-Real-IP` (alternative proxy header)
|
||||
- Uses `RemoteAddr` (direct connection)
|
||||
- Works with Nginx reverse proxy
|
||||
|
||||
**Testing Rate Limit:**
|
||||
```bash
|
||||
# Generate 4 PDFs quickly to test rate limiting
|
||||
for i in {1..4}; do
|
||||
echo "Request $i:"
|
||||
curl -w "Status: %{http_code}\n" -o /dev/null -s \
|
||||
http://localhost:1999/export/pdf?lang=en
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Expected output:
|
||||
# Request 1: Status: 200
|
||||
# Request 2: Status: 200
|
||||
# Request 3: Status: 200
|
||||
# Request 4: Status: 429
|
||||
```
|
||||
|
||||
**Customizing Rate Limits:**
|
||||
|
||||
Edit `main.go` to adjust limits:
|
||||
|
||||
```go
|
||||
// More restrictive: 5 per hour
|
||||
pdfRateLimiter := middleware.NewRateLimiter(5, 1*time.Hour)
|
||||
|
||||
// Less restrictive: 10 per minute
|
||||
pdfRateLimiter := middleware.NewRateLimiter(10, 1*time.Minute)
|
||||
```
|
||||
|
||||
For comprehensive protection documentation, see [SECURITY.md](SECURITY.md#api-protection).
|
||||
|
||||
### Security Best Practices
|
||||
|
||||
✅ **Implemented:**
|
||||
- Security headers (CSP, X-Frame-Options, etc.)
|
||||
- HSTS in production
|
||||
- Input validation
|
||||
- Error message sanitization (internal errors hidden)
|
||||
- Timeouts on all operations
|
||||
- Graceful shutdown
|
||||
- Origin checking (prevents external hotlinking)
|
||||
- Rate limiting (PDF endpoint: 3 requests/min per IP)
|
||||
- IP-based tracking (supports reverse proxies)
|
||||
|
||||
@@ -1043,13 +1237,17 @@ func RateLimit(next http.Handler) http.Handler {
|
||||
- Implement request logging with IP addresses
|
||||
- Add monitoring and alerting for 403/429 responses
|
||||
- Consider CloudFlare for additional DDoS protection
|
||||
- Set up log retention for security analysis
|
||||
|
||||
---
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
**Current State:** Not implemented
|
||||
|
||||
|
||||
### Recommended Implementation
|
||||
|
||||
### Recommended Implementation
|
||||
|
||||
#### Per-Endpoint Limits
|
||||
|
||||
| Endpoint | Recommended Limit | Burst |
|
||||
|----------|-------------------|-------|
|
||||
@@ -1731,9 +1929,9 @@ go tool trace trace.out
|
||||
**Email:** [juan.a.moreno.rubio@gmail.com](mailto:juan.a.moreno.rubio@gmail.com)
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
**Last Updated:** November 9, 2025
|
||||
|
||||
**Last Updated:** November 9, 2025
|
||||
**API Version:** 1.0.0
|
||||
**Documentation Version:** 1.0.0
|
||||
### Support
|
||||
|
||||
|
||||
Reference in New Issue
Block a user