diff --git a/PROJECT-MEMORY.md b/PROJECT-MEMORY.md
index 4ef31c6..9b3960b 100644
--- a/PROJECT-MEMORY.md
+++ b/PROJECT-MEMORY.md
@@ -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`
+
diff --git a/docs/CONTACT-FORM-QUICKSTART.md b/doc/17-CONTACT-FORM.md
similarity index 100%
rename from docs/CONTACT-FORM-QUICKSTART.md
rename to doc/17-CONTACT-FORM.md
diff --git a/docs/SECURITY-AUDIT-REPORT.md b/doc/18-SECURITY-AUDIT.md
similarity index 100%
rename from docs/SECURITY-AUDIT-REPORT.md
rename to doc/18-SECURITY-AUDIT.md
diff --git a/docs/SECURITY.md b/doc/19-SECURITY-IMPLEMENTATION.md
similarity index 100%
rename from docs/SECURITY.md
rename to doc/19-SECURITY-IMPLEMENTATION.md
diff --git a/doc/3-API.md b/doc/3-API.md
index cc5becc..3abdad4 100644
--- a/doc/3-API.md
+++ b/doc/3-API.md
@@ -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
---
-### 3. GET /export/pdf
+### 3. GET /text
+
+**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
+
+| 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.
@@ -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
diff --git a/doc/README.md b/doc/README.md
index c76a74a..aa748d3 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -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
diff --git a/docs/CMD-K-COMMAND-BAR.md b/docs/CMD-K-COMMAND-BAR.md
deleted file mode 100644
index e88ad58..0000000
--- a/docs/CMD-K-COMMAND-BAR.md
+++ /dev/null
@@ -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
diff --git a/docs/CONTACT_FORM_IMPLEMENTATION.md b/docs/CONTACT_FORM_IMPLEMENTATION.md
deleted file mode 100644
index d0115e1..0000000
--- a/docs/CONTACT_FORM_IMPLEMENTATION.md
+++ /dev/null
@@ -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
-
-
Message Sent Successfully!
-
Thank you for reaching out...
-
-```
-
-**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
-
-
-
-
-
-```
-
-### 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
diff --git a/docs/SECURITY-IMPLEMENTATION-SUMMARY.md b/docs/SECURITY-IMPLEMENTATION-SUMMARY.md
deleted file mode 100644
index 12bd748..0000000
--- a/docs/SECURITY-IMPLEMENTATION-SUMMARY.md
+++ /dev/null
@@ -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>...
-✅ 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
-
-
-
-
-
-```
-
----
-
-## 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
-
-
-
-
-```
-
-### 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=
-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)
diff --git a/tests/README.md b/tests/README.md
index 9f23713..fc562e1 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -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
diff --git a/tests/TEST-SUMMARY.md b/tests/TEST-SUMMARY.md
index f9dc40c..2b1980e 100644
--- a/tests/TEST-SUMMARY.md
+++ b/tests/TEST-SUMMARY.md
@@ -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
diff --git a/tests/mjs/README.md b/tests/mjs/README.md
index 5671684..41382ce 100644
--- a/tests/mjs/README.md
+++ b/tests/mjs/README.md
@@ -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