# Implementation Guide for Security & Performance Improvements

This guide provides step-by-step instructions for implementing the critical fixes identified in the audit.

---

## 1. SEO: Sitemap Generation

### Implementation Steps

1. **Add Sitemap Controller Routes** to `internal/routes/routes.go`:

```go
// In SetupRootRoutes function
func SetupRootRoutes(r *gin.Engine, db *gorm.DB) {
    sitemapCtrl := &controllers.SitemapController{DB: db}
    
    // Sitemap routes
    r.GET("/sitemap.xml", sitemapCtrl.GetSitemap)
    r.GET("/robots.txt", sitemapCtrl.GetRobotsTxt)
    
    // ... existing routes
}
```

2. **Update Settings Model** to include `EnableIndexing` field if not present:

```go
// In internal/models/settings.go
type Settings struct {
    // ... existing fields
    EnableIndexing bool `json:"enable_indexing" gorm:"default:true"`
}
```

3. **Test the sitemap**:
   - Visit `http://localhost:8080/sitemap.xml`
   - Visit `http://localhost:8080/robots.txt`
   - Verify XML structure is valid

---

## 2. Security: CSRF Protection

### Implementation Steps

1. **Add CSRF Token Endpoint** to routes:

```go
// In internal/routes/routes.go
import "fotbal-club/internal/middleware"

func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
    // Public CSRF token endpoint
    api.GET("/csrf-token", middleware.GetCSRFToken)
    
    // Apply CSRF protection to state-changing routes
    protected := api.Group("")
    protected.Use(middleware.CSRFProtection())
    {
        // All POST, PUT, PATCH, DELETE routes here
        protected.POST("/articles", baseCtrl.CreateArticle)
        protected.PUT("/articles/:id", baseCtrl.UpdateArticle)
        // ... etc
    }
}
```

2. **Update Frontend API Service** to fetch and include CSRF token:

```typescript
// In frontend/src/services/api.ts
let csrfToken: string | null = null;

// Fetch CSRF token on app init
export const initCSRF = async () => {
  try {
    const response = await axios.get(`${API_URL}/csrf-token`);
    csrfToken = response.data.csrf_token;
  } catch (error) {
    console.error('Failed to fetch CSRF token:', error);
  }
};

// Add CSRF token to requests
api.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // Existing auth token logic...
    
    // Add CSRF token for state-changing requests
    if (['post', 'put', 'patch', 'delete'].includes(config.method?.toLowerCase() || '')) {
      if (csrfToken) {
        config.headers = config.headers || {};
        (config.headers as any)['X-CSRF-Token'] = csrfToken;
      }
    }
    return config;
  },
  (error) => Promise.reject(error)
);
```

3. **Initialize CSRF in App**:

```typescript
// In frontend/src/index.tsx
import { initCSRF } from './services/api';

// After root.render()
initCSRF();
```

---

## 3. Security: Improved Content-Security-Policy

### Implementation Steps

1. **Update CSP in main.go**:

```go
// Replace the existing CSP in main.go middleware
csp := "default-src 'self'; " +
      "script-src 'self' https://fonts.googleapis.com https://umami.tdvorak.dev; " +
      "style-src 'self' https://fonts.googleapis.com 'unsafe-inline'; " +
      "font-src 'self' https://fonts.gstatic.com data:; " +
      "img-src 'self' data: https: blob:; " +
      "connect-src 'self' https://umami.tdvorak.dev https://zonerama.tdvorak.dev; " +
      "frame-src 'self' https://www.youtube.com https://www.youtube-nocookie.com; " +
      "object-src 'none'; " +
      "base-uri 'self'; " +
      "form-action 'self'; " +
      "frame-ancestors 'none';"

c.Writer.Header().Set("Content-Security-Policy", csp)
```

2. **Handle CSP violations** (optional):

```go
// Add CSP report endpoint
r.POST("/api/v1/csp-report", func(c *gin.Context) {
    var report map[string]interface{}
    if err := c.ShouldBindJSON(&report); err == nil {
        logger.Warn("CSP Violation: %+v", report)
    }
    c.Status(http.StatusNoContent)
})
```

3. **Update CSP to include report-uri**:

```go
csp += " report-uri /api/v1/csp-report;"
```

---

## 4. Security: Remove Dev Bypass from Production

### Implementation Steps

1. **Update DevBypass middleware** in `internal/middleware/auth.go`:

```go
func DevBypass() gin.HandlerFunc {
    return func(c *gin.Context) {
        // ONLY allow in development
        if config.AppConfig != nil && config.AppConfig.AppEnv == "development" {
            if strings.ToLower(c.GetHeader("X-Dev-Admin")) == "true" {
                logger.Warn("Dev bypass used - this should never happen in production!")
                c.Set("userRole", "admin")
                c.Set("user", &models.User{Role: "admin"})
                c.Next()
                return
            }
        }
        c.Next()
    }
}
```

2. **Remove X-Dev-Admin header from frontend in production**:

