# SmartFlow AI — Deployment (cPanel / Production)

See **README.md** for quick start; **SMARTFLOW-AI-BLUEPRINT.md** for the full product spec.

## Feature checklist (included)
- **Installer**: 6-step web UI at `/install` (env check → database → migrations → license → admin → lock).
- **Multi-tenancy**: Single DB, tenant-scoped data, no cross-tenant access.
- **Auth**: Login, logout, remember me, forgot-password info page; post-install and post-logout redirect to login with messages.
- **AI content**: Generate content via queue; knowledge-base context injected; retries and status tracking.
- **Social**: Connect accounts (stub), campaigns with schedule and status, scheduled publish job; social replies list with filter/sort/export.
- **AI auto-reply**: Webhook `POST /api/webhook/social-reply` (optional `X-Webhook-Signature` when `SOCIAL_WEBHOOK_SECRET` set); queue job with knowledge context.
- **Knowledge base**: CRUD, file upload, chunking job, context used in AI and social reply.
- **Marketplace**: Products (CRUD, search, sort, filter, bulk delete, CSV export, file upload/download); Orders (CRUD, status, sort, filter, bulk delete, CSV export, secure download, signed delivery URL); My orders.
- **Billing**: Razorpay (keys in `.env` only); plan pricing; create order → Checkout → verify → subscription + tenant plan update; payment history CSV export; subscription expiry cron (downgrade to free).
- **Plan limits**: Enforced on create routes; JSON error for API; dashboard “Plan & usage” and renewal link.
- **License**: `license_keys` table; LicenseValidationService calls configurable license server (JWT RS256 optional), 72h grace when unreachable; daily cron; never blocks login.
- **UI**: Material 3–style layout, dark mode, responsive tables, nav to all sections; dashboard cards; settings (profile, password, workspace AI tone, billing link for admins); Landing pages (Funnel); Team (members list, add member with user_limit).
- **Security**: CSRF, rate limits (login, install, AI, billing), optional webhook signature; custom error pages (403, 404, 419, 429, 500).
- **Health**: `GET /up` for monitoring.

## Server requirements
- **PHP** 8.2+ with extensions: pdo, pdo_mysql, mbstring, openssl, tokenizer, xml, ctype, json, bcmath, fileinfo, curl (installer Step 1 checks these).
- **Database**: MySQL/MariaDB or SQLite (configure in `.env`).
- **Writable**: `storage/`, `bootstrap/cache/`, and `.env` (or parent writable). Step 1 checks these.
- **Optional**: 50M+ `upload_max_filesize` and `post_max_size` for product/knowledge uploads (Step 1 shows current values).

## Document root
Point the domain document root to the **`public`** folder (e.g. `public_html/public` or `public_html` if the app is in a subfolder and `public` is the doc root). The repo includes `public/.htaccess` for Apache; ensure **mod_rewrite** is enabled.

Back up your database and `.env` regularly (e.g. via cPanel backup or a scheduled job).

**PHP**: Ensure `upload_max_filesize` and `post_max_size` (e.g. 50M or higher) allow product and knowledge-base file uploads. Installer Step 1 shows current values; set them in php.ini or .user.ini if below 50M.

## After upload
```bash
cd /home/youruser/public_html
php artisan config:cache
php artisan route:cache
php artisan view:cache
```
All routes use controller actions (no closures), so `route:cache` is fully supported.

**If you deploy from git**: Run `composer install --no-dev` first; if `.env` was created manually, run `php artisan key:generate` before caching config.

Set in `.env`:
- `APP_DEBUG=false`
- `APP_ENV=production`
- `APP_URL=https://yourdomain.com`
- `LOG_LEVEL=error` (or `warning`) to reduce log volume in production

**When you change `.env`** (e.g. Razorpay keys, database, or APP_URL), run `php artisan config:cache` again so the app picks up the new values.

For maintenance windows, use `php artisan down` (and `php artisan up` when done). Optionally: `php artisan down --secret="token"` so you can visit `?secret=token` to bypass the maintenance page.

## Queue (required for AI, campaigns, social replies)
Run the queue worker so jobs are processed:
```bash
php artisan queue:work
```
Or use a process manager (Supervisor) / cPanel "Cron Jobs" to keep `queue:work` running.

Failed jobs are stored in the database. List them with `php artisan queue:failed` and retry with `php artisan queue:retry {id}` or `php artisan queue:retry all`.

## Scheduler (for scheduled campaigns, license check, subscription expiry)
Add a cron entry:
```
* * * * * cd /home/youruser/public_html && php artisan schedule:run >> /dev/null 2>&1
```
The scheduler runs: campaign publish (every minute), license validation (daily), and **subscription expiry** (daily — marks expired subscriptions and downgrades tenants with no active subscription to the free plan).

