# Demo site reliability hotfix — deploy guide

This branch (`hotfix/demo-reliability`) ships **four fixes** that address the
"widget thinking is stuck" symptom on cPanel-hosted demo sites.

## What's in the fix

1. **Widget hang detector** — the visitor never sees an indefinite "thinking…"
   spinner. If the SSE stream goes silent for 25 s or the whole turn exceeds
   90 s, the widget aborts the request, shows a retry affordance, and the
   visitor can try again. Also: if the stream ends without a `done` event
   (silent proxy timeout), the same retry path fires.

2. **Server-side heartbeat + buffer drain** — `MessageStreamController` now
   sends a heartbeat byte before doing any work and explicitly drains every
   layer of output buffer (cPanel + LSAPI + Octane each layer one). Proxies
   that buffer "until first byte" (Cloudflare CDN, nginx) release the
   response immediately instead of waiting 30 s and dropping the connection.

3. **Queue tick endpoint + Cloudflare cron Worker auto-deploy** — cPanel
   crons + long-running `queue:work` daemons are notoriously unreliable on
   shared hosting. New flow:
   - `POST /api/v1/internal/queue-tick` processes a bounded batch of jobs
     and exits, authenticated by a shared secret in
     `app_settings.internal_queue_token`.
   - **Admin Settings → System → Cron worker → Deploy worker** uploads a
     Cloudflare Worker on the install's existing CF account, which pings
     the endpoint every minute. **Free tier**, zero cPanel cron required.

4. **Worker-script idempotency** — re-deploying overwrites the same Worker
   in place, so customers can click "Re-deploy" any time and it just works.

## How customers deploy on their installs

After they pull the branch on their demo / production server:

```bash
git pull origin hotfix/demo-reliability
composer install --no-dev --optimize-autoloader
php artisan migrate --force
npm run build
npm run build:widget
php artisan config:clear
php artisan route:clear
php artisan view:clear
```

Then in the admin panel:

1. **Settings → System → AI providers → Cloudflare** — make sure account
   ID + API token are saved (this is the existing Workers AI config —
   nothing new).
2. **Settings → System → Cron worker → Deploy worker** — one click. The
   worker uploads to their Cloudflare account, the cron schedule kicks in
   immediately, and the queue starts draining within a minute.

## Cloudflare API token scopes

The CF API token already used for Workers AI / Vectorize will need these
scopes (set them once in the Cloudflare dashboard at My Profile → API
Tokens → Edit):

- ✅ Account → Workers Scripts → Edit
- ✅ Account → Workers Routes → Edit (needed for cron triggers)

If the token only has `Workers AI: Read`, the deploy will fail with a 403.
The error message in the admin UI tells you exactly what's missing.

## Manual fallback (no Cloudflare)

If a customer doesn't want to use the auto-deploy:

1. Set `INTERNAL_QUEUE_TOKEN=<random-32-chars>` in `.env`.
2. Configure ANY external cron to hit:
   ```
   POST https://<their-domain>/api/v1/internal/queue-tick
   X-Pitchbar-Token: <same-token>
   ```
   Free options: cron-job.org, GitHub Actions schedule, UptimeRobot pings,
   any uptime monitor with cron features.

## Verification

After deploy, check from the admin's browser DevTools or curl:

```bash
# 1. queue-tick endpoint authentication works
curl -X POST https://YOUR-DOMAIN.com/api/v1/internal/queue-tick \
  -H "X-Pitchbar-Token: <token>" -H "Content-Type: application/json" \
  -d '{"max_jobs":3,"max_time":10}'
# → {"data":{"exit_code":0,"stats":{"processed":3,...}}}

# 2. Widget stream works end-to-end (after init)
curl -X POST https://YOUR-DOMAIN.com/api/v1/widget/init \
  -H "Origin: https://YOUR-DOMAIN.com" -H "Content-Type: application/json" \
  -d '{"agent_id":"<agent-uuid>"}'
# Then feed the JWT to /api/v1/widget/messages/stream and watch token events.
```

## Test coverage shipped on this branch

- 7 unit tests for `WorkerDeployer` (mocked Cloudflare API)
- 4 feature tests for `QueueTickController` (auth, tick stats)
- 7 feature tests for `CronWorkerController` (deploy / status / destroy /
  rotate-token / cross-tenant 404)
- 2 feature tests for the system settings page rendering the new tab
- All 63 existing widget tests still pass
- Live verification on `https://superbar.test` confirmed:
  - queue-tick endpoint processes jobs (3 → 51 remaining)
  - widget stream emits heartbeat + start + token + done in correct order

Total: **20 new tests + 666 existing tests passing.**
