# Implementation plan — v5 Deployment prep (cPanel shared hosting)

## Problem
v1–v4 were built for **local dev**: `start.sh` does `source .env.local` and runs
PHP's built-in server with `public/` as docroot. On cPanel there is no
`start.sh`, so `getenv('SO_*')` returns empty and the DB connection fails. The
DB name/user also differ, and there's typically no SSH to run the CLI installer.

## Approach (config-only; no feature changes)

1. **Per-server config override.** `config/config.php` now builds the base array
   (env + defaults as before), then **deep-merges** a git-ignored
   `config/config.local.php` on top, then returns it. This is the single place
   servers supply real values. A committed `config.local.php.example` documents it.

2. **Production error handling.** `config.php` sets `display_errors` from a new
   `debug` flag (default **false**) and always enables `log_errors` — once per
   request via a `SO_ERRORS_CONFIGURED` guard.

3. **Secret protection in depth.** Defensive `.htaccess` (`Require all denied`,
   with a 2.2 fallback) in `config/`, `src/`, and `install/` so those folders are
   never web-served even if the whole repo lands inside `public_html`. Preferred
   layout still puts them above the docroot (`public/`).

4. **Session hardening.** `auth.php` now calls `session_set_cookie_params` with
   `httponly`, `samesite=Lax`, and `secure` auto-detected from HTTPS /
   `X-Forwarded-Proto` / port 443, before `session_start()`.

5. **Shell-free installer.** `public/setup.php` is a one-time, token-guarded web
   installer (`install_token` in `config.local.php`, compared with `hash_equals`).
   It connects with the DB **already selected** (`Database::pdo()`), reads the
   existing `install/schema.sql` + `install/seed.sql`, and **strips
   `CREATE DATABASE` / `USE` at runtime** (regex) so the one SQL source works for
   any cPanel DB name. Seeding is opt-in via `&seed=1`. Creates/updates the admin
   (hashed). Instructs deletion afterward.

6. **Git hygiene.** `.gitignore` now excludes `config/config.local.php`.

7. **Docs.** `DEPLOY.md` gives the full cPanel runbook (create DB → upload →
   config.local → setup.php → lock down → log in).

## Files
- edit `config/config.php` — local-override merge + debug/error handling + new `debug` / `install_token` keys
- add  `config/config.local.php.example`
- add  `config/.htaccess`, `src/.htaccess`, `install/.htaccess` (deny all)
- edit `public/auth.php` — secure session cookie params
- add  `public/setup.php` — token-guarded web installer
- edit `.gitignore` — ignore `config/config.local.php`
- add  `DEPLOY.md`

## Verification done
- `php -l` clean on all changed/added PHP.
- Loader test: `config.local.php` overrides merge (db.name changed, base db.host
  kept, pass applied, install_token read); `display_errors=0` when `debug=false`.
- SQL-strip test: `CREATE DATABASE` and `USE` removed, `CREATE TABLE`s intact.

## Not done (flagged, needs the live host / user action)
- Actual FTP upload (`.ftp.env` not present on this machine).
- Running `setup.php` against the real DB.
- Rotating the chat-shared DB/mail passwords (standing security follow-up).
