# Production Runbook — cPanel / PHP 8.2+ / MySQL 8+

## 1. Pre-deployment
1. Take a database backup and retain a copy outside the web account.
2. Back up `.env` and `public/uploads`.
3. Put the site behind HTTPS before enabling production traffic.
4. Confirm PHP extensions: PDO, PDO MySQL, OpenSSL, mbstring, fileinfo, JSON.

## 2. Deploy
```bash
composer install --no-dev --optimize-autoloader
php bin/migrate.php
php bin/optimize.php
php bin/check.php
php bin/security-audit.php
php bin/test.php
```

Do not run `seed.php` on an established production property unless demo data is intentionally required.

## 3. Production `.env`
Required minimum:
```dotenv
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-hotel-domain.example
APP_KEY=base64:<32+ random bytes>
FORCE_HTTPS=true
HSTS_ENABLED=true
SESSION_SECURE=true
SESSION_IDLE_TIMEOUT=1800
SESSION_ABSOLUTE_TIMEOUT=28800
```

Leave `TRUSTED_PROXIES` empty unless the site actually runs behind a known reverse proxy. Never use a wildcard proxy trust.

## 4. Health
- `GET /healthz` checks PHP/front-controller liveness.
- `GET /readyz` checks the application key and MySQL connectivity.
- Both return minimal JSON and never expose database credentials or stack traces.

## 5. Cron
Recommended:
```cron
* * * * * /usr/local/bin/php /home/CPANEL_USER/hotel-platform/bin/cron.php >/dev/null 2>&1
```
The cron process obtains a MySQL advisory lock; a second overlapping invocation exits harmlessly.

## 6. Backups
Manual DB backup:
```bash
php bin/backup-db.php
```
Files are written under `storage/backups` with mode 0600. Copy backups to a separate protected backup destination according to hotel policy. Test restoration on a non-production database.

Example restore (confirm destination before running):
```bash
mysql -h DB_HOST -u DB_USER -p DB_NAME < storage/backups/db-....sql
```

## 7. Logs
Application exceptions are written to `storage/logs/application.log` with `request_id`. Configure cPanel log rotation/retention appropriate to the hotel's privacy policy.

## 8. Performance
Run after migration and after materially larger data growth:
```bash
php bin/optimize.php
```
It checks `INFORMATION_SCHEMA` first and creates only missing Phase 10 indexes. Do not add arbitrary indexes without checking write cost and `EXPLAIN` output.

Static CSS/JS/images use Apache expiry and compression where the corresponding modules are available. Dynamic pages default to `no-store`.

## 9. Incident actions
If compromise is suspected:
1. Remove public access or enable a cPanel maintenance rule.
2. Preserve Apache/PHP/application logs.
3. Rotate `APP_KEY` only with a planned token/QR impact assessment; QR ciphertext using the prior key may become unreadable.
4. Rotate admin credentials and integration credentials.
5. Revoke affected sessions/QR tokens where appropriate.
6. Review `audit_logs`, payment history and integration events.
7. Restore only from a verified clean backup if required.

## 10. Integration safety
Mock PMS/POS/ERP adapters are development/testing implementations. Production OPERA/POS/ERP integration requires vendor API specifications, credentials, network allow-listing and UAT. Never label a mock connection as a production hotel system integration.


## Phase 11 – Guest Waiting Experience & Promotions

After upgrading from the Phase 10/merged release:

```bash
php bin/migrate.php
php bin/seed.php   # optional demo Phase 11 promotions/events; use only when desired
php bin/check.php
php bin/test.php
```

Manage campaigns at `/admin/promotions`. The order status page loads eligible cards from `/api/v1/orders/{order}/engagement` while the guest waits. Promotion schedules use hotel-local time. Demo campaigns and events are placeholders and must be replaced with approved hotel content. Promotional discount fields are informational marketing metadata in Phase 11 and do not automatically change the current bill.
