# Law Pro cPanel Deployment

This runbook deploys the private application at `https://os.kariukikagunda.co.ke`. It does not change the existing public website.

## 1. Build the release locally

From the repository root in PowerShell:

```powershell
npm.cmd --prefix backend ci
npm.cmd --prefix backend test
npm.cmd --prefix backend run prisma:validate
npm.cmd --prefix frontend ci
npm.cmd --prefix frontend test
npm.cmd --prefix frontend run build
powershell -ExecutionPolicy Bypass -File scripts/build-cpanel-release.ps1 -SkipFrontendBuild
```

Upload `release/lawpro-cpanel-release.zip`. The archive intentionally contains only backend runtime files, Prisma migrations, the compiled frontend, and this runbook. It excludes `.env`, `node_modules`, tests, logs, local uploads, and demo storage.

## 2. Provision cPanel

1. Point `os.kariukikagunda.co.ke` at this cPanel account and enable AutoSSL.
2. In **PostgreSQL Database Wizard**, create a database and a dedicated user with a generated password. Assign the user to the database. Use **Synchronize Grants** if shown.
3. Create `/home/<cpanel-user>/lawpro` and `/home/<cpanel-user>/lawpro-data/uploads`. Keep both outside `public_html`.
4. Upload the ZIP to the `lawpro` directory and extract it there. Confirm `backend/src/index.js` and `frontend/dist/index.html` exist.
5. In **Application Manager**, register a production Node application:
   - Application URL: `os.kariukikagunda.co.ke` at `/`
   - Application root: `/home/<cpanel-user>/lawpro`
   - Startup file: `backend/src/index.js`
   - Node version: Node 20 LTS, or the newest compatible LTS offered
   - Environment: production

Do not configure a separate Apache document root for the compiled frontend. Express serves it and reserves `/api` for API traffic.

## 3. Configure environment variables

Add these in Application Manager. Do not upload a production `.env` file.

```text
NODE_ENV=production
DATABASE_URL=postgresql://<db-user>:<url-encoded-password>@localhost:<postgres-port>/<db-name>?schema=public
JWT_SECRET=<cryptographically-random-secret-at-least-32-characters>
JWT_EXPIRES_IN=7d
REFRESH_TOKEN_EXPIRES_IN=30d
CORS_ORIGIN=https://os.kariukikagunda.co.ke
LOCAL_UPLOAD_DIR=/home/<cpanel-user>/lawpro-data/uploads
```

Use the PostgreSQL host and port supplied by the hosting provider. Percent-encode reserved characters in the database password. Do not set `PORT`; Passenger supplies it. SMTP, Stripe, and Cloudinary values should be omitted until those integrations are configured and tested.

## 4. Install and initialize

Use cPanel Terminal. If Application Manager displays a command for entering its Node environment, run that first.

```bash
cd /home/<cpanel-user>/lawpro/backend
npm ci --omit=dev
npm run prisma:generate
npm run prisma:validate
npm run prisma:migrate:deploy
```

Temporarily add these four variables in Application Manager:

```text
BOOTSTRAP_ADMIN_EMAIL=<real-administrator-email>
BOOTSTRAP_ADMIN_FIRST_NAME=<first-name>
BOOTSTRAP_ADMIN_LAST_NAME=<last-name>
BOOTSTRAP_ADMIN_PASSWORD=<unique-14+-character-password>
```

Run:

```bash
cd /home/<cpanel-user>/lawpro/backend
npm run bootstrap:production
```

The bootstrap is transactional and safe to rerun. It creates or updates the administrator and foundational catalogs, but never demo clients, matters, or cases. Remove all four `BOOTSTRAP_ADMIN_*` variables immediately after it succeeds.

Restart the application in Application Manager. Where Passenger file restart is supported, the equivalent is:

```bash
cd /home/<cpanel-user>/lawpro
mkdir -p tmp
touch tmp/restart.txt
```

## 5. Verify

1. Open `https://os.kariukikagunda.co.ke/api/health`; expect HTTP 200 with `status`, `service`, and `database` set to healthy values.
2. Open the application and sign in with the production administrator.
3. Confirm the browser console has no CORS, mixed-content, redirect, or missing-asset errors.
4. Refresh a browser route directly and confirm the SPA reloads.
5. Request an unknown `/api/...` URL and confirm it returns a JSON client error rather than HTML (an anonymous request may be rejected with 401 before route matching).
6. Confirm `admin@lawpro.local / ChangeMe123!` cannot sign in.
7. Upload and download a harmless test document, restart the application, and verify the document remains available.
8. Confirm the existing public website still works on its original hostname.

Review Passenger and application logs if startup fails. The application deliberately stops when production secrets are unsafe, the frontend build is missing, the database URL is missing, or the upload directory is not writable.

## 6. Backups, updates, and rollback

- Schedule a PostgreSQL custom-format backup and a separate archive of `/home/<cpanel-user>/lawpro-data/uploads`. Store backups outside the active release and apply the hosting provider's off-server retention option where available.
- Test restoration into a temporary PostgreSQL database before relying on the backup procedure.
- Before each update, take both backups. Upload the new archive to a versioned directory, install backend dependencies, generate Prisma Client, run `prisma migrate deploy`, then restart and repeat the verification checklist.
- Retain the preceding application directory. For application rollback, point Application Manager back to it and restart. Database rollback requires a compatible forward fix or restoration of the pre-release database and upload backups; Prisma migrations are not reversed automatically.
