# Morbrick Production Deployment

This folder is a production artifact. It contains compiled frontend assets and
production Composer dependencies. It intentionally excludes local secrets,
development dependencies, tests, logs, cached sessions, uploads, generated
documents, and database data.

## 1. Server requirements

- PHP 8.2 or newer with `bcmath`, `ctype`, `curl`, `dom`, `fileinfo`, `gd`,
  `intl`, `mbstring`, `openssl`, `pdo_mysql`, `tokenizer`, and `xml`
- MySQL 8.0+ or MariaDB 10.6+
- Apache with `mod_rewrite`, or Nginx
- HTTPS certificate before enabling production traffic
- One cron job every minute
- Write access for the web-server user to `storage/` and `bootstrap/cache/`

The web server document root must point to this package's `public/` directory.
Never expose the project root, `.env`, `storage/`, or `vendor/` through the web.

## 2. Configure

1. Copy `.env.production.example` to `.env` on the server.
2. Replace every example domain and blank credential.
3. Generate a unique key with `php artisan key:generate`.
4. Keep `APP_ENV=production`, `APP_DEBUG=false`, and
   `SECURITY_ENFORCE_TRUSTED_HOSTS=true`.
5. Set `APP_URL` to the exact HTTPS origin and `SECURITY_ALLOWED_HOSTS` to the
   hostname only. Add comma-separated hostnames only when each is intentional.
6. Keep `ETIMS_ENV=sandbox` and `MPESA_ENV=sandbox` until their production
   onboarding and callback tests are complete.

Do not reuse the development database, application key, administrator password,
eTIMS key, M-Pesa key, SMTP password, or any credential from another system.

## 3. First deployment

Create an empty database and a least-privilege database user, then run:

```bash
php artisan migrate:status
php artisan migrate --force
php artisan storage:link
php artisan optimize
php artisan about --only=environment
```

Create the initial administrator only once:

1. Set strong temporary values for `ADMIN_EMAIL` and `ADMIN_PASSWORD` in `.env`.
2. Run `php artisan db:seed --class=DatabaseSeeder --force`.
3. Remove `ADMIN_EMAIL` and `ADMIN_PASSWORD` from `.env`.
4. Sign in, change the temporary password, and verify the Super Admin role.

`SEED_DEMO_DATA` must remain `false` in production.

## 4. Scheduler and queue

Add one cron entry. It runs the database-backed queue and scheduled eTIMS retry:

```cron
* * * * * cd /var/www/morbrick && php artisan schedule:run >> /dev/null 2>&1
```

Replace `/var/www/morbrick` with the deployed release path and confirm cron uses
the same PHP version as the web application.

## 5. Release update

Before every update:

- Back up the database and `storage/app/`.
- Retain the previous release directory.
- Run `php artisan migrate:status` and review pending migrations.
- Confirm `.env` will not be replaced by the package.

From the new release directory, run `scripts/deploy-production.sh`, or execute:

```bash
php artisan down --retry=60
php artisan migrate --force
php artisan optimize
php artisan storage:link
php artisan queue:restart
php artisan up
```

Migrations never run seeders. Seeders are a separate, explicit operator action.

## 6. Post-deployment verification

- `GET https://your-domain/up` returns HTTP 200.
- Login succeeds for the intended administrator.
- Dashboard loads without server errors.
- Create a test customer and quotation, then submit it for approval.
- Generate a PDF and confirm logo, watermark, company particulars, and QR code.
- Confirm `php artisan schedule:list` includes the queue and eTIMS retry tasks.
- Confirm `php artisan queue:failed` has no unexpected jobs.
- Review `storage/logs/laravel-*.log` and the security audit screen.
- Verify unknown `Host` headers are rejected.
- Verify cookies are `Secure`, `HttpOnly`, and `SameSite=Strict`.

## 7. Rollback

Rollback triggers include failed health checks, login failure, elevated HTTP 500
responses, stuck queues, or incorrect financial workflow results.

1. Run `php artisan down`.
2. Point the web server back to the previous release.
3. Restore the previous `.env` link and `storage/app/` link.
4. Restore the database only when the migration/data compatibility review says it
   is required. Do not blindly run `migrate:rollback` on production data.
5. Run `php artisan optimize`, `php artisan queue:restart`, and `php artisan up`.
6. Repeat the post-deployment verification checklist.

Keep the failed release, logs, and database backup until the incident review is
complete.
