Pitchbar encrypts every customer-controlled secret at rest under
the Laravel APP_KEY. If that key leaks, you need to
rotate to a new one without losing access to existing data. The
security:rotate-app-key Artisan command makes the
rotation safe and idempotent.
workspaces.cta_context_secretworkspaces.byok_keysworkspaces.slack_webhook_urlworkspaces.teams_webhook_urlwebhook_subscriptions.secretworkspace_api_tokens.shopper_signing_secretdsr_requests.result_payloadintegration_connections.credentials_encryptedsources.credentials_encryptedapp_settings.* (Stripe, PayPal, Razorpay,
Cloudflare, OpenAI, OpenRouter, mail, internal queue
secrets)php artisan key:generate --show
# copy the output
APP_KEY and move
the old key into APP_PREVIOUS_KEYS (comma
separated if multiple). Example:
APP_KEY=base64:NEW_KEY
APP_PREVIOUS_KEYS=base64:OLD_KEY
php artisan security:rotate-app-key --confirm-production
APP_PREVIOUS_KEYS from your env. The old key
is no longer needed for any row.--confirm-production — required in
production environment. Omit in
staging / local.--dry-run — counts rows + columns that
would be re-encrypted without writing. Useful to
preview the surface before committing.Running the command twice is harmless. The second pass decrypts and re-encrypts the same values; the ciphertext bytes change (fresh IV) but the plaintext remains intact.
The command logs the column and row id to the console and
moves on. That row stays on whatever key produced its current
ciphertext. If you removed
APP_PREVIOUS_KEYS before the sweep completed,
those rows are unrecoverable — restore from a backup and
re-run with the previous key in env.
The command does not write to audit_logs on its
own — but the operator who runs it should record the rotation
in their change-management system. If you want every rotation
auto-audited, wrap the artisan call in a deploy script that
emits an audit row.