The Payload Admin Panel sends login credentials as a _payload JSON field
within multipart/form-data, not as separate email/password fields.
This fix adds support for parsing the _payload field while maintaining
backwards compatibility with direct FormData fields and JSON body.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Use rateLimitHeaders() spread on /api/posts success response
to include X-RateLimit-Limit, X-RateLimit-Reset, Retry-After
matching /api/search and /api/search/suggestions behavior
- Remove legacy checkRateLimit, RateLimitResult, rateLimitStore,
and cleanup interval from src/lib/search.ts (dead code after
migration to central searchLimiter)
- Update tests to use searchLimiter from @/lib/security instead
of the removed checkRateLimit
All integration tests pass (20 passed, 12 skipped).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Rate Limiting Integration:
- Add authLimiter (5 attempts/15min) to both login routes for brute-force protection
- Migrate search endpoints from local checkRateLimit to central searchLimiter
- Add IP blocklist checks to auth and search endpoints
Data Masking Integration:
- Integrate maskObject/maskString from security module into audit-service
- Auto-mask previousValue, newValue, metadata, and descriptions in audit logs
- Use maskError for error logging
Pre-commit Hook:
- Add "prepare" script to package.json for automatic hook installation
- Hook is now installed automatically on pnpm install
Note: CSRF middleware is available but not enforced on API routes since
Payload CMS uses JWT auth and has built-in CORS/CSRF protection in config.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Security Features:
- Central rate-limiter service with Redis support and memory fallback
- Predefined limiters: publicApi, auth, email, search, form, strict
- Automatic cleanup of stale entries
- IP allowlist/blocklist for sensitive endpoints
- CIDR and wildcard support
- Configurable via SEND_EMAIL_ALLOWED_IPS, BLOCKED_IPS env vars
- CSRF protection with Double Submit Cookie pattern
- Token endpoint: GET /api/csrf-token
- Origin header validation
- Data masking service for sensitive data
- Automatic redaction of passwords, tokens, API keys
- Safe logger factory for consistent logging
- Recursive object masking for audit logs
Secret Scanning:
- Pre-commit hook for local secret detection
- GitHub Actions workflow with Gitleaks and CodeQL
- Gitleaks configuration file
- Dependency vulnerability scanning
Updated:
- /api/send-email now uses central rate-limiter and IP allowlist
- Redis lib exports getRedisClient and isRedisAvailable
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Extend logLoginFailed to accept ClientInfo directly (not just PayloadRequest)
- Add logPasswordReset function for password reset audit logging
- Remove duplicate manual payload.create calls in login routes
- Implement real fallback in auditAfterForgotPassword with structured JSON log
- Login routes now create single audit entry with full IP/User-Agent context
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Payload email adapter for system emails (auth, password reset)
- Add EmailLogs collection for tracking all sent emails
- Extend Tenants collection with SMTP configuration fields
- Implement tenant-specific email service with transporter caching
- Add /api/send-email endpoint with:
- Authentication required
- Tenant access control (users can only send for their tenants)
- Rate limiting (10 emails/minute per user)
- Add form submission notification hook with email logging
- Add cache invalidation hook for tenant email config changes
Security:
- SMTP passwords are never returned in API responses
- Passwords are preserved when field is left empty on update
- Only super admins can delete email logs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update payload.config.ts with new collections, blocks, and globals
- Configure i18n with DE/EN localization support
- Add multi-tenant plugin configuration
- Update ecosystem.config.cjs for PM2
- Regenerate payload-types.ts and importMap.js
- Add prettier configuration
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>