# Deployment Guide

This guide covers deploying the **Business Verifier** web package to a shared Linux host (e.g. x10) and connecting one or more **Windows home agent** PCs that run the worker pool.

---

## Objective

Your production web app needs real-time secretary-of-state (SOS) and registry verification across multiple US states, plus optional Florida DBPR professional license checks.

| Capability | Where it runs |
|------------|---------------|
| Registry lookups (document / control #, name search, verify by name) | Worker queue → `businessverifier_agent.exe` on Windows (production) or PHP direct (dev / datacenter-friendly states) |
| Florida DBPR license lookup | PHP on the web server (no agent required) |
| Job coordination | File queue on the web server (`sunbiz_queue_api.php`) |

Many registries block datacenter IPs (Cloudflare, Akamai, Imperva, reCAPTCHA). Production shared hosting uses:

1. A **file-based queue** on the web server
2. One or more **Windows PCs** with residential IPs running `businessverifier_agent.exe`
3. PHP that **enqueues and polls synchronously** (~3–15 seconds typical)

---

## Supported states

| Code | Registry | Queue / agent | Notes |
|------|----------|---------------|-------|
| FL | Florida Sunbiz | Worker queue (Cloudflare) | Document number |
| GA | Georgia SOS | Worker queue or server PHP | Control number |
| AL | Alabama SOS | Worker queue or server PHP | Entity ID |
| SC | South Carolina SOS | Worker queue or server PHP | Profile UUID |
| MS | Mississippi SOS | **Windows agent + Edge** | Akamai-protected |
| LA | Louisiana SOS | **Windows agent + Edge** | reCAPTCHA |
| NC | North Carolina SOS | **Windows agent + Edge** | Cloudflare + reCAPTCHA |
| CA | California BizFile | **Windows agent + Edge** | Imperva cookies |
| TX | Texas Comptroller | Worker queue or server PHP | SOS file / taxpayer number |
| WV | West Virginia SOS | **Windows agent + Edge** | Organization name search; invisible reCAPTCHA (no 2captcha) |
| TN | Tennessee SOS | **Windows agent + Edge** | reCAPTCHA |
| KY | Kentucky SOS | Worker queue or server PHP | Organization number; profile via UpdatePanel HTTP |
| VA | Virginia SCC | **Windows agent + Edge** | Entity ID; invisible reCAPTCHA on login search — see `sunbiz-agent-cpp/docs/VIRGINIA_SCC_EDGE.md` |

**Production (x10):** set `sunbiz_queue_url` in `hosting_config.php` so **all** registry jobs go through the queue, regardless of state.

**DBPR:** use `verifyBusiness()` / **Combined Check** in `index.html` — license is verified by PHP on the server, not the Windows agent.

---

## What you upload

Upload the entire `FloridaBusinessVerifier/` folder to your web directory:

```
public_html/
└── FloridaBusinessVerifier/
    ├── lib/                         PHP library classes
    ├── api/                         Per-state verifier implementations
    ├── autoload.php
    ├── api.php                      JSON API (test UI + integrations)
    ├── index.html                   Multi-state browser test console
    ├── sunbiz_queue_api.php         Queue REST API (app ↔ agents)
    ├── hosting_config.php           ← you create this
    ├── queue_config.php             ← you create this
    └── storage/verification_queue/  ← must be writable
```

**No Composer required on the server.** `autoload.php` loads classes from `lib/` and `api/`.

---

## Step 1 — Create server config files

### `queue_config.php`

```bash
cp queue_config.example.php queue_config.php
```

| Key | Used by |
|-----|---------|
| `app_token` | Your PHP app, `api.php`, `hosting_config.php` — enqueue and poll jobs |
| `agent_token` | Every `businessverifier_agent.exe` worker PC — claim, complete, fail, heartbeat |
| `queue_directory` | Path to `storage/verification_queue/` |
| `ttl_seconds` | Max age before completed/failed jobs are deleted (default 3600) |
| `job_lease_seconds` | How long a claimed job stays reserved for one agent (default 600); extended via heartbeat |
| `client_pending_timeout_seconds` | Pending jobs older than this are failed when the PHP client gave up waiting (default 300) |

Use long random tokens. The same `agent_token` is shared across all worker PCs; each machine uses a unique `agent_id` in `config.json`.

### `hosting_config.php`

```bash
cp hosting_config.example.php hosting_config.php
```

Minimum settings for x10 + home agent queue:

```php
return [
    'transport' => 'php',
    'verify_ssl' => true,
    'min_delay_ms' => 500,
    'timeout' => 30,

    'sunbiz_queue_url' => 'https://YOUR-DOMAIN/FloridaBusinessVerifier/sunbiz_queue_api.php',
    'sunbiz_queue_app_token' => 'same-as-app_token-in-queue_config.php',
    'sunbiz_queue_timeout' => 45,
];
```

**Queue URL options**

| Setup | `sunbiz_queue_url` |
|-------|-------------------|
| Recommended (this package) | `https://YOUR-DOMAIN/FloridaBusinessVerifier/sunbiz_queue_api.php` |
| Legacy root install | `https://YOUR-DOMAIN/sunbiz_queue_api.php` |

The agent `queue_api_url` and `hosting_config.php` must point to the **same** endpoint.

---

## Step 2 — Permissions

On the server:

```bash
chmod 775 FloridaBusinessVerifier/storage/verification_queue
```

The queue creates subfolders automatically: `pending/`, `processing/`, `completed/`, `failed/`, and `agent_registry.json` for multi-agent tracking.

---

## Step 3 — Windows home agent

The C++ agent lives in `sunbiz-agent-cpp/` (separate from this folder). Build once, then deploy to each worker PC.

### Build (one time, on Windows)

```powershell
cd C:\path\to\sunbiz-agent-cpp
.\build.ps1
```

Output: `build\Release\businessverifier_agent.exe`

### Setup package (install on other Windows PCs)

```powershell
winget install JRSoftware.InnoSetup   # one time
.\package.ps1
```

Distribute `dist\BusinessVerifierAgent-Setup-1.0.0.exe`, or copy the `build\Release/` folder including `Helper_Scripts/`.

### First-time setup on a worker PC

1. Run **`Helper_Scripts\Setup.bat`** — creates `config\config.json` from the example and `data/` folders.
2. Edit **`config\config.json`**:

```json
{
  "queue_api_url": "https://YOUR-DOMAIN/FloridaBusinessVerifier/sunbiz_queue_api.php",
  "agent_token": "same-as-agent_token-in-queue_config.php",
  "agent_id": "office-pc-1",
  "enabled_states": ["FL", "GA", "AL", "SC", "MS", "LA", "NC", "CA", "TX", "WV", "TN", "KY", "VA"],
  "long_poll_seconds": 45,
  "poll_seconds": 2,
  "worker_count": 4,
  "max_concurrent_jobs": 4,
  "queue_heartbeat_seconds": 30,
  "control_api_bind": "127.0.0.1",
  "control_api_port": 17821,
  "log_file": "data/logs/agent.log",
  "debug": {
    "enabled": false,
    "verbose_logging": false,
    "log_control_api": false,
    "log_queue_requests": false,
    "preserve_log_on_startup": true,
    "helper_script_verbose": false
  },
  "edge_pool": {
    "size": 4,
    "pre_warm_on_startup": true,
    "acquire_timeout_seconds": 90,
    "state_switch_timeout_seconds": 120
  },
  "http": {
    "transport": "auto",
    "timeout_seconds": 30,
    "verify_ssl": true,
    "min_delay_ms": 300
  }
}
```

| Setting | Notes |
|---------|-------|
| `queue_api_url` | Must match `sunbiz_queue_url` (same PHP file) |
| `agent_token` | Must match `queue_config.php` → `agent_token` |
| `agent_id` | **Unique per PC** (e.g. `office-pc-1`, `home-pc-2`) — required for multi-agent lease tracking |
| `enabled_states` | States this machine will claim jobs for — also toggled via GUI **States ▾** (two columns at 13 states; WV and VA are in the right column) |
| `worker_count` / `max_concurrent_jobs` | Parallel workers on this PC (max 25). Edge jobs also need a free pool slot. |
| `long_poll_seconds` | Hold each `claim` open up to N seconds (~1 req/min idle vs ~30/min at 2s polling) |
| `queue_heartbeat_seconds` | How often workers extend job leases while processing |
| `transport: auto` | Windows `curl.exe` for registry HTTP; libcurl for queue API |
| `edge_pool` | Shared Edge browser slots — `size` (default 4), pre-warm, acquire/migrate timeouts. See `sunbiz-agent-cpp/docs/EDGE_POOL.md` |
| `edge_sessions` | Per-state Edge settings for MS, LA, NC, CA, TN, VA, WV (setup search, refresh, debug). See `config.example.json` and `config/README.md` |

### How to run workers

| Mode | How | Best for |
|------|-----|----------|
| **Manual** | `Helper_Scripts\Start Workers (manual).bat` | Testing |
| **GUI + workers** | `Helper_Scripts\Start Workers and Monitor.bat` | Local dev |
| **Monitor only** | `Helper_Scripts\Open Monitor.bat` | View logs; workers started separately |
| **Windows Service** | `Helper_Scripts\Install Windows Service.bat` (Admin) | Production — survives logoff/reboot |

Workers run as `businessverifier_agent.exe --service` (background). The monitor GUI is a **separate** process — closing it does **not** stop workers.

Full helper reference: `Helper_Scripts/README.md` on the worker PC (copied from `sunbiz-agent-cpp/scripts/launchers/README.md` on build).

### Monitor GUI (default workflow)

Opening `businessverifier_agent.exe` (without `--service`) shows three tabs:

| Tab | Purpose |
|-----|---------|
| **Monitor** (default) | Live activity log, pause, hide window — watch jobs while workers run |
| **Server** | Start / stop / restart workers, status panel, server events log. **Auto-starts workers** on launch if they are not running |
| **Advanced** | Debug toggles, last error, Edge slot/process counts (`data/edge_pool/slot_*/`), `helper.log` tail, **Clear All Logs**, refresh diagnostics |

**States ▾** (monitor or main window): checkmarks reflect `enabled_states`. The **Enabled registries** summary line shows only checked states, not every available registry.

Local control API: `http://127.0.0.1:17821` (configurable via `control_api_bind` / `control_api_port`).

### Multi-agent deployment

- Use the **same** `agent_token` on every PC.
- Give each PC a **unique** `agent_id`.
- Split `enabled_states` across machines if desired (e.g. one PC for FL/GA/TX, another for MS/LA/NC/CA/TN).
- View per-state agent counts in `index.html` → **Queue Status** or `sunbiz_queue_api.php?action=health`.

---

## Step 4 — Verify deployment

### Queue health (browser or curl)

```
https://YOUR-DOMAIN/FloridaBusinessVerifier/sunbiz_queue_api.php?action=health
```

Expected: JSON with `pending`, `processing`, `pending_by_state`, `active_agents_by_state`, `supported_states`.

### Test UI

```
https://YOUR-DOMAIN/FloridaBusinessVerifier/index.html
```

1. Confirm status pills: config ready, queue mode = **home agent queue**, active states listed, workers reachable.
2. Pick a state from the dropdown (top right).
3. Use **Document / Control #** — examples update per state.
4. Run verification while workers are running on at least one PC with that state enabled.

Florida document example: `M22000004323`. Expect ~3–15 seconds depending on state and agent load.

**Combined Check** — registry + optional Florida DBPR license (license runs on PHP server).

### API status

```
https://YOUR-DOMAIN/FloridaBusinessVerifier/api.php?action=status
```

Returns `state_catalog`, `agent_required_states`, `queue_health`, and deployment mode flags.

### API (direct verify)

```bash
curl -X POST https://YOUR-DOMAIN/FloridaBusinessVerifier/api.php \
  -H "Content-Type: application/json" \
  -d '{"action":"verify_document","state":"FL","document_number":"M22000004323"}'
```

---

## Step 5 — Use in your application

```php
require __DIR__ . '/FloridaBusinessVerifier/autoload.php';

use VerifyBusiness\FloridaBusinessVerifier;
use VerifyBusiness\StateCodes;

$verifier = FloridaBusinessVerifier::create(
    require __DIR__ . '/FloridaBusinessVerifier/hosting_config.php'
);

// Registry lookup (state required for non-FL)
$entity = $verifier->verifyDocumentNumber('M22000004323', StateCodes::FLORIDA);

if ($entity['found'] && $entity['is_active']) {
    // entity is active
}

// Other registry methods (pass $state as last argument):
// searchBusinessByName($name, $limit, $options, $state)
// verifyBusinessByName($name, $options, $state)

// Florida DBPR only (server-side PHP, no agent):
$license = $verifier->verifyLicenseNumber('CBC1260068');

// Combined registry + optional license:
$result = $verifier->verifyBusiness('M22000004323', 'CBC1260068', StateCodes::FLORIDA);
```

In queue mode, `verifyDocumentNumber()` enqueues a job, polls until complete or timeout, then returns the entity JSON.

---

## Token cheat sheet

```
queue_config.php
├── app_token   ──────► hosting_config.php → sunbiz_queue_app_token
│                       (PHP app enqueues via QueuedSunbizVerifier)
│
└── agent_token ──────► config.json → agent_token (every worker PC)
                        (agents claim/complete/heartbeat via sunbiz_queue_api.php)

config.json (per PC, unique)
└── agent_id    ──────► identifies this machine in agent_registry.json
```

Never commit real tokens. Do not expose `agent_token` in browser-facing code.

---

## Troubleshooting

| Symptom | Likely cause | Fix |
|---------|--------------|-----|
| HTTP 401 on agent | Wrong `agent_token` | Match `config.json` to `queue_config.php` |
| HTTP 500 queue API | Missing config or unwritable storage | Create `queue_config.php`, chmod `storage/verification_queue` |
| Request times out (~45s) | No worker running, paused, or state not in `enabled_states` | Start workers via GUI **Server** tab or `Start Workers (manual).bat`; check **Queue Status** |
| `Could not connect` in `helper.log` for Control API | Local workers not running (port 17821) | Not a remote server error — start workers on that PC |
| Edge state fails (MS/LA/NC/CA/WV/TN/VA) | Edge pool slot / session / reCAPTCHA | `data/logs/*_session_record.jsonl`, `data/edge_pool/slot_*/meta.json`, `docs/EDGE_POOL.md` |
| `Timed out waiting for an Edge pool slot` | All slots busy or migration slow | Raise `edge_pool.acquire_timeout_seconds`; reduce concurrent Edge jobs; check `agent.log` |
| Jobs stuck in `processing` | Agent crashed mid-job | Restart workers; `agent_startup` fails orphans |
| Wrong state processed | `enabled_states` mismatch | Align agent config with job `state` field |
| `entity_name` null / partial data | Old agent build | Rebuild agent, run **Apply Update.bat** on worker PC |
| Cloudflare on FL | libcurl used for Sunbiz | Set `"transport": "auto"` in agent `http` config |
| Logs growing large | Normal operation | GUI **Advanced** → **Clear All Logs**, or delete `data/logs/agent.log` / `helper.log` |
| Build fails LNK1104 / exe missing | Agent still running or antivirus locked file | Close `businessverifier_agent.exe` and monitor; exclude Release + `build` from McAfee; if link failed you may only see `businessverifier_agent.exe.previous` |
| KY name search returns stub | Old agent or redirect not followed | Rebuild agent; KY profile GET uses `curl.exe` for `sosbes.sos.ky.gov` |
| VA jobs not claimed | `VA` not in `enabled_states` | Add `"VA"` in config or check **Virginia (SCC)** in **States ▾** (right column) |
| WV jobs not claimed | `WV` not in `enabled_states` | Add `"WV"` in config or check **West Virginia (SOS)** in **States ▾** |

### Log locations (worker PC)

| File | Contents |
|------|----------|
| `data/logs/agent.log` | Worker service log, Edge pool pre-warm and acquire/migrate |
| `data/logs/helper.log` | PowerShell helper script log |
| `data/logs/*_session_record.jsonl` | Per-state job + invoke trace (MS, NC, SC always log job lifecycle) |
| `data/logs/ms_setup_trace.jsonl` | Mississippi Edge setup steps |
| `data/logs/nc_setup_trace.jsonl` | North Carolina Edge setup steps |
| `data/logs/sc_session_record.jsonl` | South Carolina HTTP job trace (including `verify_detail_reused`) |
| `data/edge_pool/slot_*/meta.json` | Parked state per Edge slot |
| `data/logs/*_debug/bundle_*/` | Failure debug bundles (slot-aware when applicable) |

---

## Security checklist

- [ ] Use long random tokens for `app_token` and `agent_token`
- [ ] Do not commit `hosting_config.php`, `queue_config.php`, or `config.json` with real tokens
- [ ] Restrict write access to `storage/verification_queue/`
- [ ] Keep the control API on `127.0.0.1` (default) — not exposed to the internet
- [ ] Run agents only on trusted Windows PCs
- [ ] Remove standalone diagnostic scripts from public web roots after setup (if any)

---

## Post-deploy cleanup (optional)

After confirming everything works, remove standalone diagnostic scripts uploaded outside this folder (e.g. `test_queue.php`, `server_check.php`).

Keep:

- `FloridaBusinessVerifier/` (entire folder, preserve `storage/` and configs)
- `businessverifier_agent.exe` + `config/config.json` + `Helper_Scripts/` on each worker PC
