# Commercial Launch Readiness Runbook

This file reduces the remaining handover work to exact environment values, commands, and evidence to collect. Do not commit real secrets. Copy `.env.staging.example` or `.env.production.example` to `.env` on the target server and replace every placeholder in the server or secret manager only.

## Current Scope

The light launch package is the first commercial ticket-selling slice:

- public visitors/customers browse, select reserved or non reserved tickets, pay online, and receive tickets;
- organisers create venues, seat maps, sections, events, ticket allocations, and Stripe readiness details;
- platform admins monitor events, organisers, fees, payments, health, and launch-readiness.

Deferred roles and later-stage modules should remain closed while `APP_LAUNCH_PROFILE=ticket-selling-v1`.

## Environment Files

Use these templates:

- `.env.staging.example`: production-safety posture with Stripe test mode and a staging URL.
- `.env.production.example`: production posture for the final server.

Real environment files must be created outside Git on the target server. `.env`, `.env.staging`, `.env.production`, and `.env.*.local` are ignored by Git so real secrets are not committed.

For staging and production-like rehearsals, keep:

```env
APP_ENV=production
APP_DEBUG=false
APP_FORCE_HTTPS=true
APP_LAUNCH_PROFILE=ticket-selling-v1
MVP_RUNTIME_SCHEMA_REPAIR=false
PAYMENT_MOCK_ENABLED=false
STRIPE_CONNECT_CHARGE_MODEL=direct_charge
```

Generate non-Git secrets on the target machine:

```powershell
php bin/generate-production-secrets
```

Replace at minimum:

- `COOKIE_SECRET`
- `QR_SIGNING_SECRET`
- `MFA_OTP_SECRET`
- `SMS_OTP_SIGNING_SECRET`
- database password
- delivery provider bearer tokens
- Stripe keys and webhook secret

Production database installation must not seed demo users or demo data:

```powershell
php bin/install-database --no-seed
```

`bin/install-database` now refuses seeded installs when `APP_ENV=production` or `APP_ENV=prod`.

## Stripe Test Checkout Evidence

The system is code-ready for Stripe test mode, but real commercial launch still needs one signed webhook checkout on the deployed environment.

1. In Stripe test mode, create or select the platform account keys.
2. Configure a webhook endpoint for:

```text
https://YOUR-DOMAIN.example/api/v1/webhooks/stripe
```

3. Subscribe to at least checkout/payment completion events used by the app, then copy that endpoint's `whsec_...` value into `STRIPE_WEBHOOK_SECRET`.
4. Create or connect one organiser Stripe connected account in test mode. It must be onboarding-complete, charges-enabled, payouts-enabled, and stored in `stripe_connected_accounts`.
5. Set:

```env
STRIPE_MODE=test
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_CONNECT_CHARGE_MODEL=direct_charge
PAYMENT_MOCK_ENABLED=false
```

6. Run:

```powershell
php bin/check-stripe-readiness
php bin/check-production-launch
```

7. In the browser, buy a paid ticket using a Stripe test card. Use the hosted Stripe Checkout page, not local mock payment.
8. Confirm evidence:

- Stripe event was signed and accepted.
- Browser redirect alone did not issue tickets.
- order became paid only after webhook completion.
- payment record shows succeeded.
- tickets and QR tokens were issued.
- reserved seats moved to sold.
- ledger balances.
- platform service fee and organiser proceeds reconcile to the expected currency.
- customer wallet shows the purchased ticket.
- scanner validates the issued QR once and rejects a duplicate scan.

Record the order ID, Stripe Checkout Session ID, Stripe PaymentIntent ID, webhook event ID, connected account ID, ticket IDs, QR token count, and ledger/fee totals in the launch sign-off notes.

## PHP GD

GD is required for production media variants. Verify:

```powershell
php -m | findstr /i "^gd$"
```

Windows/XAMPP:

1. Open `C:\xampp\php\php.ini`.
2. Change `;extension=gd` to `extension=gd`.
3. Restart Apache/PHP.
4. Re-run `php -m | findstr /i "^gd$"` and `php bin/check-production-launch`.