## HTTPS
Enable HTTPS in cPanel and ensure `APP_URL` uses `https://`. For cookie security over HTTPS, set `SESSION_SECURE_COOKIE=true` in `.env` in production.

If the app is behind a reverse proxy or load balancer, configure [trusted proxies](https://laravel.com/docs/requests#configuring-trusted-proxies) so HTTPS and client IP are detected correctly.

## Security headers & indexing
- **Security headers** are applied to all web responses via `SecurityHeaders` middleware: `X-Content-Type-Options: nosniff`, `X-Frame-Options: SAMEORIGIN`, `Referrer-Policy: strict-origin-when-cross-origin`.
- **robots.txt**: `GET /robots.txt` returns rules that disallow `/install` and `/login`. If you add a physical `public/robots.txt`, the server will serve that file instead.
- **Noindex**: Install, login, forgot-password, and error pages (403, 404, 429, etc.) send `<meta name="robots" content="noindex,nofollow">` so they are not indexed by search engines.

## Health check
`GET /up` returns JSON `{"status":"ok"}` when the app is installed (lock file exists), or `{"status":"not_installed"}` otherwise. Use for load balancers or monitoring. The response sends `Cache-Control: no-store` so it is not cached.

**Favicon**: `GET /favicon.ico` returns 204 by default. To serve a real icon, add `public/favicon.ico`; you can then remove the favicon route in `routes/web.php` if you prefer the file to be served statically.

## Payments (Razorpay)
Billing uses Razorpay. Set in `.env` (backend only; no UI for keys):
- `RAZORPAY_KEY_ID=your_key_id`
- `RAZORPAY_KEY_SECRET=your_key_secret`

Optional for webhooks: `RAZORPAY_WEBHOOK_SECRET=...`

**Social reply webhook**: If you set `SOCIAL_WEBHOOK_SECRET` in `.env`, requests to `POST /api/webhook/social-reply` must include header `X-Webhook-Signature: sha256=<hmac>` where `<hmac>` is HMAC-SHA256 of the raw request body using the secret. If unset, no signature check is performed. The endpoint is rate-limited to 60 requests per minute per IP.

**Payload** (JSON): `tenant_id` (required, UUID, must exist in `tenants`), `platform` (required, one of: `facebook`, `instagram`, `whatsapp`, `linkedin`), `sender_id` (optional, string), `message` (optional, string). The job will create a social reply and process it with AI using the tenant's knowledge context.

## Troubleshooting
- **AI / campaigns / social replies not processing**: Ensure `php artisan queue:work` is running. Check `php artisan queue:failed` for failed jobs.
- **Scheduled campaigns not publishing**: Ensure the cron entry for `schedule:run` is active (every minute).
- **File uploads (products, knowledge) fail**: Raise `upload_max_filesize` and `post_max_size` in php.ini or .user.ini (see PHP note above). Installer Step 1 shows current values.
- **429 Too Many Requests**: Rate limits apply (login, install, AI, billing, webhook). Wait a minute or adjust throttle in code if you need different limits.

## Install
Users install via the browser: open `https://yourdomain.com/install` and complete the 6 steps (environment check, database, migrations, license, admin, lock). No command-line install required.

**License**: Set `LICENSE_SERVER_URL` (and optionally `LICENSE_PUBLIC_KEY` for JWT RS256) in `.env` to validate with an external server. `LICENSE_GRACE_HOURS` (default 72) applies when the server is unreachable. Purchase hash is stored in `.env` and in `license_keys` during install.

**Landing pages**: Create and publish under Landing pages in the app. Public URL (no auth) is **`/l/{tenant_id}/{slug}`** (e.g. `/l/abc-123-uuid/welcome`).

## Public marketing site
**Homepage**: `GET /` shows a public marketing page (hero, features, plans, CTAs). Guests see **Log in** / **Get started**; when the app is not yet installed, the page shows **Complete setup** linking to `/install`. Authenticated users visiting `/` are redirected to the dashboard at `/dashboard`. The dashboard and all app routes remain at `/dashboard`, `/ai/content`, etc.

## License verification server (optional)
A separate **license server** app is included in the repo at **`license-server/`**. It exposes `POST /validate` for the main app to verify purchase codes (see main app `.env`: `LICENSE_SERVER_URL`, `LICENSE_PUBLIC_KEY`).

- **Deploy**: Point a subdomain (e.g. `license.yourdomain.com`) document root to **`license-server/public/`**. PHP 8.2+ and OpenSSL required; no Composer needed.
- **Setup**: Copy `license-server/.env.example` to `license-server/.env`. Add valid purchase code hashes to `license-server/data/purchase_codes.json` (see `license-server/README.md`). Optionally generate an RS256 key pair: private key in license server, public key in main app `LICENSE_PUBLIC_KEY`.
- **Main app**: Set `LICENSE_SERVER_URL=https://license.yourdomain.com/validate` so the installer (Step 4) and daily `license:validate` cron can verify licenses.
