# Temporary deployment

How the app was put on a public URL for demos and phone testing, and how to take
it down again. **This is not a production deployment** — see the caveats at the end.

---

## What it looks like

One origin serves all three surfaces, so there is one URL to share and no CORS to
configure:

| Path | What |
|---|---|
| `/login` | Operations portal (Admin / EFU Ops / BIPL Ops) |
| `/journey` | Customer journey (the React app) |
| `/api/v1/*` | JSON API |
| `/journey-assets/*` | The SPA's compiled JS, CSS and images |

---

## Bringing it up

```bash
# 1. Build the journey so it can be served from Laravel
cd "../BIPL Frontend"
npm run build:embedded          # outputs dist-app/ using .env.deploy

# 2. Copy it into the Laravel public directory
cd "../BIPL Backend"
php artisan journey:publish

# 3. Serve, listening on all interfaces
php artisan serve --host=0.0.0.0 --port=8000

# 4. Open a public HTTPS tunnel (no account, no install — uses OpenSSH)
ssh -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 \
    -R 80:127.0.0.1:8000 nokey@localhost.run
```

The tunnel prints a line like:

```
ff47ee803ff57d.lhr.life tunneled with tls termination, https://ff47ee803ff57d.lhr.life
```

Then point the app at that address and clear the cached config:

```bash
# .env
APP_URL=https://<subdomain>.lhr.life
JOURNEY_URL=https://<subdomain>.lhr.life/journey
FRONTEND_ORIGINS="http://localhost:3000,http://127.0.0.1:3000,https://<subdomain>.lhr.life"
TRUSTED_PROXIES=*

php artisan optimize:clear
```

### Use `127.0.0.1`, not `localhost`, in the `-R` forward

On Windows, `localhost` resolves to `::1` first. `php artisan serve --host=0.0.0.0`
binds IPv4 only, so `-R 80:localhost:8000` forwards to a port nothing is listening
on and every request dies with "connection closed unexpectedly". `-R 80:127.0.0.1:8000`
avoids it.

### `TRUSTED_PROXIES`

TLS is terminated at the tunnel, so requests reach Laravel over plain HTTP. Without
trusting `X-Forwarded-Proto`, Laravel builds `http://` URLs on an `https://` site and
redirects break. `bootstrap/app.php` reads `TRUSTED_PROXIES` and only enables this
when it is set, so local development is unaffected.

---

## Taking it down

```powershell
Get-Process ssh  | Stop-Process -Force     # closes the public URL
Get-Process php  | Stop-Process -Force     # stops the server
```

Then restore local settings:

```bash
cd "../BIPL Backend"
cp .env.local-backup .env         # debug on, localhost URLs, no trusted proxies
php artisan optimize:clear
php artisan journey:publish --clean
```

The URL dies with the SSH process. localhost.run issues a new random subdomain each
time, so the old address cannot be reused by anyone.

---

## What is exposed while it is up

Anyone with the URL can reach **everything**. There is no IP allowlist.

- **The operations portal.** Passwords were rotated with `php artisan portal:rotate-passwords`
  before exposure — the seeded `Password@123` is in source control and must never be
  live on a public URL.
- **The API**, including `/entry/resolve`. Anyone who can construct a payload
  encrypted with the public key can create a customer.
- **`OTP_TEST_MODE=true`** — `/otp/send` returns the code in its own response, so OTP
  is not a real barrier. It stays on because no SMS gateway is wired up yet; turn it
  off and the journey cannot be completed at all.
- **Claim documents** are behind the journey token, but that token is obtainable by
  anyone who can complete the entry flow.

`APP_DEBUG` is off, so stack traces will not leak `APP_KEY` or the database
credentials. Keep it that way — customer CNICs and mobile numbers are encrypted with
`APP_KEY`.

**Only synthetic data should exist in this database while the tunnel is open.**

---

## Why this is not production

- `php artisan serve` is PHP's built-in server: single-threaded, one request at a
  time. Fine for a demo, useless under load.
- localhost.run is a free third-party tunnel with no uptime guarantee, and the
  subdomain changes on every reconnect.
- The SPA is served from Laravel's `public/` directory. In production it would sit
  behind a CDN, and `public/journey-assets` would not be a build artefact copied in
  by an artisan command.

For a real deployment: Nginx or Apache in front of PHP-FPM, a proper domain and
certificate, `APP_ENV=production`, `php artisan config:cache route:cache view:cache`,
a queue worker, and the scheduler on cron.
