## Example 1: PR with Security Vulnerability

**PR Description:** "Add file upload endpoint for user profile pictures."

**Diff:**
```typescript
// src/api/upload.ts (new file)
import express from 'express';
import multer from 'multer';
import path from 'path';

const upload = multer({ dest: 'uploads/' });

router.post('/upload', upload.single('file'), async (req, res) => {
  const file = req.file;
  
  // Store file path in database
  await db.query(
    `INSERT INTO uploads (user_id, filename, path) 
     VALUES (${req.user.id}, '${file.originalname}', '${file.path}')`
  );
  
  res.json({ 
    url: `/uploads/${file.filename}` 
  });
});
```

**Review:**

```
## Summary
Security-critical PR with multiple vulnerabilities. Must not merge as-is.

## Critical Issues (must fix before merge)

### 1. SQL Injection (Line 12-15) — CRITICAL
The query uses string interpolation with user-controlled values.
`file.originalname` can contain SQL injection payloads.

Fix:
```typescript
await db.query(
  'INSERT INTO uploads (user_id, filename, path) VALUES ($1, $2, $3)',
  [req.user.id, file.originalname, file.path]
);
```

### 2. No File Type Validation — CRITICAL
Any file type can be uploaded, including executables and HTML files.
This enables:
- Uploading malicious executables
- XSS via SVG/HTML files
- Server storage exhaustion

Fix: Add file type whitelist:
```typescript
const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
const upload = multer({
  dest: 'uploads/',
  fileFilter: (req, file, cb) => {
    if (ALLOWED_TYPES.includes(file.mimetype)) {
      cb(null, true);
    } else {
      cb(new Error('File type not allowed'));
    }
  },
  limits: { fileSize: 5 * 1024 * 1024 } // 5MB max
});
```

### 3. No Authentication Check — CRITICAL
The endpoint has no auth middleware. Any unauthenticated user can upload files.

Fix: Add auth middleware:
```typescript
router.post('/upload', authMiddleware, upload.single('file'), async (req, res) => {
```

## Suggestions (should consider)

### 4. Filename Collision (Line 12)
`file.originalname` is not sanitized or unique. Multiple users uploading 
"photo.jpg" will collide.

Fix: Generate unique filename:
```typescript
const uniqueName = `${Date.now()}-${Math.random().toString(36).slice(2)}${path.extname(file.originalname)}`;
```

### 5. Path Traversal Risk (Line 18)
Serving files from `uploads/` without path validation could allow 
directory traversal if filename contains `../`.

Fix: Validate filename doesn't contain path separators.

## Nits
- Add request logging for audit trail
- Consider rate limiting on upload endpoint
```

---

## Example 2: PR with Performance Issue

**PR Description:** "Add product search with filtering."

**Diff:**
```typescript
// src/api/products.ts
router.get('/search', async (req, res) => {
  const { q, category, minPrice, maxPrice } = req.query;
  
  let products = await Product.findAll();
  
  // Filter by search query
  if (q) {
    products = products.filter(p => 
      p.name.toLowerCase().includes(q.toLowerCase()) ||
      p.description.toLowerCase().includes(q.toLowerCase())
    );
  }
  
  // Filter by category
  if (category) {
    products = products.filter(p => p.category === category);
  }
  
  // Filter by price range
  if (minPrice) {
    products = products.filter(p => p.price >= Number(minPrice));
  }
  if (maxPrice) {
    products = products.filter(p => p.price <= Number(maxPrice));
  }
  
  res.json({ data: products });
});
```

**Review:**

```
## Summary
Functionally correct but will not scale. Performance issues with large datasets.

## Critical Issues (must fix before merge)

### 1. Loading All Products Into Memory — PERFORMANCE
`Product.findAll()` loads every product into memory before filtering.
With 100K+ products, this will:
- Cause memory spikes
- Timeout on large datasets
- Block the event loop during filtering

Fix: Push filtering to the database:
```typescript
router.get('/search', async (req, res) => {
  const { q, category, minPrice, maxPrice } = req.query;
  
  const where: any = {};
  
  if (q) {
    where.OR = [
      { name: { contains: q, mode: 'insensitive' } },
      { description: { contains: q, mode: 'insensitive' } }
    ];
  }
  
  if (category) where.category = category;
  if (minPrice) where.price = { ...where.price, gte: Number(minPrice) };
  if (maxPrice) where.price = { ...where.price, lte: Number(maxPrice) };
  
  const products = await Product.findMany({ where, take: 50 });
  res.json({ data: products });
});
```

### 2. No Pagination — PERFORMANCE
Returns all matching products without limit.
A search matching 10K products will return 10K objects.

Fix: Add pagination:
```typescript
const page = Number(req.query.page) || 1;
const limit = Math.min(Number(req.query.limit) || 20, 100);
const offset = (page - 1) * limit;

const [products, total] = await Promise.all([
  Product.findMany({ where, skip: offset, take: limit }),
  Product.count({ where })
]);

res.json({ 
  data: products, 
  pagination: { page, limit, total, pages: Math.ceil(total / limit) }
});
```

### 3. Missing Database Indexes — PERFORMANCE
Filtering on `category` and `price` without indexes will do full table scans.

Fix: Add indexes:
```sql
CREATE INDEX idx_products_category ON products(category);
CREATE INDEX idx_products_price ON products(price);
CREATE INDEX idx_products_name_gin ON products USING gin(name gin_trgm_ops);
```

## Suggestions (should consider)

### 4. Search Implementation
`String.includes()` is not suitable for full-text search. 
Consider using database full-text search or a search library.

### 5. Response Format
Include pagination metadata and total count for client-side rendering.

## Nits
- Add input validation for minPrice/maxPrice (ensure they are numbers)
- Consider caching frequent search queries
```