Linux example:

```bash
sudo apt-get install php8.2-gd
sudo systemctl restart php8.2-fpm apache2
php -m | grep -i '^gd$'
```

## ClamAV Or Equivalent Media Scanning

Production uploads fail closed when media scanning is required and no scanner is configured.

Linux example:

```bash
sudo apt-get install clamav clamav-daemon
sudo freshclam
clamscan --version
```

Set:

```env
MEDIA_MALWARE_SCAN_REQUIRED=true
CLAMAV_CLAMSCAN_PATH=/usr/bin/clamscan
```

Windows example:

1. Install ClamAV from the official package or approved server image.
2. Run `freshclam`.
3. Verify `clamscan --version`.
4. Set `CLAMAV_CLAMSCAN_PATH` to the full `clamscan.exe` path.

If the host uses another malware scanner, keep the same fail-closed rule and adapt `ImageUploadInspector` only after security review and test coverage.

## Media Storage

The launch templates use `MEDIA_STORAGE_DRIVER=local_public` because the current MVP upload path writes into `public/uploads`. Do not set `MEDIA_STORAGE_DRIVER=cdn` or `object_storage` until a real storage adapter has been implemented, tested, and reviewed; otherwise the readiness screen may describe an infrastructure target that uploads do not actually use.

## Composer And Dependency Checks

On a server with Composer available:

```powershell
composer validate --strict
composer audit --locked
php vendor/bin/phpunit
```

On XAMPP with a Composer PHAR:

```powershell
C:\xampp\php\php.exe composer.phar validate --strict
C:\xampp\php\php.exe composer.phar audit
C:\xampp\php\php.exe vendor\bin\phpunit
```

Do not weaken Composer TLS or audit behaviour to make a check pass.

## Deployment Readiness Commands

Run from the deployed copy after `.env` is configured:

```powershell
php -l public/index.php
php -l public/mvp.php
php bin/check-mvp-smoke --base-url=https://YOUR-DOMAIN.example
php bin/check-local-live-run --base-url=https://YOUR-DOMAIN.example
php bin/check-frontend-links --base-url=https://YOUR-DOMAIN.example
php bin/check-stripe-readiness
php bin/check-deployment-readiness
php bin/check-production-launch
```

`bin/check-production-launch` without `--allow-warnings` is the go/no-go command for real launch. Warnings can be accepted only in writing by the launch owner.

## Manual Mobile And Tablet Retest

Run the public buyer, organiser, and platform admin workflows on the deployed server at these minimum widths:

- 320 px
- 360 px
- 375 px
- 390 px
- 414 px
- 430 px
- 768 px
- 820 px
- 1024 px
- desktop/laptop

Must pass:

- homepage and event list do not horizontally overflow;
- event detail has Booking and Seat-map tabs;
- Seat-map tab is blank unless organiser uploaded a separate PDF/image reference for the selected reusable seat map;
- reserved sections use section tabs and 15-minute holds;
- non reserved sections can be bought without choosing a physical seat;
- checkout timer is capped at 15 minutes;
- Stripe checkout opens and returns safely;
- ticket wallet and QR display fit mobile;
- organiser event form, venue/seat-map builder, ticket allocation, and Stripe readiness screens are usable on tablet;
- admin fees, health, payments, organisers, and orders are readable without broken tables.

Capture screenshots for every failure with device, browser, URL, role, steps, expected result, actual result, and severity.

## Real Commercial Launch Blockers

These are the items that still need real environment access:

1. Replace staging/production `.env` placeholders outside Git.
2. Configure Stripe test keys, webhook signing secret, and a real test connected organiser account.
3. Complete one paid Stripe test checkout through the signed webhook.
4. Configure production malware scanning.
5. Run Composer validate/audit where Composer is installed.
6. Repeat manual mobile/tablet QA on the deployed server.
7. Decide whether public MVP showcase/profile pages should be removed or access-protected before internet-facing production.
