# Example: Good PR with Complete Documentation

This is an example of a well-documented pull request that follows all documentation requirements.

## PR Title

```
feat: add user authentication with JWT tokens
```

**✅ Good because:**
- Uses semantic prefix (`feat:`)
- Clear, concise description
- Describes what changed (user auth) and how (JWT tokens)

## PR Description

````markdown
## Description

Implements user authentication using JWT (JSON Web Tokens) for secure, stateless authentication.

### What Changed

**Core Features:**
- Added `/api/auth/login` and `/api/auth/register` endpoints
- Implemented JWT token generation and validation
- Created authentication middleware for protected routes
- Added password hashing using bcrypt

**Documentation:**
- Updated `README.md` with authentication setup instructions
- Added API documentation for auth endpoints in `docs/api.md`
- Updated architecture docs to explain JWT flow
- Added docstrings to all auth-related functions

**Testing:**
- Added unit tests for token generation/validation
- Added integration tests for auth endpoints
- Added security tests for password hashing

### Why

Authentication is required for:
1. Protecting user data
2. Enabling personalized features
3. Tracking user actions for audit logs
4. Supporting future features (user profiles, preferences)

JWT was chosen over session-based auth because:
- Stateless (scales horizontally)
- Works with SPAs and mobile apps
- Industry standard with good library support

### Impact

**Files changed:** 12 files (5 source, 4 docs, 3 tests)
**Lines added:** 847 (352 code, 412 docs, 83 tests)

**Breaking changes:** None
**Migration required:** No
**Feature flags:** Auth is enabled by default (can be disabled via env var)

### Related Issues

Fixes #42
Addresses feedback from #38 (comment)

---

## Documentation Checklist

- [x] README.md updated with authentication setup
- [x] API docs updated with new endpoints
- [x] Architecture docs updated with JWT flow diagram
- [x] All new functions have Google-style docstrings
- [x] Code comments added for security-critical sections
- [x] CHANGELOG.md updated
- [x] PR description explains what/why/impact

## PR Quality Checklist

- [x] Code follows project style guide
- [x] All tests pass locally
- [x] New tests added for new functionality
- [x] Code coverage maintained/improved
- [x] No security vulnerabilities introduced
- [x] Performance impact assessed (negligible)

## Testing

**Unit tests:**
```bash
$ pytest tests/unit/auth/
===== 15 passed in 0.42s =====
```

**Integration tests:**
```bash
$ pytest tests/integration/test_auth_endpoints.py
===== 8 passed in 1.23s =====
```

**Coverage:**
```bash
$ pytest --cov=src/auth
auth/token.py       100%
auth/middleware.py   95%
auth/routes.py       98%
TOTAL               97%
```

**Manual testing:**
- ✅ Login with valid credentials
- ✅ Login with invalid credentials (returns 401)
- ✅ Register new user
- ✅ Access protected route with valid token
- ✅ Access protected route without token (returns 401)
- ✅ Access protected route with expired token (returns 401)

## Security Considerations

- Passwords hashed with bcrypt (12 rounds)
- JWT tokens signed with HS256 (secret from env var)
- Tokens expire after 24 hours
- No sensitive data stored in JWT payload
- Rate limiting on auth endpoints (10 req/min)

## Additional Context

**Configuration required:**
```bash
# .env file
JWT_SECRET=<random-secret-key>  # Required
JWT_EXPIRY=86400                # Optional, default 24h
```