```typescript
// In frontend/src/services/api.ts
export const api: AxiosInstance = axios.create({
  baseURL: API_URL,
  headers: {
    // Only include dev headers in development
    ...(process.env.NODE_ENV === 'development' 
      ? { 'X-Dev-Admin': 'true' } 
      : {}),
  },
  withCredentials: true,
  timeout: 20000,
});
```

---

## 5. Security: HTML Sanitization

### Implementation Steps

1. **Use sanitization in controllers**:

```go
// In internal/controllers/base_controller.go
import "fotbal-club/pkg/utils"

func (bc *BaseController) CreateArticle(c *gin.Context) {
    // ... existing code ...
    
    // Sanitize HTML content
    body.Content = utils.SanitizeHTML(body.Content)
    body.Title = utils.RemoveNullBytes(strings.TrimSpace(body.Title))
    
    // ... rest of function
}
```

2. **Add frontend sanitization** for rich text editor:

```bash
cd frontend
npm install dompurify @types/dompurify
```

```typescript
// In frontend/src/utils/sanitize.ts
import DOMPurify from 'dompurify';

export const sanitizeHTML = (dirty: string): string => {
  return DOMPurify.sanitize(dirty, {
    ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'u', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'li', 'a', 'img', 'blockquote', 'code', 'pre'],
    ALLOWED_ATTR: ['href', 'src', 'alt', 'title', 'target', 'rel'],
  });
};
```

---

## 6. Performance: Code Splitting

### Implementation Steps

1. **Use the lazy-loaded App component**:

```typescript
// Update frontend/src/index.tsx
import AppLazy from './App.lazy';

// Replace <App /> with <AppLazy />
root.render(
  <React.StrictMode>
    <ErrorBoundary>
      <HelmetProvider>
        <ColorModeScript initialColorMode={theme.config.initialColorMode} />
        <AppLazy />
      </HelmetProvider>
    </ErrorBoundary>
  </React.StrictMode>
);
```

2. **Verify bundle splitting**:

```bash
cd frontend
npm run build
```

Check the build output - you should see multiple chunk files.

---

## 7. Performance: Add Bundle Analysis

### Implementation Steps

1. **Install webpack-bundle-analyzer**:

```bash
cd frontend
npm install --save-dev webpack-bundle-analyzer
npm install --save-dev @craco/craco
```

2. **Create craco config** if not exists (`frontend/craco.config.js`):

```javascript
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  webpack: {
    plugins: {
      add: [
        process.env.ANALYZE && new BundleAnalyzerPlugin(),
      ].filter(Boolean),
    },
  },
};
```

3. **Add analysis script** to `frontend/package.json`:

```json
{
  "scripts": {
    "analyze": "ANALYZE=true npm run build"
  }
}
```

4. **Run analysis**:

```bash
npm run analyze
```

---

## 8. Security: Add Request Size Limits

### Implementation Steps

1. **Add middleware in main.go**:

```go
// Add after router initialization
r.Use(func(c *gin.Context) {
    // Limit request body size to 10MB (except for upload endpoints)
    if !strings.HasPrefix(c.Request.URL.Path, "/api/v1/upload") {
        c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 10*1024*1024)
    }
    c.Next()
})
```

---

## Testing Checklist

After implementing these changes:

### Security Tests
- [ ] CSRF token is required for POST/PUT/DELETE requests
- [ ] Dev bypass doesn't work in production environment
- [ ] CSP blocks inline scripts
- [ ] HTML sanitization removes `<script>` tags
- [ ] Request size limit rejects large payloads

### SEO Tests
- [ ] `/sitemap.xml` returns valid XML
- [ ] `/robots.txt` includes sitemap reference
- [ ] Meta descriptions are properly set
- [ ] Structured data validates on Google's testing tool

### Performance Tests
- [ ] Multiple JS chunks are generated on build
- [ ] Initial bundle size is reduced
- [ ] Pages load incrementally
- [ ] Bundle analyzer shows size breakdown

---

## Deployment Notes

1. **Environment Variables** - Ensure production `.env` has:
   ```
   APP_ENV=production
   JWT_SECRET=<strong-random-secret>
   CONTENT_SECURITY_POLICY=<strict-policy>
   ```

2. **Database Migration** - Add `EnableIndexing` column:
   ```sql
   ALTER TABLE settings ADD COLUMN enable_indexing BOOLEAN DEFAULT true;
   ```

3. **Frontend Build** - Use production build:
   ```bash
   cd frontend
   npm run build
   ```

4. **Testing** - Test all critical paths after deployment

---

## Rollback Plan

If issues arise:

1. **CSRF Issues**: Remove `CSRFProtection()` middleware temporarily
2. **CSP Issues**: Set to `report-only` mode first
3. **Code Splitting Issues**: Use original `App.tsx` instead of `App.lazy.tsx`
4. **Sitemap Issues**: Comment out sitemap routes

---

## Support

For questions or issues during implementation:
1. Check the `COMPREHENSIVE_AUDIT_REPORT.md`
2. Review error logs in `logs/` directory
3. Test in development environment first
