- Create PSA_Cost_Tracker class with database table for API call logging
- Log prompt/completion tokens and estimated cost for every OpenRouter API call
- Implement monthly budget system with hard stop (budget of 0 = unlimited)
- Add budget checks in validate_peptide_name() and generate_peptide_content()
- Add dry_run() method to estimate costs before making API calls
- Display monthly usage summary and recent API logs in admin settings
- Add monthly_budget setting to admin interface with number input field
- Update uninstall.php to drop psa_api_logs table on plugin removal
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create PSA_Encryption class with AES-256-CBC encrypt/decrypt methods
- Derive encryption key from wp_salt('auth') using SHA-256 hash
- Prepend IV to ciphertext and base64-encode for safe storage
- Update PSA_Admin to encrypt API keys on save, mask on display
- Preserve existing key when empty/mask value submitted (no overwrite)
- Update PSA_AI_Generator to decrypt API key on read from database
- Maintain backward compatibility with plaintext keys (auto-encrypt on next save)
- Prefer wp-config constant over database value for maximum security
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SEC-001 CRITICAL: Remove spoofable X-Forwarded-For/X-Real-IP from IP detection; trust only CF-Connecting-IP + REMOTE_ADDR
SEC-004 HIGH: Add peptide name input validation with character whitelist and prompt injection blocking
SEC-006 HIGH: Add missing return after wp_send_json_success in handle_pending_retry max-retries block
SEC-007 MEDIUM: KB articles now respect auto_publish setting instead of always publishing
SEC-009 MEDIUM: Replace hardcoded page ID 73 with configurable kb_page_id setting
SEC-010 MEDIUM: Fix cache invalidation — add underscore prefix to transient name pattern
SEC-011 MEDIUM: Skip sleep() during WP-Cron to avoid blocking PHP workers on rate limit retry
SEC-012 MEDIUM: Add global daily generation cap (50/day) to prevent cost overruns
SEC-013 LOW: Add @deprecated notice to unused PSA_Error class
SEC-015 LOW: Convert uninstall.php from space to tab indentation (WPCS)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All 499 PHPCS errors were 'Tabs must be used to indent lines; spaces are not allowed'.
Converted 4-space indentation to tabs throughout class-psa-ai-generator.php.