docs: Consolidate documentation into single doc/ folder

- Move docs/ contents to doc/ with proper numbering:
  - CONTACT-FORM-QUICKSTART.md → 17-CONTACT-FORM.md
  - SECURITY-AUDIT-REPORT.md → 18-SECURITY-AUDIT.md
  - SECURITY.md → 19-SECURITY-IMPLEMENTATION.md
- Delete duplicate/redundant files from docs/:
  - CMD-K-COMMAND-BAR.md (duplicate of 16-CMD-K-API.md)
  - CONTACT_FORM_IMPLEMENTATION.md (overlaps with quickstart)
  - SECURITY-IMPLEMENTATION-SUMMARY.md (summary of audit)
- Update doc/README.md with new document references
- Update test counts to 39 test files across all READMEs
- Update all "Last Updated" dates to 2025-12-01
- Add new API endpoints documentation (text, cmd-k, contact, toggles)
- Update PROJECT-MEMORY.md with new features and correct paths
This commit is contained in:
juanatsap
2025-12-01 13:30:48 +00:00
parent 9a848e8c53
commit 949c9a0351
12 changed files with 298 additions and 1344 deletions
+78 -12
View File
@@ -32,22 +32,21 @@ const showLogos = ...
---
### 2. Hyperscript Parser Limit (REMOVED IN LATEST VERSION ✅)
### 2. Hyperscript Parser Limit (NO LONGER EXISTS ✅)
**✅ CONFIRMED: NO 3 def statement limit with latest hyperscript version**
**✅ CONFIRMED: NO def statement limit with hyperscript 0.9.14+**
**Test Results (2025-11-17):** Test 9 (`tests/mjs/9-hyperscript-def-limit.test.mjs`) confirmed:
- ✅ 1 def statement works
- ✅ 2 def statements work
- ✅ 3 def statements work
- ✅ 4 def statements work (beyond historical limit)
- ✅ 5 def statements work (well beyond limit)
- ✅ 5+ def statements work (no limit)
**Historical Context:**
- Hyperscript 0.9.12 had a hard 3 def limit
- Hyperscript 0.9.14+ removed this limitation
- Functions were moved to JavaScript as workaround
- **NOW MIGRATED BACK** to hyperscript with JavaScript wrappers (2025-11-17)
**Historical Context (for reference only):**
- Hyperscript 0.9.12 had a hard 3 def limit (fixed in 0.9.14)
- Current version has NO def statement limit
- Functions can be freely organized across multiple files
**Current Architecture (2025-11-17):**
- Core logic in hyperscript (`static/hyperscript/*.hs`)
@@ -581,9 +580,9 @@ document.addEventListener('keydown', (e) => {
---
**Last Updated:** 2025-11-17
**Project Status:** Production - Migrating to hyperscript architecture
**Test Coverage:** 10 systematic tests, 100% core features + def limit verification
**Last Updated:** 2025-12-01
**Project Status:** Production - Full feature set including CMD+K command palette and contact form
**Test Coverage:** 39 test files, 100% core features + CMD+K, contact form, PDF generation
**Critical Memory Files:** This file + `~/.claude/cv-icons-migration.md`
---
@@ -677,7 +676,74 @@ When adding new test files:
3. Update test count at bottom of TEST-SUMMARY.md
4. Add to New Tests section with date
**Current Test Count:** 12 active (0-11), 60+ archived
**Current Test Count:** 39 test files (comprehensive coverage)
**Master test runner:** `tests/run-all.mjs` (auto-discovers numbered tests)
---
### 6. Contact Form (2025-12-01)
**Secure contact form with comprehensive security middleware chain:**
**Security Features:**
- **BrowserOnly middleware** - Blocks curl/Postman/bots (requires HX-Request header)
- **Rate limiting** - 5 submissions per hour per IP
- **CSRF protection** - Token validation against session
**Files:**
- `internal/handlers/cv_contact.go` - Contact form handler
- `internal/middleware/browser_only.go` - Browser validation middleware
- `internal/middleware/contact_rate_limit.go` - Rate limiting
- `templates/partials/modals/contact-modal.html` - Contact form UI
**Documentation:**
- `doc/17-CONTACT-FORM.md` - Quick start guide
- `doc/18-SECURITY-AUDIT.md` - Security audit including contact form
- `doc/19-SECURITY-IMPLEMENTATION.md` - Security controls documentation
**Tests:** `tests/mjs/73-contact-form.test.mjs`
---
### 7. Plain Text CV (2025-12-01)
**CLI-friendly plain text output for curl, wget, lynx, w3m:**
**Features:**
- Auto-detected via User-Agent header
- 80-character line width
- Unicode/emoji support with proper centering
- Useful for AI assistants reading CV content
**Files:**
- `internal/handlers/cv_text.go` - Plain text handler
- `templates/cv-text.txt` - Plain text template
**Usage:**
```bash
curl http://localhost:1999/text
curl http://localhost:1999/text?lang=es
```
---
### 8. CMD+K Command Palette (2025-12-01)
**ninja-keys integration for quick navigation:**
**Features:**
- Dynamic entries from CV data (experiences, projects, courses)
- Scroll-to-section functionality
- Language-aware responses
- 1-hour cache headers
**Files:**
- `internal/handlers/cv_cmdk.go` - CMD+K API handler
- `static/js/ninja-keys-init.js` - Frontend initialization
- `doc/16-CMD-K-API.md` - API documentation
**Tests:**
- `tests/mjs/71-cmd-k-api-scroll.test.mjs`
- `tests/mjs/72-cmd-k-button.test.mjs`
+198 -4
View File
@@ -200,7 +200,15 @@ This architecture provides:
|--------|------|-------------|--------------|------------|
| GET | `/` | Full CV page (home) | ❌ No | None |
| GET | `/cv` | CV content partial | ✅ Yes | None |
| GET | `/text` | Plain text CV for CLI/terminal | ❌ No | None |
| GET | `/api/cmd-k` | CMD+K command palette data (JSON) | ❌ No | Cache Control (1h) |
| POST | `/api/contact` | Contact form submission | ✅ Yes | BrowserOnly + Rate Limit + CSRF |
| GET | `/switch-language` | Language switching | ✅ Yes | None |
| GET | `/toggle/length` | CV length toggle | ✅ Yes | None |
| GET | `/toggle/icons` | Icon visibility toggle | ✅ Yes | None |
| GET | `/toggle/theme` | Theme toggle | ✅ Yes | None |
| GET | `/export/pdf` | PDF export | ❌ No | ✅ Rate Limited + Origin Check |
| GET | `/cv-jamr-{year}-{lang}.pdf` | Shortcut PDF download routes | ❌ No | Redirect to /export/pdf |
| GET | `/health` | Health check | ❌ No | None |
| GET | `/static/*` | Static files (CSS, JS, images) | ❌ No | Cache Control |
@@ -379,7 +387,193 @@ Content-Type: text/html
**Description:** Returns a plain text version of the CV, optimized for CLI tools (curl, wget) and text browsers (lynx, w3m). Auto-detected via User-Agent header.
#### Query Parameters
#### Query Parameters
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `lang` | string | No | `en` | Language code (`en` or `es`) |
#### Response
**Status Code:** `200 OK`
**Content-Type:** `text/plain; charset=utf-8`
**Response Body:** 80-character wrapped plain text CV with ASCII formatting
#### Examples
```bash
# Get plain text CV (auto-detected via curl User-Agent)
curl http://localhost:1999/text
# Spanish version
curl http://localhost:1999/text?lang=es
# View in text browser
lynx http://localhost:1999/text
```
#### Notes
- Returns CV content formatted for terminal display
- 80-character line width for optimal terminal viewing
- Unicode characters properly handled
- Useful for AI assistants reading CV content
---
### 4. GET /api/cmd-k
**Description:** Returns JSON data for the CMD+K command palette (ninja-keys integration). Provides dynamic entries for experiences, projects, and courses that can be searched.
#### Query Parameters
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `lang` | string | No | `en` | Language code (`en` or `es`) |
#### Response
**Status Code:** `200 OK`
**Content-Type:** `application/json`
**Cache-Control:** `public, max-age=3600` (1 hour)
**Response Body:**
```json
{
"experiences": [
{"id": "exp-1", "title": "Senior Developer", "section": "experience", "keywords": "..."}
],
"projects": [
{"id": "proj-1", "title": "Project Name", "section": "projects", "keywords": "..."}
],
"courses": [
{"id": "course-1", "title": "Course Name", "section": "courses", "keywords": "..."}
]
}
```
#### Examples
```bash
# Get CMD+K data
curl -s http://localhost:1999/api/cmd-k | jq
# Count experiences
curl -s http://localhost:1999/api/cmd-k | jq '.experiences | length'
```
#### Notes
- Used by ninja-keys web component for command palette
- Cached for 1 hour to reduce server load
- Entries include scroll-to-section functionality
---
### 5. POST /api/contact
**Description:** Contact form submission endpoint with comprehensive security middleware chain.
#### Request Headers
| Header | Required | Description |
|--------|----------|-------------|
| `HX-Request` | Yes | Must be `true` (browser validation) |
| `Referer` or `Origin` | Yes | Must match allowed origins |
| `Content-Type` | Yes | `application/x-www-form-urlencoded` |
#### Request Body
| Field | Type | Required | Validation |
|-------|------|----------|------------|
| `name` | string | Yes | 2-100 characters |
| `email` | string | Yes | Valid email format |
| `message` | string | Yes | 10-5000 characters |
| `_csrf` | string | Yes | Valid CSRF token from session |
#### Security Middleware
1. **BrowserOnly** - Blocks curl/Postman/bots (requires HX-Request header)
2. **Rate Limiting** - 5 submissions per hour per IP
3. **CSRF Protection** - Token validation against session
#### Response
**Status Code:** `200 OK` (success) or `400/403/429` (error)
**Content-Type:** `text/html` (HTMX partial)
#### Error Responses
| Code | Reason |
|------|--------|
| 400 | Validation failed (missing fields, invalid email) |
| 403 | Security check failed (no browser headers, invalid CSRF) |
| 429 | Rate limit exceeded (5/hour per IP) |
| 500 | Email sending failed |
#### Notes
- See `docs/CONTACT-FORM-QUICKSTART.md` for implementation details
- SMTP configuration via environment variables
- Returns HTMX partial for seamless form updates
---
### 6. GET /switch-language
**Description:** HTMX endpoint for language switching. Returns updated UI elements.
#### Query Parameters
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `lang` | string | Yes | - | Target language (`en` or `es`) |
#### Response
Returns HTMX partial with updated language-specific content.
---
### 7. GET /toggle/{preference}
**Description:** HTMX endpoints for CV preference toggles.
#### Endpoints
- `GET /toggle/length` - Toggle CV length (short/long)
- `GET /toggle/icons` - Toggle icon visibility (show/hide)
- `GET /toggle/theme` - Toggle theme (default/clean)
#### Response
Returns HTMX partial with updated toggle state.
---
### 8. GET /cv-jamr-{year}-{lang}.pdf
**Description:** Shortcut routes for default CV PDF downloads. Redirects to `/export/pdf` with appropriate parameters.
#### Examples
```
/cv-jamr-2025-en.pdf → /export/pdf?lang=en&length=short&icons=show&version=clean
/cv-jamr-2025-es.pdf → /export/pdf?lang=es&length=short&icons=show&version=clean
```
---
### 9. GET /export/pdf
**Description:** Generates and downloads a PDF version of the CV using headless Chrome (chromedp). The PDF is generated from the rendered HTML page with customizable parameters for language, length, icons, and version.
#### Query Parameters
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
@@ -2051,6 +2245,6 @@ go tool trace trace.out
---
**Last Updated:** November 12, 2025
**API Version:** 1.1.0
**Documentation Version:** 1.1.0
**Last Updated:** December 1, 2025
**API Version:** 1.2.0
**Documentation Version:** 1.2.0
+14 -3
View File
@@ -19,6 +19,12 @@
- [12. CSS Architecture](12-CSS-ARCHITECTURE.md) - Modular CSS structure and ITCSS organization ⭐
- [13. Toast Notifications](13-TOAST-NOTIFICATIONS.md) - Toast notification system for PDF downloads and user feedback
- [14. Backend Handlers](14-BACKEND-HANDLERS.md) - Handler architecture, type safety, middleware, and testing ⭐
- [16. CMD+K API](16-CMD-K-API.md) - Command palette API for ninja-keys integration ⭐
**Contact Form & Security**
- [17. Contact Form](17-CONTACT-FORM.md) - Quick start guide for contact form with SMTP setup
- [18. Security Audit](18-SECURITY-AUDIT.md) - Comprehensive security audit report (OWASP Top 10)
- [19. Security Implementation](19-SECURITY-IMPLEMENTATION.md) - Detailed security controls documentation
**Deployment & Operations**
- [8. Deployment Guide](8-DEPLOYMENT.md) - Production deployment instructions
@@ -48,6 +54,11 @@
| 12 | [CSS-ARCHITECTURE.md](12-CSS-ARCHITECTURE.md) | Modular CSS structure, ITCSS layers, HTMX integration | Frontend developers, designers |
| 13 | [TOAST-NOTIFICATIONS.md](13-TOAST-NOTIFICATIONS.md) | Toast notification system, PDF download feedback, user notifications | Frontend developers, UX designers |
| 14 | [BACKEND-HANDLERS.md](14-BACKEND-HANDLERS.md) | Handler architecture, type safety, middleware pattern, testing strategy | Backend developers |
| 15 | [SEO.md](15-SEO.md) | SEO optimization and best practices | Frontend developers |
| 16 | [CMD-K-API.md](16-CMD-K-API.md) | CMD+K command palette API, ninja-keys integration | Frontend developers |
| 17 | [CONTACT-FORM.md](17-CONTACT-FORM.md) | Contact form quick start guide | Backend developers |
| 18 | [SECURITY-AUDIT.md](18-SECURITY-AUDIT.md) | Comprehensive security audit (OWASP Top 10) | Security teams |
| 19 | [SECURITY-IMPLEMENTATION.md](19-SECURITY-IMPLEMENTATION.md) | Security controls implementation details | Backend developers, Security |
### User & Operations Documentation
@@ -141,6 +152,6 @@ All documentation in this project follows these standards:
---
**Last Updated**: 2025-11-20
**Documentation Status**: ✅ Clean, organized, zero redundancy
**Total Active Docs**: 14 core documents + archive
**Last Updated**: 2025-12-01
**Documentation Status**: ✅ Clean, organized, single doc/ folder
**Total Active Docs**: 19 core documents + archive
-214
View File
@@ -1,214 +0,0 @@
# CMD+K Command Bar - Implementation Guide
## Overview
A keyboard-driven command palette (similar to VS Code, Vercel, and Linear) implemented using the [ninja-keys](https://github.com/nicholascelestin/ninja-keys) Web Component. Provides quick access to all CV navigation, actions, and downloads via keyboard shortcuts.
## Features Implemented
### 1. Ninja Keys Integration (`static/js/ninja-keys-init.js`)
- Web Component loaded via CDN (unpkg)
- 50+ searchable actions organized by category
- Smooth animated scrolling to sections
- Modal integration for dialogs
- External link handling
### 2. Action Categories
#### Navigation (9 actions)
- Jump to Top, Experience, Education, Skills, Projects, Courses, Languages, Awards, Other
#### Experience - Companies (7 actions)
- Olympic Broadcasting Services
- LIV Golf
- AENA (Spanish Airports)
- SAP
- Gigya
- Drolosoft (Freelance)
- Emailing Network
#### Skills by Category (9 actions)
- Programming Languages
- JavaScript Ecosystem
- Go Ecosystem
- Frontend Technologies
- Backend Technologies
- Infrastructure & DevOps
- Databases
- SAP Technologies
- AI-Assisted Development
#### Social Links (4 actions)
- LinkedIn Profile
- GitHub Profile
- Domestika Portfolio
- Personal Website
#### Keyboard Shortcuts (5 actions)
- Toggle CV Length (L key)
- Toggle Icons (I key)
- Toggle Theme (V key)
- Show Shortcuts Help (? key)
- Print CV (Cmd/Ctrl+P)
#### Downloads (5 actions)
- Download PDF (Default - 5 pages)
- Download PDF (Short - 4 pages)
- Download PDF (Extended - 9 pages)
- View Text CV (opens in new tab)
- Download Text CV (.txt file)
#### Actions (6 actions)
- Open Contact Form
- Show Site Info
- Toggle Zoom Controls
- Switch to English
- Switch to Spanish
- Change Color Theme
### 3. CSS Styling (`static/css/04-interactive/_buttons.css`)
- Custom ninja-keys theming with CSS variables
- Light and dark mode support
- Matches site design system (Quicksand font, purple accent)
- CMD+K button with hover/active states
### 4. UI Strings (`data/ui-en.json`, `data/ui-es.json`)
- Internationalized labels for all actions
- Button tooltips and ARIA labels
- Placeholder text and section headers
### 5. Keyboard Shortcut Conflict Prevention
- Page shortcuts (L, I, V, ?) disabled when ninja-keys is open
- Implemented via hyperscript `ninjaOpen` check in body handler
## Technical Details
### Activation Methods
1. **Keyboard**: `Cmd+K` (Mac) or `Ctrl+K` (Windows/Linux)
2. **Button**: Click the magnifying glass button (top-left position)
### Button Position (Left Column)
1. **CMD+K Button** (top) - `bottom: 30rem`
2. Download PDF Button - `bottom: 26rem`
3. Print Button - `bottom: 22rem`
4. Zoom Toggle - `bottom: 10rem`
5. Shortcuts Help - `bottom: 6rem`
### Backend Changes
#### Text CV Download (`internal/handlers/cv_text.go`)
Added `download` query parameter support:
```go
// GET /text?lang=en&download=true
// Returns: Content-Disposition: attachment; filename="cv-jamr-2025-en.txt"
```
#### UI Model (`internal/models/ui/ui.go`)
Added CmdK struct for internationalization:
```go
type CmdK struct {
Placeholder string `json:"placeholder"`
NoResults string `json:"noResults"`
Sections CmdKSections `json:"sections"`
Actions CmdKActions `json:"actions"`
Button CmdKButton `json:"button"`
}
```
## Usage Examples
### Search Commands
- Type "SAP" to find SAP experience entry and SAP skills
- Type "download" to see all download options
- Type "contact" to open contact form
### Quick Navigation
1. Press `Cmd+K`
2. Type section name (e.g., "skills")
3. Press Enter to scroll to section
### Download PDF
1. Press `Cmd+K`
2. Type "pdf"
3. Select desired format (short/default/extended)
## CSS Variables
```css
ninja-keys {
--ninja-font-family: 'Quicksand', sans-serif;
--ninja-accent-color: #667eea;
--ninja-z-index: 10000;
--ninja-width: 640px;
--ninja-backdrop-filter: blur(8px);
--ninja-modal-background: rgba(255, 255, 255, 0.95);
--ninja-selected-background: #667eea;
}
```
### Dark Mode
```css
[data-color-theme="dark"] ninja-keys {
--ninja-modal-background: rgba(40, 40, 40, 0.95);
--ninja-text-color: #e0e0e0;
--ninja-actions-background: #2a2a2a;
}
```
## Testing
### Unit Tests
Located in `internal/handlers/cv_text_test.go`:
- Test PlainText handler with various parameters
- Test download filename format
- Test text browser detection
### Manual Testing
1. Press `Cmd+K` to open command bar
2. Type to search actions
3. Use arrow keys to navigate
4. Press Enter to execute action
5. Press Escape to close
### Test Commands
```bash
# Run text handler tests
go test ./internal/handlers/ -run TestPlainText -v
# Test text download endpoint
curl -I "http://localhost:1999/text?lang=en&download=true"
```
## Files Modified/Created
### Created
- `static/js/ninja-keys-init.js` - Action definitions and initialization
- `templates/partials/widgets/cmd-k-button.html` - Button widget
- `docs/CMD-K-COMMAND-BAR.md` - This documentation
- `internal/handlers/cv_text_test.go` - Unit tests
### Modified
- `templates/index.html` - Added ninja-keys CDN, element, and script
- `static/css/04-interactive/_buttons.css` - Button and ninja-keys styling
- `templates/partials/modals/shortcuts-modal.html` - Added CMD+K entry
- `internal/handlers/cv_text.go` - Added download parameter
- `internal/models/ui/ui.go` - Added CmdK struct
- `data/ui-en.json` - English UI strings
- `data/ui-es.json` - Spanish UI strings
## Browser Support
- Chrome 80+
- Firefox 75+
- Safari 13.1+
- Edge 80+
Requires ES modules support for ninja-keys Web Component.
## Accessibility
- Full keyboard navigation
- ARIA labels on button
- Focus management in modal
- Screen reader compatible
- Respects reduced motion preferences
-472
View File
@@ -1,472 +0,0 @@
# Contact Form Email Backend - Implementation Guide
## Overview
Complete backend implementation for a contact form with email delivery using SMTP (Gmail), featuring comprehensive security measures including CSRF protection, rate limiting, bot protection, and browser-only access.
## Features Implemented
### 1. Email Service (`internal/services/email.go`)
- ✅ SMTP-based email sending with TLS support
- ✅ Gmail App Password authentication
- ✅ Email validation and sanitization
- ✅ Header injection prevention
- ✅ Configurable via environment variables
- ✅ Comprehensive error handling and logging
- ✅ Template-based email formatting
### 2. Contact Handler (`internal/handlers/contact.go`)
- ✅ POST endpoint: `/api/contact`
- ✅ Form field validation (email, name, company, subject, message)
- ✅ Bot protection with honeypot field
- ✅ Timing check (rejects forms submitted < 2 seconds)
- ✅ HTMX-friendly responses
- ✅ Detailed logging (without sensitive data)
### 3. Security Middleware
#### Contact Rate Limiting (`internal/middleware/contact_rate_limit.go`)
- ✅ 5 requests per hour per IP address
- ✅ Automatic cleanup of expired entries
- ✅ HTMX-friendly error responses
- ✅ Configurable limits and windows
#### CSRF Protection (`internal/middleware/csrf.go`)
- ✅ Token generation and validation
- ✅ 24-hour token TTL
- ✅ Cookie-based token storage
- ✅ Automatic token cleanup
- ✅ Support for forms and AJAX requests
#### Browser-Only Access (`internal/middleware/browser_only.go`)
- ✅ Blocks curl, Postman, wget, and other HTTP clients
- ✅ User-Agent validation
- ✅ Referer/Origin header validation
- ✅ Custom header requirement (HTMX or X-Browser-Request)
- ✅ Comprehensive bot detection
### 4. Configuration (`internal/config/config.go`)
- ✅ Email settings added to config struct
- ✅ Environment variable support
- ✅ Sensible defaults for development
### 5. HTMX Response Templates
-`templates/partials/contact_success.html` - Success message with animation
-`templates/partials/contact_error.html` - Error message with shake animation
### 6. Route Registration (`internal/routes/routes.go`)
- ✅ Endpoint registered with full middleware chain
- ✅ Proper middleware ordering
## Security Features
### Multi-Layer Protection
```
Request → Browser-Only → Contact Rate Limit → CSRF → Handler
```
1. **Browser-Only Middleware**
- Blocks non-browser clients (curl, Postman, etc.)
- Validates User-Agent, Referer, and custom headers
2. **Contact Rate Limiting**
- 5 submissions per hour per IP
- Prevents spam and abuse
3. **CSRF Protection**
- Validates security tokens
- Prevents cross-site request forgery
4. **Bot Protection in Handler**
- Honeypot field detection
- Timing validation (min 2 seconds)
5. **Input Validation**
- Email format validation
- Length restrictions
- Header injection prevention
- XSS protection via sanitization
## Environment Configuration
### Required Variables
```bash
# SMTP Configuration (Gmail)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_FROM_EMAIL=your-email@gmail.com
CONTACT_EMAIL=txeo.msx@gmail.com
```
### Gmail App Password Setup
1. Enable 2FA in your Google account
2. Visit: https://myaccount.google.com/apppasswords
3. Generate an App Password for "Mail"
4. Use the generated password in `SMTP_PASSWORD`
**Important**: Never use your regular Gmail password - always use an App Password.
## API Endpoint
### POST /api/contact
**Request Format:**
```http
POST /api/contact
Content-Type: application/x-www-form-urlencoded
HX-Request: true
Referer: http://yourdomain.com/
email=user@example.com
&name=John Doe
&company=Acme Inc
&subject=Partnership Inquiry
&message=Hello, I would like to discuss...
&website=
&submit_time=1701360000000
&csrf_token=abc123...
```
**Required Fields:**
- `email` - Valid email address (max 254 chars)
- `message` - Message text (10-5000 chars)
**Optional Fields:**
- `name` - Sender name (max 100 chars)
- `company` - Company name (max 100 chars)
- `subject` - Email subject (max 200 chars)
**Special Fields:**
- `website` - Honeypot (must be empty)
- `submit_time` - Unix timestamp in milliseconds
- `csrf_token` - CSRF token from cookie
**Success Response (200):**
```html
<div class="alert alert-success">
<h3>Message Sent Successfully!</h3>
<p>Thank you for reaching out...</p>
</div>
```
**Error Responses:**
- **403 Forbidden** - Non-browser client, CSRF failure, or rate limit
- **400 Bad Request** - Validation error
- **429 Too Many Requests** - Rate limit exceeded
## Testing
### Test 1: Curl Request (Should Fail - 403)
```bash
curl -X POST http://localhost:1999/api/contact \
-d "email=test@example.com&message=Test" \
-w "\nStatus: %{http_code}\n"
```
**Expected:** `Forbidden: Browser access only` (403)
### Test 2: Postman Request (Should Fail - 403)
```bash
curl -X POST http://localhost:1999/api/contact \
-H "User-Agent: PostmanRuntime/7.32.0" \
-H "Referer: http://localhost:1999/" \
-d "email=test@example.com&message=Test" \
-w "\nStatus: %{http_code}\n"
```
**Expected:** `Forbidden: Browser access only` (403)
### Test 3: Browser-like Request (Should Fail - CSRF)
```bash
curl -X POST http://localhost:1999/api/contact \
-H "User-Agent: Mozilla/5.0 (Macintosh)" \
-H "Referer: http://localhost:1999/" \
-H "HX-Request: true" \
-d "email=test@example.com&message=Test" \
-w "\nStatus: %{http_code}\n"
```
**Expected:** CSRF validation error (403)
### Test 4: Complete Browser Request
Use the test HTML file: `test_contact_form.html`
```bash
# Start server
go run main.go
# Open in browser
open http://localhost:1999/test_contact_form.html
# Fill and submit form
# Should succeed if SMTP credentials are configured
```
## Integration Example
### HTML Contact Form
```html
<form
hx-post="/api/contact"
hx-target="#response"
hx-headers='{"X-Browser-Request": "true"}'
hx-on::before-request="this.submitTime.value = Date.now()"
>
<input type="hidden" name="submit_time" class="submitTime">
<input type="hidden" name="csrf_token" value="{{ .CSRFToken }}">
<!-- Honeypot -->
<div style="position: absolute; left: -9999px;">
<input type="text" name="website" tabindex="-1">
</div>
<input type="email" name="email" required>
<input type="text" name="name">
<input type="text" name="company">
<input type="text" name="subject">
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>
<div id="response"></div>
<script>
// Initialize submit time
document.querySelector('.submitTime').value = Date.now();
</script>
```
### JavaScript (Fetch API)
```javascript
// Get CSRF token from cookie
const csrfToken = document.cookie
.split('; ')
.find(row => row.startsWith('csrf_token='))
?.split('=')[1];
const submitTime = Date.now();
// Wait at least 2 seconds before allowing submit
setTimeout(() => {
fetch('/api/contact', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Browser-Request': 'true'
},
body: new URLSearchParams({
email: 'user@example.com',
name: 'John Doe',
message: 'Hello!',
website: '', // Honeypot
submit_time: submitTime,
csrf_token: csrfToken
})
})
.then(response => response.text())
.then(html => {
document.getElementById('response').innerHTML = html;
});
}, 2000);
```
## Email Template
The email sent to `CONTACT_EMAIL` follows this format:
```
Subject: [CV Contact] {subject or "New Message"}
New contact form submission:
From: user@example.com
Name: John Doe
Company: Acme Inc
Subject: Partnership Inquiry
Message:
Hello, I would like to discuss a potential partnership...
---
IP: 192.168.1.1
Time: 2025-11-30 13:45:22 UTC
```
## Monitoring & Logging
### Security Events Logged
1. **Blocked Requests**
- Non-browser User-Agents
- Missing Referer/Origin
- Missing browser headers
- CSRF validation failures
- Rate limit exceeded
- Honeypot triggered
- Form submitted too fast
2. **Successful Submissions**
- Email sent successfully (logs email address and IP)
3. **Errors**
- SMTP connection failures
- Email sending errors
- Template rendering errors
### Log Format
```
2025/11/30 13:45:22 SECURITY: Blocked non-browser User-Agent from IP 192.168.1.1: curl/7.88.1
2025/11/30 13:45:23 SECURITY: CSRF validation failed from IP 192.168.1.2
2025/11/30 13:45:24 Contact form submitted successfully from user@example.com (192.168.1.3)
```
## Production Deployment
### Checklist
- [ ] Configure SMTP credentials in environment
- [ ] Set `CONTACT_EMAIL` to your email address
- [ ] Enable HTTPS (middleware automatically enables HSTS)
- [ ] Configure `ALLOWED_ORIGINS` if using custom domain
- [ ] Set up log monitoring
- [ ] Test email delivery
- [ ] Monitor rate limit statistics
- [ ] Set up email delivery monitoring
- [ ] Configure email bounce handling
- [ ] Review security headers
### Production Environment
```bash
# Production .env
GO_ENV=production
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-password
CONTACT_EMAIL=your-email@gmail.com
ALLOWED_ORIGINS=yourdomain.com,www.yourdomain.com
```
## Troubleshooting
### Email Not Sending
1. **Check SMTP credentials**
- Verify App Password is correct
- Ensure 2FA is enabled on Google account
2. **Check logs**
- Look for SMTP connection errors
- Verify email service initialization
3. **Test SMTP connection**
```bash
telnet smtp.gmail.com 587
```
### Rate Limiting Issues
1. **IP address detection**
- Check `X-Forwarded-For` header if behind proxy
- Verify IP extraction in logs
2. **Adjust limits**
- Modify `limit` and `window` in `contact_rate_limit.go`
- Default: 5 requests per hour
### CSRF Token Issues
1. **Token not set**
- Ensure cookie is being set on GET requests
- Check browser cookie settings
2. **Token mismatch**
- Verify token is passed in form or header
- Check token expiration (24 hours)
## Files Modified/Created
### New Files
- `internal/services/email.go` - Email service with SMTP
- `internal/handlers/contact.go` - Contact form handler
- `internal/middleware/contact_rate_limit.go` - Rate limiting
- `internal/middleware/csrf.go` - CSRF protection
- `internal/middleware/browser_only.go` - Browser validation
- `templates/partials/contact_success.html` - Success template
- `templates/partials/contact_error.html` - Error template
- `test_contact_form.html` - Test page
### Modified Files
- `internal/config/config.go` - Added email configuration
- `internal/routes/routes.go` - Registered contact endpoint
- `main.go` - Initialized contact handler and email service
- `.env.example` - Added email configuration example
## Security Considerations
### What's Protected Against
✅ **CSRF Attacks** - Token validation
✅ **Rate Limiting Bypass** - IP-based limiting
✅ **Bot Submissions** - Honeypot + timing + User-Agent
✅ **Email Header Injection** - Newline filtering
✅ **XSS** - Input sanitization
✅ **External API Access** - Browser-only enforcement
✅ **Spam** - Rate limiting + bot protection
✅ **Brute Force** - Rate limiting
### What's NOT Protected Against
⚠️ **Distributed Attacks** - Single-IP rate limiting only
⚠️ **Sophisticated Bots** - May bypass basic User-Agent checks
⚠️ **Email Bombing** - Recipient rate limiting not implemented
### Recommended Additions for Production
1. **CAPTCHA** - Add reCAPTCHA or hCaptcha
2. **Email Verification** - Verify sender's email address
3. **Advanced Bot Detection** - Integrate with services like Cloudflare
4. **Distributed Rate Limiting** - Use Redis for multi-server deployments
5. **Email Queue** - Use background job processor for email sending
6. **Delivery Monitoring** - Track email delivery success/failure
7. **Spam Detection** - Content-based spam filtering
## License & Reusability
This implementation is designed to be reusable across projects. Feel free to:
- Copy the entire `services/email.go` for email functionality
- Reuse middleware components independently
- Adapt the contact handler for your needs
- Modify rate limits and validation rules
All code follows Go best practices and is production-ready.
## Support
For issues or questions:
- Check the logs for detailed error messages
- Review security event logs for blocked requests
- Test with the included `test_contact_form.html`
- Verify SMTP credentials are correct
---
**Implementation Date:** November 30, 2025
**Version:** 1.0.0
**Author:** Backend Craftsman
-631
View File
@@ -1,631 +0,0 @@
# Security Implementation Summary
## Completed Security Audit & Implementation
**Date:** 2025-11-30
**Project:** CV Portfolio Site (Go/HTMX)
**Status:** ✅ All Security Controls Implemented & Tested
---
## Files Created/Modified
### 1. Security Audit Report
📄 **`SECURITY-AUDIT-REPORT.md`**
- Comprehensive 100+ page security analysis
- OWASP Top 10 2021 compliance check
- Contact form security design
- Linux server hardening guide
- Nginx security configuration
- Penetration testing guide
- Incident response playbook
### 2. Middleware (Already Implemented ✅)
📁 **`internal/middleware/`**
- `csrf.go` - CSRF token generation & validation
- `browser_only.go` - Blocks non-browser requests (curl, Postman, etc.)
- `contact_rate_limit.go` - Contact form rate limiting (5/hour per IP)
- `security_logger.go` - Structured security event logging
- `security.go` - Comprehensive security headers (CSP, HSTS, etc.)
### 3. Input Validation (New ✨)
📁 **`internal/validation/`**
-`contact.go` - Contact form validation & sanitization
-`contact_test.go` - Comprehensive test suite (100% coverage)
---
## Security Controls Implemented
### ✅ 1. Origin Validation (Browser-Only Access)
**Location:** `internal/middleware/browser_only.go`
**Blocks:**
- ❌ curl, wget, Postman, HTTPie, Python requests
- ❌ All command-line HTTP clients
- ❌ Bots and scrapers
- ❌ Missing Origin/Referer headers
- ❌ Missing AJAX/HTMX headers
**Allows:**
- ✅ Only genuine browser requests with proper headers
- ✅ Same-origin requests only
- ✅ HTMX/fetch requests with X-Requested-With header
**Test Results:**
```bash
✅ Blocks curl: 403 Forbidden
✅ Blocks Postman: 403 Forbidden
✅ Blocks missing headers: 403 Forbidden
✅ Allows browser with Origin header: 200 OK
```
---
### ✅ 2. CSRF Protection
**Location:** `internal/middleware/csrf.go`
**Features:**
- Cryptographically secure token generation (32 bytes)
- Automatic token expiration (24 hours)
- Constant-time comparison (prevents timing attacks)
- Automatic cleanup of expired tokens
**Usage:**
```go
// Generate token on page load
token, err := csrfProtection.GetToken(w, r)
// Validate on POST
csrfProtection.Middleware(next)
```
**Test Results:**
```bash
✅ Rejects requests without token: 403 Forbidden
✅ Rejects expired tokens: 403 Forbidden
✅ Accepts valid token: 200 OK
```
---
### ✅ 3. Input Validation
**Location:** `internal/validation/contact.go`
**Validates:**
1. **Email** - RFC 5322 format, TLD required, max 254 chars
2. **Name** - Unicode letters/spaces/hyphens/apostrophes only, max 100 chars
3. **Company** - Optional, alphanumeric + business punctuation, max 100 chars
4. **Subject** - Alphanumeric + safe punctuation, max 200 chars
5. **Message** - Max 5000 chars, HTML escaped
**Security Features:**
- ✅ Email header injection prevention (strips CRLF, validates headers)
- ✅ Bot detection (honeypot field + timing validation)
- ✅ HTML escaping (prevents XSS in email clients)
- ✅ Whitespace normalization
- ✅ International character support (UTF-8 names, subjects)
**Test Coverage:** 100% (15 test suites, 60+ test cases)
**Test Results:**
```bash
✅ All validation tests pass
✅ Email injection blocked: "test\nBcc: evil@example.com" → REJECTED
✅ SQL injection blocked: "Robert'; DROP TABLE users; --" → REJECTED
✅ XSS escaped: "<script>alert(1)</script>"&lt;script&gt;...
✅ Bot detection: honeypot filled → REJECTED
✅ Bot detection: submitted <2 seconds → REJECTED
```
---
### ✅ 4. Rate Limiting
**Location:** `internal/middleware/contact_rate_limit.go`
**Limits:**
- Contact form: 5 requests/hour per IP
- PDF export: 3 requests/minute per IP (already implemented)
**Features:**
- In-memory rate limiting with automatic cleanup
- X-Forwarded-For support (proxy-aware)
- Friendly error messages for HTMX requests
- Retry-After header
**Test Results:**
```bash
✅ Allows 5 requests within hour: 200 OK
✅ Blocks 6th request: 429 Too Many Requests
✅ Retry-After header present: "3600" (1 hour)
```
---
### ✅ 5. Security Headers
**Location:** `internal/middleware/security.go`
**Headers Applied:**
```
✅ Content-Security-Policy (comprehensive)
✅ Strict-Transport-Security (HSTS, 1 year)
✅ X-Frame-Options (clickjacking prevention)
✅ X-Content-Type-Options (MIME sniffing prevention)
✅ X-XSS-Protection (legacy browser protection)
✅ Referrer-Policy (privacy)
✅ Permissions-Policy (feature restrictions)
```
**Recommended Additions:**
```
⚠️ X-Permitted-Cross-Domain-Policies: none
⚠️ Cross-Origin-Opener-Policy: same-origin
⚠️ Cross-Origin-Embedder-Policy: require-corp
```
---
### ✅ 6. Security Logging
**Location:** `internal/middleware/security_logger.go`
**Logged Events:**
- BLOCKED - Non-browser requests rejected
- CSRF_VIOLATION - Token validation failure
- ORIGIN_VIOLATION - Invalid origin detected
- RATE_LIMIT_EXCEEDED - Rate limit hit
- VALIDATION_FAILED - Input validation failure
- SUSPICIOUS_USER_AGENT - Bot/crawler detected
- CONTACT_FORM_SENT - Successful submission
- BOT_DETECTED - Honeypot/timing check triggered
**Log Format:** Structured JSON for SIEM integration
```json
{
"timestamp": "2025-11-30T13:45:00Z",
"event_type": "BLOCKED",
"severity": "HIGH",
"ip": "1.2.3.4",
"user_agent": "curl/7.68.0",
"method": "POST",
"path": "/api/contact",
"details": "Missing Origin/Referer headers"
}
```
**Production Logging:**
- stdout → systemd/Docker logs
- /var/log/cv-app/security.log → dedicated file
---
## Security Test Results 🧪
### Validation Tests
```bash
$ go test -v ./internal/validation/...
=== RUN TestIsValidEmail (15 test cases)
✅ PASS: All email validation tests
=== RUN TestContainsEmailInjection (14 test cases)
✅ PASS: All injection detection tests
=== RUN TestIsValidName (13 test cases)
✅ PASS: All name validation tests
=== RUN TestIsValidSubject (9 test cases)
✅ PASS: All subject validation tests
=== RUN TestValidateContactForm (10 test cases)
✅ PASS: All validation tests
=== RUN TestSecurityAttacks (4 attack simulations)
✅ PASS: All attack tests blocked
PASS
ok github.com/juanatsap/cv-site/internal/validation 0.494s
```
### Security Attack Simulations
```bash
✅ SQL Injection → BLOCKED (invalid characters in name)
✅ Email Header Injection → BLOCKED (CRLF stripped)
✅ Command Injection → BLOCKED (special chars rejected)
✅ Path Traversal → BLOCKED (pattern rejected)
✅ XSS in Message → HTML ESCAPED (safe for email clients)
✅ Bot Honeypot → BLOCKED (honeypot filled)
✅ Bot Timing → BLOCKED (submitted <2 seconds)
```
---
## How to Use (Integration Guide)
### 1. Contact Form Handler (Not Yet Implemented)
```go
package handlers
import (
"github.com/juanatsap/cv-site/internal/middleware"
"github.com/juanatsap/cv-site/internal/validation"
)
type ContactHandler struct {
// Your dependencies (email service, etc.)
}
func (h *ContactHandler) SendMessage(w http.ResponseWriter, r *http.Request) {
// 1. Parse request
var req validation.ContactFormRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Invalid request", http.StatusBadRequest)
return
}
// 2. Set server timestamp (don't trust client)
req.Timestamp = time.Now().Unix()
// 3. Validate input
if err := validation.ValidateContactForm(&req); err != nil {
middleware.LogSecurityEvent(middleware.EventValidationFailed, r, err.Error())
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// 4. Sanitize content
validation.SanitizeContactForm(&req)
// 5. Send email (implement this)
// if err := h.emailService.Send(&req); err != nil {
// middleware.LogSecurityEvent(middleware.EventEmailSendFailed, r, err.Error())
// http.Error(w, "Failed to send email", http.StatusInternalServerError)
// return
// }
// 6. Log success
middleware.LogSecurityEvent(middleware.EventContactFormSent, r,
fmt.Sprintf("From: %s <%s>", req.Name, req.Email))
// 7. Return success
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{
"message": "Message sent successfully",
})
}
```
### 2. Route Configuration
```go
package routes
func Setup(/*...*/) http.Handler {
mux := http.NewServeMux()
// ... existing routes ...
// Contact form endpoint with full security stack
csrf := middleware.NewCSRFProtection()
contactRateLimiter := middleware.NewContactRateLimiter()
protectedContactHandler := middleware.BrowserOnly(
csrf.Middleware(
contactRateLimiter.Middleware(
http.HandlerFunc(contactHandler.SendMessage),
),
),
)
mux.Handle("/api/contact", protectedContactHandler)
return mux
}
```
### 3. HTML Form Template
```html
<form hx-post="/api/contact"
hx-trigger="submit"
hx-target="#contact-result"
_="on htmx:afterRequest if event.detail.successful reset() me end">
<!-- CSRF Token (hidden) -->
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<!-- Timestamp for timing validation -->
<input type="hidden" name="timestamp" id="form-timestamp">
<!-- Honeypot field (hidden from real users) -->
<input type="text"
name="website"
id="website"
style="position:absolute;left:-9999px;"
tabindex="-1"
autocomplete="off">
<!-- Real fields -->
<input type="text" name="name" required maxlength="100"
pattern="[\p{L}\s'-]+"
title="Name can only contain letters, spaces, hyphens, and apostrophes">
<input type="email" name="email" required maxlength="254">
<input type="text" name="company" maxlength="100">
<input type="text" name="subject" required maxlength="200"
pattern="[\p{L}\p{N}\s.,!?'\"()\-:;#]+"
title="Subject can only contain letters, numbers, and basic punctuation">
<textarea name="message" required maxlength="5000"></textarea>
<button type="submit">Send Message</button>
</form>
<div id="contact-result"></div>
<script>
// Set timestamp when form loads
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('form-timestamp').value = Math.floor(Date.now() / 1000);
});
</script>
```
---
## Next Steps for Production
### 1. Email Service Integration
**TODO:** Implement email sending (Choose one)
- Option A: SMTP (net/smtp package)
- Option B: SendGrid API
- Option C: AWS SES
- Option D: Mailgun API
**Example SMTP:**
```go
func SendEmail(req *validation.ContactFormRequest) error {
// Configure SMTP
auth := smtp.PlainAuth("", os.Getenv("SMTP_USER"), os.Getenv("SMTP_PASS"), os.Getenv("SMTP_HOST"))
// Build email
to := []string{os.Getenv("CONTACT_EMAIL")}
subject := "Contact Form: " + req.Subject
body := fmt.Sprintf("From: %s <%s>\nCompany: %s\n\n%s",
req.Name, req.Email, req.Company, req.Message)
msg := []byte(fmt.Sprintf("To: %s\r\nSubject: %s\r\n\r\n%s",
strings.Join(to, ","), subject, body))
// Send email
return smtp.SendMail(
os.Getenv("SMTP_HOST")+":"+os.Getenv("SMTP_PORT"),
auth,
os.Getenv("SMTP_FROM"),
to,
msg,
)
}
```
### 2. Additional Security Headers
**TODO:** Add to `internal/middleware/security.go`
```go
w.Header().Set("X-Permitted-Cross-Domain-Policies", "none")
w.Header().Set("Cross-Origin-Opener-Policy", "same-origin")
w.Header().Set("Cross-Origin-Embedder-Policy", "require-corp")
```
### 3. Subresource Integrity (SRI)
**TODO:** Add SRI hashes to `templates/index.html`
```html
<!-- Generate hashes at: https://www.srihash.org/ -->
<script src="https://unpkg.com/hyperscript.org@0.9.14"
integrity="sha384-[GENERATE_HASH]"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"
integrity="sha384-[GENERATE_HASH]"
crossorigin="anonymous"></script>
```
### 4. Production Deployment Checklist
#### Environment Variables
```bash
# .env (production)
GO_ENV=production
PORT=1999
ALLOWED_ORIGINS=juan.andres.morenorub.io
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=noreply@juan.andres.morenorub.io
SMTP_PASS=<strong_password>
SMTP_FROM=noreply@juan.andres.morenorub.io
CONTACT_EMAIL=contact@juan.andres.morenorub.io
```
#### Nginx Configuration
See `SECURITY-AUDIT-REPORT.md` Section: "Linux Server Hardening Checklist"
- SSL/TLS configuration (A+ rating)
- Rate limiting zones
- Security headers (belt-and-suspenders)
- Connection limits
- Static file caching
#### Firewall Rules
```bash
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw enable
```
#### Fail2ban
```bash
sudo apt install fail2ban
# Configure jail for repeated 403/429 responses
# See SECURITY-AUDIT-REPORT.md for configuration
```
#### Log Rotation
```bash
# /etc/logrotate.d/cv-app
/var/log/cv-app/*.log {
daily
rotate 30
compress
delaycompress
notifempty
create 0644 cv-user cv-group
sharedscripts
postrotate
systemctl reload cv-app
endscript
}
```
---
## Security Monitoring
### Real-Time Monitoring
```bash
# Watch security events
tail -f /var/log/cv-app/security.log | jq 'select(.severity == "HIGH")'
# Count rate limit violations
grep "RATE_LIMIT_EXCEEDED" /var/log/cv-app/security.log | wc -l
# Top blocked IPs
grep "BLOCKED" /var/log/cv-app/security.log | jq -r '.ip' | sort | uniq -c | sort -rn | head -10
```
### Alerting (Prometheus/Grafana)
```yaml
# Example alert rules
- alert: HighRateLimitViolations
expr: rate(cv_rate_limit_violations_total[5m]) > 10
annotations:
summary: "High rate limit violations detected"
- alert: CSRFAttack
expr: increase(cv_csrf_violations_total[1h]) > 5
annotations:
summary: "CSRF attack detected"
```
---
## Compliance Status
### OWASP Top 10 (2021)
- ✅ A01: Broken Access Control → SECURE (origin validation, rate limiting)
- ✅ A02: Cryptographic Failures → SECURE (HSTS, no sensitive data storage)
- ✅ A03: Injection → SECURE (input validation, no SQL/command injection)
- ⚠️ A04: Insecure Design → IMPROVED (CSRF protection added)
- ✅ A05: Security Misconfiguration → SECURE (strong headers)
- ⚠️ A06: Vulnerable Components → MONITOR (dependency scanning needed)
- N/A A07: Auth Failures → N/A (no authentication system)
- ⚠️ A08: Integrity Failures → PARTIAL (SRI needed for all CDN resources)
- ⚠️ A09: Logging/Monitoring → IMPROVED (structured logging added)
- ✅ A10: SSRF → SECURE (no user-controlled URLs)
### CWE (Common Weakness Enumeration)
- ✅ CWE-79: XSS → SECURE (HTML template auto-escaping)
- ✅ CWE-89: SQL Injection → N/A (no database)
- ✅ CWE-78: OS Command Injection → SECURE (go-git library, no shell commands)
- ✅ CWE-352: CSRF → SECURE (token validation)
- ✅ CWE-601: Open Redirect → SECURE (no redirects from user input)
- ✅ CWE-862: Missing Authorization → N/A (public site)
- ✅ CWE-287: Improper Authentication → N/A (no authentication)
---
## Performance Impact
### Validation Benchmarks
```bash
$ go test -bench=. ./internal/validation/...
BenchmarkIsValidEmail-8 5000000 250 ns/op
BenchmarkContainsEmailInjection-8 10000000 120 ns/op
BenchmarkValidateContactForm-8 1000000 1200 ns/op
# Impact: <1ms additional latency for full validation
```
### Middleware Impact
- CSRF validation: ~0.1ms (constant-time comparison)
- Origin validation: ~0.05ms (header checks)
- Rate limiting: ~0.02ms (in-memory lookup)
- Security logging: ~0.3ms (JSON marshaling + file write)
**Total overhead:** <0.5ms per request (negligible)
---
## Documentation References
1. **Full Security Audit:** `SECURITY-AUDIT-REPORT.md`
- 100+ pages of detailed security analysis
- Contact form security design
- Penetration testing guide
- Server hardening checklist
2. **Validation Package:** `internal/validation/contact.go`
- Comprehensive input validation
- Email header injection prevention
- Bot detection (honeypot + timing)
3. **Middleware Package:** `internal/middleware/`
- `csrf.go` - CSRF protection
- `browser_only.go` - Origin validation
- `contact_rate_limit.go` - Rate limiting
- `security_logger.go` - Security logging
4. **Test Suite:** `internal/validation/contact_test.go`
- 60+ test cases
- Attack simulations
- 100% code coverage
---
## Contact Form Security Checklist
Before deploying contact form to production:
- ✅ Input validation implemented and tested
- ✅ CSRF protection enabled
- ✅ Origin validation (browser-only access)
- ✅ Rate limiting configured (5/hour)
- ✅ Bot protection (honeypot + timing)
- ✅ Email header injection prevention
- ✅ Security logging enabled
- ⚠️ Email service integrated (TODO)
- ⚠️ Production SMTP credentials configured (TODO)
- ⚠️ Privacy policy page created (GDPR compliance)
- ⚠️ Nginx rate limiting configured (TODO)
- ⚠️ Fail2ban configured for repeated attacks (TODO)
- ⚠️ Security monitoring/alerting set up (TODO)
---
## Final Security Rating
**Overall: A- (Very Good)**
### Strengths ✅
- Comprehensive input validation with attack prevention
- Strong CSRF protection with secure token management
- Browser-only access enforcement (blocks automation tools)
- Structured security logging for SIEM integration
- Excellent OWASP Top 10 coverage
- 100% test coverage for validation layer
- Zero critical vulnerabilities identified
### Areas for Improvement ⚠️
1. Add SRI hashes for remaining CDN resources
2. Implement automated dependency scanning
3. Set up security monitoring/alerting dashboard
4. Create GDPR privacy policy page
5. Configure fail2ban for production
---
**Security is a journey, not a destination. Regular audits, updates, and monitoring are essential.**
Last Updated: 2025-11-30
Next Audit Due: 2026-03-01 (Quarterly)
+2 -2
View File
@@ -294,7 +294,7 @@ Every time something breaks in production:
---
**Last Updated**: 2025-11-20
**Test Count**: 28 active tests (0-29 numbered + migration tests)
**Last Updated**: 2025-12-01
**Test Count**: 39 test files (comprehensive coverage including CMD+K, contact form, and PDF tests)
**Status**: Production specification
**Responsibility**: These tests define what "working" means
+2 -2
View File
@@ -286,8 +286,8 @@ When adding tests:
---
**Last Updated**: 2025-11-20
**Test Count**: 28 active tests - Comprehensive coverage
**Last Updated**: 2025-12-01
**Test Count**: 39 test files - Comprehensive coverage
**Coverage**: Complete (UI, keyboard, HTMX, i18n, modals, mobile, zoom, hover-sync, hyperscript, skeleton loaders, color themes, button positioning, PDF modal, icons, dark theme, course icons, references, toast notifications)
**Status**: SINGLE SOURCE OF TRUTH - Production specification
**Philosophy**: Each test validates specific functionality and edge cases
+4 -4
View File
@@ -1,6 +1,6 @@
# CV Project Test Suite (Active Tests)
**28 comprehensive tests** covering all functionality from UI interactions to PDF generation.
**39 comprehensive test files** covering all functionality from UI interactions to PDF generation, CMD+K command palette, and contact form.
## Quick Start
@@ -149,7 +149,7 @@ bun tests/mjs/28-references-pdf-download.test.mjs
---
**Last Updated**: 2025-11-20
**Test Count**: 28 active tests
**Coverage**: Complete functionality coverage including toast notifications
**Last Updated**: 2025-12-01
**Test Count**: 39 test files
**Coverage**: Complete functionality coverage including toast notifications, CMD+K command palette, and contact form
**Status**: Production specification