# Deployment Guide — Namecheap cPanel Shared Hosting

Time needed: **~30 minutes**. No SSH, no Composer, no Node.js required.

## What you need before starting

| Item | Where to get it |
|---|---|
| PHP 8.1+ hosting (8.2 recommended) | cPanel → **MultiPHP Manager** — select `8.2` for the domain |
| PHP extensions `pdo_mysql`, `curl`, `openssl`, `mbstring`, `fileinfo`, `gd` | cPanel → **Select PHP Version** → Extensions (tick them) |
| A MySQL database + user | cPanel → **MySQL® Databases** |
| A subdomain for the app | cPanel → **Domains → Create a New Domain**, e.g. `socialops.yourdomain.com` |
| OpenAI API key (optional) | platform.openai.com — the app runs fully without it using rule-based agents |

---

## Step 1 — Create the database

1. cPanel → **MySQL® Databases**.
2. Under *Create a New Database*: name it e.g. `socialops` → **Create Database**.
   (cPanel prefixes it: `cpuser_socialops`.)
3. Under *MySQL Users → Add New User*: create user `socialops` with a strong
   password → **Create User**. **Save this password** — the installer asks for it.
4. Under *Add User to Database*: pick the user + database → **Add**.
5. On the next screen tick **ALL PRIVILEGES** → **Make Changes**.

## Step 2 — Upload the application

1. Download `socialops-agent-hub.zip` (packaged with this project).
2. cPanel → **File Manager**. Navigate to your **home directory**
   (`/home/CPUSER/`) — *not* `public_html`.
3. Click **Upload** → select the zip → back in File Manager right-click the zip
   → **Extract**. You now have `/home/CPUSER/socialops/`.
4. Verify these folders exist:
   ```
   /home/CPUSER/socialops/app/
   /home/CPUSER/socialops/public/
   /home/CPUSER/socialops/database/
   /home/CPUSER/socialops/storage/        ← must exist, writable
   ```

## Step 3 — Point the subdomain at /public

1. cPanel → **Domains** → find `socialops.yourdomain.com` → **Manage**.
2. Set **Document Root** to: `/home/CPUSER/socialops/public`
3. Save. Wait 1–2 minutes for Apache to reload.

> ⚠️ **Critical:** the document root must be the `public` folder — this is what
> keeps `storage/` (encryption keys, uploads, config) unreachable from the web.

## Step 4 — Run the installer

1. Visit `https://socialops.yourdomain/install.php`.
   The installer performs three steps:
   - **Environment check** — verifies PHP version + required extensions and
     that `storage/` is writable. Fix anything red before continuing.
   - **Database + site URL** — enter DB host `localhost`, DB name
     `cpuser_socialops`, DB user `cpuser_socialops`, password, and your site URL
     (`https://socialops.yourdomain`). It writes `storage/config.php`,
     generates the AES-256 encryption key into `storage/keys/app_key.bin`
     (mode 0600), creates all tables from `database/schema.sql`, and seeds
     default settings.
   - **First Super Admin** — choose email + strong password. This account can
     do everything, including final approvals.
2. After success, **delete `install.php`** (File Manager → Delete). The app
   refuses to run it again once `storage/config.php` exists, but removing it is
   good hygiene.
3. For HTTPS enforcement, cPanel → **SSL/TLS Status** → *Run AutoSSL* for the
   subdomain if the padlock is missing.

## Step 5 — Log in and set up the first project

1. Open `https://socialops.yourdomain/login.php` and sign in as the super admin.
2. **Projects → New Project (wizard)**:
   1. *Brand* — name, industry (choose **Insurance** for the compliance rule
      engine), timezone, brand colors/voice.
   2. *Rules* — compliance mode, prohibited claims (IRDAI presets are
      pre-filled for insurance: "guaranteed returns", "risk-free", etc.),
      approval note.
   3. *Sources* — add official domains only, e.g.
      `irdai.gov.in`, `licindia.in`, your insurer's press pages. Uncheck
      "allow Wikipedia" if you want strict official-source mode.
   4. *Pillars & cadence* — content pillars (Awareness / Education / Product /
      Trust) and posts per week; the Strategy Agent fills the monthly calendar
      from these.
3. Toggle the project **Active** on the Projects page.

## Step 6 — (Optional) Connect OpenAI

1. **Settings** page → *AI provider* → paste your `sk-…` key → Save.
2. The key is stored **encrypted** with the app key; it is never shown again
   and never written to logs. Test with the **Agent Chat** page.
3. Without a key, every agent still works using deterministic rule-based
   logic — research classification, drafting, fact-checking, compliance
   scanning, uniqueness checks and scheduling all function offline.

## Step 7 — Set up the worker cron (required for scheduling & publishing)

1. cPanel → **Cron Jobs** → *Add New Cron Job*.
2. Common Settings → **Once Per Five Minutes (*/5 * * * *)**.
3. Command:
   ```
   php -q /home/CPUSER/socialops/worker_cron.php >/dev/null 2>&1
   ```
   (If `php` is not on PATH, use e.g. `/usr/local/bin/php` or
   `/opt/alt/php82/usr/bin/php` — visible under MultiPHP Manager or ask support.)
4. Save. The worker every run: claims due scheduled posts from the MySQL queue,
   verifies the **approval gate** again server-side, publishes to connected
   platforms, records results, marks failures, and sends health notifications.

Alternative: URL-based cron (if CLI is unavailable) — Cron Jobs → command
`curl -s "https://socialops.yourdomain/worker.php?token=YOUR_WORKER_TOKEN"`.
The token is generated into `storage/config.php` at install; view it on the
Settings page.

## Step 8 — Connect social accounts

Follow `CONNECTOR_CHECKLIST.md` — official OAuth only, one app per platform,
tokens stored encrypted. Never paste any platform password anywhere in the app.

## Step 9 — Daily operation (the happy path)

1. **Sources → Run collector** (or let the daily cron collect): new official
   items appear for classification.
2. Open **Sources** → review classified items → send one to the **Content Agent**
   → it creates a Content record with per-platform variants.
3. **Approvals** → reviewer/admin checks facts, sources, compliance result →
   **Approve** (approval is bound to the exact content hash).
4. On the content page choose **Schedule** → pick date/time + platform accounts.
5. At the scheduled minute the cron publishes it. **Reports** shows published
   posts, UTM-tagged links and failures. Nothing is ever published without a
   valid approval — verified again inside the publisher at execution time.

## Updating the app later

1. Download the new zip, extract, and copy `app/`, `public/`, `database/` over
   the old ones (keep `storage/` — it holds your config, key and uploads).
2. If `database/UPGRADE-*.sql` files ship with a release, run them in phpMyAdmin
   (oldest first).
3. `worker_cron.php` and docs can simply be replaced.

## Troubleshooting

| Symptom | Fix |
|---|---|
| Blank page | cPanel → *Errors* (or `storage/logs/`); usually a missing extension — recheck Step 0 |
| `Access denied for user` | DB user not added to DB with ALL PRIVILEGES (Step 1.4) |
| Installer says storage not writable | File Manager → `storage` → Permissions → 755 (dir) / config written as 644 |
| Cron publishes late | Shared-hosting cron can drift minutes; this is expected (PRD §15). Job stays queued until it runs |
| OAuth redirect mismatch | Redirect URI in the platform app must exactly match the one shown on the Social page |
| 429 / rate limits | The queue retries with backoff; nothing is lost |
| Emails not sending | Check spam; Namecheap requires the From: domain to match your sending domain in PHP mail settings |
