# v79 — cPanel Online Staging Deployment

v79 deploys a production-mode staging copy to shared cPanel without changing the
application architecture.

## Confirmed hosting capabilities

The target account exposes:
- PHP 8.3 after account correction;
- `pdo_pgsql` / `pgsql`;
- PHP Redis extension;
- PostgreSQL tooling;
- Redis application support;
- Terminal;
- Cron Jobs;
- Git;
- `/home/zagazig/public_html`.

Node and Composer on the hosting account are intentionally not required by deployment.
React and Composer production dependencies are built locally into the immutable upload
artifact.

## Layout

Application code is kept outside the public web root:

`~/retail-pos-staging/releases/<commit>`

Stable symlink:

`~/retail-pos-staging/current`

Shared secrets/runtime:

`~/retail-pos-staging/shared`

Default web document root:

`~/public_html/retail-pos-staging`

The web root contains only React/Laravel public files. Its generated `index.php` boots
Laravel from the private application path.

## Same-origin frontend/API

React is built into Laravel's public artifact. Apache routing sends:
- `/api/*`, `/up/*`, `/sanctum/*` to Laravel;
- static files directly;
- all remaining paths to React `index.html`.

The frontend therefore keeps its existing `/api/v1` default and requires no CORS
workaround for staging.

## Redis

cPanel Redis may be TCP or Unix-socket based. The installer supports both. For a Unix
socket use the socket path as `REDIS_HOST` and port `0`.

A blank `redis-cli ping` against default TCP is not treated as proof that Redis is
unavailable; the preflight prints accessible socket candidates.

## Queue on shared cPanel

A permanently supervised worker cannot be assumed on shared hosting. Staging uses a
bounded once-per-minute queue worker:

`queue:work redis --stop-when-empty --max-time=50`

and the normal Laravel scheduler every minute. `flock` is used when available to avoid
overlap.

This is acceptable for staging acceptance, not the final production worker topology.

## PostgreSQL

The CLI version alone is not treated as the server version. Installation connects using
the real staging credentials and prints the actual server version before migrations.

## Secrets

The upload ZIP contains no `.env` secrets. The server installer asks for DB/Redis
credentials interactively, generates a fresh APP_KEY, writes `shared/.env` with mode
0600, and symlinks it into the active release.

## Demo data

The staging environment intentionally runs `demo:seed-retail --force` so browser
acceptance has the same known tenant/login dataset as local E2E testing. Never run this
staging workflow against a production customer database.
