# cPanel Deployment Guide

Internal document. Do not publish. Replace `USER` with the cPanel username and `your-domain.com` with the live domain.

Target layout on the server:

```
/home/USER/drixem_app/          <- the whole Laravel app (NOT web-accessible)
/home/USER/drixem_app/public/   <- the only folder the domain points at
/home/USER/drixem_app/storage/app/private/kyc/    <- KYC documents
```

## 1. Build the release on your own computer

Needs PHP 8.2+ and Composer locally.

```bash
composer create-project laravel/laravel:^12.0 drixem_app
cd drixem_app

# Remove Laravel's stock migrations (our schema replaces them) and welcome page
rm database/migrations/0001_01_01_*.php
rm resources/views/welcome.blade.php

# Copy this package over the top (overwrite when asked)
cp -R /path/to/drixem/. .

composer install --no-dev --optimize-autoloader

# Optional but recommended: compiled CSS instead of the CDN script
npm install && npm run build
#   then in resources/views/layouts/app.blade.php replace the two Tailwind
#   <script> tags with: <link rel="stylesheet" href="{{ asset('build/app.css') }}">

zip -r drixem_release.zip . -x "node_modules/*" ".git/*" ".env"
```

## 2. Prepare cPanel

1. **MultiPHP Manager** -> set the domain to PHP 8.2 or newer.
2. **Select PHP Version / Extensions** -> enable `pdo_mysql`, `mbstring`, `fileinfo`, `openssl`, `ctype`, `tokenizer`, `xml`, `curl`.
3. **MultiPHP INI Editor** -> `upload_max_filesize = 10M`, `post_max_size = 12M`, `memory_limit = 256M`.
4. **MySQL Databases** -> create database `USER_drixem`, create a user with a strong password, add the user to the database with ALL PRIVILEGES.
5. **SSL/TLS Status** -> run AutoSSL so the domain serves HTTPS.

## 3. Upload

1. **File Manager** -> go to `/home/USER/` (one level above `public_html`).
2. Create folder `drixem_app`, upload `drixem_release.zip` into it, Extract, delete the zip.

## 4. Point the domain at `public/`

**Option A (preferred): change the document root.**
Domains -> Manage -> Document Root -> `drixem_app/public`. Done.

**Option B (primary domain locked to `public_html`): symlink.**
In cPanel Terminal:

```bash
cd ~
mv public_html public_html_old
ln -s ~/drixem_app/public ~/public_html
```

**Option C (no Terminal, no symlink):** copy everything inside `drixem_app/public/` into `public_html/`, then edit `public_html/index.php` and change the three paths from `__DIR__.'/../'` to `__DIR__.'/../drixem_app/'`.

Never upload the app itself into `public_html`. `.env` and `storage/` must stay above the web root.

## 5. Configure `.env`

```bash
cd ~/drixem_app
cp .env.example .env
php artisan key:generate
```

Edit `.env` (File Manager -> show hidden files):

```
APP_URL=https://your-domain.com
APP_DEBUG=false
DB_DATABASE=USER_drixem
DB_USERNAME=USER_drixem
DB_PASSWORD=********
MAIL_HOST / MAIL_USERNAME / MAIL_PASSWORD   (cPanel Email Accounts -> Connect Devices)
ADMIN_EMAIL=you@your-domain.com
ADMIN_PASSWORD=a-long-unique-passphrase
```

No Terminal? Run `php artisan key:generate --show` locally and paste the value into `APP_KEY=`.

## 6. Folder permissions and private KYC storage

```bash
cd ~/drixem_app
mkdir -p storage/app/private/kyc storage/app/private/deals \
         storage/framework/{cache/data,sessions,views} storage/logs

find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;
chmod -R 775 storage bootstrap/cache
chmod 600 .env
chmod -R 700 storage/app/private       # KYC + deal documents: owner only
```

(On cPanel, PHP runs as your own account, so `700` still lets the app read and write.)

Verify the vault is unreachable. Both must return 404 or 403:

```
https://your-domain.com/storage/app/private/
https://your-domain.com/.env
```

Do **not** run `php artisan storage:link`. Nothing in this app needs public storage.

## 7. Run migrations

With Terminal:

```bash
php artisan migrate --force
php artisan db:seed --class=AdminSeeder --force
```

Without Terminal: phpMyAdmin -> select the database -> Import -> `database/schema.sql`. Then create the admin by running the seeder locally against a copy and exporting the `users` row, or ask your host to run the two commands above once. (The schema uses `CREATE TABLE IF NOT EXISTS`, so running `migrate` later is harmless.)

After the admin exists, **delete `ADMIN_PASSWORD` from `.env`**.

## 8. Optimise and go live

```bash
php artisan config:cache
php artisan route:cache
php artisan view:cache
```

Re-run these three after every code or `.env` change (`php artisan optimize:clear` to undo).

## 9. Smoke test

1. Sign in as the admin -> Price desk -> publish a CPO price -> ticker shows it.
2. Register a seller in a private window -> upload the five documents -> approve from Admin -> Verifications -> "Verified Mill" badge appears -> publish a listing.
3. Register a buyer -> upload four documents -> approve -> Marketplace -> Request quote -> submit.
4. Seller: RFQs -> submit quote. Buyer: accept -> deal room opens -> Proforma Invoice prints.
5. Register an affiliate -> approve -> copy referral link -> sign up a new buyer through it -> complete a deal -> commission appears under Admin -> Commissions.

## 10. Operations

- **Backups:** cPanel Backup (or JetBackup) must include both the MySQL database and `drixem_app/storage/app/private/`. KYC files cannot be regenerated.
- **Logs:** `storage/logs/laravel-YYYY-MM-DD.log`. Keep `APP_DEBUG=false` in production so errors never reveal server paths or infrastructure details.
- **Updates:** upload changed files, then `php artisan migrate --force` and the three cache commands.
- **Data protection:** you are storing identity documents (IC/passport) and company records. Limit admin accounts, and set a retention/deletion policy that fits PDPA and the laws of your users' countries.