**Next steps:**
- [ ] Add refresh token support (issue #99)
- [ ] Implement OAuth2 providers (issue #100)
- [ ] Add 2FA support (future)

---

Generated with [Claude Code](https://claude.com/claude-code)
````

## Files Changed

### 1. Source Code (`src/auth/token.py`)

**Before:** (didn't exist)

**After:**
```python
"""JWT token generation and validation."""

import jwt
from datetime import datetime, timedelta
from typing import Optional
from ..config import settings


def generate_token(user_id: int) -> str:
    """Generate JWT token for authenticated user.

    Args:
        user_id: Unique identifier for the user

    Returns:
        Encoded JWT token string

    Example:
        >>> token = generate_token(123)
        >>> print(token)
        'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
    """
    # Token expires after configured duration (default 24h)
    expiry = datetime.utcnow() + timedelta(seconds=settings.JWT_EXPIRY)

    # Payload contains user_id and expiry, but no sensitive data
    # (following JWT best practices)
    payload = {
        "user_id": user_id,
        "exp": expiry,
        "iat": datetime.utcnow()
    }

    # Sign with HS256 algorithm using secret key from environment
    # Never hardcode secrets in source code
    return jwt.encode(payload, settings.JWT_SECRET, algorithm="HS256")


def validate_token(token: str) -> Optional[int]:
    """Validate JWT token and extract user ID.

    Args:
        token: JWT token string to validate

    Returns:
        User ID if token is valid, None otherwise

    Example:
        >>> user_id = validate_token("eyJhbGciOiJIUzI1...")
        >>> print(user_id)
        123
    """
    try:
        # Decode and verify signature, expiry, etc.
        payload = jwt.decode(
            token,
            settings.JWT_SECRET,
            algorithms=["HS256"]
        )
        return payload.get("user_id")

    except jwt.ExpiredSignatureError:
        # Token expired - user needs to login again
        return None
    except jwt.InvalidTokenError:
        # Invalid token - tampered or malformed
        return None
```

### 2. Documentation (`README.md`)

**Before:**
```markdown
# My Project

A web application.

## Installation

```bash
pip install -r requirements.txt
```

## Usage

```bash
python app.py
```
```

**After:**
```markdown
# My Project

A web application with user authentication.

## Features

- User authentication with JWT tokens
- Secure password storage with bcrypt
- Protected API endpoints
- RESTful API

## Installation

```bash
pip install -r requirements.txt
```

## Configuration

Create a `.env` file with required settings:

```bash
# Required: Secret key for JWT signing (generate with: openssl rand -hex 32)
JWT_SECRET=your-secret-key-here

# Optional: Token expiry in seconds (default: 86400 = 24 hours)
JWT_EXPIRY=86400
```

⚠️ **Security:** Never commit your `.env` file or share your JWT_SECRET.

## Usage

### Start the server

```bash
python app.py
```

### Authentication

**Register a new user:**
```bash
curl -X POST http://localhost:5000/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"username": "alice", "password": "secret123"}'
```

**Login:**
```bash
curl -X POST http://localhost:5000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username": "alice", "password": "secret123"}'

# Response:
# {"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}
```

**Access protected routes:**
```bash
curl http://localhost:5000/api/protected \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
```

## API Documentation

See [API Documentation](docs/api.md) for complete endpoint reference.
```

### 3. API Documentation (`docs/api.md`)

**Before:** (didn't exist)

**After:**
```markdown
# API Documentation

## Authentication Endpoints

### POST /api/auth/register

Register a new user account.

**Request:**
```json
{
  "username": "alice",
  "password": "secret123"
}
```

**Response (201 Created):**
```json
{
  "id": 1,
  "username": "alice",
  "created_at": "2025-01-07T12:00:00Z"
}
```

**Errors:**
- `400 Bad Request`: Username already exists
- `422 Unprocessable Entity`: Invalid input (e.g., password too short)

---

### POST /api/auth/login

Authenticate user and receive JWT token.

**Request:**
```json
{
  "username": "alice",
  "password": "secret123"
}
```

**Response (200 OK):**
```json
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_at": "2025-01-08T12:00:00Z"
}
```

**Errors:**
- `401 Unauthorized`: Invalid credentials
- `422 Unprocessable Entity`: Missing username or password

---

## Protected Endpoints

All endpoints below require authentication via JWT token in Authorization header:

```
Authorization: Bearer <your-jwt-token>
```

### GET /api/protected

Example protected endpoint.

**Response (200 OK):**
```json
{
  "message": "Hello, authenticated user!",
  "user_id": 1
}
```

**Errors:**
- `401 Unauthorized`: Missing or invalid token
```

## Why This Example Is Good

✅ **Complete PR description:**
- Explains what changed
- Explains why (business justification)
- Lists impact (files, lines)
- Includes testing results
- Notes security considerations

✅ **Documentation checklist complete:**
- README updated with auth setup
- API docs added for new endpoints
- All functions have docstrings
- Code comments for security sections

✅ **All code has docstrings:**
- Google-style format
- Explains purpose, parameters, returns
- Includes examples

✅ **README updated:**
- Configuration requirements documented
- Usage examples provided
- Security warnings included

✅ **API docs comprehensive:**
- Request/response examples
- Error codes documented
- Authentication requirements clear

## Compare to Bad Example

See `examples/documentation/bad-pr-example.md` for what NOT to do.

## Related Documentation

- **PR template**: `.github/PULL_REQUEST_TEMPLATE.md`
- **Playbook**: `playbooks/updating-documentation.md`
- **Knowledge base**: `.claude/knowledge/documentation/keeping-docs-updated.md`
- **Engineering standards**: `.claude/standards/ENGINEERING_STANDARDS.md#documentation-requirements`
