TradingAgents/.claude/skills/github-workflow/examples/pr-template.md

306 lines
12 KiB
Markdown

# Example Pull Request Description
## Summary
Add JWT-based authentication to replace session-based auth, enabling horizontal scaling and stateless API architecture.
## Motivation
Current session-based authentication requires sticky sessions in the load balancer, preventing horizontal scaling and blocking mobile app launch. This migration enables:
- Dynamic server scaling during traffic spikes
- Mobile app support (no cookie requirement)
- Reduced infrastructure costs (~30%)
## Changes
### Added
- JWT token generation and validation service (`src/auth/jwt_service.py`)
- Authentication endpoints (`/auth/login`, `/auth/refresh`, `/auth/logout`)
- JWT validation middleware for API route protection
- Refresh token mechanism with 7-day expiry
- Rate limiting on authentication endpoints (10 req/min per IP)
- Token revocation support for logout
### Changed
- API middleware now checks for JWT in `Authorization: Bearer <token>` header
- Error responses return 401 Unauthorized for invalid/expired tokens
- Configuration updated with JWT_SECRET and TOKEN_EXPIRY settings
### Removed
- ~~Session management middleware~~ (deprecated, will be removed in v3.0)
## Test plan
### Manual Testing
```bash
# 1. Install dependencies
pip install -r requirements.txt
# 2. Set JWT_SECRET environment variable
export JWT_SECRET="your-secret-key-here"
# 3. Start server
python run.py
# 4. Test login endpoint
curl -X POST http://localhost:5000/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"test123"}'
# Expected response:
# {
# "access_token": "eyJ...",
# "refresh_token": "eyJ...",
# "expires_in": 900
# }
# 5. Test protected endpoint with token
curl http://localhost:5000/api/users \
-H "Authorization: Bearer <access_token>"
# Expected: 200 OK with user list
# 6. Test with invalid token
curl http://localhost:5000/api/users \
-H "Authorization: Bearer invalid_token"
# Expected: 401 Unauthorized
# 7. Test refresh token
curl -X POST http://localhost:5000/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token":"<refresh_token>"}'
# Expected: New access token
```
### Automated Tests
- **Unit tests**: `tests/test_jwt_service.py` (15 tests, all passing)
- Token generation
- Token validation
- Token expiration
- Token revocation
- **Integration tests**: `tests/integration/test_auth_endpoints.py` (12 tests, all passing)
- Login flow
- Token refresh flow
- Protected endpoint access
- Error handling
- **Coverage**: 96% of auth module (78/81 lines)
### Load Testing
```bash
# Test with 10,000 concurrent users
locust -f tests/load/test_auth.py --users 10000 --spawn-rate 100
Results:
- Average response time: 45ms
- 99th percentile: 120ms
- Error rate: 0%
- Memory usage: Stable at ~500MB (vs 2GB with sessions)
```
### Edge Cases Tested
- Expired access token → Returns 401, client refreshes successfully
- Expired refresh token → Returns 401, client re-authenticates
- Malformed JWT → Returns 401 with clear error message
- Missing Authorization header → Returns 401
- Token revoked via logout → Subsequent requests fail with 401
- Concurrent requests with same token → All succeed (no race conditions)
## Breaking Changes
### Migration Required
**Sessions will be deprecated in v3.0** (90 days from now). During the transition period, both session-based and JWT-based authentication are supported.
#### For API Clients
**Before (session-based):**
```python
# Login
response = requests.post("/api/login", json={"username": "user", "password": "pass"})
session_cookie = response.cookies["session_id"]
# Authenticated request
requests.get("/api/users", cookies={"session_id": session_cookie})
```
**After (JWT-based):**
```python
# Login
response = requests.post("/auth/login", json={"username": "user", "password": "pass"})
access_token = response.json()["access_token"]
refresh_token = response.json()["refresh_token"]
# Authenticated request
requests.get("/api/users", headers={"Authorization": f"Bearer {access_token}"})
# Refresh when access token expires
response = requests.post("/auth/refresh", json={"refresh_token": refresh_token})
new_access_token = response.json()["access_token"]
```
#### Migration Steps
1. Update client code to use `/auth/login` endpoint
2. Store `access_token` and `refresh_token` from login response
3. Send `Authorization: Bearer <access_token>` header with all API requests
4. Implement token refresh logic when access token expires (15 min)
5. Handle 401 responses by refreshing or re-authenticating
#### Migration Guide
See full migration guide: [docs/auth-migration-guide.md](docs/auth-migration-guide.md)
## Performance Impact
### Improvements
- **Memory usage**: 75% reduction (2GB → 500MB for 10K users)
- **Response time**: 20% faster (session lookup eliminated)
- **Scalability**: Supports 5x more concurrent users (10K → 50K)
- **Cost**: ~30% infrastructure savings (no sticky sessions)
### Regressions
None identified
### Benchmarks
| Metric | Before (Sessions) | After (JWT) | Change |
|--------|-------------------|-------------|--------|
| Avg response time | 55ms | 45ms | -18% ⬇️ |
| P99 response time | 180ms | 120ms | -33% ⬇️ |
| Memory (10K users) | 2GB | 500MB | -75% ⬇️ |
| Max concurrent users | 10,000 | 50,000 | +400% ⬆️ |
| Infrastructure cost | $5,000/mo | $3,500/mo | -30% ⬇️ |
## Security Considerations
### Security Measures Implemented
- **RS256 algorithm**: Asymmetric signing (public/private key pair)
- **Short token expiry**: Access tokens expire after 15 minutes
- **Refresh token rotation**: New refresh token issued on each refresh
- **Rate limiting**: 10 login attempts per minute per IP
- **Secure storage**: Refresh tokens HttpOnly, Secure flags
- **No sensitive data**: JWT payload contains only user_id, role
- **Token revocation**: Logout invalidates refresh tokens
### Security Audit
- [x] Penetration testing completed (no critical issues)
- [x] Security review completed (approved by security team)
- [x] OWASP Top 10 compliance verified
- [x] Token storage best practices followed
## Documentation Updates
- [x] API documentation updated with JWT examples ([docs/api/authentication.md](docs/api/authentication.md))
- [x] Migration guide published ([docs/auth-migration-guide.md](docs/auth-migration-guide.md))
- [x] Admin guide for token management added ([docs/admin/token-management.md](docs/admin/token-management.md))
- [x] Security best practices documented ([docs/security/jwt-best-practices.md](docs/security/jwt-best-practices.md))
- [x] CHANGELOG.md updated with breaking changes
## Rollout Plan
### Phase 1: Internal Beta (Week 1)
- Deploy to staging environment
- Dev team tests JWT authentication
- Monitor for issues
### Phase 2: Gradual Rollout (Week 2-3)
- Enable JWT for 10% of users (feature flag)
- Monitor error rates, performance
- Increase to 50% if no issues
- Increase to 100% by end of Week 3
### Phase 3: Deprecation Notice (Week 4)
- Display migration banner for session-based users
- Send email notification to API clients
- Update documentation with deprecation timeline
### Phase 4: Session Removal (90 days)
- Remove session-based authentication code
- Release v3.0 with breaking changes
## Checklist
- [x] Tests added for new functionality
- [x] All tests pass locally (`pytest tests/`)
- [x] Integration tests pass (`pytest tests/integration/`)
- [x] Load testing completed (10K concurrent users)
- [x] Security audit completed
- [x] API documentation updated
- [x] Migration guide published
- [x] CHANGELOG.md updated
- [x] Breaking changes documented
- [x] No new linter warnings
- [x] Code coverage >95%
- [x] Feature flag added for gradual rollout
- [x] Rollback plan documented
## Related
- Closes #123 (JWT authentication feature request)
- Blocks #125 (Mobile app launch)
- Related to #124 (Horizontal scaling infrastructure)
- Follow-up to #100 (Session management refactoring)
## Screenshots / Diagrams
### Authentication Flow
```
┌─────────┐ ┌─────────────┐
│ Client │ │ Auth API │
└─────────┘ └─────────────┘
│ │
│ 1. POST /auth/login │
│ { username, password } │
│──────────────────────────────────────────> │
│ │
│ │ 2. Validate credentials
│ │ 3. Generate tokens
│ │
│ 4. Return tokens │
│ { access_token, refresh_token } │
│ <──────────────────────────────────────── │
│ │
│ 5. Store tokens │
│ │
│ ┌───────────────┐
│ 6. API request + access_token │ API Server │
│──────────────────────────────────> └───────────────┘
│ │
│ │ 7. Validate JWT
│ │ 8. Process request
│ │
│ 9. Response │
│ <──────────────────────────────────────── │
```
### Token Refresh Flow
```
┌─────────┐ ┌─────────────┐
│ Client │ │ Auth API │
└─────────┘ └─────────────┘
│ │
│ 1. API request with expired token │
│──────────────────────────────────────────> │
│ │
│ 2. 401 Unauthorized │
│ <──────────────────────────────────────── │
│ │
│ 3. POST /auth/refresh │
│ { refresh_token } │
│──────────────────────────────────────────> │
│ │
│ │ 4. Validate refresh_token
│ │ 5. Generate new access_token
│ │
│ 6. Return new access_token │
│ { access_token } │
│ <──────────────────────────────────────── │
│ │
│ 7. Retry API request with new token │
│──────────────────────────────────────────> │
│ │
│ 8. Success response │
│ <──────────────────────────────────────── │
```
---
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>